diff --git a/TESTS/mbed_hal/critical_section/main.cpp b/TESTS/mbed_hal/critical_section/main.cpp index faa0039fc8..3f7dd920fe 100644 --- a/TESTS/mbed_hal/critical_section/main.cpp +++ b/TESTS/mbed_hal/critical_section/main.cpp @@ -20,7 +20,7 @@ #include "greentea-client/test_env.h" #include "mbed.h" #include "cmsis.h" -#ifdef TARGET_NRF5 // for all NRF5x targets +#if defined(TARGET_NRF5) || defined(TARGET_NRF5x) // for all NRF5x targets #include "nrf_nvic.h" // for __NRF_NVIC_APP_IRQS_0 / __NRF_NVIC_APP_IRQS_1 #endif @@ -30,7 +30,7 @@ bool test_are_interrupts_enabled(void) { // NRF5x targets don't disable interrupts when in critical section, instead they mask application interrupts this is due to BLE stack // (BLE to be operational requires some interrupts to be always enabled) -#ifdef TARGET_NRF52_DK +#ifdef TARGET_NRF52 // check if APP interrupts are masked for NRF52_DK board return (((NVIC->ISER[0] & __NRF_NVIC_APP_IRQS_0) != 0) || ((NVIC->ISER[1] & __NRF_NVIC_APP_IRQS_1) != 0)); #elif TARGET_NRF5 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/CHANGELOG.md b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/CHANGELOG.md new file mode 100644 index 0000000000..bb4dad9a4a --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/CHANGELOG.md @@ -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)* \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/LICENSE b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/LICENSE new file mode 100644 index 0000000000..60744edab2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/LICENSE @@ -0,0 +1,6 @@ +This module contains softdevice which comes with The Nordic Softdevice License Agreement, +a BSD-like licence for binary distributions, offered by Nordic for use in mbed. Some +other files come from the mbed SDK, and are licensed under Apache-2.0. Unless +specifically indicated otherwise in a file, files are licensed under the +Apache 2.0 license, as can be found in: apache-2.0.txt. The Nordic Semiconductor Softdevice +License Agreement can be found in softdevice_nrf51822_licence_agreement.txt. diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/apache-2.0.txt b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/apache-2.0.txt new file mode 100644 index 0000000000..9327527edd --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/apache-2.0.txt @@ -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. diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/module.json b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/module.json new file mode 100644 index 0000000000..b45b894f0e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/module.json @@ -0,0 +1,36 @@ +{ + "name": "ble-nrf51822", + "version": "2.7.1", + "description": "Nordic stack and drivers for the mbed BLE API.", + "keywords": [ + "Bluetooth", + "BLE", + "mbed", + "mbed-official" + ], + "author": "Rohit Grover", + "repository": { + "url": "git@github.com:ARMmbed/ble-nRF51822.git", + "type": "git" + }, + "homepage": "https://developer.mbed.org/teams/Nordic-Semiconductor/", + "licenses": [ + { + "url": "https://spdx.org/licenses/Apache-2.0", + "type": "Apache-2.0" + }, + { + "type": "LicenseRef-softdevice_nrf51822_licence_agreement.txt" + } + ], + "dependencies": { + "ble": "^2.6.0", + "nrf51-sdk": "^2.4.0" + }, + "extraIncludes": [ + "source/btle", + "source/btle/custom", + "source/common" + ], + "targetDependencies": {} +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/softdevice_nrf51822_licence_agreement.txt b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/softdevice_nrf51822_licence_agreement.txt new file mode 100644 index 0000000000..8e447f4c64 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/softdevice_nrf51822_licence_agreement.txt @@ -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. + * + * / diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp new file mode 100644 index 0000000000..5d6def57ac --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -0,0 +1,490 @@ +/* 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 "custom/custom_helper.h" + +#include "ble/GapEvents.h" +#include "nRF5xn.h" + +// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work +#undef STATIC_ASSERT_SIMPLE +#undef STATIC_ASSERT_MSG + +// FIXME : We can't use mbed_assert.h because we're using these macros within functions +#define STATIC_ASSERT_MSG(EXPR, MSG) +#define STATIC_ASSERT_SIMPLE(EXPR) + +#warning FIXME : We can't use mbed_assert.h because we're using these within functions + +#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 "nrf_fstorage.h" + #include "fds.h" + #include "peer_manager.h" + #include "ble_conn_state.h" +#endif + +#include "nrf_sdh.h" +#include "nrf_sdh_ble.h" +} + +#include "headers/ble_hci.h" + +#include "nRF5XPalGattClient.h" + + +// Make this volatile at it will be set in interrupt context +volatile 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); + +// Before SDK 14, the softdevice handler is implemented within the SDK +// In SDK 14+, we have to implement it as we're using the "polling" mode for the SD +extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector. + +#if NRF_SDK14PLUS_EVENT_HANDLERS +static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); +#else +static void btle_handler(ble_evt_t *p_ble_evt); +#endif + +#if !NRF_SDK14PLUS_EVENT_HANDLERS +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 +} +#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; + ret_code_t err_code; + + // register softdevice handler vector + NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler); + +#if (NRF_SD_BLE_API_VERSION >= 5) + err_code = nrf_sdh_enable_request(); + ASSERT_STATUS(err_code); +#else + // 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); +#endif + + // Enable BLE stack + #if (NRF_SD_BLE_API_VERSION >= 5) + // Configure softdevice manually + // We could have used nrf_sdh_ble_default_cfg_set() but it's tightly coupled with the macros defined in sdk_config.h + ble_cfg_t ble_cfg; + uint32_t ram_start = 0; + + // Recover start address of application's RAM + err_code = nrf_sdh_ble_app_ram_start_get(&ram_start); + ASSERT_STATUS(err_code); + + // First configure GAP parameters, including the maximum number of connections + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG; + ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = TOTAL_LINK_COUNT; + ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = NRF_SDH_BLE_GAP_EVENT_LENGTH; // FIXME? + + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // GAP - Configure the number of peripheral and central links + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG; + ble_cfg.gap_cfg.role_count_cfg.periph_role_count = PERIPHERAL_LINK_COUNT; + ble_cfg.gap_cfg.role_count_cfg.central_role_count = CENTRAL_LINK_COUNT; + ble_cfg.gap_cfg.role_count_cfg.central_sec_count = CENTRAL_LINK_COUNT ? + BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT : 0; + + err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // Configure GATT + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.conn_cfg.conn_cfg_tag = NRF_CONNECTION_TAG; + ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATT, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // Number of custom UUIDs + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = UUID_TABLE_MAX_ENTRIES; + + err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // GATT Server attribute table size + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = GATTS_ATTR_TAB_SIZE; + + err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // GATT Server, Service Changed characteristic + memset(&ble_cfg, 0, sizeof(ble_cfg_t)); + ble_cfg.gatts_cfg.service_changed.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT; + + err_code = sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &ble_cfg, ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + + // Enable BLE stack in softdevice + err_code = nrf_sdh_ble_enable(&ram_start); + if(err_code != NRF_SUCCESS) { + return ERROR_INVALID_PARAM; + } + #else + ble_enable_params_t ble_enable_params; + 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; + } + #endif + + // 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 + +// From SDK 14 onwards event handlers are registered differently +// http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fmigration.html +#if NRF_SDK14PLUS_EVENT_HANDLERS + // Register a handler for our BLE events. + NRF_SDH_BLE_OBSERVER(m_ble_observer, 3 /* default priority for user events */, btle_handler, NULL); +#else + ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler)); + ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch)); +#endif + + return btle_gap_init(); +} + +#if NRF_SDK14PLUS_EVENT_HANDLERS +static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context) +#else +static void btle_handler(ble_evt_t *p_ble_evt) +#endif +{ +#if NRF_SDK14PLUS_EVENT_HANDLERS + (void)p_context; // Keep compiler happy +#endif + using ble::pal::vendor::nordic::nRF5XGattClient; + +// In SDK14+, all other modules from the SDK will be registered independently as softdevice events observers +#if !NRF_SDK14PLUS_EVENT_HANDLERS + /* 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 +#endif + +#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) + nRF5XGattClient::handle_events(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(p_ble_evt->evt.gap_evt.params.connected.role); +#endif + gap.setConnectionHandle(handle); + const Gap::ConnectionParams_t *params = reinterpret_cast(&(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(peer->addr_type), peer->addr, + static_cast(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(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(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::handle_connection_termination(handle); +#endif + + gap.processDisconnectionEvent(handle, reason); + break; + } + + +#if (NRF_SD_BLE_API_VERSION >= 5) +#ifndef S140 + // Handle PHY upgrade request + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: + { + ble_gap_phys_t const phys = + { + /* rx_phys */ BLE_GAP_PHY_AUTO, + /* tx_phys */ BLE_GAP_PHY_AUTO, + }; + ASSERT_STATUS_RET_VOID( sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys) ); + break; + } +#endif + + // Handle Data length negotiation request + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + { + ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; + uint8_t const data_length_peer = + p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; + + const uint8_t max_data_length = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + 4 /* L2CAP header size */; + + uint8_t const data_length = MIN(max_data_length, data_length_peer); + + ble_gap_data_length_params_t const dlp = + { + /* max_rx_octets */ data_length, + /* max_tx_octets */ data_length + }; + + ASSERT_STATUS_RET_VOID(sd_ble_gap_data_length_update(p_gap_evt->conn_handle, &dlp, NULL)); + break; + } + + // Handle MTU exchange request + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + { + // Respond with the server MTU + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + ASSERT_STATUS_RET_VOID(sd_ble_gatts_exchange_mtu_reply(conn_handle, NRF_SDH_BLE_GATT_MAX_MTU_SIZE)); + break; + } +#endif + + 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(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(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); +} + +#if NRF_SD_BLE_API_VERSION >= 5 +/*! + @brief Handler for general errors above the SoftDevice layer. + Typically we can' recover from this so we do a reset. + This implementation will override the default weak symbol generated by the Nordic SDK +*/ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + ASSERT_STATUS_RET_VOID( id ); + NVIC_SystemReset(); +} +#else +/*! + @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(); +} +#endif + +#if NRF_SDK14PLUS_EVENT_HANDLERS +/*! + @brief Handler of Softdevice events. + This signals that the softdevie has events that need to be processed. +*/ +extern "C" void SD_EVT_IRQHandler(void) +{ + ASSERT_STATUS_RET_VOID(signalEvent()); +} +#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h new file mode 100644 index 0000000000..9b75ed1714 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h @@ -0,0 +1,75 @@ +/* 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/nrf_ble.h" + +#if NRF_SD_BLE_API_VERSION >= 5 +#include "sdk_config.h" +#endif + +#define NRF_CONNECTION_TAG 1 /**= 5) // Softdevice event dispatching has changed in SDK14 + +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 volatile bool isEventsSignaled; + +#ifdef __cplusplus +} +#endif + +#endif // ifndef _BTLE_H_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_clock.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_clock.h new file mode 100644 index 0000000000..bc4c1e29f4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_clock.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_ + + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp new file mode 100644 index 0000000000..085fb1e08e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp @@ -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 "headers/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 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h new file mode 100644 index 0000000000..828da3cd78 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h @@ -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_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp new file mode 100644 index 0000000000..389c9b5c4c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp @@ -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(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(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 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h new file mode 100644 index 0000000000..a1354a36ee --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.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. + */ + +#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); + +#if (NRF_SD_BLE_API_VERSION >= 3) + /** + * @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. + * + * @retval BLE_ERROR_NONE if successful. + * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. + */ + ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList); +#endif + +#endif /* _BTLE_SECURITY_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp new file mode 100644 index 0000000000..cdc5eba3d9 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp @@ -0,0 +1,488 @@ +/* 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" + +extern "C" void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash); + +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(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); +} + + +#if (NRF_SD_BLE_API_VERSION >= 3) +ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) +{ + pm_peer_id_t peer_id; + ret_code_t ret; + pm_peer_data_bonding_t bond_data; + + addrList.size = 0; + peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); + + /** + * Fill addresses list: + * Copy addresses from bond table, or + * for every private resolvable address in the bond table generate the resolvable address. + */ + while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pm_peer_data_bonding_load(peer_id, &bond_data); + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) { + // Peer data could not be found in flash or peer ID is not valid. + return BLE_ERROR_UNSPECIFIED; + } + + if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { + btle_generateResolvableAddress(bond_data.peer_ble_id.id_info, + (ble_gap_addr_t &) addrList.addresses[addrList.size].address); + } else { + memcpy(&addrList.addresses[addrList.size].address, + &bond_data.peer_ble_id.id_addr_info.addr, + sizeof(addrList.addresses[0].address)); + } + + addrList.addresses[addrList.size].type = static_cast (bond_data.peer_ble_id.id_addr_info.addr_type); + + addrList.size++; + + // get next peer id + peer_id = pm_next_peer_id_get(peer_id); + } + + return BLE_ERROR_NONE; +} +#endif + +#endif // defined(S130) || defined(S132) || defined(S140) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp new file mode 100644 index 0000000000..ea6e63c74c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp @@ -0,0 +1,372 @@ +/* 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" +#include "../btle.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, + const uint8_t *presentationFormatDescriptorValuePtr, + uint16_t presentationFormatDescriptorValueLen, + 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(userDescriptionDescriptorValuePtr); + char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen; + char_md.char_user_desc_size = userDescriptionDescriptorValueLen; + } + if ((presentationFormatDescriptorValueLen > 0) && (presentationFormatDescriptorValuePtr != NULL)) { + ASSERT_TRUE( sizeof(ble_gatts_char_pf_t) == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM ); + ASSERT_TRUE( presentationFormatDescriptorValueLen == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM ); + char_md.p_char_pf = const_cast(reinterpret_cast(presentationFormatDescriptorValuePtr)); + } + + /* 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; +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h new file mode 100644 index 0000000000..49505c5eec --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h @@ -0,0 +1,70 @@ +/* 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/nrf_ble.h" +#include "ble/UUID.h" +#include "ble/GattCharacteristic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 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, + const uint8_t *presentationFormatDescriptorValuePtr, + uint16_t presentationFormatDescriptorValueLen, + 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_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ansi_escape.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ansi_escape.h new file mode 100644 index 0000000000..392dedb44f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ansi_escape.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_ */ + +/** @} */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/assertion.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/assertion.h new file mode 100644 index 0000000000..71bacb3e81 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/assertion.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_ */ + +/** @} */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/binary.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/binary.h new file mode 100644 index 0000000000..585787eb2f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/binary.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_ */ + +/** @} */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ble_error.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ble_error.h new file mode 100644 index 0000000000..36deb33080 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/ble_error.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_ */ + + /** @} */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/common.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/common.h new file mode 100644 index 0000000000..6002c6dfb7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/common.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 +#include +#include +#include +#include + +//------------- 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_ */ + +/** @} */ +/** @} */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/compiler.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/compiler.h new file mode 100644 index 0000000000..5b04ac05d0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/common/compiler.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_ */ + +/// @} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp new file mode 100644 index 0000000000..ebd194cd76 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp @@ -0,0 +1,1681 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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 + +#include "nRF5XPalGattClient.h" + +#include "ble/pal/PalGattClient.h" +#include "ble/pal/SimpleAttServerMessage.h" + +#include "headers/nrf_ble.h" +#include "headers/ble_gatt.h" +#include "headers/ble_types.h" +#include "headers/ble_err.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +namespace { + +/** + * Extract an uint16_t value from a memory location. + */ +static uint16_t bytes_to_u16(const void* b) +{ + uint16_t res; + memcpy(&res, b, sizeof(uint16_t)); + return res; +} + +/** + * Push an uint16_t value into a byte stream. + * + * @note it is incremented. + */ +static void u16_to_stream(uint8_t *&it, uint16_t v) +{ + memcpy(it, &v, sizeof(uint16_t)); + it += 2; +} + +/** + * Convert a pal::attribute_handle_range_t into a ble_gattc_handle_range_t. + */ +static ble_gattc_handle_range_t to_nordic_handle_range(const attribute_handle_range_t &range) +{ + ble_gattc_handle_range_t result = { + range.begin, + range.end + }; + return result; +} + +/** + * Convert a ble_gattc_handle_range_t into a pal::attribute_handle_range_t. + */ +static attribute_handle_range_t to_ble_handle_range(const ble_gattc_handle_range_t &range) +{ + attribute_handle_range_t result = { + range.start_handle, + range.end_handle + }; + return result; +} + +/** + * Convert an error from the softdevice into a ble_error_t + */ +static ble_error_t convert_sd_error(uint32_t err) +{ + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_DATA_SIZE: + return BLE_ERROR_PARAM_OUT_OF_RANGE; +#if (NRF_SD_BLE_API_VERSION <= 3) // Removed in Softdevice v4.0 + case BLE_ERROR_NO_TX_PACKETS: + return BLE_ERROR_NO_MEM; +#endif + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +/** + * Convert a UUID into a ble_uuid_t . + * If the UUID is a 128 bit one then it is registered into the softdevice. + */ +static ble_error_t to_nordic_uuid(const UUID &uuid, ble_uuid_t &nordic_uuid) +{ + if (uuid.getLen() == UUID::LENGTH_OF_LONG_UUID) { + // first try to get the long UUID in the table of UUIDs + uint32_t err = sd_ble_uuid_decode( + uuid.getLen(), + uuid.getBaseUUID(), + &nordic_uuid + ); + + // UUID found and filed, return. + if (err == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + + ble_uuid128_t uuid128; + memcpy(uuid128.uuid128, uuid.getBaseUUID(), sizeof(uuid128.uuid128)); + + // UUID not found, try to register it + err = sd_ble_uuid_vs_add(&uuid128, &nordic_uuid.type); + if (err == NRF_SUCCESS) { + nordic_uuid.uuid = bytes_to_u16(uuid.getBaseUUID() + 12); + } + + return convert_sd_error(err); + } else { + nordic_uuid.type = BLE_UUID_TYPE_BLE; + nordic_uuid.uuid = uuid.getShortUUID(); + return BLE_ERROR_NONE; + } +} + +/** + * Convert an attribute error code from the softdevice into a valid ATT error. + */ +static uint8_t convert_sd_att_error_code(uint16_t err) +{ + if (err < 0x101 || err > 0x1FF) { + return AttErrorResponse::UNLIKELY_ERROR; + } else { + return err & 0xFF; + } +} + +static const size_t long_uuid_length = 16; +static const size_t read_by_group_type_long_uuid_index = 4; +static const size_t characteristic_declaration_length = 1 + 2 + 16; + +} // end of anonymous namespace + +nRF5XGattClient::nRF5XGattClient() : + ble::pal::GattClient(), + _procedures() +{ +} + +nRF5XGattClient::~nRF5XGattClient() +{ + terminate(); +} + +ble_error_t nRF5XGattClient::initialize() +{ + return BLE_ERROR_NONE; +} + +ble_error_t nRF5XGattClient::exchange_mtu(connection_handle_t connection) +{ + // FIXME: implement when SD 140 5.x.x is present + // (see sd_ble_gatts_exchange_mtu_reply) + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5XGattClient::get_mtu_size( + connection_handle_t connection_handle, uint16_t& mtu_size +) { +#if (NRF_SD_BLE_API_VERSION >= 3) + // FIXME: implement when MTU size can be configured; the mtu size must be + // stored locally when BLE_GATTC_EVT_EXCHANGE_MTU_RSP has been received + mtu_size = BLE_GATT_MTU_SIZE_DEFAULT; +#else + mtu_size = GATT_RX_MTU; +#endif + return BLE_ERROR_NONE; +} + +ble_error_t nRF5XGattClient::discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining +) { + return launch_procedure( + connection, discovery_range_begining + ); +} + +ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_beginning, + const UUID& uuid +) { + return launch_procedure( + connection_handle, discovery_range_beginning, uuid + ); +} + +ble_error_t nRF5XGattClient::find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range +) { + return launch_procedure( + connection_handle, service_range + ); +} + +ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range +) { + return launch_procedure( + connection_handle, discovery_range + ); +} + +ble_error_t nRF5XGattClient::discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range +) { + return launch_procedure( + connection_handle, descriptors_discovery_range + ); +} + +ble_error_t nRF5XGattClient::read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle +) { + return launch_procedure( + connection_handle, attribute_handle + ); +} + +ble_error_t nRF5XGattClient::read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid +) { + return launch_procedure( + connection_handle, read_range, uuid + ); +} + +ble_error_t nRF5XGattClient::read_attribute_blob( + connection_handle_t connection, + attribute_handle_t attribute_handle, + uint16_t offset +) { + return launch_procedure( + connection, attribute_handle, offset + ); +} + +ble_error_t nRF5XGattClient::read_multiple_characteristic_values( + connection_handle_t connection, + const ArrayView& characteristic_handles +) { + return launch_procedure( + connection, characteristic_handles + ); +} + +ble_error_t nRF5XGattClient::write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value +) { + ble_gattc_write_params_t write_params = { + BLE_GATT_OP_WRITE_CMD, + /* exec flags */ 0, + characteristic_value_handle, + /* offset */ 0, + static_cast(value.size()), + const_cast(value.data()) + }; + + uint32_t err = sd_ble_gattc_write(connection_handle, &write_params); + return convert_sd_error(err); +} + +ble_error_t nRF5XGattClient::signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value +) { + ble_gattc_write_params_t write_params = { + BLE_GATT_OP_SIGN_WRITE_CMD, + /* exec flags */ 0, + characteristic_value_handle, + /* offset */ 0, + static_cast(value.size()), + const_cast(value.data()) + }; + + uint32_t err = sd_ble_gattc_write(connection_handle, &write_params); + return convert_sd_error(err); +} + +ble_error_t nRF5XGattClient::write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value +) { + return launch_procedure( + connection_handle, attribute_handle, value + ); +} + +ble_error_t nRF5XGattClient::queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset +) { + return launch_procedure( + connection_handle, characteristic_value_handle, value, offset + ); +} + +ble_error_t nRF5XGattClient::execute_write_queue( + connection_handle_t connection_handle, + bool execute +) { + return launch_procedure( + connection_handle, execute + ); +} + + +/** + * Base definition of a GATT procedure. + * + * Nordic implementation of discovery procedures requires more than a single + * request to the BLE peer when it involves 128bit UUID. As a consequence it is + * necessary to reserve the connection slot, maintain state between requests and + * interpret responses depending on the context. + * + * The concept of procedures for Gatt operations formalize the process. A + * procedure lifecycle is defined by three function: + * - start: Launch of the procedure. It initiate the first request to send to + * the peer. It must be implemented by Procedure derived classes. + * - handle: Event handler that process ble events comming from the softdevice. + * This function drive the procedure flow and must be implemented by + * Procedure derived classes. + * - terminate: end the procedure and forward the result to the GattClient + * event handle. + * + * @note Commands such as write without response or signed write without response + * are not procedures. + */ +struct nRF5XGattClient::GattProcedure { + /** + * Initialize the procedure. + * + * @param connection Handle representing the connection used by the procedure. + * @param op Opcode of the procedure. + */ + GattProcedure(connection_handle_t connection, AttributeOpcode op) : + connection_handle(connection), procedure_opcode(op) { } + + /** + * To overide in child if necessary. + */ + virtual ~GattProcedure() { } + + /** + * Handle events targeting the connection. + */ + virtual void handle(const ble_evt_t &evt) = 0; + + /** + * Terminate the execution of the procedure and forward msg to the handler + * registered in the client. + * + * @note delete this. + */ + void terminate(const AttServerMessage &msg) + { + get_client().remove_procedure(this); + get_client().on_server_event(connection_handle, msg); + delete this; + } + + /** + * Terminate the procedure with an unlikely error. + */ + void abort() + { + terminate(AttErrorResponse( + procedure_opcode, AttErrorResponse::UNLIKELY_ERROR + )); + } + + const connection_handle_t connection_handle; + const AttributeOpcode procedure_opcode; +}; + + +/** + * A regular procedure is a procedure that follows Gatt specification. + * + * It initiate a single request to the peer and excepts a single response. This + * kind of procedure doesn't requires extra processing step. + * + * Given that such procedure expects a single event type from the soft device, + * error handling can be generalized. + */ +struct nRF5XGattClient::RegularGattProcedure : GattProcedure { + + /** + * Construct a RegularGattProcedure. + * + * @param connection Handle of the connection used by the procedure. + * @param op Attribute operation code + * @param event_type Type of event expected by the stack. + */ + RegularGattProcedure( + connection_handle_t connection, AttributeOpcode op, BLE_GATTC_EVTS event_type + ) : GattProcedure(connection, op), _event_type(event_type) { } + + /** + * Handle events from the BLE stack; do not overide in child. + * + * @note This function offload error handling from user error handler. If + * the event in input match the expected event type and does not carry error + * then it is forwarded to the do_handle function. Otherwise the procedure + * is terminated and an error is forwarded to the client event handler. + */ + virtual void handle(const ble_evt_t &evt) + { + if (evt.header.evt_id == _event_type) { + const ble_gattc_evt_t &gattc_evt = evt.evt.gattc_evt; + if (gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { + terminate(AttErrorResponse( + procedure_opcode, + gattc_evt.error_handle, + convert_sd_att_error_code(gattc_evt.gatt_status) + )); + return; + } else { + do_handle(gattc_evt); + } + } else { + abort(); + } + } + + /** + * Handle gatt event received from the stack. + * + * @note The event passed in parameter is valid. + */ + virtual void do_handle(const ble_gattc_evt_t &evt) = 0; + +protected: + BLE_GATTC_EVTS _event_type; +}; + + +/** + * Procedure that handle discovery of primary services. + * + * The softdevice doesn't forward to user UUID of services that are 128 bit long. + * In such case a read request is issued for each service attribute handle + * to extract that information. + */ +struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { + + typedef ArrayView services_array_t; + + DiscoverPrimaryServiceProcedure(connection_handle_t connection) : + GattProcedure(connection, AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST), + response(NULL), count(0), idx(0) { } + + virtual ~DiscoverPrimaryServiceProcedure() + { + if (response) { + delete[] response; + } + } + + ble_error_t start(attribute_handle_t begining) + { + uint32_t err = sd_ble_gattc_primary_services_discover( + connection_handle, begining, /* p_srvc_uuid */ NULL + ); + return convert_sd_error(err); + } + + /** + * Dispatch responses either to service discovery handler or attribute read + * handler. + */ + virtual void handle(const ble_evt_t &evt) + { + switch (evt.header.evt_id) { + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + handle_service_discovered(evt.evt.gattc_evt); + return; + case BLE_GATTC_EVT_READ_RSP: + handle_uuid_read(evt.evt.gattc_evt); + return; + default: + abort(); + return; + } + } + + /** + * Dispatch service discovery response either to the short UUID handler or + * the long UUID handler. + */ + void handle_service_discovered(const ble_gattc_evt_t &evt) + { + if (evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { + terminate(AttErrorResponse( + AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST, + convert_sd_att_error_code(evt.gatt_status) + )); + return; + } + + services_array_t services( + evt.params.prim_srvc_disc_rsp.services, + evt.params.prim_srvc_disc_rsp.count + ); + + // note 128 bit and 16 bits UUID cannot be mixed up + if (services[0].uuid.type == BLE_UUID_TYPE_BLE) { + handle_16bit_services_discovered(services); + } else { + handle_128bit_services_discovered(services); + } + } + + /** + * Handle discovery of services with a 16 bit UUID. + * + * The procedure ends here. + */ + void handle_16bit_services_discovered(const services_array_t &services) + { + /** + * Custom implementation of AttReadByGroupTypeResponse that can be used + * with data returned by the nordic stack. + */ + struct CustomAttReadByGroupTypeResponse : AttReadByGroupTypeResponse { + CustomAttReadByGroupTypeResponse(const services_array_t &s) : + AttReadByGroupTypeResponse(), services(s) { + } + + virtual size_t size() const + { + return services.size(); + } + + virtual attribute_data_t operator[](size_t i) const + { + attribute_data_t result = { + to_ble_handle_range(services[i].handle_range), + make_const_ArrayView( + reinterpret_cast(&services[i].uuid.uuid), + sizeof(uint16_t) + ) + }; + return result; + } + + const services_array_t &services; + }; + + terminate(CustomAttReadByGroupTypeResponse(services)); + } + + /** + * Handle discovery of services with a 128 UUID. + * + * Handle of the services discovered will be stored locally then the + * procedure sequentially initiate a read request of each of these attribute + * handle to acquire the value of the UUID of the service. + * + * The procedure ends once all the informations initially sent by the peer + * has been reconstructed and forwarded to the registered client handler. + */ + void handle_128bit_services_discovered(const services_array_t &services) + { + response = new(std::nothrow) packed_discovery_response_t[services.size()]; + if (!response) { + abort(); + return; + } + + count = services.size(); + idx = 0; + for (size_t i = 0; i < count; ++i) { + uint8_t *it = &response[i][0]; + u16_to_stream(it, services[i].handle_range.start_handle); + u16_to_stream(it, services[i].handle_range.end_handle); + } + + read_service_uuid(); + } + + /** + * Initiate the read request of the next service attribute handle. + */ + void read_service_uuid(void) + { + // note: use read multiple once different mtu size are supported ? + uint16_t attribute_handle = bytes_to_u16(&response[idx][0]); + + uint32_t err = sd_ble_gattc_read(connection_handle, attribute_handle, 0); + if (err) { + abort(); + } + } + + /** + * Handle reception of a service (long) UUID. + */ + void handle_uuid_read(const ble_gattc_evt_t &evt) + { + if (evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { + terminate(AttErrorResponse( + AttributeOpcode::READ_REQUEST, + convert_sd_att_error_code(evt.gatt_status) + )); + return; + } + + const ble_gattc_evt_read_rsp_t &rsp = evt.params.read_rsp; + + uint16_t expected_handle = bytes_to_u16(&response[idx][0]); + + if (rsp.handle != expected_handle || rsp.offset != 0 || + rsp.len != long_uuid_length) { + abort(); + return; + } + + memcpy(&response[idx][read_by_group_type_long_uuid_index], rsp.data, rsp.len); + + ++idx; + + if (idx == count) { + terminate(SimpleAttReadByGroupTypeResponse( + sizeof(packed_discovery_response_t), + make_const_ArrayView( + reinterpret_cast(response), + count * sizeof(packed_discovery_response_t) + )) + ); + } else { + read_service_uuid(); + } + } + + // Hold read by group type response of services with 128 bit UUID. + // The response is composed of the service attribute handle (2 bytes), the + // end group handle (2 bytes) and the service UUID (16 bytes). + typedef uint8_t packed_discovery_response_t[20]; + + packed_discovery_response_t* response; + uint16_t count; + uint16_t idx; +}; + + +/** + * Procedure that manage Discover Primary Service by Service UUID transactions. + * + * @note Even if the softdevice doesn't forward the complete content of the peer + * response it is possible to reconstruct it by keeping a copy of the UUID to + * find. + */ +struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { + + typedef ArrayView services_array_t; + + DiscoverPrimaryServiceByUUIDProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST, + BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP + ), + _service_uuid() { } + + ble_error_t start(attribute_handle_t begining, const UUID &uuid) + { + ble_uuid_t nordic_uuid; + ble_error_t ble_err = to_nordic_uuid(uuid, nordic_uuid); + if (ble_err) { + return ble_err; + } + + uint32_t err = sd_ble_gattc_primary_services_discover( + connection_handle, begining, &nordic_uuid + ); + if (!err) { + _service_uuid = uuid; + } + + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + services_array_t services( + evt.params.prim_srvc_disc_rsp.services, + evt.params.prim_srvc_disc_rsp.count + ); + + /** + * Implementation of AttReadByGroupTypeResponse that addapt Nordic data + * structure. + */ + struct CustomAttReadByGroupTypeResponse : AttReadByGroupTypeResponse { + CustomAttReadByGroupTypeResponse(const services_array_t &s, const UUID &u) : + AttReadByGroupTypeResponse(), services(s), uuid(u) { + } + + virtual size_t size() const + { + return services.size(); + } + + virtual attribute_data_t operator[](size_t i) const + { + attribute_data_t result = { + to_ble_handle_range(services[i].handle_range), + make_ArrayView(uuid.getBaseUUID(), uuid.getLen()) + }; + return result; + } + + const services_array_t &services; + const UUID &uuid; + }; + + terminate(CustomAttReadByGroupTypeResponse(services, _service_uuid)); + } + + UUID _service_uuid; +}; + + +/** + * Procedure that manage Find Included Services transactions. + */ +struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { + + typedef ArrayView services_array_t; + + FindIncludedServicesProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::READ_BY_TYPE_REQUEST, + BLE_GATTC_EVT_REL_DISC_RSP + ) { } + + ble_error_t start(attribute_handle_range_t service_range) + { + ble_gattc_handle_range_t range = to_nordic_handle_range(service_range); + uint32_t err = sd_ble_gattc_relationships_discover( + connection_handle, &range + ); + + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + // recompose the message into a raw att read by type response. + const ble_gattc_evt_rel_disc_rsp_t &resp = evt.params.rel_disc_rsp; + + bool contain_short_uuid = + (resp.includes[0].included_srvc.uuid.type == BLE_UUID_TYPE_BLE); + + uint8_t element_size = 6; + if (contain_short_uuid) { + element_size += 2; + } + + // It would be more efficient to use an API like alloca but it is + // unavailable and unsafe. Another alternative would be to have a fixed + // size stack buffer since the size of the MTU is fixed however once new + // softdevices lands could would have to be rewritten because they support + // variable MTU size. + size_t buffer_size = element_size * resp.count; + uint8_t* buffer = new(std::nothrow) uint8_t[buffer_size]; + if (!buffer) { + abort(); + return; + } + + uint8_t *it = buffer; + for(size_t i = 0; i < resp.count; ++i) { + u16_to_stream(it, resp.includes[i].handle); + u16_to_stream(it, resp.includes[i].included_srvc.handle_range.start_handle); + u16_to_stream(it, resp.includes[i].included_srvc.handle_range.end_handle); + if (contain_short_uuid) { + u16_to_stream(it, resp.includes[i].included_srvc.uuid.uuid); + } + } + + terminate(SimpleAttReadByTypeResponse( + element_size, + make_const_ArrayView(buffer, buffer_size) + )); + + delete[] buffer; + } + + UUID _service_uuid; +}; + + +/** + * Procedure that handle Discover All Characteristics of a Service transactions. + * + * The softdevice doesn't forward to user UUID of services that are 128 bit long. + * In such case a read request is issued for each attribute handle of + * characteristics that exposes a long UUID. + */ +struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { + /** + * Data structure returned by the function flatten_response. + */ + struct read_by_type_response_t { + uint16_t count; + uint16_t element_size; + uint8_t* buffer; + }; + + DiscoverCharacteristicsProcedure(connection_handle_t connection) : + GattProcedure(connection, AttributeOpcode::READ_BY_TYPE_REQUEST), + _response(), _idx(0) { } + + virtual ~DiscoverCharacteristicsProcedure() + { + if (_response.buffer) { + delete[] _response.buffer; + } + } + + ble_error_t start(attribute_handle_range_t discovery_range) + { + ble_gattc_handle_range_t range = to_nordic_handle_range(discovery_range); + uint32_t err = sd_ble_gattc_characteristics_discover( + connection_handle, + &range + ); + + return convert_sd_error(err); + } + + /** + * Dispatch ble events to the appropriate handler: + * - handle_characteristic_discovered: For a discovery response. + * - handle_uuid_read: For a read response. + */ + virtual void handle(const ble_evt_t &evt) + { + switch (evt.header.evt_id) { + case BLE_GATTC_EVT_CHAR_DISC_RSP: + handle_characteristic_discovered(evt.evt.gattc_evt); + return; + case BLE_GATTC_EVT_READ_RSP: + handle_uuid_read(evt.evt.gattc_evt); + return; + default: + abort(); + return; + } + } + + void handle_characteristic_discovered(const ble_gattc_evt_t &evt) + { + if (evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { + terminate(AttErrorResponse( + AttributeOpcode::READ_BY_TYPE_REQUEST, + convert_sd_att_error_code(evt.gatt_status) + )); + return; + } + + // layout the data structure into a flat byte array. + _response = flatten_response(evt.params.char_disc_rsp); + if (!_response.buffer) { + abort(); + return; + } + + // If element size is equal to 7 then the characteristic discovered + // have 16 bit UUID. It is not necessary to read their characteristic + // declaration attribute. + if (_response.element_size == 7) { + forward_response_and_terminate(); + } else { + // 128 bit UUID. + // read sequentially each characteristic declaration attribute + // discovered. + _idx = 0; + read_characteristic_uuid(); + } + } + + /** + * Initiate read of the next characteristic declaration attribute. + */ + void read_characteristic_uuid(void) + { + // note: use read multiple once different mtu size are supported ? + uint16_t attribute_handle = + bytes_to_u16(&_response.buffer[_idx * _response.element_size]); + + uint32_t err = sd_ble_gattc_read(connection_handle, attribute_handle, 0); + if (err) { + abort(); + } + } + + /** + * Handle read response of a characteristic declaration attribute. + * It add the data in the response then initiate the read of the next + * attribute or terminate the procedure if all characteristic declaration + * attributes have been read. + */ + void handle_uuid_read(const ble_gattc_evt_t &evt) + { + // should never happen + if (!_response.buffer) { + abort(); + return; + } + + if (evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { + terminate(AttErrorResponse( + AttributeOpcode::READ_REQUEST, + convert_sd_att_error_code(evt.gatt_status) + )); + return; + } + + const ble_gattc_evt_read_rsp_t &rsp = evt.params.read_rsp; + uint8_t* current_element = &_response.buffer[_idx * _response.element_size]; + uint16_t expected_handle = bytes_to_u16(current_element); + + if (rsp.handle != expected_handle || rsp.offset != 0 || + rsp.len != characteristic_declaration_length) { + abort(); + return; + } + + // note: elements are the pair characteristic declaration handle followed + // by the attribute value. + memcpy(current_element + 2, rsp.data, rsp.len); + + ++_idx; + + if (_idx == _response.count) { + forward_response_and_terminate(); + } else { + read_characteristic_uuid(); + } + } + + /** + * Terminate the procedure by forwarding the AttReadByTypeResponse built. + */ + void forward_response_and_terminate() { + terminate(SimpleAttReadByTypeResponse( + _response.element_size, + make_const_ArrayView( + _response.buffer, + _response.element_size * _response.count + ) + )); + } + + /** + * Convert a ble_gattc_evt_char_disc_rsp_t into a raw response. + * + * If UUIDs present are 16 bits long then the output contain the whole + * response. Otherwise only the handle declaration of each characteristic + * discovered is present and properties, handle value and UUID are populated + * by reading the attribute handle. + */ + static read_by_type_response_t flatten_response(const ble_gattc_evt_char_disc_rsp_t& resp) + { + read_by_type_response_t result = { resp.count, 0 }; + + bool short_uuid = (resp.chars[0].uuid.type == BLE_UUID_TYPE_BLE); + + // att handle + prop + value handle + uuid size + result.element_size = 5 + (short_uuid ? 2 : 16) ; + + size_t buffer_size = resp.count * result.element_size; + result.buffer = new(std::nothrow) uint8_t[buffer_size]; + if(!result.buffer) { + return result; + } + + uint8_t *it = result.buffer; + for(size_t i = 0; i < resp.count; ++i) { + u16_to_stream(it, resp.chars[i].handle_decl); + if (short_uuid) { + *it++ = get_properties(resp.chars[i]); + u16_to_stream(it, resp.chars[i].handle_value); + u16_to_stream(it, resp.chars[i].uuid.uuid); + } else { + // leave the characteristic value declaration empty; it will be + // fullfiled by a read of the attribute. + it += (1 + 2 + 16); + } + } + + return result; + } + + /** + * Compute characteristic properties from ble_gattc_char_t. + */ + static uint8_t get_properties(const ble_gattc_char_t& char_desc) + { + return + (char_desc.char_props.broadcast << 0) | + (char_desc.char_props.read << 1) | + (char_desc.char_props.write_wo_resp << 2) | + (char_desc.char_props.write << 3) | + (char_desc.char_props.notify << 4) | + (char_desc.char_props.indicate << 5) | + (char_desc.char_props.auth_signed_wr << 6) | + (char_desc.char_ext_props << 7); + } + + read_by_type_response_t _response; + uint16_t _idx; +}; + +/** + * Procedure that handle discovery of characteristic descriptors. + */ +struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { + DiscoverDescriptorsProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::FIND_INFORMATION_REQUEST, + BLE_GATTC_EVT_ATTR_INFO_DISC_RSP + ) { + } + + ble_error_t start(attribute_handle_range_t discovery_range) + { + ble_gattc_handle_range_t range = to_nordic_handle_range(discovery_range); + uint32_t err = sd_ble_gattc_attr_info_discover( + connection_handle, + &range + ); + + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + /** + * Adapt ble_gattc_evt_attr_info_disc_rsp_t into + * pal::AttFindInformationResponse + */ + struct CustomFindInformationResponse : AttFindInformationResponse { + CustomFindInformationResponse(const ble_gattc_evt_attr_info_disc_rsp_t &resp) : + AttFindInformationResponse(), response(resp) {} + + virtual size_t size() const + { + return response.count; + } + +#if (NRF_SD_BLE_API_VERSION < 3) + virtual information_data_t operator[](size_t i) const + { + information_data_t result = { + response.attr_info[i].handle + }; + + if (response.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT) { + result.uuid = UUID(response.attr_info[i].info.uuid16.uuid); + } else { + result.uuid = UUID( + response.attr_info[i].info.uuid128.uuid128, + UUID::LSB + ); + } + + return result; + } +#else + virtual information_data_t operator[](size_t i) const + { + if (response.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT) { + information_data_t result = { + response.info.attr_info16[i].handle, + UUID(response.info.attr_info16[i].uuid.uuid) + }; + + return result; + } else { + information_data_t result = { + response.info.attr_info128[i].handle, + UUID( + response.info.attr_info128[i].uuid.uuid128, + UUID::LSB + ) + }; + + return result; + } + } + + +#endif + + + const ble_gattc_evt_attr_info_disc_rsp_t &response; + }; + + terminate(CustomFindInformationResponse(evt.params.attr_info_disc_rsp)); + } +}; + + +/** + * Procedure that handle read of attribute handles. + */ +struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { + ReadAttributeProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, AttributeOpcode::READ_REQUEST, BLE_GATTC_EVT_READ_RSP + ) { } + + ble_error_t start(attribute_handle_t attribute_handle) + { + uint32_t err = sd_ble_gattc_read(connection_handle, attribute_handle, 0); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + const ble_gattc_evt_read_rsp_t& rsp = evt.params.read_rsp; + if (rsp.offset != 0 ) { + abort(); + return; + } + + terminate(AttReadResponse(make_const_ArrayView(rsp.data, rsp.len))); + } +}; + +/** + * Procedure that handle read of characteristic using characteristic UUID. + */ +struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { + ReadUsingCharacteristicUUIDProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::READ_BY_TYPE_REQUEST, + BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP + ) { } + + ble_error_t start(attribute_handle_range_t read_range, const UUID& uuid) + { + ble_uuid_t nordic_uuid = { 0 }; + ble_error_t ble_err = to_nordic_uuid(uuid, nordic_uuid); + if (ble_err) { + return ble_err; + } + + ble_gattc_handle_range_t range = { + read_range.begin, + read_range.end + }; + + uint32_t err = sd_ble_gattc_char_value_by_uuid_read( + connection_handle, + &nordic_uuid, + &range + ); + return convert_sd_error(err); + } + +#if (NRF_SD_BLE_API_VERSION >= 3) + /** + * Adapt ble_gattc_evt_char_val_by_uuid_read_rsp_t into AttReadByTypeResponse. + */ + virtual void do_handle(const ble_gattc_evt_t &evt) + { + const ble_gattc_evt_char_val_by_uuid_read_rsp_t &rsp = + evt.params.char_val_by_uuid_read_rsp; + + uint8_t element_size = sizeof(uint16_t) + rsp.value_len; + + terminate(SimpleAttReadByTypeResponse( + element_size, + make_const_ArrayView( + rsp.handle_value, + rsp.count * element_size + ) + )); + } + +#else + /** + * Adapt ble_gattc_evt_char_val_by_uuid_read_rsp_t into AttReadByTypeResponse. + */ + virtual void do_handle(const ble_gattc_evt_t &evt) + { + struct CustomReadByTypeResponse : AttReadByTypeResponse { + CustomReadByTypeResponse(const ble_gattc_evt_char_val_by_uuid_read_rsp_t& rsp) : + AttReadByTypeResponse(), response(rsp) { } + + virtual size_t size() const + { + return response.count; + } + + virtual attribute_data_t operator[](size_t i) const + { + attribute_data_t result = { + response.handle_value[i].handle, + make_const_ArrayView( + response.handle_value[i].p_value, + response.value_len + ) + }; + return result; + } + + const ble_gattc_evt_char_val_by_uuid_read_rsp_t& response; + } + + terminate(CustomReadByTypeResponse(evt.params.char_val_by_uuid_read_rsp)); + } +#endif +}; + +/** + * Procedure that handles read blob transactions. + */ +struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { + ReadAttributeBlobProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, AttributeOpcode::READ_BLOB_REQUEST, BLE_GATTC_EVT_READ_RSP + ) { } + + ble_error_t start(attribute_handle_t attribute_handle, uint16_t offset) + { + uint32_t err = sd_ble_gattc_read( + connection_handle, attribute_handle, offset + ); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + terminate(AttReadBlobResponse(make_const_ArrayView( + evt.params.read_rsp.data, + evt.params.read_rsp.len + ))); + } +}; + +/** + * Procedure that handles Read Multiple Characteristic Values transactions. + */ +struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { + ReadMultipleCharacteristicsProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::READ_MULTIPLE_REQUEST, + BLE_GATTC_EVT_CHAR_VALS_READ_RSP + ) { } + + ble_error_t start(const ArrayView& characteristic_handles) + { + uint32_t err = sd_ble_gattc_char_values_read( + connection_handle, + characteristic_handles.data(), + characteristic_handles.size() + ); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + terminate(AttReadMultipleResponse(make_const_ArrayView( + evt.params.char_vals_read_rsp.values, + evt.params.char_vals_read_rsp.len + ))); + } +}; + +/** + * Procedure that handles Write transactions. + */ +struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { + WriteAttributeProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, AttributeOpcode::WRITE_REQUEST, BLE_GATTC_EVT_WRITE_RSP + ) { } + + ble_error_t start( + attribute_handle_t attribute_handle, const ArrayView& value + ) { + ble_gattc_write_params_t write_params = { + BLE_GATT_OP_WRITE_REQ, + /* exec flags */ 0, + attribute_handle, + /* offset */ 0, + static_cast(value.size()), + const_cast(value.data()) + }; + + uint32_t err = sd_ble_gattc_write(connection_handle, &write_params); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + terminate(AttWriteResponse()); + } +}; + +/** + * Procedure that handles Prepare Write transactions. + */ +struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { + QueuePrepareWriteProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::PREPARE_WRITE_REQUEST, + BLE_GATTC_EVT_WRITE_RSP + ) { } + + ble_error_t start( + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) { + ble_gattc_write_params_t write_params = { + BLE_GATT_OP_PREP_WRITE_REQ, + /* exec flags */ 0, + characteristic_value_handle, + offset, + static_cast(value.size()), + const_cast(value.data()) + }; + + uint32_t err = sd_ble_gattc_write(connection_handle, &write_params); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + const ble_gattc_evt_write_rsp_t &response = evt.params.write_rsp; + + if (response.write_op != BLE_GATT_OP_PREP_WRITE_REQ) { + abort(); + return; + } + + terminate(AttPrepareWriteResponse( + response.handle, + response.offset, + make_const_ArrayView(response.data, response.len) + )); + } +}; + +/** + * Procedure that handles Execute Write transactions. + */ +struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { + ExecuteWriteQueueProcedure(connection_handle_t connection) : + RegularGattProcedure( + connection, + AttributeOpcode::EXECUTE_WRITE_REQUEST, + BLE_GATTC_EVT_WRITE_RSP + ) { } + + ble_error_t start(bool execute) { + ble_gattc_write_params_t write_params = { + BLE_GATT_OP_EXEC_WRITE_REQ, + static_cast( + execute ? + BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL : + BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE + ), + /* attribute handle */ 0, + /* value offset */ 0, + /* buffer size*/ 0, + /* buffer data */ NULL + }; + + uint32_t err = sd_ble_gattc_write(connection_handle, &write_params); + return convert_sd_error(err); + } + + virtual void do_handle(const ble_gattc_evt_t &evt) + { + const ble_gattc_evt_write_rsp_t &response = evt.params.write_rsp; + if (response.write_op != BLE_GATT_OP_EXEC_WRITE_REQ) { + abort(); + return; + } + + terminate(AttExecuteWriteResponse()); + } +}; + +// NOTE: position after declaration of GattProcedure on purpose. +ble_error_t nRF5XGattClient::terminate() +{ + for (size_t i = 0; i < max_procedures_count; ++i) { + if (_procedures[i]) { + _procedures[i]->abort(); + _procedures[i] = NULL; + } + } + + return BLE_ERROR_NONE; +} + +template +ble_error_t nRF5XGattClient::launch_procedure( + connection_handle_t connection, const A0& a0 +) { + ProcType* p = new(std::nothrow) ProcType(connection); + if (!p) { + return BLE_ERROR_NO_MEM; + } + + if (!register_procedure(p)) { + delete p; + return BLE_ERROR_INVALID_STATE; + } + + ble_error_t err = p->start(a0); + if (err) { + remove_procedure(p); + delete p; + } + + return err; +} + +template +ble_error_t nRF5XGattClient::launch_procedure( + connection_handle_t connection, const A0& a0, const A1& a1 +) { + ProcType* p = new(std::nothrow) ProcType(connection); + if (!p) { + return BLE_ERROR_NO_MEM; + } + + if (!register_procedure(p)) { + delete p; + return BLE_ERROR_INVALID_STATE; + } + + ble_error_t err = p->start(a0, a1); + if (err) { + remove_procedure(p); + delete p; + } + + return err; +} + +template +ble_error_t nRF5XGattClient::launch_procedure( + connection_handle_t connection, + const A0& a0, const A1& a1, const A2& a2 +) { + ProcType* p = new(std::nothrow) ProcType(connection); + if (!p) { + return BLE_ERROR_NO_MEM; + } + + if (!register_procedure(p)) { + delete p; + return BLE_ERROR_INVALID_STATE; + } + + ble_error_t err = p->start(a0, a1, a2); + if (err) { + remove_procedure(p); + delete p; + } + + return err; +} + +template +ble_error_t nRF5XGattClient::launch_procedure( + connection_handle_t connection, + const A0& a0, const A1& a1, const A2& a2, const A3& a3 +) { + ProcType* p = new(std::nothrow) ProcType(connection); + if (!p) { + return BLE_ERROR_NO_MEM; + } + + if (!register_procedure(p)) { + delete p; + return BLE_ERROR_INVALID_STATE; + } + + ble_error_t err = p->start(a0, a1, a2, a3); + if (err) { + remove_procedure(p); + delete p; + } + + return err; +} + +nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( + connection_handle_t connection +) const { + for (size_t i = 0; i < max_procedures_count; ++i) { + if (_procedures[i] && _procedures[i]->connection_handle == connection) { + return _procedures[i]; + } + } + return NULL; +} + +bool nRF5XGattClient::register_procedure(GattProcedure *p) +{ + if (get_procedure(p->connection_handle)) { + return false; + } + + for (size_t i = 0; i < max_procedures_count; ++i) { + if (!_procedures[i]) { + _procedures[i] = p; + return true; + } + } + + return false; +} + +bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) +{ + for (size_t i = 0; i < max_procedures_count; ++i) { + if (_procedures[i] == p) { + _procedures[i] = NULL; + return true; + } + } + + return false; +} + +// singleton of the ARM Cordio client +nRF5XGattClient& nRF5XGattClient::get_client() +{ + static nRF5XGattClient _client; + return _client; +} + +void nRF5XGattClient::handle_events(const ble_evt_t *evt) { + switch (evt->header.evt_id) { + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + case BLE_GATTC_EVT_REL_DISC_RSP: + case BLE_GATTC_EVT_CHAR_DISC_RSP: + case BLE_GATTC_EVT_DESC_DISC_RSP: + case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP: + case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP: + case BLE_GATTC_EVT_READ_RSP: + case BLE_GATTC_EVT_CHAR_VALS_READ_RSP: + case BLE_GATTC_EVT_WRITE_RSP: + get_client().handle_procedure_event(*evt); + break; + case BLE_GATTC_EVT_HVX: + get_client().handle_hvx_event(*evt); + break; + case BLE_GATTC_EVT_TIMEOUT: + get_client().handle_timeout_event(*evt); + break; + } +} + +void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) +{ + GattProcedure* p = get_procedure(evt.evt.gattc_evt.conn_handle); + if (p) { + p->handle(evt); + } +} + +void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) +{ + connection_handle_t connection = evt.evt.gattc_evt.conn_handle; + const ble_gattc_evt_hvx_t &hvx_evt = evt.evt.gattc_evt.params.hvx; + + switch (hvx_evt.type) { + case BLE_GATT_HVX_NOTIFICATION: + on_server_event( + connection, + AttHandleValueNotification( + hvx_evt.handle, + make_const_ArrayView(hvx_evt.data, hvx_evt.len) + ) + ); + return; + case BLE_GATT_HVX_INDICATION: + // send confirmation first then process the event + sd_ble_gattc_hv_confirm(connection, hvx_evt.handle); + on_server_event( + connection, + AttHandleValueIndication( + hvx_evt.handle, + make_const_ArrayView(hvx_evt.data, hvx_evt.len) + ) + ); + return; + default: + return; + } +} + +void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) +{ + connection_handle_t connection = evt.evt.gattc_evt.conn_handle; + GattProcedure* p = get_procedure(connection); + if (p) { + p->abort(); + } + + on_transaction_timeout(connection); +} + +void nRF5XGattClient::handle_connection_termination(connection_handle_t connection) +{ + GattProcedure* p = get_client().get_procedure(connection); + if (p) { + p->abort(); + } +} + +} // nordic +} // vendor +} // pal +} // ble + + + + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h new file mode 100644 index 0000000000..79633d6fa3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h @@ -0,0 +1,257 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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 BLE_NORDIC_PAL_GATT_CLIENT_H_ +#define BLE_NORDIC_PAL_GATT_CLIENT_H_ + +#include "ble/pal/PalGattClient.h" +#include "ble/blecommon.h" +#include "ble/UUID.h" + +#include "headers/nrf_ble.h" +#include "headers/ble_gatt.h" +#include "headers/ble_types.h" +#include "btle.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +/** + * Implementation of pal::GattClient for the Nordic stack. + */ +class nRF5XGattClient : public ble::pal::GattClient { + +public: + nRF5XGattClient(); + + virtual ~nRF5XGattClient(); + + /** + * see pal::GattClient::initialize . + */ + virtual ble_error_t initialize(); + + /** + * see pal::GattClient::terminate . + */ + virtual ble_error_t terminate(); + + /** + * see pal::GattClient::exchange_mtu . + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection); + + /** + * see pal::GattClient::get_mtu_size . + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, uint16_t& mtu_size + ); + + /** + * see pal::GattClient::discover_primary_service . + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ); + + /** + * see pal::GattClient::discover_primary_service_by_service_uuid . + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_beginning, + const UUID& uuid + ); + + /** + * see pal::GattClient::find_included_service . + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ); + + /** + * see pal::GattClient::discover_characteristics_of_a_service . + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ); + + /** + * see pal::GattClient::discover_characteristics_descriptors . + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ); + + /** + * see pal::GattClient::read_attribute_value . + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ); + + /** + * see pal::GattClient::read_using_characteristic_uuid . + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ); + + /** + * see pal::GattClient::read_attribute_blob . + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection, + attribute_handle_t attribute_handle, + uint16_t offset + ); + + /** + * see pal::GattClient::read_multiple_characteristic_values . + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection, + const ArrayView& characteristic_handles + ); + + /** + * see pal::GattClient::write_without_response . + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ); + + /** + * see pal::GattClient::signed_write_without_response . + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ); + + /** + * see pal::GattClient::write_attribute . + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ); + + /** + * see pal::GattClient::queue_prepare_write . + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ); + + /** + * see pal::GattClient::execute_write_queue . + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ); + + // singleton of the ARM Cordio client + static nRF5XGattClient& get_client(); + + /** + * Function call from btle.cpp + * + * Do not call directly. + */ + static void handle_events(const ble_evt_t *p_ble_evt); + + /** + * Called by btle.cpp when a disconnection happens. + */ + static void handle_connection_termination(connection_handle_t connection); + +private: + struct GattProcedure; + struct RegularGattProcedure; + struct DiscoverPrimaryServiceProcedure; + struct DiscoverPrimaryServiceByUUIDProcedure; + struct FindIncludedServicesProcedure; + struct DiscoverCharacteristicsProcedure; + struct DiscoverDescriptorsProcedure; + struct ReadAttributeProcedure; + struct ReadUsingCharacteristicUUIDProcedure; + struct ReadAttributeBlobProcedure; + struct ReadMultipleCharacteristicsProcedure; + struct WriteAttributeProcedure; + struct QueuePrepareWriteProcedure; + struct ExecuteWriteQueueProcedure; + + template + ble_error_t launch_procedure(connection_handle_t connection, const A0& a0); + + template + ble_error_t launch_procedure( + connection_handle_t connection, const A0& a0, const A1& a1 + ); + + template + ble_error_t launch_procedure( + connection_handle_t connection, + const A0& a0, const A1& a1, const A2& a2 + ); + + template + ble_error_t launch_procedure( + connection_handle_t connection, + const A0& a0, const A1& a1, const A2& a2, const A3& a3 + ); + + GattProcedure* get_procedure(connection_handle_t) const; + bool register_procedure(GattProcedure*); + bool remove_procedure(GattProcedure*); + + void handle_procedure_event(const ble_evt_t &evt); + void handle_hvx_event(const ble_evt_t &evt); + void handle_timeout_event(const ble_evt_t &evt); + + static const size_t max_procedures_count = + CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT; + + // Note: Ideally we would have used an array of variant here + GattProcedure* _procedures[max_procedures_count]; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif /* BLE_NORDIC_PAL_GATT_CLIENT_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp new file mode 100644 index 0000000000..09f99fb12f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp @@ -0,0 +1,1239 @@ +/* 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 "nRF5xn.h" +#ifdef YOTTA_CFG_MBED_OS + #include "mbed-drivers/mbed.h" +#else + #include "mbed.h" +#endif +#include "ble/BLE.h" + +#include "common/common.h" +#include "ble_advdata.h" +#include "headers/ble_hci.h" + +#if (NRF_SD_BLE_API_VERSION >= 3) + #include "peer_manager.h" + #include "peer_data_storage.h" +#endif + + +void radioNotificationStaticCallback(bool param) { + nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); + gap.processRadioNotificationEvent(param); +} + +/**************************************************************************/ +/*! + @brief Sets the advertising parameters and payload for the device + + @param[in] params + Basic advertising details, including the advertising + delay, timeout and how the device should be advertised + @params[in] advData + The primary advertising data payload + @params[in] scanResponse + The optional Scan Response payload if the advertising + type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED + in \ref GapAdveritinngParams + + @returns \ref ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @retval BLE_ERROR_BUFFER_OVERFLOW + The proposed action would cause a buffer overflow. All + advertising payloads must be <= 31 bytes, for example. + + @retval BLE_ERROR_NOT_IMPLEMENTED + A feature was requested that is not yet supported in the + nRF51 firmware or hardware. + + @retval BLE_ERROR_PARAM_OUT_OF_RANGE + One of the proposed values is outside the valid range. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) +{ + /* Make sure we don't exceed the advertising payload length */ + if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + /* Make sure we have a payload! */ + if (advData.getPayloadLen() == 0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check the scan response payload limits */ + //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) + //{ + // /* Check if we're within the upper limit */ + // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) + // { + // return BLE_ERROR_BUFFER_OVERFLOW; + // } + // /* Make sure we have a payload! */ + // if (advData.getPayloadLen() == 0) + // { + // return BLE_ERROR_PARAM_OUT_OF_RANGE; + // } + //} + + /* Send advertising data! */ + ASSERT_TRUE(ERROR_NONE == + sd_ble_gap_adv_data_set(advData.getPayload(), + advData.getPayloadLen(), + scanResponse.getPayload(), + scanResponse.getPayloadLen()), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + /* Make sure the GAP Service appearance value is aligned with the + *appearance from GapAdvertisingData */ + ASSERT_TRUE(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ + /* contains a flags AD type, etc. */ + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Starts the BLE HW, initialising any services that were + added before this function was called. + + @note All services must be added before calling this function! + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) +{ + uint32_t err; + ble_gap_adv_params_t adv_para = {0}; + + /* Make sure we support the advertising type */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { + /* ToDo: This requires a propery security implementation, etc. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /* Check interval range */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min delay is slightly longer for unconnectable devices */ + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } else { + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + /* Check timeout is zero for Connectable Directed */ + if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { + /* Timeout must be 0 with this type, although we'll never get here */ + /* since this isn't implemented yet anyway */ + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check timeout for other advertising types */ + if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && + (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + +#if (NRF_SD_BLE_API_VERSION <= 2) + /* Allocate the stack's whitelist statically */ + ble_gap_whitelist_t whitelist; + ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; + ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + /* Initialize the whitelist */ + whitelist.pp_addrs = whitelistAddressPtrs; + whitelist.pp_irks = whitelistIrkPtrs; + whitelist.addr_count = 0; + whitelist.irk_count = 0; + + /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ + if (advertisingPolicyMode != Gap::ADV_POLICY_IGNORE_WHITELIST) { + ble_error_t error = generateStackWhitelist(whitelist); + if (error != BLE_ERROR_NONE) { + return error; + } + } + + adv_para.p_whitelist = &whitelist; +#endif + /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ + + /* Start Advertising */ + + + adv_para.type = params.getAdvertisingType(); + adv_para.p_peer_addr = NULL; // Undirected advertisement + adv_para.fp = advertisingPolicyMode; + adv_para.interval = params.getIntervalInADVUnits(); // advertising interval (in units of 0.625 ms) + adv_para.timeout = params.getTimeout(); + +#if (NRF_SD_BLE_API_VERSION >= 5) + err = sd_ble_gap_adv_start(&adv_para, NRF_CONNECTION_TAG); +#else + err = sd_ble_gap_adv_start(&adv_para); +#endif + switch(err) { + case ERROR_NONE: + return BLE_ERROR_NONE; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +/* 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) +ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) +{ + + ble_gap_scan_params_t scanParams; + +#if (NRF_SD_BLE_API_VERSION <= 2) + /* Allocate the stack's whitelist statically */ + ble_gap_whitelist_t whitelist; + ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; + ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + /* Initialize the whitelist */ + whitelist.pp_addrs = whitelistAddressPtrs; + whitelist.pp_irks = whitelistIrkPtrs; + whitelist.addr_count = 0; + whitelist.irk_count = 0; + + /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ + if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { + ble_error_t error = generateStackWhitelist(whitelist); + if (error != BLE_ERROR_NONE) { + return error; + } + } + + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ + scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ +#else + /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ + + scanParams.use_whitelist = scanningPolicyMode; + scanParams.adv_dir_report = 0; +#endif + + scanParams.active = scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ + + scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + + if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::stopScan(void) { + if (sd_ble_gap_scan_stop() == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + + return BLE_STACK_BUSY; +} +#endif + +/**************************************************************************/ +/*! + @brief Stops the BLE HW and disconnects from any devices + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::stopAdvertising(void) +{ + /* Stop Advertising */ + ASSERT_TRUE(ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE); + + state.advertising = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::connect(const Address_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn) +{ + ble_gap_addr_t addr; + addr.addr_type = peerAddrType; + memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); + + ble_gap_conn_params_t connParams; + if (connectionParams != NULL) { + connParams.min_conn_interval = connectionParams->minConnectionInterval; + connParams.max_conn_interval = connectionParams->maxConnectionInterval; + connParams.slave_latency = connectionParams->slaveLatency; + connParams.conn_sup_timeout = connectionParams->connectionSupervisionTimeout; + } else { + connParams.min_conn_interval = 50; + connParams.max_conn_interval = 100; + connParams.slave_latency = 0; + connParams.conn_sup_timeout = 600; + } + + ble_gap_scan_params_t scanParams ={0}; + +#if (NRF_SD_BLE_API_VERSION <= 2) + /* Allocate the stack's whitelist statically */ + ble_gap_whitelist_t whitelist; + ble_gap_addr_t *whitelistAddressPtrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; + ble_gap_irk_t *whitelistIrkPtrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + /* Initialize the whitelist */ + whitelist.pp_addrs = whitelistAddressPtrs; + whitelist.pp_irks = whitelistIrkPtrs; + whitelist.addr_count = 0; + whitelist.irk_count = 0; + + /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ + if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { + ble_error_t error = generateStackWhitelist(whitelist); + if (error != BLE_ERROR_NONE) { + return error; + } + } + + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ + scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ +#else + /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ + + scanParams.use_whitelist = (whitelistAddressesSize) ? 1 : 0; + + if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + || (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { + /* If a device is using Resolvable Private Addresses Section 1.3.2.2 (Core spec v4.2 volume 6 part B), + it shall also have an Identity Address that is either a Public or Random Static address type.” + To establish a connection, a static address must be provided by the application to the SoftDevice. + The SoftDevice resolves the address and connects to the right device if it is available. */ + addr.addr_id_peer = 1; + addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + } else { + addr.addr_id_peer = 0; + } + +#endif + + if (scanParamsIn != NULL) { + scanParams.active = scanParamsIn->getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ + scanParams.interval = scanParamsIn->getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.window = scanParamsIn->getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.timeout = scanParamsIn->getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + } else { + scanParams.active = _scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ + scanParams.interval = _scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.window = _scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + scanParams.timeout = _scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + } + +#if NRF_SD_BLE_API_VERSION >= 5 + uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams, NRF_CONNECTION_TAG); +#else + uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); +#endif + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } + switch (rc) { + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_PARAM: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + case BLE_ERROR_GAP_WHITELIST_IN_USE: + return BLE_ERROR_UNSPECIFIED; + } +} + +ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) +{ + uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; + switch (reason) { + case REMOTE_USER_TERMINATED_CONNECTION: + code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; + break; + case CONN_INTERVAL_UNACCEPTABLE: + code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE; + break; + default: + break; + } + + /* Disconnect if we are connected to a central device */ + ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +/*! + @brief Disconnects if we are connected to a central device + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +ble_error_t nRF5xGap::disconnect(DisconnectionReason_t reason) +{ + return disconnect(m_connectionHandle, reason); +} + +ble_error_t nRF5xGap::getPreferredConnectionParams(ConnectionParams_t *params) +{ + ASSERT_INT(NRF_SUCCESS, + sd_ble_gap_ppcp_get(reinterpret_cast(params)), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPreferredConnectionParams(const ConnectionParams_t *params) +{ + ASSERT_INT(NRF_SUCCESS, + sd_ble_gap_ppcp_set(reinterpret_cast(params)), + BLE_ERROR_PARAM_OUT_OF_RANGE); + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) +{ + uint32_t rc; + + rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast(const_cast(newParams))); + if (rc == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +/**************************************************************************/ +/*! + @brief Clear nRF5xGap's state. + + @returns ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::reset(void) +{ + /* Clear all state that is from the parent, including private members */ + if (Gap::reset() != BLE_ERROR_NONE) { + return BLE_ERROR_INVALID_STATE; + } + + /* Clear derived class members */ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; + + /* Set the whitelist policy filter modes to IGNORE_WHITELIST */ + advertisingPolicyMode = Gap::ADV_POLICY_IGNORE_WHITELIST; + scanningPolicyMode = Gap::SCAN_POLICY_IGNORE_WHITELIST; + + /* Clear the internal whitelist */ + whitelistAddressesSize = 0; + + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Sets the 16-bit connection handle +*/ +/**************************************************************************/ +void nRF5xGap::setConnectionHandle(uint16_t con_handle) +{ + m_connectionHandle = con_handle; +} + +/**************************************************************************/ +/*! + @brief Gets the 16-bit connection handle +*/ +/**************************************************************************/ +uint16_t nRF5xGap::getConnectionHandle(void) +{ + return m_connectionHandle; +} + +/**************************************************************************/ +/*! + @brief Sets the BLE device address + + @returns ble_error_t + + @section EXAMPLE + + @code + + uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 }; + nrf.getGap().setAddress(Gap::BLEProtocol::AddressType::RANDOM_STATIC, device_address); + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) +{ +#if (NRF_SD_BLE_API_VERSION <= 2) + uint8_t cycle_mode; +#else + ble_gap_privacy_params_t privacy_params = {0}; +#endif + + + ble_gap_addr_t dev_addr; + + /* When using Public or Static addresses, the cycle mode must be None. + When using Random Private addresses, the cycle mode must be Auto. + In auto mode, the given address is ignored. + */ + if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) + { + memcpy(dev_addr.addr, address, ADDR_LEN); +#if (NRF_SD_BLE_API_VERSION <= 2) + cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; +#else + privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; + dev_addr.addr_type = type; + + ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); +#endif + } + else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) + { +#if (NRF_SD_BLE_API_VERSION <= 2) + cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; +#else + privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; + privacy_params.private_addr_type = type; + + ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); +#endif + // address is ignored when in auto mode + } + else + { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + +#if (NRF_SD_BLE_API_VERSION <= 2) + dev_addr.addr_type = type; + ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); +#endif + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) +{ + ble_gap_addr_t dev_addr; + ble_gap_irk_t irk = {0}; + ble_gap_privacy_params_t privacy_params = {0}; + privacy_params.p_device_irk = &irk; + +#if (NRF_SD_BLE_API_VERSION <= 2) + if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +#else + // Check privacy mode + if( pm_privacy_get(&privacy_params) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + // If in private mode, the address is generated by softdevice, so return a nulled address with correct type + if( privacy_params.privacy_mode == BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY ) + { + memset(address, 0, ADDR_LEN); + switch( privacy_params.private_addr_type ) + { + case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: + *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE; + break; + case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE: + default: + *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + } + return BLE_ERROR_NONE; + } + + // Otherwise recover public/static address + if (sd_ble_gap_addr_get(&dev_addr) != NRF_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +#endif + + if (typeP != NULL) { + *typeP = static_cast(dev_addr.addr_type); + } + if (address != NULL) { + memcpy(address, dev_addr.addr, ADDR_LEN); + } + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setDeviceName(const uint8_t *deviceName) +{ + ble_gap_conn_sec_mode_t sec_mode; + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed + + if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) +{ + if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF5xGap::setAppearance(GapAdvertisingData::Appearance appearance) +{ + if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +ble_error_t nRF5xGap::getAppearance(GapAdvertisingData::Appearance *appearanceP) +{ + if ((sd_ble_gap_appearance_get(reinterpret_cast(appearanceP)) == NRF_SUCCESS)) { + return BLE_ERROR_NONE; + } else { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } +} + +/* (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ +ble_error_t nRF5xGap::setTxPower(int8_t txPower) +{ + unsigned rc; + if ((rc = sd_ble_gap_tx_power_set(txPower)) != NRF_SUCCESS) { + switch (rc) { + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_PARAM: + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + return BLE_ERROR_NONE; +} + +void nRF5xGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) +{ +#if defined(NRF51) + static const int8_t permittedTxValues[] = { + -30, -20, -16, -12, -8, -4, 0, 4 + }; +#elif defined(NRF52) +#if NRF_SD_BLE_API_VERSION >= 5 + static const int8_t permittedTxValues[] = { + -40, -20, -16, -12, -8, -4, 0, 3, 4 + }; +#else + static const int8_t permittedTxValues[] = { + -40, -20, -16, -12, -8, -4, 0, 4 + }; +#endif +#elif defined(NRF52840_XXAA) + static const int8_t permittedTxValues[] = { + -40, -20, -16, -12, -8, -4, 0, 2, 3, 4, 5, 6, 7, 8, 9 + }; +#else +#error permitted TX power values unknown for this SOC +#endif + + *valueArrayPP = permittedTxValues; + *countP = sizeof(permittedTxValues) / sizeof(int8_t); +} + +/**************************************************************************/ +/*! + @brief Get the capacity of the internal whitelist maintained by this + implementation. + + @returns The capacity of the internal whitelist. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +uint8_t nRF5xGap::getMaxWhitelistSize(void) const +{ + return YOTTA_CFG_WHITELIST_MAX_SIZE; +} + +/**************************************************************************/ +/*! + @brief Get a copy of the implementation's internal whitelist. + + @param[out] whitelistOut + A \ref Gap::Whitelist_t structure containing a copy of the + addresses in the implemenetation's internal whitelist. + + @returns \ref ble_errror_t + + @retval BLE_ERROR_NONE + Everything executed properly. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const +{ + uint32_t i; + for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { + memcpy( &whitelistOut.addresses[i].address, &whitelistAddresses[i].addr, sizeof(whitelistOut.addresses[0].address)); + whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); + + + } + whitelistOut.size = i; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Set the whitelist that will be used in the next call to + startAdvertising(). + + @param[in] whitelistIn + A reference to a \ref Gap::Whitelist_t structure + representing a whitelist containing all the white listed + BLE addresses. + + @returns \ref ble_errror_t + + @retval BLE_ERROR_NONE + Everything executed properly. + + BLE_ERROR_INVALID_PARAM + The supplied whitelist contains a private non-resolvable + address + + BLE_ERROR_PARAM_OUT_OF_RANGE + The size of the supplied whitelist exceeds the maximum + capacity of the implementation's internal whitelist. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) +{ + if (whitelistIn.size > getMaxWhitelistSize()) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Test for invalid parameters before we change the internal state */ + for (uint32_t i = 0; i < whitelistIn.size; ++i) { + if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + /* This is not allowed because it is completely meaningless */ + return BLE_ERROR_INVALID_PARAM; + } + } + + whitelistAddressesSize = whitelistIn.size; + + for (uint32_t i = 0; i < whitelistIn.size; ++i) { + memcpy(&whitelistAddresses[i].addr , &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr)); + whitelistAddresses[i].addr_type = static_cast (whitelistIn.addresses[i].type); + } + +#if (NRF_SD_BLE_API_VERSION >= 3) + updateWhiteAndIdentityListInStack(); +#endif + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Set the advertising policy filter mode that will be used in + the next call to startAdvertising(). + + @returns \ref ble_errror_t + + @retval BLE_ERROR_NONE + Everything executed properly. + + BLE_ERROR_NOT_IMPLEMENTED + This feature is currently note implemented. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode) +{ + advertisingPolicyMode = mode; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Set the scanning policy filter mode that will be used in + the next call to startAdvertising(). + + @returns \ref ble_errror_t + + @retval BLE_ERROR_NONE + Everything executed properly. + + BLE_ERROR_NOT_IMPLEMENTED + This feature is currently note implemented. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setScanningPolicyMode(Gap::ScanningPolicyMode_t mode) +{ + scanningPolicyMode = mode; + + return BLE_ERROR_NONE; +} + +/**************************************************************************/ +/*! + @brief Set the initiator policy filter mode that will be used in + the next call to startAdvertising() + + @returns \ref ble_errror_t + + @retval BLE_ERROR_NONE + Everything executed properly. + + BLE_ERROR_NOT_IMPLEMENTED + This feature is currently note implemented. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::setInitiatorPolicyMode(Gap::InitiatorPolicyMode_t mode) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +/**************************************************************************/ +/*! + @brief Get the current advertising policy filter mode. + + @returns The advertising policy filter mode. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +Gap::AdvertisingPolicyMode_t nRF5xGap::getAdvertisingPolicyMode(void) const +{ + return advertisingPolicyMode; +} + +/**************************************************************************/ +/*! + @brief Get the current scanning policy filter mode. + + @returns The scanning policy filter mode. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +Gap::ScanningPolicyMode_t nRF5xGap::getScanningPolicyMode(void) const +{ + return scanningPolicyMode; +} + +/**************************************************************************/ +/*! + @brief Get the current initiator policy filter mode. + + @returns The initiator policy filter mode. + + @note Currently initiator filtering using the whitelist is not + implemented in this module. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const +{ + return Gap::INIT_POLICY_IGNORE_WHITELIST; +} + +#if (NRF_SD_BLE_API_VERSION <= 2) +/**************************************************************************/ +/*! + @brief Helper function used to populate the ble_gap_whitelist_t that + will be used by the SoftDevice for filtering requests. + + @returns \ref ble_error_t + + @retval BLE_ERROR_NONE + Everything executed properly + + @retval BLE_ERROR_INVALID_STATE + The internal stack was not initialized correctly. + + @note Both the SecurityManager and Gap must initialize correctly for + this function to succeed. + + @note 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. + + @section EXAMPLE + + @code + + @endcode +*/ +/**************************************************************************/ +ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) +{ + ble_gap_whitelist_t whitelistFromBondTable; + ble_gap_addr_t *addressPtr[1]; + ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + + nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); + + if (securityManager.hasInitialized()) { + /* We do not care about the addresses, set the count to 0 */ + whitelistFromBondTable.addr_count = 0; + /* The Nordic SDK will return a failure if we set pp_addr to NULL */ + whitelistFromBondTable.pp_addrs = addressPtr; + /* We want all the IRKs we can get because we do not know which ones match the addresses */ + whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; + whitelistFromBondTable.pp_irks = irkPtr; + + /* Use the security manager to get the IRKs from the bond table */ + ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); + if (error != BLE_ERROR_NONE) { + return error; + } + } else { + /** + * If there is no security manager then we cannot access the bond table, + * so disable IRK matching + */ + whitelistFromBondTable.addr_count = 0; + whitelistFromBondTable.irk_count = 0; + } + + /** + * For every private resolvable address in the local whitelist check if + * there is an IRK for said address in the bond table and add it to the + * local IRK list. + */ + whitelist.irk_count = 0; + whitelist.addr_count = 0; + for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { + if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { + /* Test if there is a matching IRK for this private resolvable address */ + for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { + if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { + /* Found the corresponding IRK, add it to our local whitelist */ + whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; + whitelist.irk_count++; + /* Make sure we do not look at this IRK again */ + if (j != whitelistFromBondTable.irk_count - 1) { + /** + * This is not the last IRK, so replace the pointer + * with the last pointer in the array + */ + whitelistFromBondTable.pp_irks[j] = + whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; + } + /** + * If the IRK is the last pointer in the array simply + * decrement the total IRK count + */ + whitelistFromBondTable.irk_count--; + break; + } + } + } else { + /* Include the address into the whitelist */ + whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; + whitelist.addr_count++; + } + } + + return BLE_ERROR_NONE; +} +#endif + +#if (NRF_SD_BLE_API_VERSION >= 3) + +/** + * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. + * + * Gap::setWhitelist provides the base for preparation of these settings. + * This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table. + * Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice) + * are passed to the identities list (intended to be passed to the Softdevice). + * + * @param[out] gapAdrHelper Reference to the struct for storing settings. + */ + +ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) +{ + pm_peer_id_t peer_id; + + ret_code_t ret; + + pm_peer_data_bonding_t bond_data; + + uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE]; + + memset(irk_found, 0x00, sizeof(irk_found)); + + + gapAdrHelper.identities_cnt = 0; + + + peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); + + nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); + + /** + * Build identities list: + * For every private resolvable address in the bond table check if + * there is maching address in th provided whitelist. + */ + while (peer_id != PM_PEER_ID_INVALID) + { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pm_peer_data_bonding_load(peer_id, &bond_data); + + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) + { + // Peer data could not be found in flash or peer ID is not valid. + return BLE_ERROR_UNSPECIFIED; + } + + if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) + { + for (uint8_t i = 0; i < whitelistAddressesSize; ++i) + { + if (!irk_found[i]) + { + if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) + { + + //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; + if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info)) + { + // Copy data to the buffer. + memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); + gapAdrHelper.identities_cnt++; + + irk_found[i] = 1; // don't look at this address again + } + } + } + } + } + + // get next peer id + peer_id = pm_next_peer_id_get(peer_id); + } + + gapAdrHelper.addrs_cnt = 0; + + /** + * Build whitelist from the rest of addresses (explicit addresses) + */ + for (uint8_t i = 0; i < whitelistAddressesSize; ++i) + { + if (!irk_found[i]) + { + memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t)); + gapAdrHelper.addrs[i].addr_id_peer = 0; + gapAdrHelper.addrs_cnt++; + } + } + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) +{ + uint32_t retc; + + if (gapAdrHelper.identities_cnt == 0) { + retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); + } else { + ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + + for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i) + { + pp_identities[i] = &gapAdrHelper.identities[i]; + } + + retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); + } + + if (retc == NRF_SUCCESS) { + if (gapAdrHelper.addrs_cnt == 0) { + retc = sd_ble_gap_whitelist_set(NULL, 0); + } else { + ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + + for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i) + { + pp_addrs[i] = &gapAdrHelper.addrs[i]; + } + + retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); + } + } + + switch(retc) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + + case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared. + case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared. + return BLE_ERROR_ALREADY_INITIALIZED; + + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied. + case NRF_ERROR_DATA_SIZE: + case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. + return BLE_ERROR_INVALID_PARAM; + + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() +{ + GapWhiteAndIdentityList_t whiteAndIdentityList; + uint32_t err; + + err = getStackWhiteIdentityList(whiteAndIdentityList); + + if (err != BLE_ERROR_NONE) { + return (ble_error_t)err; + } + + return applyWhiteIdentityList(whiteAndIdentityList); +} +#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h new file mode 100644 index 0000000000..05ccc2d863 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h @@ -0,0 +1,285 @@ +/* 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/nrf_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 { + #if (NRF_SD_BLE_API_VERSION >= 5) // In SD v5+, non connectable advertising interval is the same as connectable advertising interval + // The Mbed infrastructure expects 100ms+ - so for now return that + // return getMinAdvertisingInterval(); + // FIXME infrastructure + return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; + #else + return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN); + #endif + } + 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(&radioNotificationCallback, &FunctionPointerWithContext::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__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp new file mode 100644 index 0000000000..f606d541a0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp @@ -0,0 +1,847 @@ +/* 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 + } + } +}; + +static ble_error_t set_attribute_value( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + ble_gatts_value_t *value +) { + uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, value); + switch(err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case NRF_ERROR_INVALID_PARAM: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_NOT_FOUND: + case NRF_ERROR_DATA_SIZE: + case BLE_ERROR_INVALID_CONN_HANDLE: + case BLE_ERROR_GATTS_INVALID_ATTR_TYPE: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + case NRF_ERROR_FORBIDDEN: + return BLE_ERROR_OPERATION_NOT_PERMITTED; + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +} // end of anonymous namespace + +/**************************************************************************/ +/*! + @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); + GattAttribute *p_description_descriptor = NULL; + GattAttribute *p_presentation_format_descriptor = NULL; + + /* 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 and presentation-format descriptors are special cases + * that need to be handled at the time of adding each characteristic. The + * following block is meant to discover their presence. */ + const uint8_t *userDescriptionDescriptorValuePtr = NULL; + uint16_t userDescriptionDescriptorValueLen = 0; + const uint8_t *presentationFormatDescriptorValuePtr = NULL; + uint16_t presentationFormatDescriptorValueLen = 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) { + p_description_descriptor = p_desc; + userDescriptionDescriptorValuePtr = p_desc->getValuePtr(); + userDescriptionDescriptorValueLen = p_desc->getLength(); + } + if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) { + p_presentation_format_descriptor = p_desc; + presentationFormatDescriptorValuePtr = p_desc->getValuePtr(); + presentationFormatDescriptorValueLen = 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, + presentationFormatDescriptorValuePtr, + presentationFormatDescriptorValueLen, + 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); + if (p_description_descriptor) { + p_description_descriptor->setHandle( + nrfCharacteristicHandles[characteristicCount].user_desc_handle + ); + } + if (p_presentation_format_descriptor) { + // The handle is not available from the SoftDevice + p_presentation_format_descriptor->setHandle(GattAttribute::INVALID_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 or presentation-format descriptor here; + * they have already been handled when adding the characteristic (above). */ + if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC + || p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) { + 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(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(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(); + } + + bool updatesEnabled = false; + if (connectionHandle != BLE_CONN_HANDLE_INVALID) { + ble_error_t err = areUpdatesEnabled(connectionHandle, attributeHandle, &updatesEnabled); + + // FIXME: The softdevice allocates and populates CCCD when the client + // interract with them. Checking for updates may return an out of + // range error in such case. + if(err && err != BLE_ERROR_PARAM_OUT_OF_RANGE) { + return err; + } + } + + if (updatesEnabled) { + 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 { + returnValue = set_attribute_value(connectionHandle, attributeHandle, &value); + } + } else { + returnValue = set_attribute_value(connectionHandle, attributeHandle, &value); + } + + 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) +{ + return areUpdatesEnabled(connectionHandle, characteristic.getValueHandle(), enabledP); +} + +ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, bool *enabledP) +{ + int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle); + 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(&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(const 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; + +#if NRF_SD_BLE_API_VERSION >= 4 // This event has been renamed in API V4+ + case BLE_GATTS_EVT_HVN_TX_COMPLETE: { + handleDataSentEvent(p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count); + return; + } +#else + case BLE_EVT_TX_COMPLETE: { + handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); + return; + } +#endif + + 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(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(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(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(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; + } + } +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.h new file mode 100644 index 0000000000..6be90ff733 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.h @@ -0,0 +1,167 @@ +/* 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 + +#include "ble/blecommon.h" +#include "headers/nrf_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(const 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(); + + /** + * Query if updates of a characteristics are enabled for a given connection. + */ + ble_error_t areUpdatesEnabled( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t valueHandle, + bool *enabledP + ); + +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__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h new file mode 100644 index 0000000000..0e901b5701 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h @@ -0,0 +1,194 @@ +/* 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 + +#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. + */ + 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; + } +#else // -> NRF_SD_BLE_API_VERSION >= 3 + /** + * @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. + * + * @retval BLE_ERROR_NONE if successful. + * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. + */ + virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { + return btle_getAddressesFromBondTable(addresses); + } +#endif // #if (NRF_SD_BLE_API_VERSION <= 2) + + + + /** + * @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__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp new file mode 100644 index 0000000000..7bc8b821b7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp @@ -0,0 +1,241 @@ +/* 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 "nrf_sdh.h" +} + +#include "nRF5XPalGattClient.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), + gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())), + 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 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 NRF_SD_BLE_API_VERSION >= 5 + if (nrf_sdh_disable_request() != NRF_SUCCESS) { + return BLE_STACK_BUSY; + } + #else + if (softdevice_handler_sd_disable() != NRF_SUCCESS) { + return BLE_STACK_BUSY; + } + #endif + + /* 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) + error = getGattClient().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() { + core_util_critical_section_enter(); + while (isEventsSignaled) { + isEventsSignaled = false; + core_util_critical_section_exit(); + #if NRF_SD_BLE_API_VERSION >= 5 + // We use the "polling" dispatch model + // http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v14.2.0/group__nrf__sdh.html?cp=4_0_0_6_11_60_20#gab4d7be69304d4f5feefd1d440cc3e6c7 + // This will process any pending events from the Softdevice + nrf_sdh_evts_poll(); + #else + intern_softdevice_events_execute(); + #endif + + core_util_critical_section_enter(); + } + core_util_critical_section_exit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h new file mode 100644 index 0000000000..154b9e49dc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h @@ -0,0 +1,179 @@ +/* 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 "ble/generic/GenericGattClient.h" + +#include "nRF5xGap.h" +#include "nRF5xGattServer.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 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 GattClient &getGattClient() { + return gattClient; + } + + /** + * 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. */ + ble::generic::GenericGattClient gattClient; + + 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 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/projectconfig.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/projectconfig.h new file mode 100644 index 0000000000..15959850c4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/projectconfig.h @@ -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_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/supress-warnings.cmake b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/supress-warnings.cmake new file mode 100644 index 0000000000..60061399da --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/supress-warnings.cmake @@ -0,0 +1,21 @@ +# Copyright 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. + +message("suppressing warnings from ble-nrf51822") + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set_target_properties(ble-nrf51822 + PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function -Wno-missing-field-initializers" + ) +endif() diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/LF_Clock_config.md b/targets/TARGET_NORDIC/TARGET_NRF5x/LF_Clock_config.md new file mode 100644 index 0000000000..22852ae261 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/LF_Clock_config.md @@ -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" + } + } +} + +``` + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPins.h b/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPins.h new file mode 100644 index 0000000000..037b13a390 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPins.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 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_PERIPHERALPINS_H +#define MBED_PERIPHERALPINS_H + +#include "pinmap.h" +#include "PeripheralNames.h" + +#if DEVICE_ANALOGIN +/************ADC***************/ +extern const PinMap PinMap_ADC[]; +#endif + +#endif // MBED_PERIPHERALPINS_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPinsDefault.c b/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPinsDefault.c new file mode 100644 index 0000000000..fcd4797797 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/PeripheralPinsDefault.c @@ -0,0 +1,46 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 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 "pinmap_ex.h" +#include "mbed_toolchain.h" + +/* Default mapping between I2C pins and I2C instance. + * Can be overwritten by user. + */ +MBED_WEAK const PinMapI2C PinMap_I2C[1] = { + { NC, NC, NC } +}; + +/* Default mapping between SPI pins and SPI instance. + * Can be overwritten by user. + */ +MBED_WEAK const PinMapSPI PinMap_SPI[1] = { + { NC, NC, NC, NC } +}; + +/* Default mapping between PWM pins and PWM instance. + * Can be overwritten by user. + */ +MBED_WEAK const PinMapPWM PinMap_PWM[1] = { + { NC, NC } +}; + +/* Default mapping between UART pins and UART instance. + * Can be overwritten by user. + */ +MBED_WEAK const PinMapUART PinMap_UART[1] = { + { NC, NC, NC } +}; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/README.md new file mode 100644 index 0000000000..d8505f65d3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/README.md @@ -0,0 +1,153 @@ +# Nordic NRF52 + +## Adding New Targets Based On Nordic NRF52832 And NRF52840 MCUs + +First, create a new entry in `mbed-os/targets/targets.json` using the template below: + +```json +{ + "target_name": { + "inherits": [""], + "release_versions": ["5"], + "device_name": "" + }, +} +``` + +Where `target_name` is the name of the new target, `inherits` can be either `MCU_NRF52832` or `MCU_NRF52840`, and `device_name` is the ID specifying actual RAM and flash size, for example, `nRF52832_xxAA` and `nRF52840_xxAA`. The `release_version` specifies that the target is compatible with Mbed OS 5. + +This entry enables the new target in the Mbed OS build system. + +Next, add optional target specific configuration in `mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/mbed_lib.json`. + +```json +{ + "target_overrides": { + "target_name": { + "target.macros_add": [ + "optional macros" + ], + "optional configuration" + } + } +} +``` + +The optional configuration includes specifying errata fixes specific for the MCU release used on the target, configuring the low-frequency clock source, and configuring the UART behavior. See targets `NRF52_DK` and `NRF52840_DK` for examples. + +### LF Clock Configuration + +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. + +Default clock source is XTAL oscillator. There are three options that can be configured as the clock source: + - NRF_LF_SRC_XTAL + - NRF_LF_SRC_RC + - NRF_LF_SRC_SYNTH + +Set `lf_clock_src` to what is most suitable for the target. This value can later be overridden by the user application if necessary. + + +## Mbed HAL Implementation Details + +### SPI and I2C + +The TWI/TWIM (I2C) and SPI/SPIM module shares the same underlying hardware and each instance can only provide one functionality at a time. Both the NRF52832 and NRF52840 have 2 TWI/TWIM modules and 3 SPI/SPIM: + +| Instance 0 | Instance 1 | Instance 2 | +| :---: | :---: | :---: | +| SPI0/SPIM0 | SPI1/SPIM1 | SPI2/SPIM2 | +| TWI0/TWIM0 | TWI1/TWIM1 | | + +When instantiating a new Mbed SPI object or I2C object, the object will be assigned a hardware instance. By default, the HAL implementation will automatically pick a hardware instance based on the assigned pins in the following order: + +1. The driver will look up the pins in the configuration table and pick a pre-assigned instance. +1. If the pins can't be found in the configuration table, the driver will check if a hardware instance has already been assigned to those pins so that objects using the same pins will share the same instance. +1. If no instance has been assigned, the driver will look for a free instane. For I2C objects instances are assigned from 0 to 1. For SPI objects instances are assigned from 2 to 0. This ensures that no matter the order of instantiation the first three objects can be guaranteed to be on separate instances no matter the pins being used. +1. If no unused instance can be found, objects not sharing any pins will be assigned to the same default instance, which is `Instance 0` for I2C and `Instance 2` for SPI. + +#### Customization + +A custom configuration table can be provided by overriding the weakly defined default empty table. In the example below, I2C objects using pins `p1` and `p2` for `SDA` and `SCL` will always be assigned to `Instance 1` and SPI objects using pins `p3`, `p4`, `p5` for `MOSI`, `MISO`, and `CLOCK` will be assigned to `Instance 2` and SPI objects using pins `p6`, `p7`, and `p8` will be assigned to `Instance 0`. The custom configuration table must always be terminated with a row of `NC`. + +``` +const PinMapI2C PinMap_I2C[] = { + {p1, p2, 1}, + {NC, NC, NC} +}; + +const PinMapSPI PinMap_SPI[] = { + {p3, p4, p5, 2}, + {p6, p7, p8, 0}, + {NC, NC, NC, NC} +}; +``` + +The tables must be placed in a C compilation file. + +#### Concurrency + +1. When called from the same thread, it is safe to assign I2C and SPI objects to the same instance. +1. If an instance is being used exclusively for either I2C or SPI, the objects can safely be called from multiple threads. +1. If an instance is being used for both I2C and SPI, the user must provide thread safety between the objects. + + +### Serial + +The serial implementation uses the UARTE module which works exclusively through EasyDMA and RAM buffers. For optimal performance, each configured instance (NRF52832 has 1, NRF52840 has 2) has three buffers statically assigned: + +1. Rx DMA buffer, which EasyDMA is currently writing to. +1. Rx DMA buffer, pre-loaded in EasyDMA for automatic switchover. +1. Rx FIFO buffer, for serving data to the application. + +When the first DMA buffer is full or flushed the interrupt handler will automatically copy the DMA buffer to the FIFO buffer. This happens in interrupt context to avoid data loss and with UARTE interrupts set at the highest priority. The FIFO buffer is backed by the Nordic atomic fifo, which can be read and written to safely without disabling interrupts. + +#### Customization + +All buffers can be resized to fit the application: + +``` + "name": "nordic", + "config": { + "uart-dma-size": { + "help": "UART DMA buffer. 2 buffers per instance. DMA buffer is filled by UARTE", + "value": 8 + }, + "uart-0-fifo-size": { + "help": "UART0 FIFO buffer. FIFO buffer is filled from DMA buffer.", + "value": 32 + }, + "uart-1-fifo-size": { + "help": "UART1 FIFO buffer. FIFO buffer is filled from DMA buffer.", + "value": 32 + } + } +``` + +All DMA buffers are the same size and must be at least 5 bytes due to hardware restrictions. DMA buffers should be sized to handle the worst expected interrupt latency. FIFO buffers can be configured per instance and the size should reflect the largest expected burst data. For example, a serial debug port might receive a line of data at a time, so an 80 byte FIFO buffer would be adequate. A serial port connected to a wifi radio should have a FIFO buffer in the kilo byte range. + +For the NRF52840, UARTE instances are assigned based on pins and calling order. Serial objects with the same pin configurations will go to the same instance. A custom configuration table can be provided by overriding the weakly defined default empty table. In the example below, serial objects using pins `p1` and `p2` for `Tx` and `Rx` will always be assigned to `Instance 1` and serial objects using pins `p3` and `p4` for `Tx` and `Rx` will be assigned to `Instance 0` regardless of calling order. The custom configuration table must always be terminated with a row of `NC`. + +``` +const PinMapI2C PinMap_UART[] = { + {p1, p2, 1}, + {p3, p4, 0}, + {NC, NC, NC} +}; +``` + +The table must be placed in a C compilation file. + + +#### RTC2 + +Because each DMA buffer must be at least 5 bytes deep, each buffer is automatically flushed after a certain idle period to ensure low latency and correctness. This idle timeout is implemented using 2 of the 4 channels on RTC instance 2. This leaves RTC0 for the SoftDevice and RTC1 for Mbed tickers. + +The RTC2 ISR is set at the lowest interrupt priority to ensure that UARTE interrupts take precedence. The last 2 of the 4 RTC channels are used for decoupling UARTE ISR context from Mbed IRQ events. This ensures that any user code will only delay other user callbacks and idle flushing and puts an upper bound on the interrupt handling time for the UARTE ISR. + +#### Limitations + + * The UARTE hardware only supports 8-bit, None/Even parity, and 1 stop bit. + * The asynchronous read and write implementation currently only support 255 byte transfers. + * The EasyDMA hardware can only read from RAM, which means all Tx buffers must reside in RAM. If a Tx buffer residing in flash is passed to the asynchronous write function, the function will try to copy the Tx buffer to a temporary internal buffer and transmit the data from there. + * It is not possible to do an asynchronous write from flash and receive non-asynchronously at the same time since the non-asynchronous receive buffer is being used as the temporary transmission buffer. + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralNames.h new file mode 100644 index 0000000000..7e9274d7c7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralNames.h @@ -0,0 +1,77 @@ +/* + * 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 + +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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralPins.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralPins.c new file mode 100644 index 0000000000..aa0813e64a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PeripheralPins.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018 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 "PeripheralPins.h" + +typedef enum { + NRF_SAADC_CHANNEL_0 = 0, + NRF_SAADC_CHANNEL_1 = 1, + NRF_SAADC_CHANNEL_2 = 2, + NRF_SAADC_CHANNEL_3 = 3, + NRF_SAADC_CHANNEL_4 = 4, + NRF_SAADC_CHANNEL_5 = 5, + NRF_SAADC_CHANNEL_6 = 6, + NRF_SAADC_CHANNEL_7 = 7, +} nrf_saadc_channel_t; + +/************ADC***************/ +/* The third "function" value is used to select the correct ADC channel */ +#if DEVICE_ANALOGIN +const PinMap PinMap_ADC[] = { + { p2, ADC0_0, NRF_SAADC_CHANNEL_0 }, + { p3, ADC0_0, NRF_SAADC_CHANNEL_1 }, + { p4, ADC0_0, NRF_SAADC_CHANNEL_2 }, + { p5, ADC0_0, NRF_SAADC_CHANNEL_3 }, + { p28, ADC0_0, NRF_SAADC_CHANNEL_4 }, + { p29, ADC0_0, NRF_SAADC_CHANNEL_5 }, + { p30, ADC0_0, NRF_SAADC_CHANNEL_6 }, + { p31, ADC0_0, NRF_SAADC_CHANNEL_7 }, + { NC, NC, NC } +}; +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PortNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PortNames.h new file mode 100644 index 0000000000..c63624639b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/PortNames.h @@ -0,0 +1,53 @@ +/* + * 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 +} PortName; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/PinNames.h new file mode 100644 index 0000000000..18d89777bf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/PinNames.h @@ -0,0 +1,204 @@ +/* + * 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" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + + P0_0 = p0, + P0_1 = p1, + P0_2 = p2, + P0_3 = p3, + P0_4 = p4, + P0_5 = p5, + P0_6 = p6, + P0_7 = p7, + + P0_8 = p8, + P0_9 = p9, + P0_10 = p10, + P0_11 = p11, + P0_12 = p12, + P0_13 = p13, + P0_14 = p14, + P0_15 = p15, + + P0_16 = p16, + P0_17 = p17, + P0_18 = p18, + P0_19 = p19, + P0_20 = p20, + P0_21 = p21, + P0_22 = p22, + P0_23 = p23, + + P0_24 = p24, + P0_25 = p25, + P0_26 = p26, + P0_27 = p27, + P0_28 = p28, + P0_29 = p29, + P0_30 = p30, + + LED1 = p17, + LED2 = p18, + LED3 = p19, + LED4 = p20, + + BUTTON1 = p13, + BUTTON2 = p14, + BUTTON3 = p15, + BUTTON4 = p16, + + RX_PIN_NUMBER = p11, + TX_PIN_NUMBER = p12, + CTS_PIN_NUMBER = p13, + RTS_PIN_NUMBER = p14, + + // mBed interface Pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + + SPI_PSELMOSI0 = p23, + SPI_PSELMISO0 = p24, + SPI_PSELSS0 = p22, + SPI_PSELSCK0 = p25, + + SPI_PSELMOSI1 = p12, + SPI_PSELMISO1 = p13, + SPI_PSELSS1 = p11, + SPI_PSELSCK1 = p14, + + SPIS_PSELMOSI = p12, + SPIS_PSELMISO = p13, + SPIS_PSELSS = p11, + SPIS_PSELSCK = p14, + + I2C_SDA0 = p26, + I2C_SCL0 = p27, + + D0 = p11, + D1 = p12, + D2 = p13, + D3 = p14, + D4 = p15, + D5 = p16, + D6 = p17, + D7 = p18, + + D8 = p19, + D9 = p20, + D10 = p22, + D11 = p23, + D12 = p24, + D13 = p25, + + 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/device.h new file mode 100644 index 0000000000..2427e752ea --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/device.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/mbed_overrides.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/mbed_overrides.c new file mode 100644 index 0000000000..fd32a74329 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_DELTA_DFBM_NQ620/mbed_overrides.c @@ -0,0 +1,22 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-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. + */ + +void mbed_sdk_init() +{ + char* debug_date = __DATE__; + char* debug_time = __TIME__; + +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/PinNames.h new file mode 100644 index 0000000000..8ce74b2356 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/PinNames.h @@ -0,0 +1,247 @@ +/* mbed Microcontroller Library + * Copyright (c) 2013 Nordic Semiconductor + * + * 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_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + + + P0_0 = p0, + P0_1 = p1, + P0_2 = p2, + P0_3 = p3, + P0_4 = p4, + P0_5 = p5, + P0_6 = p6, + P0_7 = p7, + + P0_8 = p8, + P0_9 = p9, + P0_10 = p10, + P0_11 = p11, + P0_12 = p12, + P0_13 = p13, + P0_14 = p14, + P0_15 = p15, + + P0_16 = p16, + P0_17 = p17, + P0_18 = p18, + P0_19 = p19, + P0_20 = p20, + P0_21 = p21, + P0_22 = p22, + P0_23 = p23, + + P0_24 = p24, + P0_25 = p25, + P0_26 = p26, + P0_27 = p27, + P0_28 = p28, + P0_29 = p29, + P0_30 = p30, + P0_31 = p31, + + // Module pins. Refer datasheet for pin numbers. + SIO_1 = P0_1, + SIO_2 = P0_2, + SIO_3 = P0_3, + SIO_4 = P0_4, + SIO_5 = P0_5, + SIO_6 = P0_6, + SIO_7 = P0_7, + SIO_8 = P0_8, + SIO_9 = P0_9, //NFC1 + SIO_10 = P0_10, //NFC2 + SIO_11 = P0_11, + SIO_12 = P0_12, + SIO_13 = P0_13, + SIO_14 = P0_14, + SIO_15 = P0_15, + SIO_16 = P0_16, + SIO_17 = P0_17, + SIO_18 = P0_18, + SIO_19 = P0_19, + SIO_20 = P0_20, + + SIO_22 = P0_22, + SIO_23 = P0_23, + SIO_24 = P0_24, + SIO_25 = P0_25, + SIO_26 = P0_26, + SIO_27 = P0_27, + SIO_28 = P0_28, + SIO_29 = P0_29, + SIO_30 = P0_30, + SIO_31 = P0_31, + SIO_0 = P0_0, + + // Not connected + NC = (int)0xFFFFFFFF, + + //Mbed MTB pin defines. + P_1 = NC, + P_2 = SIO_24, //MISO + P_3 = SIO_23, //MOSI + P_4 = SIO_22, +// P_5 = SWDIO, +// P_6 = SWDCLK, +// P_7 = NRST, + P_8 = SIO_20, + P_9 = SIO_18, + P_10 = SIO_16, + P_11 = SIO_14, + P_12 = SIO_12, + P_13 = SIO_11, + P_14 = SIO_10, + P_15 = SIO_9, + P_16 = NC, + P_17 = SIO_8, + P_18 = SIO_7, + P_19 = SIO_6, + P_20 = SIO_5, + P_21 = SIO_4, + P_22 = SIO_3, + P_23 = SIO_2, + P_24 = SIO_1, + P_25 = SIO_0, + P_26 = NC, + P_27 = NC, + P_28 = SIO_13, + P_29 = SIO_15, + P_30 = SIO_17, + P_31 = SIO_19, + P_32 = SIO_31, + P_33 = SIO_30, + P_34 = SIO_29, + P_35 = SIO_28, + P_36 = SIO_27, + P_37 = SIO_26, + P_38 = SIO_25, + P_39 = NC, + + //LEDs + LED1 = SIO_28, + LED2 = SIO_29, + LED3 = SIO_30, + LED_RED = LED1, + LED_GREEN = LED2, + LED_BLUE = LED3, + + GP0 = SIO_11, + //Standardized button name + BUTTON1 = GP0, + + //Nordic SDK pin names + RX_PIN_NUMBER = SIO_8, + TX_PIN_NUMBER = SIO_6, + CTS_PIN_NUMBER = SIO_7, + RTS_PIN_NUMBER = SIO_5, + + // mBed interface Pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + STDIO_UART_CTS = CTS_PIN_NUMBER, + STDIO_UART_RTS = RTS_PIN_NUMBER, + + SPI_MOSI = SIO_23, + SPI_MISO = SIO_24, + SPI_SS0 = SIO_17, //CS for LCD on MTB + SPI_SS1 = SIO_10, //CS for SD card on MTB + SPI_SCK1 = SIO_25, + SPI_SCK2 = SIO_31, + + //Default SPI + SPI_SCK = SPI_SCK1, + SPI_CS = SPI_SS1, + + I2C_SDA = SIO_26, + I2C_SCL = SIO_27, + + //MTB aliases + GP1 = SIO_13, + AIN0 = SIO_2, + AIN1 = SIO_3, + AIN2 = SIO_4, + GP2 = SIO_10, + GP3 = SIO_9, + GP4 = SIO_22, + GP5 = SIO_19, //A0 for LCD on MTB + GP6 = SIO_18, //RESET for LCD on MTB + GP7 = SIO_17, + GP8 = SIO_15, + +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/device.h new file mode 100644 index 0000000000..493844b801 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_LAIRD_BL652/device.h @@ -0,0 +1,23 @@ +// 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/PinNames.h new file mode 100644 index 0000000000..87b07172c7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/PinNames.h @@ -0,0 +1,157 @@ +/* mbed Microcontroller Library + * 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_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + // nRF52 pin names + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + NC = (int)0xFFFFFFFF, // Not connected + + //NINA-B112 module pin names + P_1 = p8, + P_2 = p11, + P_3 = p12, + P_4 = p13, + P_5 = p14, + P_6 = NC, + P_7 = p16, + P_8 = p18, + P_9 = NC, + P_10 = NC, + P_11 = NC, + P_12 = NC, + P_13 = NC, + P_14 = NC, + P_15 = NC, + P_16 = p28, + P_17 = p29, + P_18 = p30, + P_19 = p21, + P_20 = p31, + P_21 = p7, + P_22 = p6, + P_23 = p5, + P_24 = p2, + P_25 = p3, + P_26 = NC, + P_27 = p4, + P_28 = p9, + P_29 = p10, + P_30 = NC, + + // MTB aliases + GPIO18 = p30, + + LED1 = p4, // Red LED + LED2 = p10, // Green LED + GPIO27 = LED1, +// GPIO29 = LED2, + + GPIO7 = p16, //A0 for LCD + GPIO16 = p28, //RESET for LCD + + SW1 = p29, + GPIO17 = SW1, + //Standardized button names + BUTTON1 = SW1, + + // Nordic SDK pin names + RX_PIN_NUMBER = p5, + TX_PIN_NUMBER = p6, + CTS_PIN_NUMBER = p7, + RTS_PIN_NUMBER = p31, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + + I2C_SDA = p2, + I2C_SCL = p3, + + SPI0_MOSI = p13, + SPI0_MISO = p12, + SPI0_SCK = p14, + SPI0_CS = p11, + SPI1_CS = p8, + + SPI_MOSI = SPI0_MOSI, + SPI_MISO = SPI0_MISO, + SPI_SCK = SPI0_SCK, + SPI_CS = SPI0_CS, + + // DAPLink + USBRX = RX_PIN_NUMBER, + USBTX = TX_PIN_NUMBER, + NTRST = p21, + SWO = p18, + +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/device.h new file mode 100644 index 0000000000..99a6e40f2a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_MTB_UBLOX_NINA_B1/device.h @@ -0,0 +1,21 @@ +/* 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h new file mode 100644 index 0000000000..72ec717547 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/PinNames.h @@ -0,0 +1,207 @@ +/* + * 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" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + + P0_0 = p0, + P0_1 = p1, + P0_2 = p2, + P0_3 = p3, + P0_4 = p4, + P0_5 = p5, + P0_6 = p6, + P0_7 = p7, + + P0_8 = p8, + P0_9 = p9, + P0_10 = p10, + P0_11 = p11, + P0_12 = p12, + P0_13 = p13, + P0_14 = p14, + P0_15 = p15, + + P0_16 = p16, + P0_17 = p17, + P0_18 = p18, + P0_19 = p19, + P0_20 = p20, + P0_21 = p21, + P0_22 = p22, + P0_23 = p23, + + P0_24 = p24, + P0_25 = p25, + P0_26 = p26, + P0_27 = p27, + P0_28 = p28, + P0_29 = p29, + P0_30 = p30, + P0_31 = p31, + + LED1 = p17, + LED2 = p18, + LED3 = p19, + LED4 = p20, + + BUTTON1 = p13, + BUTTON2 = p14, + BUTTON3 = p15, + BUTTON4 = p16, + + 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, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + STDIO_UART_CTS = CTS_PIN_NUMBER, + STDIO_UART_RTS = RTS_PIN_NUMBER, + + SPI_PSELMOSI0 = p23, + SPI_PSELMISO0 = p24, + SPI_PSELSS0 = p22, + SPI_PSELSCK0 = p25, + + SPI_PSELMOSI1 = p12, + SPI_PSELMISO1 = p13, + SPI_PSELSS1 = p11, + SPI_PSELSCK1 = p14, + + SPIS_PSELMOSI = p12, + SPIS_PSELMISO = p13, + SPIS_PSELSS = p11, + SPIS_PSELSCK = p14, + + I2C_SDA0 = p26, + I2C_SCL0 = p27, + + D0 = p11, + D1 = p12, + D2 = p13, + D3 = p14, + D4 = p15, + D5 = p16, + D6 = p17, + D7 = p18, + + D8 = p19, + D9 = p20, + D10 = p22, + D11 = p23, + D12 = p24, + D13 = p25, + + 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/device.h new file mode 100644 index 0000000000..2427e752ea --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_NRF52_DK/device.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/PinNames.h new file mode 100644 index 0000000000..dd61f6f206 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/PinNames.h @@ -0,0 +1,196 @@ +/* + * 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" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + + P0_0 = p0, + P0_1 = p1, + P0_2 = p2, + P0_3 = p3, + P0_4 = p4, + P0_5 = p5, + P0_6 = p6, + P0_7 = p7, + + P0_8 = p8, + P0_9 = p9, + P0_10 = p10, + P0_11 = p11, + P0_12 = p12, + P0_13 = p13, + P0_14 = p14, + P0_15 = p15, + + P0_16 = p16, + P0_17 = p17, + P0_18 = p18, + P0_19 = p19, + P0_20 = p20, + P0_21 = p21, + P0_22 = p22, + P0_23 = p23, + + P0_24 = p24, + P0_25 = p25, + P0_26 = p26, + P0_27 = p27, + P0_28 = p28, + P0_29 = p29, + P0_30 = p30, + + LED1 = p11, + LED2 = p11, + LED3 = p11, + LED4 = p11, + + RX_PIN_NUMBER = p30, + TX_PIN_NUMBER = p29, + CTS_PIN_NUMBER = p28, + RTS_PIN_NUMBER = p2, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + + // mBed interface Pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER, + + SPI_PSELMOSI0 = p6, + SPI_PSELMISO0 = p7, + SPI_PSELSS0 = p3, + SPI_PSELSCK0 = p8, + + SPI_PSELMOSI1 = p29, + SPI_PSELMISO1 = p30, + SPI_PSELSS1 = p28, + SPI_PSELSCK1 = p2, + + SPIS_PSELMOSI = p29, + SPIS_PSELMISO = p30, + SPIS_PSELSS = p28, + SPIS_PSELSCK = p2, + + I2C_SDA0 = p28, + I2C_SCL0 = p2, + + D0 = p30, + D1 = p29, + D2 = p28, + D3 = p2, + + D4 = p3, + D5 = p6, + D6 = p7, + D7 = p8, + D8 = p21, + + D9 = p4, + D10 = p5, + + D13 = p11, + + A0 = p28, + A1 = p29, + A2 = p30, + A3 = p2, + A4 = p4, + A5 = p5, + + // Not connected + NC = (int)0xFFFFFFFF +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/device.h new file mode 100644 index 0000000000..493844b801 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_RBLAB_BLENANO2/device.h @@ -0,0 +1,23 @@ +// 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/PinNames.h new file mode 100644 index 0000000000..cfb9917ac4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/PinNames.h @@ -0,0 +1,109 @@ +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + // nRF52 pin names + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + NC = (int)0xFFFFFFFF, // Not connected + + //NINA-B1 module pin names + NINA_B1_GPIO_1 = p8, + NINA_B1_GPIO_2 = p11, + NINA_B1_GPIO_3 = p12, + NINA_B1_GPIO_4 = p13, + NINA_B1_GPIO_5 = p14, + NINA_B1_GPIO_7 = p16, + NINA_B1_GPIO_8 = p18, + + NINA_B1_GPIO_16 = p28, + NINA_B1_GPIO_17 = p29, + NINA_B1_GPIO_18 = p30, + + NINA_B1_GPIO_20 = p31, + NINA_B1_GPIO_21 = p7, + NINA_B1_GPIO_22 = p6, + NINA_B1_GPIO_23 = p5, + NINA_B1_GPIO_24 = p2, + NINA_B1_GPIO_25 = p3, + NINA_B1_GPIO_27 = p4, + NINA_B1_GPIO_28 = p9, + NINA_B1_GPIO_29 = p10, + + // Board pins + LED1 = NINA_B1_GPIO_7, // ORANGE + LED2 = NC, + LED3 = NC, + LED4 = NC, + + // Nordic SDK pin names + RX_PIN_NUMBER = p5, + TX_PIN_NUMBER = p6, + CTS_PIN_NUMBER = p7, + RTS_PIN_NUMBER = p31, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + + I2C_SDA0 = p2, + I2C_SCL0 = p3, + + // mBed interface pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} + +#endif +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/device.h new file mode 100644 index 0000000000..493844b801 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVA_NINA/device.h @@ -0,0 +1,23 @@ +// 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/PinNames.h new file mode 100644 index 0000000000..8d83928e45 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/PinNames.h @@ -0,0 +1,131 @@ +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + // nRF52 pin names + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + NC = (int)0xFFFFFFFF, // Not connected + + //NINA-B1 module pin names + NINA_B1_GPIO_1 = p8, + NINA_B1_GPIO_2 = p11, + NINA_B1_GPIO_3 = p12, + NINA_B1_GPIO_4 = p13, + NINA_B1_GPIO_5 = p14, + NINA_B1_GPIO_7 = p16, + NINA_B1_GPIO_8 = p18, + + NINA_B1_GPIO_16 = p28, + NINA_B1_GPIO_17 = p29, + NINA_B1_GPIO_18 = p30, + + NINA_B1_GPIO_20 = p31, + NINA_B1_GPIO_21 = p7, + NINA_B1_GPIO_22 = p6, + NINA_B1_GPIO_23 = p5, + NINA_B1_GPIO_24 = p2, + NINA_B1_GPIO_25 = p3, + NINA_B1_GPIO_27 = p4, + NINA_B1_GPIO_28 = p9, + NINA_B1_GPIO_29 = p10, + + // EVK-NINA-B1 board + LED1 = NINA_B1_GPIO_1, // Red + LED2 = NINA_B1_GPIO_7, // Green/SW1 + LED3 = NINA_B1_GPIO_8, // Blue + LED4 = NINA_B1_GPIO_8, + SW1 = NINA_B1_GPIO_7, + SW2 = NINA_B1_GPIO_18, + D0 = NINA_B1_GPIO_23, + D1 = NINA_B1_GPIO_22, + D2 = NINA_B1_GPIO_21, + D3 = NINA_B1_GPIO_20, + D4 = NINA_B1_GPIO_8, + D5 = NC, // SWDIO + D6 = NINA_B1_GPIO_28, + D7 = NINA_B1_GPIO_29, + D8 = NC, // SWDCLK + D9 = NINA_B1_GPIO_1, + D10 = NINA_B1_GPIO_2, + D11 = NINA_B1_GPIO_4, + D12 = NINA_B1_GPIO_3, + D13 = NINA_B1_GPIO_5, + D14 = NINA_B1_GPIO_24, + D15 = NINA_B1_GPIO_25, + A0 = NINA_B1_GPIO_25, + A1 = NINA_B1_GPIO_24, + A2 = NINA_B1_GPIO_27, + A3 = NINA_B1_GPIO_18, + A4 = NINA_B1_GPIO_17, + A5 = NINA_B1_GPIO_16, + // Nordic SDK pin names + RX_PIN_NUMBER = p5, + TX_PIN_NUMBER = p6, + CTS_PIN_NUMBER = p7, + RTS_PIN_NUMBER = p31, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + STDIO_UART_CTS = CTS_PIN_NUMBER, + STDIO_UART_RTS = RTS_PIN_NUMBER, + I2C_SDA0 = p2, + I2C_SCL0 = p3, + // mBed interface pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/device.h new file mode 100644 index 0000000000..74bc43e66c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_UBLOX_EVK_NINA_B1/device.h @@ -0,0 +1,6 @@ +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +#include "objects.h" + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/PinNames.h new file mode 100644 index 0000000000..bd6fae90bf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/PinNames.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2017 VNG IoT Lab, Vietnam + * 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. + * + */ + +/* + * PinNames for the VBLUno52 board + */ +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 3 + +typedef enum { + p0 = 0, + p1 = 1, + p2 = 2, + p3 = 3, + p4 = 4, + p5 = 5, + p6 = 6, + p7 = 7, + p8 = 8, + p9 = 9, + p10 = 10, + p11 = 11, + p12 = 12, + p13 = 13, + p14 = 14, + p15 = 15, + p16 = 16, + p17 = 17, + p18 = 18, + p19 = 19, + p20 = 20, + p21 = 21, + p22 = 22, + p23 = 23, + p24 = 24, + p25 = 25, + p26 = 26, + p27 = 27, + p28 = 28, + p29 = 29, + p30 = 30, + p31 = 31, + + P0_0 = p0, + P0_1 = p1, + P0_2 = p2, + P0_3 = p3, + P0_4 = p4, + P0_5 = p5, + P0_6 = p6, + P0_7 = p7, + + P0_8 = p8, + P0_9 = p9, + P0_10 = p10, + P0_11 = p11, + P0_12 = p12, + P0_13 = p13, + P0_14 = p14, + P0_15 = p15, + + P0_16 = p16, + P0_17 = p17, + P0_18 = p18, + P0_19 = p19, + P0_20 = p20, + P0_21 = p21, + P0_22 = p22, + P0_23 = p23, + + P0_24 = p24, + P0_25 = p25, + P0_26 = p26, + P0_27 = p27, + P0_28 = p28, + P0_29 = p29, + P0_30 = p30, + P0_31 = p31, + + //only for mbed test suite + LED1 = p12, + LED2 = p18, + LED3 = p19, + LED4 = p20, + + //only for mbed test suite + BUTTON1 = p17, + BUTTON2 = p3, + BUTTON3 = p4, + BUTTON4 = p28, + + RX_PIN_NUMBER = p8, + TX_PIN_NUMBER = p6, + CTS_PIN_NUMBER = p7, //not on Header + RTS_PIN_NUMBER = p5, //not on Header + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + STDIO_UART_CTS = CTS_PIN_NUMBER, + STDIO_UART_RTS = RTS_PIN_NUMBER, + + // mBed interface Pins + USBTX = TX_PIN_NUMBER, + USBRX = RX_PIN_NUMBER, + + SPI_PSELMOSI0 = p13, + SPI_PSELMISO0 = p14, + SPI_PSELSS0 = p11, + SPI_PSELSCK0 = p15, + + SPI_PSELMOSI1 = p13, + SPI_PSELMISO1 = p14, + SPI_PSELSS1 = p11, + SPI_PSELSCK1 = p15, + + SPIS_PSELMOSI = p13, + SPIS_PSELMISO = p14, + SPIS_PSELSS = p11, + SPIS_PSELSCK = p15, + + I2C_SDA = p26, + I2C_SCL = p27, + + I2C_SDA0 = p26, + I2C_SCL0 = p27, + + I2C_SDA1 = p30, + I2C_SCL1 = p31, + + RESET = p21, + + NFC1 = p9, + NFC2 = p10, + + //Adruino interface pins + D0 = p8, + D1 = p6, + D2 = p24, + D3 = p23, + D4 = p22, + D5 = p18, + D6 = p19, + D7 = p20, + + D8 = p9, + D9 = p10, + D10 = p11, + D11 = p13, + D12 = p14, + D13 = p15, + + D14 = p3, + D15 = p4, + D16 = p28, + D17 = p29, + D18 = p30, + D19 = p31, + + D20 = p26, + D21 = p27, + + D22 = p12, + D23 = p17, + + D24 = p5, + D25 = p7, + + A0 = D14, + A1 = D15, + A2 = D16, + A3 = D17, + A4 = D18, + A5 = D19, + + SS = D10, + MOSI = D11, + MISO = D12, + SCK = D13, + + SDA0 = D20, + SCL0 = D21, + SDA1 = D18, + SCL1 = D19, + SDA = SDA0, + SCL = SCL0, + + RX = D0, + TX = D1, + RTS = D24, //not on Header + CTS = D25, //not on Header + + LED = D22, //not on Header + BUT = D23, //not on Header + + // Not connected + NC = (int)0xFFFFFFFF +} PinName; + +typedef enum { + PullNone = 0, + PullDown = 1, + PullUp = 3, + PullDefault = PullUp +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/device.h new file mode 100644 index 0000000000..493844b801 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/TARGET_VBLUNO52/device.h @@ -0,0 +1,23 @@ +// 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/config/sdk_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/config/sdk_config.h new file mode 100644 index 0000000000..89a3a962ef --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/config/sdk_config.h @@ -0,0 +1,8744 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// Board Support + +//========================================================== +// BSP_BTN_BLE_ENABLED - bsp_btn_ble - Button Control for BLE + + +#ifndef BSP_BTN_BLE_ENABLED +#define BSP_BTN_BLE_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_ANT + +//========================================================== +// ANTFS_ENABLED - ant_fs - ANT File Share module. +//========================================================== +#ifndef ANTFS_ENABLED +#define ANTFS_ENABLED 0 +#endif +// ANTFS_CONFIG_NETWORK_NUMBER - ANT-FS network number. +#ifndef ANTFS_CONFIG_NETWORK_NUMBER +#define ANTFS_CONFIG_NETWORK_NUMBER 0 +#endif + +// ANTFS_CONFIG_CHANNEL_NUMBER - ANT-FS channel number. +#ifndef ANTFS_CONFIG_CHANNEL_NUMBER +#define ANTFS_CONFIG_CHANNEL_NUMBER 0 +#endif + +// ANTFS_CONFIG_PAIRING_TIMEOUT - Pairing timeout - how long the UI will wait for a response to a pairing request before switching to the link layer, in seconds. +#ifndef ANTFS_CONFIG_PAIRING_TIMEOUT +#define ANTFS_CONFIG_PAIRING_TIMEOUT 120 +#endif + +// ANTFS_CONFIG_LINK_COMMAND_TIMEOUT - Command timeout - how long the client will wait without receiving any commands before switching to the link layer, in seconds. +#ifndef ANTFS_CONFIG_LINK_COMMAND_TIMEOUT +#define ANTFS_CONFIG_LINK_COMMAND_TIMEOUT 10 +#endif + +// ANTFS_CONFIG_TRANS_TYPE - ANT-FS Transmission Type. +#ifndef ANTFS_CONFIG_TRANS_TYPE +#define ANTFS_CONFIG_TRANS_TYPE 10 +#endif + +// ANTFS_CONFIG_DEVICE_TYPE - ANT device type for channel configuration. +#ifndef ANTFS_CONFIG_DEVICE_TYPE +#define ANTFS_CONFIG_DEVICE_TYPE 1 +#endif + +// ANTFS_CONFIG_BEACON_STATUS_PERIOD - ANT-FS Beacon Message Period. + +// <0=> 0.5 Hz +// <1=> 1 Hz +// <2=> 2 Hz +// <3=> 4 Hz +// <4=> 8 Hz + +#ifndef ANTFS_CONFIG_BEACON_STATUS_PERIOD +#define ANTFS_CONFIG_BEACON_STATUS_PERIOD 3 +#endif + +// ANTFS_CONFIG_TRANSMIT_POWER - ANT Transmit Power. + +// <0=> Lowest ANT Tx power level setting. (-20dBm) +// <1=> ANT Tx power > Lvl 0. (-12dBm) +// <2=> ANT Tx power > Lvl 1. (-4dBm) +// <3=> ANT Tx power > Lvl 2. Default tx power level. (0dBm) +// <4=> ANT Tx power > Lvl 3. (+4dBm) +// <128=> Custom tx power selection + +#ifndef ANTFS_CONFIG_TRANSMIT_POWER +#define ANTFS_CONFIG_TRANSMIT_POWER 3 +#endif + +// ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER - ANT Custom Transmit Power. +#ifndef ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER +#define ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED - Use pairing and key exchange authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED - Use passkey authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED - Allow host to bypass authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED 0 +#endif + +// ANTFS_CONFIG_UPLOAD_ENABLED - Support upload operation. + + +#ifndef ANTFS_CONFIG_UPLOAD_ENABLED +#define ANTFS_CONFIG_UPLOAD_ENABLED 0 +#endif + +// ANTFS_CONFIG_DEBUG_LED_ENABLED - Enables LED debug in the module. + + +#ifndef ANTFS_CONFIG_DEBUG_LED_ENABLED +#define ANTFS_CONFIG_DEBUG_LED_ENABLED 0 +#endif + +// + +// ANT_BPWR_ENABLED - ant_bpwr - Bicycle Power Profile +//========================================================== +#ifndef ANT_BPWR_ENABLED +#define ANT_BPWR_ENABLED 0 +#endif +// ANT_BPWR_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_BPWR_LOG_ENABLED +#define ANT_BPWR_LOG_ENABLED 0 +#endif +// ANT_BPWR_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_LOG_LEVEL +#define ANT_BPWR_LOG_LEVEL 3 +#endif + +// ANT_BPWR_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_INFO_COLOR +#define ANT_BPWR_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_COMMON_LOG_ENABLED - Enables logging of BPWR tracing common data. +//========================================================== +#ifndef ANT_BPWR_COMMON_LOG_ENABLED +#define ANT_BPWR_COMMON_LOG_ENABLED 0 +#endif +// ANT_BPWR_COMMON_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_COMMON_LOG_LEVEL +#define ANT_BPWR_COMMON_LOG_LEVEL 3 +#endif + +// ANT_BPWR_COMMON_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_COMMON_INFO_COLOR +#define ANT_BPWR_COMMON_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_TORQUE_LOG_ENABLED - Enables logging of BPWR torque page in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_TORQUE_LOG_ENABLED +#define ANT_BPWR_PAGE_TORQUE_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_TORQUE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_TORQUE_LOG_LEVEL +#define ANT_BPWR_PAGE_TORQUE_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_TORQUE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_TORQUE_INFO_COLOR +#define ANT_BPWR_PAGE_TORQUE_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_1_LOG_ENABLED - Enables logging of BPWR page 1 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_1_LOG_ENABLED +#define ANT_BPWR_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_1_LOG_LEVEL +#define ANT_BPWR_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_1_INFO_COLOR +#define ANT_BPWR_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_16_LOG_ENABLED - Enables logging of BPWR page 16 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_16_LOG_ENABLED +#define ANT_BPWR_PAGE_16_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_16_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_16_LOG_LEVEL +#define ANT_BPWR_PAGE_16_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_16_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_16_INFO_COLOR +#define ANT_BPWR_PAGE_16_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_17_LOG_ENABLED - Enables logging of BPWR page 17 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_17_LOG_ENABLED +#define ANT_BPWR_PAGE_17_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_17_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_17_LOG_LEVEL +#define ANT_BPWR_PAGE_17_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_17_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_17_INFO_COLOR +#define ANT_BPWR_PAGE_17_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_18_LOG_ENABLED - Enables logging of BPWR page 18 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_18_LOG_ENABLED +#define ANT_BPWR_PAGE_18_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_18_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_18_LOG_LEVEL +#define ANT_BPWR_PAGE_18_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_18_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_18_INFO_COLOR +#define ANT_BPWR_PAGE_18_INFO_COLOR 0 +#endif + +// + +// + +// ANT_BSC_ENABLED - ant_bsc - Bicycle Speed and Cadence Profile +//========================================================== +#ifndef ANT_BSC_ENABLED +#define ANT_BSC_ENABLED 0 +#endif +// ANT_BSC_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_BSC_LOG_ENABLED +#define ANT_BSC_LOG_ENABLED 0 +#endif +// ANT_BSC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_LOG_LEVEL +#define ANT_BSC_LOG_LEVEL 3 +#endif + +// ANT_BSC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_INFO_COLOR +#define ANT_BSC_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED - Enables logging of BSC Combined page 0 in the module. +//========================================================== +#ifndef ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED +#define ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL +#define ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_BSC_COMBINED_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_COMBINED_PAGE_0_INFO_COLOR +#define ANT_BSC_COMBINED_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_0_LOG_ENABLED - Enables logging of BSC page 0 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_0_LOG_ENABLED +#define ANT_BSC_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_0_LOG_LEVEL +#define ANT_BSC_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_0_INFO_COLOR +#define ANT_BSC_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_1_LOG_ENABLED - Enables logging of BSC page 1 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_1_LOG_ENABLED +#define ANT_BSC_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_1_LOG_LEVEL +#define ANT_BSC_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_1_INFO_COLOR +#define ANT_BSC_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_2_LOG_ENABLED - Enables logging of BSC page 2 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_2_LOG_ENABLED +#define ANT_BSC_PAGE_2_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_2_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_2_LOG_LEVEL +#define ANT_BSC_PAGE_2_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_2_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_2_INFO_COLOR +#define ANT_BSC_PAGE_2_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_3_LOG_ENABLED - Enables logging of BSC page 3 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_3_LOG_ENABLED +#define ANT_BSC_PAGE_3_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_3_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_3_LOG_LEVEL +#define ANT_BSC_PAGE_3_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_3_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_3_INFO_COLOR +#define ANT_BSC_PAGE_3_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_4_LOG_ENABLED - Enables logging of BSC page 4 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_4_LOG_ENABLED +#define ANT_BSC_PAGE_4_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_4_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_4_LOG_LEVEL +#define ANT_BSC_PAGE_4_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_4_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_4_INFO_COLOR +#define ANT_BSC_PAGE_4_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_5_LOG_ENABLED - Enables logging of BSC page 5 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_5_LOG_ENABLED +#define ANT_BSC_PAGE_5_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_5_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_5_LOG_LEVEL +#define ANT_BSC_PAGE_5_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_5_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_5_INFO_COLOR +#define ANT_BSC_PAGE_5_INFO_COLOR 0 +#endif + +// + +// + +// ANT_CHANNEL_CONFIG_ENABLED - ant_channel_config - ANT common channel configuration + + +#ifndef ANT_CHANNEL_CONFIG_ENABLED +#define ANT_CHANNEL_CONFIG_ENABLED 0 +#endif + +// ANT_COMMON_PAGE_70_ENABLED - ant_common_page_70 - ANT+ common page 70 +//========================================================== +#ifndef ANT_COMMON_PAGE_70_ENABLED +#define ANT_COMMON_PAGE_70_ENABLED 0 +#endif +// ANT_COMMON_PAGE_70_LOG_ENABLED - Enables logging of common page 70 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_70_LOG_ENABLED +#define ANT_COMMON_PAGE_70_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_70_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_70_LOG_LEVEL +#define ANT_COMMON_PAGE_70_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_70_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_70_INFO_COLOR +#define ANT_COMMON_PAGE_70_INFO_COLOR 0 +#endif + +// + +// + +// ANT_COMMON_PAGE_80_ENABLED - ant_common_page_80 - ANT+ common page 80 +//========================================================== +#ifndef ANT_COMMON_PAGE_80_ENABLED +#define ANT_COMMON_PAGE_80_ENABLED 0 +#endif +// ANT_COMMON_PAGE_80_LOG_ENABLED - Enables logging of common page 80 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_80_LOG_ENABLED +#define ANT_COMMON_PAGE_80_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_80_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_80_LOG_LEVEL +#define ANT_COMMON_PAGE_80_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_80_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_80_INFO_COLOR +#define ANT_COMMON_PAGE_80_INFO_COLOR 0 +#endif + +// + +// + +// ANT_COMMON_PAGE_81_ENABLED - ant_common_page_81 - ANT+ common page 81 +//========================================================== +#ifndef ANT_COMMON_PAGE_81_ENABLED +#define ANT_COMMON_PAGE_81_ENABLED 0 +#endif +// ANT_COMMON_PAGE_81_LOG_ENABLED - Enables logging of common page 81 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_81_LOG_ENABLED +#define ANT_COMMON_PAGE_81_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_81_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_81_LOG_LEVEL +#define ANT_COMMON_PAGE_81_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_81_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_81_INFO_COLOR +#define ANT_COMMON_PAGE_81_INFO_COLOR 0 +#endif + +// + +// + +// ANT_ENCRYPT_CONFIG_ENABLED - ant_encrypt_config - Cryptographic ANT stack configuration + + +#ifndef ANT_ENCRYPT_CONFIG_ENABLED +#define ANT_ENCRYPT_CONFIG_ENABLED 0 +#endif + +// ANT_HRM_ENABLED - ant_hrm - Heart Rate Monitor Profile +//========================================================== +#ifndef ANT_HRM_ENABLED +#define ANT_HRM_ENABLED 0 +#endif +// ANT_HRM_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_HRM_LOG_ENABLED +#define ANT_HRM_LOG_ENABLED 0 +#endif +// ANT_HRM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_LOG_LEVEL +#define ANT_HRM_LOG_LEVEL 3 +#endif + +// ANT_HRM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_INFO_COLOR +#define ANT_HRM_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_0_LOG_ENABLED - Enables logging of HRM page 0 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_0_LOG_ENABLED +#define ANT_HRM_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_0_LOG_LEVEL +#define ANT_HRM_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_0_INFO_COLOR +#define ANT_HRM_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_1_LOG_ENABLED - Enables logging of HRM page 1 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_1_LOG_ENABLED +#define ANT_HRM_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_1_LOG_LEVEL +#define ANT_HRM_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_1_INFO_COLOR +#define ANT_HRM_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_2_LOG_ENABLED - Enables logging of HRM page 2 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_2_LOG_ENABLED +#define ANT_HRM_PAGE_2_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_2_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_2_LOG_LEVEL +#define ANT_HRM_PAGE_2_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_2_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_2_INFO_COLOR +#define ANT_HRM_PAGE_2_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_3_LOG_ENABLED - Enables logging of HRM page 3 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_3_LOG_ENABLED +#define ANT_HRM_PAGE_3_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_3_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_3_LOG_LEVEL +#define ANT_HRM_PAGE_3_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_3_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_3_INFO_COLOR +#define ANT_HRM_PAGE_3_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_4_LOG_ENABLED - Enables logging of HRM page 4 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_4_LOG_ENABLED +#define ANT_HRM_PAGE_4_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_4_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_4_LOG_LEVEL +#define ANT_HRM_PAGE_4_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_4_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_4_INFO_COLOR +#define ANT_HRM_PAGE_4_INFO_COLOR 0 +#endif + +// + +// + +// ANT_KEY_MANAGER_ENABLED - ant_key_manager - Software Component + + +#ifndef ANT_KEY_MANAGER_ENABLED +#define ANT_KEY_MANAGER_ENABLED 0 +#endif + +// ANT_REQUEST_CONTROLLER_ENABLED - ant_request_controller - ANT+ request controller + + +#ifndef ANT_REQUEST_CONTROLLER_ENABLED +#define ANT_REQUEST_CONTROLLER_ENABLED 0 +#endif + +// ANT_SDM_ENABLED - ant_sdm - Stride Based Speed and Distance Monitor Profile +//========================================================== +#ifndef ANT_SDM_ENABLED +#define ANT_SDM_ENABLED 0 +#endif +// ANT_SDM_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_SDM_LOG_ENABLED +#define ANT_SDM_LOG_ENABLED 0 +#endif +// ANT_SDM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_SDM_LOG_LEVEL +#define ANT_SDM_LOG_LEVEL 3 +#endif + +// ANT_SDM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_SDM_INFO_COLOR +#define ANT_SDM_INFO_COLOR 0 +#endif + +// + +// + +// ANT_SEARCH_CONFIG_ENABLED - ant_search_config - ANT common search configuration +//========================================================== +#ifndef ANT_SEARCH_CONFIG_ENABLED +#define ANT_SEARCH_CONFIG_ENABLED 0 +#endif +// ANT_DEFAULT_LOW_PRIORITY_TIMEOUT - Default low priority search time-out. <0-255> + + +#ifndef ANT_DEFAULT_LOW_PRIORITY_TIMEOUT +#define ANT_DEFAULT_LOW_PRIORITY_TIMEOUT 2 +#endif + +// ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT - Default high priority search time-out. <0-255> + + +#ifndef ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT +#define ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT 10 +#endif + +// + +// ANT_STACK_CONFIG_ENABLED - ant_stack_config - Common ANT stack configuration +//========================================================== +#ifndef ANT_STACK_CONFIG_ENABLED +#define ANT_STACK_CONFIG_ENABLED 0 +#endif +// ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED - Allocated ANT channels +#ifndef ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED +#define ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED 0 +#endif + +// ANT_CONFIG_ENCRYPTED_CHANNELS - Encrypted ANT channels +#ifndef ANT_CONFIG_ENCRYPTED_CHANNELS +#define ANT_CONFIG_ENCRYPTED_CHANNELS 0 +#endif + +// ANT_CONFIG_EVENT_QUEUE_SIZE - Event queue size +#ifndef ANT_CONFIG_EVENT_QUEUE_SIZE +#define ANT_CONFIG_EVENT_QUEUE_SIZE 32 +#endif + +// ANT_CONFIG_BURST_QUEUE_SIZE - ANT burst queue size +#ifndef ANT_CONFIG_BURST_QUEUE_SIZE +#define ANT_CONFIG_BURST_QUEUE_SIZE 128 +#endif + +// + +// ANT_STATE_INDICATOR_ENABLED - ant_state_indicator - ANT state indicator using BSP +//========================================================== +#ifndef ANT_STATE_INDICATOR_ENABLED +#define ANT_STATE_INDICATOR_ENABLED 0 +#endif +// ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY - Shutdown observer priority. +#ifndef ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY +#define ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY 1 +#endif + +// + +// +//========================================================== + +// nRF_BLE + +//========================================================== +// BLE_ADVERTISING_ENABLED - ble_advertising - Advertising module + + +#ifndef BLE_ADVERTISING_ENABLED +#define BLE_ADVERTISING_ENABLED 0 +#endif + +// BLE_DTM_ENABLED - ble_dtm - Module for testing RF/PHY using DTM commands + + +#ifndef BLE_DTM_ENABLED +#define BLE_DTM_ENABLED 0 +#endif + +// BLE_RACP_ENABLED - ble_racp - Record Access Control Point library + + +#ifndef BLE_RACP_ENABLED +#define BLE_RACP_ENABLED 0 +#endif + +// NRF_BLE_CONN_PARAMS_ENABLED - ble_conn_params - Initiating and executing a connection parameters negotiation procedure +//========================================================== +#ifndef NRF_BLE_CONN_PARAMS_ENABLED +#define NRF_BLE_CONN_PARAMS_ENABLED 0 +#endif +// NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION - The largest acceptable deviation in slave latency. +// The largest deviation (+ or -) from the requested slave latency that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION 499 +#endif + +// NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION - The largest acceptable deviation (in 10 ms units) in supervision timeout. +// The largest deviation (+ or -, in 10 ms units) from the requested supervision timeout that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION 65535 +#endif + +// + +// NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write) + + +#ifndef NRF_BLE_QWR_ENABLED +#define NRF_BLE_QWR_ENABLED 0 +#endif + +// PEER_MANAGER_ENABLED - peer_manager - Peer Manager +//========================================================== +#ifndef PEER_MANAGER_ENABLED +#define PEER_MANAGER_ENABLED 0 +#endif +// PM_MAX_REGISTRANTS +// Number of event handlers that can be registered. + +#ifndef PM_MAX_REGISTRANTS +#define PM_MAX_REGISTRANTS 3 +#endif + +// PM_FLASH_BUFFERS +// Number of internal buffers for flash operations. +// Decrease this value to lower RAM usage. + +#ifndef PM_FLASH_BUFFERS +#define PM_FLASH_BUFFERS 8 +#endif + +// + +// +//========================================================== + +// nRF_BLE_Services + +//========================================================== +// BLE_ANCS_C_ENABLED - ble_ancs_c - Apple Notification Service Client + + +#ifndef BLE_ANCS_C_ENABLED +#define BLE_ANCS_C_ENABLED 0 +#endif + +// BLE_ANS_C_ENABLED - ble_ans_c - Alert Notification Service Client + + +#ifndef BLE_ANS_C_ENABLED +#define BLE_ANS_C_ENABLED 0 +#endif + +// BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client + + +#ifndef BLE_BAS_C_ENABLED +#define BLE_BAS_C_ENABLED 0 +#endif + +// BLE_BAS_ENABLED - ble_bas - Battery Service + + +#ifndef BLE_BAS_ENABLED +#define BLE_BAS_ENABLED 0 +#endif + +// BLE_CSCS_ENABLED - ble_cscs - Cycling Speed and Cadence Service + + +#ifndef BLE_CSCS_ENABLED +#define BLE_CSCS_ENABLED 0 +#endif + +// BLE_CTS_C_ENABLED - ble_cts_c - Current Time Service Client + + +#ifndef BLE_CTS_C_ENABLED +#define BLE_CTS_C_ENABLED 0 +#endif + +// BLE_DIS_ENABLED - ble_dis - Device Information Service + + +#ifndef BLE_DIS_ENABLED +#define BLE_DIS_ENABLED 0 +#endif + +// BLE_GLS_ENABLED - ble_gls - Glucose Service + + +#ifndef BLE_GLS_ENABLED +#define BLE_GLS_ENABLED 0 +#endif + +// BLE_HIDS_ENABLED - ble_hids - Human Interface Device Service + + +#ifndef BLE_HIDS_ENABLED +#define BLE_HIDS_ENABLED 0 +#endif + +// BLE_HRS_C_ENABLED - ble_hrs_c - Heart Rate Service Client + + +#ifndef BLE_HRS_C_ENABLED +#define BLE_HRS_C_ENABLED 0 +#endif + +// BLE_HRS_ENABLED - ble_hrs - Heart Rate Service + + +#ifndef BLE_HRS_ENABLED +#define BLE_HRS_ENABLED 0 +#endif + +// BLE_HTS_ENABLED - ble_hts - Health Thermometer Service + + +#ifndef BLE_HTS_ENABLED +#define BLE_HTS_ENABLED 0 +#endif + +// BLE_IAS_C_ENABLED - ble_ias_c - Immediate Alert Service Client + + +#ifndef BLE_IAS_C_ENABLED +#define BLE_IAS_C_ENABLED 0 +#endif + +// BLE_IAS_ENABLED - ble_ias - Immediate Alert Service + + +#ifndef BLE_IAS_ENABLED +#define BLE_IAS_ENABLED 0 +#endif + +// BLE_LBS_C_ENABLED - ble_lbs_c - Nordic LED Button Service Client + + +#ifndef BLE_LBS_C_ENABLED +#define BLE_LBS_C_ENABLED 0 +#endif + +// BLE_LBS_ENABLED - ble_lbs - LED Button Service + + +#ifndef BLE_LBS_ENABLED +#define BLE_LBS_ENABLED 0 +#endif + +// BLE_LLS_ENABLED - ble_lls - Link Loss Service + + +#ifndef BLE_LLS_ENABLED +#define BLE_LLS_ENABLED 0 +#endif + +// BLE_NUS_C_ENABLED - ble_nus_c - Nordic UART Central Service + + +#ifndef BLE_NUS_C_ENABLED +#define BLE_NUS_C_ENABLED 0 +#endif + +// BLE_NUS_ENABLED - ble_nus - Nordic UART Service + + +#ifndef BLE_NUS_ENABLED +#define BLE_NUS_ENABLED 0 +#endif + +// BLE_RSCS_C_ENABLED - ble_rscs_c - Running Speed and Cadence Client + + +#ifndef BLE_RSCS_C_ENABLED +#define BLE_RSCS_C_ENABLED 0 +#endif + +// BLE_RSCS_ENABLED - ble_rscs - Running Speed and Cadence Service + + +#ifndef BLE_RSCS_ENABLED +#define BLE_RSCS_ENABLED 0 +#endif + +// BLE_TPS_ENABLED - ble_tps - TX Power Service + + +#ifndef BLE_TPS_ENABLED +#define BLE_TPS_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Core + +//========================================================== +// NRF_MPU_ENABLED - nrf_mpu - Module for MPU +//========================================================== +#ifndef NRF_MPU_ENABLED +#define NRF_MPU_ENABLED 0 +#endif +// NRF_MPU_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_MPU_CLI_CMDS +#define NRF_MPU_CLI_CMDS 1 +#endif + +// + +// NRF_STACK_GUARD_ENABLED - nrf_stack_guard - Module for Protecting Stack +//========================================================== +#ifndef NRF_STACK_GUARD_ENABLED +#define NRF_STACK_GUARD_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_SIZE - Size of stack guard + +// <5=> 32 bytes +// <6=> 64 bytes +// <7=> 128 bytes +// <8=> 256 bytes +// <9=> 512 bytes +// <10=> 1024 bytes +// <11=> 2048 bytes +// <12=> 4096 bytes + +#ifndef NRF_STACK_GUARD_CONFIG_SIZE +#define NRF_STACK_GUARD_CONFIG_SIZE 7 +#endif + +// + +// +//========================================================== + +// nRF_Crypto + +//========================================================== +// NRF_CRYPTO_ENABLED - nrf_crypto - Cryptography library +//========================================================== +#ifndef NRF_CRYPTO_ENABLED +#define NRF_CRYPTO_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_LIB - Enable the ARM Cryptocell CC310 backend + + +// The hardware-accelerated cryptography backend is available only on nRF52840. + +#ifndef NRF_CRYPTO_BACKEND_CC310_LIB +#define NRF_CRYPTO_BACKEND_CC310_LIB 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC - Enable the micro-ecc software backend + +// The micro-ecc library provides a software implementation of ECC cryptography for nRF5 Series devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC +#define NRF_CRYPTO_BACKEND_MICRO_ECC 0 +#endif +// NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 - Enable SHA256 + + +// Enable SHA256 cryptographic hash functionality. +// Enable this setting if you need SHA256 support, for example to verify signatures. + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 +#define NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_RNG - Enable random number generator + + +// Enable random number generation. +// Enable this setting if you need to generate cryptographic keys. +// This setting requires the RNG peripheral driver to be present. + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_RNG +#define NRF_CRYPTO_BACKEND_MICRO_ECC_RNG 0 +#endif + +// + +// + +// +//========================================================== + +// nRF_DFU + +//========================================================== +// ble_dfu - Device Firmware Update + +//========================================================== +// BLE_DFU_ENABLED - Enable DFU Service. + + +#ifndef BLE_DFU_ENABLED +#define BLE_DFU_ENABLED 0 +#endif + +// NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS - Buttonless DFU supports bonds. + + +#ifndef NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS +#define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Drivers + +//========================================================== +// APP_USBD_ENABLED - app_usbd - USB Device library +//========================================================== +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 0 +#endif +// APP_USBD_VID - Vendor ID <0x0000-0xFFFF> + + +// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ + +#ifndef APP_USBD_VID +#define APP_USBD_VID 0 +#endif + +// APP_USBD_PID - Product ID <0x0000-0xFFFF> + + +// Selected Product ID + +#ifndef APP_USBD_PID +#define APP_USBD_PID 0 +#endif + +// APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MAJOR +#define APP_USBD_DEVICE_VER_MAJOR 1 +#endif + +// APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MINOR +#define APP_USBD_DEVICE_VER_MINOR 0 +#endif + +// APP_USBD_EVENT_QUEUE_ENABLE - Enable event queue + +// This is the default configuration when all the events are placed into internal queue. +// Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts. +// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. +// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable and disable. +//========================================================== +#ifndef APP_USBD_EVENT_QUEUE_ENABLE +#define APP_USBD_EVENT_QUEUE_ENABLE 1 +#endif +// APP_USBD_EVENT_QUEUE_SIZE - The size of event queue <16-64> + + +// The size of the queue for the events that would be processed in the main loop. + +#ifndef APP_USBD_EVENT_QUEUE_SIZE +#define APP_USBD_EVENT_QUEUE_SIZE 32 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CONFIG_LOG_LEVEL +#define APP_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_INFO_COLOR +#define APP_USBD_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_DEBUG_COLOR +#define APP_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver +//========================================================== +#ifndef CLOCK_ENABLED +#define CLOCK_ENABLED 0 +#endif +// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency + +// <0=> Default (64 MHz) + +#ifndef CLOCK_CONFIG_XTAL_FREQ +#define CLOCK_CONFIG_XTAL_FREQ 0 +#endif + +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// COMP_ENABLED - nrf_drv_comp - COMP peripheral driver +//========================================================== +#ifndef COMP_ENABLED +#define COMP_ENABLED 0 +#endif +// COMP_CONFIG_REF - Reference voltage + +// <0=> Internal 1.2V +// <1=> Internal 1.8V +// <2=> Internal 2.4V +// <4=> VDD +// <7=> ARef + +#ifndef COMP_CONFIG_REF +#define COMP_CONFIG_REF 1 +#endif + +// COMP_CONFIG_MAIN_MODE - Main mode + +// <0=> Single ended +// <1=> Differential + +#ifndef COMP_CONFIG_MAIN_MODE +#define COMP_CONFIG_MAIN_MODE 0 +#endif + +// COMP_CONFIG_SPEED_MODE - Speed mode + +// <0=> Low power +// <1=> Normal +// <2=> High speed + +#ifndef COMP_CONFIG_SPEED_MODE +#define COMP_CONFIG_SPEED_MODE 2 +#endif + +// COMP_CONFIG_HYST - Hystheresis + +// <0=> No +// <1=> 50mV + +#ifndef COMP_CONFIG_HYST +#define COMP_CONFIG_HYST 0 +#endif + +// COMP_CONFIG_ISOURCE - Current Source + +// <0=> Off +// <1=> 2.5 uA +// <2=> 5 uA +// <3=> 10 uA + +#ifndef COMP_CONFIG_ISOURCE +#define COMP_CONFIG_ISOURCE 0 +#endif + +// COMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_INPUT +#define COMP_CONFIG_INPUT 0 +#endif + +// COMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_IRQ_PRIORITY +#define COMP_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// EGU_ENABLED - nrf_drv_swi - SWI(EGU) peripheral driver + + +#ifndef EGU_ENABLED +#define EGU_ENABLED 0 +#endif + +// GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver +//========================================================== +#ifndef GPIOTE_ENABLED +#define GPIOTE_ENABLED 1 +#endif +// GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins +#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +// GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef GPIOTE_CONFIG_IRQ_PRIORITY +#define GPIOTE_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// I2S_ENABLED - nrf_drv_i2s - I2S peripheral driver +//========================================================== +#ifndef I2S_ENABLED +#define I2S_ENABLED 0 +#endif +// I2S_CONFIG_SCK_PIN - SCK pin <0-31> + + +#ifndef I2S_CONFIG_SCK_PIN +#define I2S_CONFIG_SCK_PIN 31 +#endif + +// I2S_CONFIG_LRCK_PIN - LRCK pin <1-31> + + +#ifndef I2S_CONFIG_LRCK_PIN +#define I2S_CONFIG_LRCK_PIN 30 +#endif + +// I2S_CONFIG_MCK_PIN - MCK pin +#ifndef I2S_CONFIG_MCK_PIN +#define I2S_CONFIG_MCK_PIN 255 +#endif + +// I2S_CONFIG_SDOUT_PIN - SDOUT pin <0-31> + + +#ifndef I2S_CONFIG_SDOUT_PIN +#define I2S_CONFIG_SDOUT_PIN 29 +#endif + +// I2S_CONFIG_SDIN_PIN - SDIN pin <0-31> + + +#ifndef I2S_CONFIG_SDIN_PIN +#define I2S_CONFIG_SDIN_PIN 28 +#endif + +// I2S_CONFIG_MASTER - Mode + +// <0=> Master +// <1=> Slave + +#ifndef I2S_CONFIG_MASTER +#define I2S_CONFIG_MASTER 0 +#endif + +// I2S_CONFIG_FORMAT - Format + +// <0=> I2S +// <1=> Aligned + +#ifndef I2S_CONFIG_FORMAT +#define I2S_CONFIG_FORMAT 0 +#endif + +// I2S_CONFIG_ALIGN - Alignment + +// <0=> Left +// <1=> Right + +#ifndef I2S_CONFIG_ALIGN +#define I2S_CONFIG_ALIGN 0 +#endif + +// I2S_CONFIG_SWIDTH - Sample width (bits) + +// <0=> 8 +// <1=> 16 +// <2=> 24 + +#ifndef I2S_CONFIG_SWIDTH +#define I2S_CONFIG_SWIDTH 1 +#endif + +// I2S_CONFIG_CHANNELS - Channels + +// <0=> Stereo +// <1=> Left +// <2=> Right + +#ifndef I2S_CONFIG_CHANNELS +#define I2S_CONFIG_CHANNELS 1 +#endif + +// I2S_CONFIG_MCK_SETUP - MCK behavior + +// <0=> Disabled +// <2147483648=> 32MHz/2 +// <1342177280=> 32MHz/3 +// <1073741824=> 32MHz/4 +// <805306368=> 32MHz/5 +// <671088640=> 32MHz/6 +// <536870912=> 32MHz/8 +// <402653184=> 32MHz/10 +// <369098752=> 32MHz/11 +// <285212672=> 32MHz/15 +// <268435456=> 32MHz/16 +// <201326592=> 32MHz/21 +// <184549376=> 32MHz/23 +// <142606336=> 32MHz/30 +// <138412032=> 32MHz/31 +// <134217728=> 32MHz/32 +// <100663296=> 32MHz/42 +// <68157440=> 32MHz/63 +// <34340864=> 32MHz/125 + +#ifndef I2S_CONFIG_MCK_SETUP +#define I2S_CONFIG_MCK_SETUP 536870912 +#endif + +// I2S_CONFIG_RATIO - MCK/LRCK ratio + +// <0=> 32x +// <1=> 48x +// <2=> 64x +// <3=> 96x +// <4=> 128x +// <5=> 192x +// <6=> 256x +// <7=> 384x +// <8=> 512x + +#ifndef I2S_CONFIG_RATIO +#define I2S_CONFIG_RATIO 2000 +#endif + +// I2S_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef I2S_CONFIG_IRQ_PRIORITY +#define I2S_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// LPCOMP_ENABLED - nrf_drv_lpcomp - LPCOMP peripheral driver +//========================================================== +#ifndef LPCOMP_ENABLED +#define LPCOMP_ENABLED 0 +#endif +// LPCOMP_CONFIG_REFERENCE - Reference voltage + +// <0=> Supply 1/8 +// <1=> Supply 2/8 +// <2=> Supply 3/8 +// <3=> Supply 4/8 +// <4=> Supply 5/8 +// <5=> Supply 6/8 +// <6=> Supply 7/8 +// <8=> Supply 1/16 (nRF52) +// <9=> Supply 3/16 (nRF52) +// <10=> Supply 5/16 (nRF52) +// <11=> Supply 7/16 (nRF52) +// <12=> Supply 9/16 (nRF52) +// <13=> Supply 11/16 (nRF52) +// <14=> Supply 13/16 (nRF52) +// <15=> Supply 15/16 (nRF52) +// <7=> External Ref 0 +// <65543=> External Ref 1 + +#ifndef LPCOMP_CONFIG_REFERENCE +#define LPCOMP_CONFIG_REFERENCE 3 +#endif + +// LPCOMP_CONFIG_DETECTION - Detection + +// <0=> Crossing +// <1=> Up +// <2=> Down + +#ifndef LPCOMP_CONFIG_DETECTION +#define LPCOMP_CONFIG_DETECTION 2 +#endif + +// LPCOMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_INPUT +#define LPCOMP_CONFIG_INPUT 0 +#endif + +// LPCOMP_CONFIG_HYST - Hysteresis + + +#ifndef LPCOMP_CONFIG_HYST +#define LPCOMP_CONFIG_HYST 0 +#endif + +// LPCOMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_IRQ_PRIORITY +#define LPCOMP_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// PDM_ENABLED - nrf_drv_pdm - PDM peripheral driver +//========================================================== +#ifndef PDM_ENABLED +#define PDM_ENABLED 0 +#endif +// PDM_CONFIG_MODE - Mode + +// <0=> Stereo +// <1=> Mono + +#ifndef PDM_CONFIG_MODE +#define PDM_CONFIG_MODE 1 +#endif + +// PDM_CONFIG_EDGE - Edge + +// <0=> Left falling +// <1=> Left rising + +#ifndef PDM_CONFIG_EDGE +#define PDM_CONFIG_EDGE 0 +#endif + +// PDM_CONFIG_CLOCK_FREQ - Clock frequency + +// <134217728=> 1000k +// <138412032=> 1032k (default) +// <142606336=> 1067k + +#ifndef PDM_CONFIG_CLOCK_FREQ +#define PDM_CONFIG_CLOCK_FREQ 138412032 +#endif + +// PDM_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PDM_CONFIG_IRQ_PRIORITY +#define PDM_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// PERIPHERAL_RESOURCE_SHARING_ENABLED - nrf_drv_common - Peripheral drivers common module + + +#ifndef PERIPHERAL_RESOURCE_SHARING_ENABLED +#define PERIPHERAL_RESOURCE_SHARING_ENABLED 1 +#endif + +// POWER_ENABLED - nrf_drv_power - POWER peripheral driver +//========================================================== +#ifndef POWER_ENABLED +#define POWER_ENABLED 0 +#endif +// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef POWER_CONFIG_IRQ_PRIORITY +#define POWER_CONFIG_IRQ_PRIORITY 7 +#endif + +// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCEN +#define POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCENHV +#define POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + +// PPI_ENABLED - nrf_drv_ppi - PPI peripheral driver + + +#ifndef PPI_ENABLED +#define PPI_ENABLED 0 +#endif + +// PWM_ENABLED - nrf_drv_pwm - PWM peripheral driver +//========================================================== +#ifndef PWM_ENABLED +#define PWM_ENABLED 1 +#endif +// PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT0_PIN +#define PWM_DEFAULT_CONFIG_OUT0_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT1_PIN - Out1 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT1_PIN +#define PWM_DEFAULT_CONFIG_OUT1_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT2_PIN - Out2 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT2_PIN +#define PWM_DEFAULT_CONFIG_OUT2_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT3_PIN - Out3 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT3_PIN +#define PWM_DEFAULT_CONFIG_OUT3_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_BASE_CLOCK - Base clock + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz + +#ifndef PWM_DEFAULT_CONFIG_BASE_CLOCK +#define PWM_DEFAULT_CONFIG_BASE_CLOCK 4 +#endif + +// PWM_DEFAULT_CONFIG_COUNT_MODE - Count mode + +// <0=> Up +// <1=> Up and Down + +#ifndef PWM_DEFAULT_CONFIG_COUNT_MODE +#define PWM_DEFAULT_CONFIG_COUNT_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_TOP_VALUE - Top value +#ifndef PWM_DEFAULT_CONFIG_TOP_VALUE +#define PWM_DEFAULT_CONFIG_TOP_VALUE 1000 +#endif + +// PWM_DEFAULT_CONFIG_LOAD_MODE - Load mode + +// <0=> Common +// <1=> Grouped +// <2=> Individual +// <3=> Waveform + +#ifndef PWM_DEFAULT_CONFIG_LOAD_MODE +#define PWM_DEFAULT_CONFIG_LOAD_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_STEP_MODE - Step mode + +// <0=> Auto +// <1=> Triggered + +#ifndef PWM_DEFAULT_CONFIG_STEP_MODE +#define PWM_DEFAULT_CONFIG_STEP_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define PWM_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// PWM0_ENABLED - Enable PWM0 instance + + +#ifndef PWM0_ENABLED +#define PWM0_ENABLED 1 +#endif + +// PWM1_ENABLED - Enable PWM1 instance + + +#ifndef PWM1_ENABLED +#define PWM1_ENABLED 1 +#endif + +// PWM2_ENABLED - Enable PWM2 instance + + +#ifndef PWM2_ENABLED +#define PWM2_ENABLED 1 +#endif + +// PWM3_ENABLED - Enable PWM3 instance + + +#ifndef PWM3_ENABLED +#define PWM3_ENABLED 0 +#endif + +// + +// QDEC_ENABLED - nrf_drv_qdec - QDEC peripheral driver +//========================================================== +#ifndef QDEC_ENABLED +#define QDEC_ENABLED 0 +#endif +// QDEC_CONFIG_REPORTPER - Report period + +// <0=> 10 Samples +// <1=> 40 Samples +// <2=> 80 Samples +// <3=> 120 Samples +// <4=> 160 Samples +// <5=> 200 Samples +// <6=> 240 Samples +// <7=> 280 Samples + +#ifndef QDEC_CONFIG_REPORTPER +#define QDEC_CONFIG_REPORTPER 0 +#endif + +// QDEC_CONFIG_SAMPLEPER - Sample period + +// <0=> 128 us +// <1=> 256 us +// <2=> 512 us +// <3=> 1024 us +// <4=> 2048 us +// <5=> 4096 us +// <6=> 8192 us +// <7=> 16384 us + +#ifndef QDEC_CONFIG_SAMPLEPER +#define QDEC_CONFIG_SAMPLEPER 7 +#endif + +// QDEC_CONFIG_PIO_A - A pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_A +#define QDEC_CONFIG_PIO_A 31 +#endif + +// QDEC_CONFIG_PIO_B - B pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_B +#define QDEC_CONFIG_PIO_B 31 +#endif + +// QDEC_CONFIG_PIO_LED - LED pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_LED +#define QDEC_CONFIG_PIO_LED 31 +#endif + +// QDEC_CONFIG_LEDPRE - LED pre +#ifndef QDEC_CONFIG_LEDPRE +#define QDEC_CONFIG_LEDPRE 511 +#endif + +// QDEC_CONFIG_LEDPOL - LED polarity + +// <0=> Active low +// <1=> Active high + +#ifndef QDEC_CONFIG_LEDPOL +#define QDEC_CONFIG_LEDPOL 1 +#endif + +// QDEC_CONFIG_DBFEN - Debouncing enable + + +#ifndef QDEC_CONFIG_DBFEN +#define QDEC_CONFIG_DBFEN 0 +#endif + +// QDEC_CONFIG_SAMPLE_INTEN - Sample ready interrupt enable + + +#ifndef QDEC_CONFIG_SAMPLE_INTEN +#define QDEC_CONFIG_SAMPLE_INTEN 0 +#endif + +// QDEC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QDEC_CONFIG_IRQ_PRIORITY +#define QDEC_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// RNG_ENABLED - nrf_drv_rng - RNG peripheral driver +//========================================================== +#ifndef RNG_ENABLED +#define RNG_ENABLED 1 +#endif +// RNG_CONFIG_ERROR_CORRECTION - Error correction + + +#ifndef RNG_CONFIG_ERROR_CORRECTION +#define RNG_CONFIG_ERROR_CORRECTION 1 +#endif + +// RNG_CONFIG_POOL_SIZE - Pool size +#ifndef RNG_CONFIG_POOL_SIZE +#define RNG_CONFIG_POOL_SIZE 64 +#endif + +// RNG_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RNG_CONFIG_IRQ_PRIORITY +#define RNG_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// RTC_ENABLED - nrf_drv_rtc - RTC peripheral driver +//========================================================== +#ifndef RTC_ENABLED +#define RTC_ENABLED 0 +#endif +// RTC_DEFAULT_CONFIG_FREQUENCY - Frequency <16-32768> + + +#ifndef RTC_DEFAULT_CONFIG_FREQUENCY +#define RTC_DEFAULT_CONFIG_FREQUENCY 32768 +#endif + +// RTC_DEFAULT_CONFIG_RELIABLE - Ensures safe compare event triggering + + +#ifndef RTC_DEFAULT_CONFIG_RELIABLE +#define RTC_DEFAULT_CONFIG_RELIABLE 0 +#endif + +// RTC_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define RTC_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// RTC0_ENABLED - Enable RTC0 instance + + +#ifndef RTC0_ENABLED +#define RTC0_ENABLED 0 +#endif + +// RTC1_ENABLED - Enable RTC1 instance + + +#ifndef RTC1_ENABLED +#define RTC1_ENABLED 0 +#endif + +// RTC2_ENABLED - Enable RTC2 instance + + +#ifndef RTC2_ENABLED +#define RTC2_ENABLED 0 +#endif + +// NRF_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt +#ifndef NRF_MAXIMUM_LATENCY_US +#define NRF_MAXIMUM_LATENCY_US 2000 +#endif + +// + +// SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver +//========================================================== +#ifndef SAADC_ENABLED +#define SAADC_ENABLED 1 +#endif +// SAADC_CONFIG_RESOLUTION - Resolution + +// <0=> 8 bit +// <1=> 10 bit +// <2=> 12 bit +// <3=> 14 bit + +#ifndef SAADC_CONFIG_RESOLUTION +#define SAADC_CONFIG_RESOLUTION 2 +#endif + +// SAADC_CONFIG_OVERSAMPLE - Sample period + +// <0=> Disabled +// <1=> 2x +// <2=> 4x +// <3=> 8x +// <4=> 16x +// <5=> 32x +// <6=> 64x +// <7=> 128x +// <8=> 256x + +#ifndef SAADC_CONFIG_OVERSAMPLE +#define SAADC_CONFIG_OVERSAMPLE 0 +#endif + +// SAADC_CONFIG_LP_MODE - Enabling low power mode + + +#ifndef SAADC_CONFIG_LP_MODE +#define SAADC_CONFIG_LP_MODE 0 +#endif + +// SAADC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SAADC_CONFIG_IRQ_PRIORITY +#define SAADC_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// SPIS_ENABLED - nrf_drv_spis - SPI Slave driver +//========================================================== +#ifndef SPIS_ENABLED +#define SPIS_ENABLED 1 +#endif +// SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// SPIS_DEFAULT_MODE - Mode + +// <0=> MODE_0 +// <1=> MODE_1 +// <2=> MODE_2 +// <3=> MODE_3 + +#ifndef SPIS_DEFAULT_MODE +#define SPIS_DEFAULT_MODE 0 +#endif + +// SPIS_DEFAULT_BIT_ORDER - SPIS default bit order + +// <0=> MSB first +// <1=> LSB first + +#ifndef SPIS_DEFAULT_BIT_ORDER +#define SPIS_DEFAULT_BIT_ORDER 0 +#endif + +// SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef SPIS_DEFAULT_DEF +#define SPIS_DEFAULT_DEF 255 +#endif + +// SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef SPIS_DEFAULT_ORC +#define SPIS_DEFAULT_ORC 255 +#endif + +// SPIS0_ENABLED - Enable SPIS0 instance + + +#ifndef SPIS0_ENABLED +#define SPIS0_ENABLED 1 +#endif + +// SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef SPIS1_ENABLED +#define SPIS1_ENABLED 0 +#endif + +// SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef SPIS2_ENABLED +#define SPIS2_ENABLED 0 +#endif + +// + +// SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver +//========================================================== +#ifndef SPI_ENABLED +#define SPI_ENABLED 1 +#endif +// SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRF_SPI_DRV_MISO_PULLUP_CFG - MISO PIN pull-up configuration. + +// <0=> NRF_GPIO_PIN_NOPULL +// <1=> NRF_GPIO_PIN_PULLDOWN +// <3=> NRF_GPIO_PIN_PULLUP + +#ifndef NRF_SPI_DRV_MISO_PULLUP_CFG +#define NRF_SPI_DRV_MISO_PULLUP_CFG 1 +#endif + +// SPI0_ENABLED - Enable SPI0 instance +//========================================================== +#ifndef SPI0_ENABLED +#define SPI0_ENABLED 1 +#endif +// SPI0_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI0_USE_EASY_DMA +#define SPI0_USE_EASY_DMA 0 +#endif + +// SPI0_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI0_DEFAULT_FREQUENCY +#define SPI0_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// SPI1_ENABLED - Enable SPI1 instance +//========================================================== +#ifndef SPI1_ENABLED +#define SPI1_ENABLED 1 +#endif +// SPI1_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI1_USE_EASY_DMA +#define SPI1_USE_EASY_DMA 0 +#endif + +// SPI1_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI1_DEFAULT_FREQUENCY +#define SPI1_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// SPI2_ENABLED - Enable SPI2 instance +//========================================================== +#ifndef SPI2_ENABLED +#define SPI2_ENABLED 1 +#endif +// SPI2_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI2_USE_EASY_DMA +#define SPI2_USE_EASY_DMA 0 +#endif + +// SPI2_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI2_DEFAULT_FREQUENCY +#define SPI2_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// + +// TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver +//========================================================== +#ifndef TIMER_ENABLED +#define TIMER_ENABLED 0 +#endif +// TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef TIMER_DEFAULT_CONFIG_FREQUENCY +#define TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef TIMER_DEFAULT_CONFIG_MODE +#define TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef TIMER0_ENABLED +#define TIMER0_ENABLED 0 +#endif + +// TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef TIMER1_ENABLED +#define TIMER1_ENABLED 0 +#endif + +// TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef TIMER2_ENABLED +#define TIMER2_ENABLED 0 +#endif + +// TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef TIMER3_ENABLED +#define TIMER3_ENABLED 0 +#endif + +// TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef TIMER4_ENABLED +#define TIMER4_ENABLED 0 +#endif + +// + +// TWIS_ENABLED - nrf_drv_twis - TWIS peripheral driver +//========================================================== +#ifndef TWIS_ENABLED +#define TWIS_ENABLED 0 +#endif +// TWIS_DEFAULT_CONFIG_ADDR0 - Address0 +#ifndef TWIS_DEFAULT_CONFIG_ADDR0 +#define TWIS_DEFAULT_CONFIG_ADDR0 0 +#endif + +// TWIS_DEFAULT_CONFIG_ADDR1 - Address1 +#ifndef TWIS_DEFAULT_CONFIG_ADDR1 +#define TWIS_DEFAULT_CONFIG_ADDR1 0 +#endif + +// TWIS_DEFAULT_CONFIG_SCL_PULL - SCL pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SCL_PULL +#define TWIS_DEFAULT_CONFIG_SCL_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_SDA_PULL - SDA pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SDA_PULL +#define TWIS_DEFAULT_CONFIG_SDA_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TWIS0_ENABLED - Enable TWIS0 instance + + +#ifndef TWIS0_ENABLED +#define TWIS0_ENABLED 0 +#endif + +// TWIS1_ENABLED - Enable TWIS1 instance + + +#ifndef TWIS1_ENABLED +#define TWIS1_ENABLED 0 +#endif + +// TWIS_ASSUME_INIT_AFTER_RESET_ONLY - Assume that any instance would be initialized only once + + +// Optimization flag. Registers used by TWIS are shared by other peripherals. Normally, during initialization driver tries to clear all registers to known state before doing the initialization itself. This gives initialization safe procedure, no matter when it would be called. If you activate TWIS only once and do never uninitialize it - set this flag to 1 what gives more optimal code. + +#ifndef TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +#endif + +// TWIS_NO_SYNC_MODE - Remove support for synchronous mode + + +// Synchronous mode would be used in specific situations. And it uses some additional code and data memory to safely process state machine by polling it in status functions. If this functionality is not required it may be disabled to free some resources. + +#ifndef TWIS_NO_SYNC_MODE +#define TWIS_NO_SYNC_MODE 0 +#endif + +// + +// TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver +//========================================================== +#ifndef TWI_ENABLED +#define TWI_ENABLED 1 +#endif +// TWI_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef TWI_DEFAULT_CONFIG_FREQUENCY +#define TWI_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// TWI_DEFAULT_CONFIG_CLR_BUS_INIT - Enables bus clearing procedure during init + + +#ifndef TWI_DEFAULT_CONFIG_CLR_BUS_INIT +#define TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0 +#endif + +// TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// TWI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TWI0_ENABLED - Enable TWI0 instance +//========================================================== +#ifndef TWI0_ENABLED +#define TWI0_ENABLED 1 +#endif +// TWI0_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI0_USE_EASY_DMA +#define TWI0_USE_EASY_DMA 0 +#endif + +// + +// TWI1_ENABLED - Enable TWI1 instance +//========================================================== +#ifndef TWI1_ENABLED +#define TWI1_ENABLED 1 +#endif +// TWI1_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI1_USE_EASY_DMA +#define TWI1_USE_EASY_DMA 0 +#endif + +// + +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 1 +#endif +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 1 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 2576384 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 1 +#endif + +// UART0_ENABLED - Enable UART0 instance +//========================================================== +#ifndef UART0_ENABLED +#define UART0_ENABLED 1 +#endif +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// UART1_ENABLED - Enable UART1 instance +//========================================================== +#ifndef UART1_ENABLED +#define UART1_ENABLED 0 +#endif +// UART1_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART1_CONFIG_USE_EASY_DMA +#define UART1_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// + +// USBD_ENABLED - nrf_drv_usbd - USB driver +//========================================================== +#ifndef USBD_ENABLED +#define USBD_ENABLED 0 +#endif +// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef USBD_CONFIG_IRQ_PRIORITY +#define USBD_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRF_DRV_USBD_DMASCHEDULER_MODE - USBD SMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef NRF_DRV_USBD_DMASCHEDULER_MODE +#define NRF_DRV_USBD_DMASCHEDULER_MODE 0 +#endif + +// + +// WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver +//========================================================== +#ifndef WDT_ENABLED +#define WDT_ENABLED 0 +#endif +// WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode + +// <1=> Run in SLEEP, Pause in HALT +// <8=> Pause in SLEEP, Run in HALT +// <9=> Run in SLEEP and HALT +// <0=> Pause in SLEEP and HALT + +#ifndef WDT_CONFIG_BEHAVIOUR +#define WDT_CONFIG_BEHAVIOUR 1 +#endif + +// WDT_CONFIG_RELOAD_VALUE - Reload value <15-4294967295> + + +#ifndef WDT_CONFIG_RELOAD_VALUE +#define WDT_CONFIG_RELOAD_VALUE 2000 +#endif + +// WDT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef WDT_CONFIG_IRQ_PRIORITY +#define WDT_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_GPIOTE_ENABLED - app_gpiote - GPIOTE events dispatcher + + +#ifndef APP_GPIOTE_ENABLED +#define APP_GPIOTE_ENABLED 0 +#endif + +// APP_PWM_ENABLED - app_pwm - PWM functionality + + +#ifndef APP_PWM_ENABLED +#define APP_PWM_ENABLED 0 +#endif + +// APP_SCHEDULER_ENABLED - app_scheduler - Events scheduler +//========================================================== +#ifndef APP_SCHEDULER_ENABLED +#define APP_SCHEDULER_ENABLED 0 +#endif +// APP_SCHEDULER_WITH_PAUSE - Enabling pause feature + + +#ifndef APP_SCHEDULER_WITH_PAUSE +#define APP_SCHEDULER_WITH_PAUSE 0 +#endif + +// APP_SCHEDULER_WITH_PROFILER - Enabling scheduler profiling + + +#ifndef APP_SCHEDULER_WITH_PROFILER +#define APP_SCHEDULER_WITH_PROFILER 0 +#endif + +// + +// APP_TIMER_ENABLED - app_timer - Application timer functionality +//========================================================== +#ifndef APP_TIMER_ENABLED +#define APP_TIMER_ENABLED 0 +#endif +// APP_TIMER_CONFIG_RTC_FREQUENCY - Configure RTC prescaler. + +// <0=> 32768 Hz +// <1=> 16384 Hz +// <3=> 8192 Hz +// <7=> 4096 Hz +// <15=> 2048 Hz +// <31=> 1024 Hz + +#ifndef APP_TIMER_CONFIG_RTC_FREQUENCY +#define APP_TIMER_CONFIG_RTC_FREQUENCY 0 +#endif + +// APP_TIMER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef APP_TIMER_CONFIG_IRQ_PRIORITY +#define APP_TIMER_CONFIG_IRQ_PRIORITY 7 +#endif + +// APP_TIMER_CONFIG_OP_QUEUE_SIZE - Capacity of timer requests queue. +// Size of the queue depends on how many timers are used +// in the system, how often timers are started and overall +// system latency. If queue size is too small app_timer calls +// will fail. + +#ifndef APP_TIMER_CONFIG_OP_QUEUE_SIZE +#define APP_TIMER_CONFIG_OP_QUEUE_SIZE 10 +#endif + +// APP_TIMER_CONFIG_USE_SCHEDULER - Enable scheduling app_timer events to app_scheduler + + +#ifndef APP_TIMER_CONFIG_USE_SCHEDULER +#define APP_TIMER_CONFIG_USE_SCHEDULER 0 +#endif + +// APP_TIMER_WITH_PROFILER - Enable app_timer profiling + + +#ifndef APP_TIMER_WITH_PROFILER +#define APP_TIMER_WITH_PROFILER 0 +#endif + +// APP_TIMER_KEEPS_RTC_ACTIVE - Enable RTC always on + + +// If option is enabled RTC is kept running even if there is no active timers. +// This option can be used when app_timer is used for timestamping. + +#ifndef APP_TIMER_KEEPS_RTC_ACTIVE +#define APP_TIMER_KEEPS_RTC_ACTIVE 0 +#endif + +// APP_TIMER_CONFIG_SWI_NUMBER - Configure SWI instance used. + +// <0=> 0 +// <1=> 1 + +#ifndef APP_TIMER_CONFIG_SWI_NUMBER +#define APP_TIMER_CONFIG_SWI_NUMBER 0 +#endif + +// + +// NRF_TWI_MNGR_ENABLED - nrf_twi_mngr - TWI transaction manager + + +#ifndef NRF_TWI_MNGR_ENABLED +#define NRF_TWI_MNGR_ENABLED 0 +#endif + +// APP_UART_ENABLED - app_uart - UART driver +//========================================================== +#ifndef APP_UART_ENABLED +#define APP_UART_ENABLED 0 +#endif +// APP_UART_DRIVER_INSTANCE - UART instance used + +// <0=> 0 + +#ifndef APP_UART_DRIVER_INSTANCE +#define APP_UART_DRIVER_INSTANCE 0 +#endif + +// + +// APP_USBD_CLASS_AUDIO_ENABLED - app_usbd_audio - USB AUDIO class + + +#ifndef APP_USBD_CLASS_AUDIO_ENABLED +#define APP_USBD_CLASS_AUDIO_ENABLED 0 +#endif + +// APP_USBD_CLASS_CDC_ACM_ENABLED - app_usbd_cdc_acm - USB CDC ACM class + + +#ifndef APP_USBD_CLASS_CDC_ACM_ENABLED +#define APP_USBD_CLASS_CDC_ACM_ENABLED 0 +#endif + +// APP_USBD_CLASS_HID_ENABLED - app_usbd_hid - USB HID class + + +#ifndef APP_USBD_CLASS_HID_ENABLED +#define APP_USBD_CLASS_HID_ENABLED 0 +#endif + +// APP_USBD_HID_GENERIC_ENABLED - app_usbd_hid_generic - USB HID generic + + +#ifndef APP_USBD_HID_GENERIC_ENABLED +#define APP_USBD_HID_GENERIC_ENABLED 0 +#endif + +// APP_USBD_HID_KBD_ENABLED - app_usbd_hid_kbd - USB HID keyboard + + +#ifndef APP_USBD_HID_KBD_ENABLED +#define APP_USBD_HID_KBD_ENABLED 0 +#endif + +// APP_USBD_HID_MOUSE_ENABLED - app_usbd_hid_mouse - USB HID mouse + + +#ifndef APP_USBD_HID_MOUSE_ENABLED +#define APP_USBD_HID_MOUSE_ENABLED 0 +#endif + +// APP_USBD_MSC_ENABLED - app_usbd_msc - USB MSC class + + +#ifndef APP_USBD_MSC_ENABLED +#define APP_USBD_MSC_ENABLED 0 +#endif + +// BUTTON_ENABLED - app_button - buttons handling module + + +#ifndef BUTTON_ENABLED +#define BUTTON_ENABLED 0 +#endif + +// CRC16_ENABLED - crc16 - CRC16 calculation routines + + +#ifndef CRC16_ENABLED +#define CRC16_ENABLED 0 +#endif + +// CRC32_ENABLED - crc32 - CRC32 calculation routines + + +#ifndef CRC32_ENABLED +#define CRC32_ENABLED 0 +#endif + +// ECC_ENABLED - ecc - Elliptic Curve Cryptography Library + + +#ifndef ECC_ENABLED +#define ECC_ENABLED 0 +#endif + +// FDS_ENABLED - fds - Flash data storage module +//========================================================== +#ifndef FDS_ENABLED +#define FDS_ENABLED 1 +#endif +// Pages - Virtual page settings + +// Configure the number of virtual pages to use and their size. +//========================================================== +// FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. +// One of the virtual pages is reserved by the system for garbage collection. +// Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection. +// The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes. + +#ifndef FDS_VIRTUAL_PAGES +#define FDS_VIRTUAL_PAGES 3 +#endif + +// FDS_VIRTUAL_PAGE_SIZE - The size of a virtual flash page. + + +// Expressed in number of 4-byte words. +// By default, a virtual page is the same size as a physical page. +// The size of a virtual page must be a multiple of the size of a physical page. +// <1024=> 1024 +// <2048=> 2048 + +#ifndef FDS_VIRTUAL_PAGE_SIZE +#define FDS_VIRTUAL_PAGE_SIZE 1024 +#endif + +// +//========================================================== + +// Backend - Backend configuration + +// Configure which nrf_fstorage backend is used by FDS to write to flash. +//========================================================== +// FDS_BACKEND - FDS flash backend. + + +// NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present. +// NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice. +// <1=> NRF_FSTORAGE_NVMC +// <2=> NRF_FSTORAGE_SD + +#ifndef FDS_BACKEND +#define FDS_BACKEND 1 +#endif + +// +//========================================================== + +// Queue - Queue settings + +//========================================================== +// FDS_OP_QUEUE_SIZE - Size of the internal queue. +// Increase this value if you frequently get synchronous FDS_ERR_NO_SPACE_IN_QUEUES errors. + +#ifndef FDS_OP_QUEUE_SIZE +#define FDS_OP_QUEUE_SIZE 4 +#endif + +// +//========================================================== + +// CRC - CRC functionality + +//========================================================== +// FDS_CRC_CHECK_ON_READ - Enable CRC checks. + +// Save a record's CRC when it is written to flash and check it when the record is opened. +// Records with an incorrect CRC can still be 'seen' by the user using FDS functions, but they cannot be opened. +// Additionally, they will not be garbage collected until they are deleted. +//========================================================== +#ifndef FDS_CRC_CHECK_ON_READ +#define FDS_CRC_CHECK_ON_READ 0 +#endif +// FDS_CRC_CHECK_ON_WRITE - Perform a CRC check on newly written records. + + +// Perform a CRC check on newly written records. +// This setting can be used to make sure that the record data was not altered while being written to flash. +// <1=> Enabled +// <0=> Disabled + +#ifndef FDS_CRC_CHECK_ON_WRITE +#define FDS_CRC_CHECK_ON_WRITE 0 +#endif + +// + +// +//========================================================== + +// Users - Number of users + +//========================================================== +// FDS_MAX_USERS - Maximum number of callbacks that can be registered. +#ifndef FDS_MAX_USERS +#define FDS_MAX_USERS 4 +#endif + +// +//========================================================== + +// + +// HARDFAULT_HANDLER_ENABLED - hardfault_default - HardFault default handler for debugging and release +//========================================================== +#ifndef HARDFAULT_HANDLER_ENABLED +#define HARDFAULT_HANDLER_ENABLED 0 +#endif +// HARDFAULT_HANDLER_GDB_PSP_BACKTRACE - Bypass the GDB problem with multiple stack pointers backtrace + + +// There is a known bug in GDB which causes it to incorrectly backtrace the code +// when multiple stack pointers are used (main and process stack pointers). +// This option enables the fix for that problem and allows to see the proper backtrace info. +// It makes it possible to trace the code to the exact point where a HardFault appeared. +// This option requires additional commands and may temporarily switch MSP stack to store data on PSP space. +// This is an optional parameter - enable it while debugging. +// Before a HardFault handler exits, the stack will be reverted to its previous value. + +#ifndef HARDFAULT_HANDLER_GDB_PSP_BACKTRACE +#define HARDFAULT_HANDLER_GDB_PSP_BACKTRACE 1 +#endif + +// + +// HCI_MEM_POOL_ENABLED - hci_mem_pool - memory pool implementation used by HCI +//========================================================== +#ifndef HCI_MEM_POOL_ENABLED +#define HCI_MEM_POOL_ENABLED 0 +#endif +// HCI_TX_BUF_SIZE - TX buffer size in bytes. +#ifndef HCI_TX_BUF_SIZE +#define HCI_TX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_SIZE - RX buffer size in bytes. +#ifndef HCI_RX_BUF_SIZE +#define HCI_RX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_QUEUE_SIZE - RX buffer queue size. +#ifndef HCI_RX_BUF_QUEUE_SIZE +#define HCI_RX_BUF_QUEUE_SIZE 4 +#endif + +// + +// HCI_SLIP_ENABLED - hci_slip - SLIP protocol implementation used by HCI +//========================================================== +#ifndef HCI_SLIP_ENABLED +#define HCI_SLIP_ENABLED 0 +#endif +// HCI_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef HCI_UART_BAUDRATE +#define HCI_UART_BAUDRATE 30801920 +#endif + +// HCI_UART_FLOW_CONTROL - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef HCI_UART_FLOW_CONTROL +#define HCI_UART_FLOW_CONTROL 0 +#endif + +// HCI_UART_RX_PIN - UART RX pin +#ifndef HCI_UART_RX_PIN +#define HCI_UART_RX_PIN 8 +#endif + +// HCI_UART_TX_PIN - UART TX pin +#ifndef HCI_UART_TX_PIN +#define HCI_UART_TX_PIN 6 +#endif + +// HCI_UART_RTS_PIN - UART RTS pin +#ifndef HCI_UART_RTS_PIN +#define HCI_UART_RTS_PIN 5 +#endif + +// HCI_UART_CTS_PIN - UART CTS pin +#ifndef HCI_UART_CTS_PIN +#define HCI_UART_CTS_PIN 7 +#endif + +// + +// HCI_TRANSPORT_ENABLED - hci_transport - HCI transport +//========================================================== +#ifndef HCI_TRANSPORT_ENABLED +#define HCI_TRANSPORT_ENABLED 0 +#endif +// HCI_MAX_PACKET_SIZE_IN_BITS - Maximum size of a single application packet in bits. +#ifndef HCI_MAX_PACKET_SIZE_IN_BITS +#define HCI_MAX_PACKET_SIZE_IN_BITS 8000 +#endif + +// + +// LED_SOFTBLINK_ENABLED - led_softblink - led_softblink module + + +#ifndef LED_SOFTBLINK_ENABLED +#define LED_SOFTBLINK_ENABLED 0 +#endif + +// LOW_POWER_PWM_ENABLED - low_power_pwm - low_power_pwm module + + +#ifndef LOW_POWER_PWM_ENABLED +#define LOW_POWER_PWM_ENABLED 0 +#endif + +// MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator +//========================================================== +#ifndef MEM_MANAGER_ENABLED +#define MEM_MANAGER_ENABLED 0 +#endif +// MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block. <0-255> + + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT 1 +#endif + +// MEMORY_MANAGER_SMALL_BLOCK_SIZE - Size of each memory blocks identified as 'small' block. +// Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE 32 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block. <0-255> + + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_SIZE - Size of each memory blocks identified as 'medium' block. +// Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block. <0-255> + + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_SIZE - Size of each memory blocks identified as 'large' block. +// Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra large' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 1320 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra large' block. +// Size of each memory blocks identified as 'extra extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 3444 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra small' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 64 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra small' block. +// Size of each memory blocks identified as 'extra extra small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 32 +#endif + +// MEM_MANAGER_DISABLE_API_PARAM_CHECK - Disable API parameter checks in the module. + + +#ifndef MEM_MANAGER_DISABLE_API_PARAM_CHECK +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK 0 +#endif + +// + +// NRF_BALLOC_ENABLED - nrf_balloc - Block allocator module +//========================================================== +#ifndef NRF_BALLOC_ENABLED +#define NRF_BALLOC_ENABLED 1 +#endif +// NRF_BALLOC_CONFIG_DEBUG_ENABLED - Enables debug mode in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_CONFIG_DEBUG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS - Number of words used as head guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS +#define NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS - Number of words used as tail guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS +#define NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED - Enables basic checks in this module. + + +#ifndef NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED +#define NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED - Enables double memory free check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED - Enables free memory corruption check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED 0 +#endif + +// + +// + +// NRF_CSENSE_ENABLED - nrf_csense - Capacitive sensor module +//========================================================== +#ifndef NRF_CSENSE_ENABLED +#define NRF_CSENSE_ENABLED 0 +#endif +// NRF_CSENSE_PAD_HYSTERESIS - Minimum value of change required to determine that a pad was touched. +#ifndef NRF_CSENSE_PAD_HYSTERESIS +#define NRF_CSENSE_PAD_HYSTERESIS 15 +#endif + +// NRF_CSENSE_PAD_DEVIATION - Minimum value measured on a pad required to take it into account while calculating the step. +#ifndef NRF_CSENSE_PAD_DEVIATION +#define NRF_CSENSE_PAD_DEVIATION 70 +#endif + +// NRF_CSENSE_MIN_PAD_VALUE - Minimum normalized value on a pad required to take its value into account. +#ifndef NRF_CSENSE_MIN_PAD_VALUE +#define NRF_CSENSE_MIN_PAD_VALUE 20 +#endif + +// NRF_CSENSE_MAX_PADS_NUMBER - Maximum number of pads used for one instance. +#ifndef NRF_CSENSE_MAX_PADS_NUMBER +#define NRF_CSENSE_MAX_PADS_NUMBER 20 +#endif + +// NRF_CSENSE_MAX_VALUE - Maximum normalized value obtained from measurement. +#ifndef NRF_CSENSE_MAX_VALUE +#define NRF_CSENSE_MAX_VALUE 1000 +#endif + +// NRF_CSENSE_OUTPUT_PIN - Output pin used by the low-level module. +// This is used when capacitive sensor does not use COMP. + +#ifndef NRF_CSENSE_OUTPUT_PIN +#define NRF_CSENSE_OUTPUT_PIN 26 +#endif + +// + +// NRF_DRV_CSENSE_ENABLED - nrf_drv_csense - Capacitive sensor low-level module +//========================================================== +#ifndef NRF_DRV_CSENSE_ENABLED +#define NRF_DRV_CSENSE_ENABLED 0 +#endif +// USE_COMP - Use the comparator to implement the capacitive sensor driver. + +// Due to Anomaly 84, COMP I_SOURCE is not functional. It has too high a varation. +//========================================================== +#ifndef USE_COMP +#define USE_COMP 0 +#endif +// TIMER0_FOR_CSENSE - First TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER0_FOR_CSENSE +#define TIMER0_FOR_CSENSE 1 +#endif + +// TIMER1_FOR_CSENSE - Second TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER1_FOR_CSENSE +#define TIMER1_FOR_CSENSE 2 +#endif + +// MEASUREMENT_PERIOD - Single measurement period. +// Time of a single measurement can be calculated as +// T = (1/2)*MEASUREMENT_PERIOD*(1/f_OSC) where f_OSC = I_SOURCE / (2C*(VUP-VDOWN) ). +// I_SOURCE, VUP, and VDOWN are values used to initialize COMP and C is the capacitance of the used pad. + +#ifndef MEASUREMENT_PERIOD +#define MEASUREMENT_PERIOD 20 +#endif + +// + +// + +// NRF_FPRINTF_ENABLED - nrf_fprintf - fprintf function. + + +#ifndef NRF_FPRINTF_ENABLED +#define NRF_FPRINTF_ENABLED 0 +#endif + +// NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library +//========================================================== +#ifndef NRF_FSTORAGE_ENABLED +#define NRF_FSTORAGE_ENABLED 1 +#endif +// nrf_fstorage_sd - Implementation using the SoftDevice. + +// Configuration options for the fstorage implementation using the SoftDevice. +//========================================================== +// NRF_FSTORAGE_SD_QUEUE_SIZE - Size of the internal queue of operations. +// Increase this value if API calls frequently return the error @ref NRF_ERROR_NO_MEM. + +#ifndef NRF_FSTORAGE_SD_QUEUE_SIZE +#define NRF_FSTORAGE_SD_QUEUE_SIZE 4 +#endif + +// NRF_FSTORAGE_SD_MAX_RETRIES - Maximum number of attempts at executing an operation when the SoftDevice is busy. +// Increase this value if events frequently return the @ref NRF_ERROR_TIMEOUT error. +// The SoftDevice might fail to schedule flash access due to high BLE activity. + +#ifndef NRF_FSTORAGE_SD_MAX_RETRIES +#define NRF_FSTORAGE_SD_MAX_RETRIES 8 +#endif + +// NRF_FSTORAGE_SD_MAX_WRITE_SIZE - Maximum number of bytes to be written to flash in a single operation. +// This value must be a multiple of four. +// Lowering this value can increase the chances of the SoftDevice being able to execute flash operations in between radio activity. +// This value is bound by the maximum number of bytes that can be written to flash in a single call to @ref sd_flash_write. +// That is 1024 bytes for nRF51 ICs and 4096 bytes for nRF52 ICs. + +#ifndef NRF_FSTORAGE_SD_MAX_WRITE_SIZE +#define NRF_FSTORAGE_SD_MAX_WRITE_SIZE 4096 +#endif + +// +//========================================================== + +// + +// NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module + + +#ifndef NRF_MEMOBJ_ENABLED +#define NRF_MEMOBJ_ENABLED 0 +#endif + +// NRF_PWR_MGMT_ENABLED - nrf_pwr_mgmt - Power management module +//========================================================== +#ifndef NRF_PWR_MGMT_ENABLED +#define NRF_PWR_MGMT_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. + +// Selected pin will be set when CPU is in sleep mode. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED +#define NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// NRF_PWR_MGMT_SLEEP_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef NRF_PWR_MGMT_SLEEP_DEBUG_PIN +#define NRF_PWR_MGMT_SLEEP_DEBUG_PIN 31 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED - Enables CPU usage monitor. + + +// Module will trace percentage of CPU usage in one second intervals. + +#ifndef NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED +#define NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED 0 +#endif + +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED - Enable standby timeout. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S - Standby timeout (in seconds). +// Shutdown procedure will begin no earlier than after this number of seconds. + +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S 3 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED - Enables FPU event cleaning. + + +#ifndef NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED +#define NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED 1 +#endif + +// NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY - Blocked shutdown procedure will be retried every second. + + +#ifndef NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY +#define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 0 +#endif + +// NRF_PWR_MGMT_CONFIG_USE_SCHEDULER - Module will use @ref app_scheduler. + + +#ifndef NRF_PWR_MGMT_CONFIG_USE_SCHEDULER +#define NRF_PWR_MGMT_CONFIG_USE_SCHEDULER 0 +#endif + +// NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT - The number of priorities for module handlers. +// The number of stages of the shutdown process. + +#ifndef NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT +#define NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT 3 +#endif + +// + +// NRF_QUEUE_ENABLED - nrf_queue - Queue module + + +#ifndef NRF_QUEUE_ENABLED +#define NRF_QUEUE_ENABLED 1 +#endif + +// NRF_SECTION_ITER_ENABLED - nrf_section_iter - Section iterator + + +#ifndef NRF_SECTION_ITER_ENABLED +#define NRF_SECTION_ITER_ENABLED 1 +#endif + +// NRF_STRERROR_ENABLED - nrf_strerror - Library for converting error code to string. + + +#ifndef NRF_STRERROR_ENABLED +#define NRF_STRERROR_ENABLED 0 +#endif + +// SLIP_ENABLED - slip - SLIP encoding and decoding + + +#ifndef SLIP_ENABLED +#define SLIP_ENABLED 0 +#endif + +// TASK_MANAGER_ENABLED - task_manager - Task manager. +//========================================================== +#ifndef TASK_MANAGER_ENABLED +#define TASK_MANAGER_ENABLED 0 +#endif +// TASK_MANAGER_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef TASK_MANAGER_CLI_CMDS +#define TASK_MANAGER_CLI_CMDS 1 +#endif + +// TASK_MANAGER_CONFIG_MAX_TASKS - Maximum number of tasks which can be created +#ifndef TASK_MANAGER_CONFIG_MAX_TASKS +#define TASK_MANAGER_CONFIG_MAX_TASKS 2 +#endif + +// TASK_MANAGER_CONFIG_STACK_SIZE - Stack size for every task (power of 2) +#ifndef TASK_MANAGER_CONFIG_STACK_SIZE +#define TASK_MANAGER_CONFIG_STACK_SIZE 1024 +#endif + +// TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED - Enable stack profiling. + + +#ifndef TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED +#define TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED 1 +#endif + +// TASK_MANAGER_CONFIG_STACK_GUARD - Configures stack guard. + +// <0=> Disabled +// <4=> 32 bytes +// <5=> 64 bytes +// <6=> 128 bytes +// <7=> 256 bytes +// <8=> 512 bytes + +#ifndef TASK_MANAGER_CONFIG_STACK_GUARD +#define TASK_MANAGER_CONFIG_STACK_GUARD 7 +#endif + +// + +// nrf_cli - Command line interface. + +//========================================================== +// NRF_CLI_ENABLED - Enable/disable CLI module. + + +#ifndef NRF_CLI_ENABLED +#define NRF_CLI_ENABLED 0 +#endif + +// NRF_CLI_ARGC_MAX - Maximum number of parameters passed to command handler. +#ifndef NRF_CLI_ARGC_MAX +#define NRF_CLI_ARGC_MAX 12 +#endif + +// NRF_CLI_BUILD_IN_CMDS_ENABLED - CLI build in commands. + + +#ifndef NRF_CLI_BUILD_IN_CMDS_ENABLED +#define NRF_CLI_BUILD_IN_CMDS_ENABLED 1 +#endif + +// NRF_CLI_CMD_BUFF_SIZE - Maximum buffer size for single command. +#ifndef NRF_CLI_CMD_BUFF_SIZE +#define NRF_CLI_CMD_BUFF_SIZE 128 +#endif + +// NRF_CLI_PRINTF_BUFF_SIZE - Maximum print buffer size. +#ifndef NRF_CLI_PRINTF_BUFF_SIZE +#define NRF_CLI_PRINTF_BUFF_SIZE 23 +#endif + +// NRF_CLI_HISTORY_ENABLED - Enable CLI history mode. +//========================================================== +#ifndef NRF_CLI_HISTORY_ENABLED +#define NRF_CLI_HISTORY_ENABLED 1 +#endif +// NRF_CLI_HISTORY_ELEMENT_SIZE - Size of one memory object reserved for CLI history +#ifndef NRF_CLI_HISTORY_ELEMENT_SIZE +#define NRF_CLI_HISTORY_ELEMENT_SIZE 32 +#endif + +// NRF_CLI_HISTORY_ELEMENT_COUNT - Number of history memory objects +#ifndef NRF_CLI_HISTORY_ELEMENT_COUNT +#define NRF_CLI_HISTORY_ELEMENT_COUNT 8 +#endif + +// + +// NRF_CLI_VT100_COLORS_ENABLED - CLI VT100 colors. + + +#ifndef NRF_CLI_VT100_COLORS_ENABLED +#define NRF_CLI_VT100_COLORS_ENABLED 1 +#endif + +// NRF_CLI_LOG_BACKEND - Enable logger backend interface. + + +#ifndef NRF_CLI_LOG_BACKEND +#define NRF_CLI_LOG_BACKEND 1 +#endif + +// NRF_CLI_USES_TASK_MANAGER_ENABLED - Enable CLI to use task_manager + + +#ifndef NRF_CLI_USES_TASK_MANAGER_ENABLED +#define NRF_CLI_USES_TASK_MANAGER_ENABLED 0 +#endif + +// +//========================================================== + +// nrf_cli_rtt - RTT command line interface transport. + +//========================================================== +// NRF_CLI_RTT_ENABLED - Enable/disable CLI RTT module. + + +#ifndef NRF_CLI_RTT_ENABLED +#define NRF_CLI_RTT_ENABLED 0 +#endif + +// NRF_CLI_RTT_TERMINAL_ID - RTT terminal ID for CLI. +#ifndef NRF_CLI_RTT_TERMINAL_ID +#define NRF_CLI_RTT_TERMINAL_ID 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Log + +//========================================================== +// NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend +//========================================================== +#ifndef NRF_LOG_BACKEND_RTT_ENABLED +#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#endif +// NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#endif + +// + +// NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend +//========================================================== +#ifndef NRF_LOG_BACKEND_UART_ENABLED +#define NRF_LOG_BACKEND_UART_ENABLED 0 +#endif +// NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin +#ifndef NRF_LOG_BACKEND_UART_TX_PIN +#define NRF_LOG_BACKEND_UART_TX_PIN 6 +#endif + +// NRF_LOG_BACKEND_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRF_LOG_BACKEND_UART_BAUDRATE +#define NRF_LOG_BACKEND_UART_BAUDRATE 30801920 +#endif + +// NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE 64 +#endif + +// + +// nrf_log - Logging + +//========================================================== +// NRF_LOG_ENABLED - Logging module for nRF5 SDK +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0 +#endif +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 0 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 0 +#endif + +// + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + + +// Log data is buffered and can be processed in idle. + +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 1 +#endif + +// NRF_LOG_BUFSIZE - Size of the buffer for storing logs (in bytes). + + +// Must be power of 2 and multiple of 4. +// If NRF_LOG_DEFERRED = 0 then buffer size can be reduced to minimum. +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 +// <2048=> 2048 +// <4096=> 4096 +// <8192=> 8192 +// <16384=> 16384 + +#ifndef NRF_LOG_BUFSIZE +#define NRF_LOG_BUFSIZE 1024 +#endif + +// NRF_LOG_ALLOW_OVERFLOW - Configures behavior when circular buffer is full. + + +// If set then oldest logs are overwritten. Otherwise a +// marker is injected informing about overflow. + +#ifndef NRF_LOG_ALLOW_OVERFLOW +#define NRF_LOG_ALLOW_OVERFLOW 1 +#endif + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + + +// Function for getting the timestamp is provided by the user + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +// NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. + + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 1 +#endif + +// NRF_LOG_CLI_CMDS - Enable CLI commands for the module. + + +#ifndef NRF_LOG_CLI_CMDS +#define NRF_LOG_CLI_CMDS 1 +#endif + +// Log message pool - Configuration of log message pool + +//========================================================== +// NRF_LOG_MSGPOOL_ELEMENT_SIZE - Size of a single element in the pool of memory objects. +// If a small value is set, then performance of logs processing +// is degraded because data is fragmented. Bigger value impacts +// RAM memory utilization. The size is set to fit a message with +// a timestamp and up to 2 arguments in a single memory object. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_SIZE +#define NRF_LOG_MSGPOOL_ELEMENT_SIZE 20 +#endif + +// NRF_LOG_MSGPOOL_ELEMENT_COUNT - Number of elements in the pool of memory objects +// If a small value is set, then it may lead to a deadlock +// in certain cases if backend has high latency and holds +// multiple messages for long time. Bigger value impacts +// RAM memory usage. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_COUNT +#define NRF_LOG_MSGPOOL_ELEMENT_COUNT 8 +#endif + +// +//========================================================== + +// + +// nrf_log module configuration + +//========================================================== +// nrf_log in nRF_Core + +//========================================================== +// NRF_MPU_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MPU_CONFIG_LOG_ENABLED +#define NRF_MPU_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MPU_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MPU_CONFIG_LOG_LEVEL +#define NRF_MPU_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MPU_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_CONFIG_INFO_COLOR +#define NRF_MPU_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MPU_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_CONFIG_DEBUG_COLOR +#define NRF_MPU_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_STACK_GUARD_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_STACK_GUARD_CONFIG_LOG_ENABLED +#define NRF_STACK_GUARD_CONFIG_LOG_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_STACK_GUARD_CONFIG_LOG_LEVEL +#define NRF_STACK_GUARD_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_STACK_GUARD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_INFO_COLOR +#define NRF_STACK_GUARD_CONFIG_INFO_COLOR 0 +#endif + +// NRF_STACK_GUARD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_DEBUG_COLOR +#define NRF_STACK_GUARD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TASK_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TASK_MANAGER_CONFIG_LOG_ENABLED +#define TASK_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// TASK_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TASK_MANAGER_CONFIG_LOG_LEVEL +#define TASK_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// TASK_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_INFO_COLOR +#define TASK_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// TASK_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_DEBUG_COLOR +#define TASK_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Drivers + +//========================================================== +// CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef CLOCK_CONFIG_LOG_ENABLED +#define CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef CLOCK_CONFIG_LOG_LEVEL +#define CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_INFO_COLOR +#define CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_DEBUG_COLOR +#define CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMMON_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMMON_CONFIG_LOG_ENABLED +#define COMMON_CONFIG_LOG_ENABLED 0 +#endif +// COMMON_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMMON_CONFIG_LOG_LEVEL +#define COMMON_CONFIG_LOG_LEVEL 3 +#endif + +// COMMON_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMMON_CONFIG_INFO_COLOR +#define COMMON_CONFIG_INFO_COLOR 0 +#endif + +// COMMON_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMMON_CONFIG_DEBUG_COLOR +#define COMMON_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMP_CONFIG_LOG_ENABLED +#define COMP_CONFIG_LOG_ENABLED 0 +#endif +// COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMP_CONFIG_LOG_LEVEL +#define COMP_CONFIG_LOG_LEVEL 3 +#endif + +// COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_INFO_COLOR +#define COMP_CONFIG_INFO_COLOR 0 +#endif + +// COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_DEBUG_COLOR +#define COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef GPIOTE_CONFIG_LOG_ENABLED +#define GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef GPIOTE_CONFIG_LOG_LEVEL +#define GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_INFO_COLOR +#define GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_DEBUG_COLOR +#define GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// I2S_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef I2S_CONFIG_LOG_ENABLED +#define I2S_CONFIG_LOG_ENABLED 0 +#endif +// I2S_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef I2S_CONFIG_LOG_LEVEL +#define I2S_CONFIG_LOG_LEVEL 3 +#endif + +// I2S_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_INFO_COLOR +#define I2S_CONFIG_INFO_COLOR 0 +#endif + +// I2S_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_DEBUG_COLOR +#define I2S_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef LPCOMP_CONFIG_LOG_ENABLED +#define LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef LPCOMP_CONFIG_LOG_LEVEL +#define LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_INFO_COLOR +#define LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_DEBUG_COLOR +#define LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PDM_CONFIG_LOG_ENABLED +#define PDM_CONFIG_LOG_ENABLED 0 +#endif +// PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PDM_CONFIG_LOG_LEVEL +#define PDM_CONFIG_LOG_LEVEL 3 +#endif + +// PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_INFO_COLOR +#define PDM_CONFIG_INFO_COLOR 0 +#endif + +// PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_DEBUG_COLOR +#define PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PPI_CONFIG_LOG_ENABLED +#define PPI_CONFIG_LOG_ENABLED 0 +#endif +// PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PPI_CONFIG_LOG_LEVEL +#define PPI_CONFIG_LOG_LEVEL 3 +#endif + +// PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_INFO_COLOR +#define PPI_CONFIG_INFO_COLOR 0 +#endif + +// PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_DEBUG_COLOR +#define PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PWM_CONFIG_LOG_ENABLED +#define PWM_CONFIG_LOG_ENABLED 0 +#endif +// PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PWM_CONFIG_LOG_LEVEL +#define PWM_CONFIG_LOG_LEVEL 3 +#endif + +// PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_INFO_COLOR +#define PWM_CONFIG_INFO_COLOR 0 +#endif + +// PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_DEBUG_COLOR +#define PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef QDEC_CONFIG_LOG_ENABLED +#define QDEC_CONFIG_LOG_ENABLED 0 +#endif +// QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef QDEC_CONFIG_LOG_LEVEL +#define QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_INFO_COLOR +#define QDEC_CONFIG_INFO_COLOR 0 +#endif + +// QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_DEBUG_COLOR +#define QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RNG_CONFIG_LOG_ENABLED +#define RNG_CONFIG_LOG_ENABLED 0 +#endif +// RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RNG_CONFIG_LOG_LEVEL +#define RNG_CONFIG_LOG_LEVEL 3 +#endif + +// RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_INFO_COLOR +#define RNG_CONFIG_INFO_COLOR 0 +#endif + +// RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_DEBUG_COLOR +#define RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED - Enables logging of random numbers. + + +#ifndef RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED +#define RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED 0 +#endif + +// + +// RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RTC_CONFIG_LOG_ENABLED +#define RTC_CONFIG_LOG_ENABLED 0 +#endif +// RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RTC_CONFIG_LOG_LEVEL +#define RTC_CONFIG_LOG_LEVEL 3 +#endif + +// RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_INFO_COLOR +#define RTC_CONFIG_INFO_COLOR 0 +#endif + +// RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_DEBUG_COLOR +#define RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SAADC_CONFIG_LOG_ENABLED +#define SAADC_CONFIG_LOG_ENABLED 0 +#endif +// SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SAADC_CONFIG_LOG_LEVEL +#define SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_INFO_COLOR +#define SAADC_CONFIG_INFO_COLOR 0 +#endif + +// SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_DEBUG_COLOR +#define SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPIS_CONFIG_LOG_ENABLED +#define SPIS_CONFIG_LOG_ENABLED 0 +#endif +// SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPIS_CONFIG_LOG_LEVEL +#define SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_INFO_COLOR +#define SPIS_CONFIG_INFO_COLOR 0 +#endif + +// SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_DEBUG_COLOR +#define SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SWI_CONFIG_LOG_ENABLED +#define SWI_CONFIG_LOG_ENABLED 0 +#endif +// SWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SWI_CONFIG_LOG_LEVEL +#define SWI_CONFIG_LOG_LEVEL 3 +#endif + +// SWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SWI_CONFIG_INFO_COLOR +#define SWI_CONFIG_INFO_COLOR 0 +#endif + +// SWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SWI_CONFIG_DEBUG_COLOR +#define SWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TIMER_CONFIG_LOG_ENABLED +#define TIMER_CONFIG_LOG_ENABLED 0 +#endif +// TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TIMER_CONFIG_LOG_LEVEL +#define TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_INFO_COLOR +#define TIMER_CONFIG_INFO_COLOR 0 +#endif + +// TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_DEBUG_COLOR +#define TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWIS_CONFIG_LOG_ENABLED +#define TWIS_CONFIG_LOG_ENABLED 0 +#endif +// TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWIS_CONFIG_LOG_LEVEL +#define TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_INFO_COLOR +#define TWIS_CONFIG_INFO_COLOR 0 +#endif + +// TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_DEBUG_COLOR +#define TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWI_CONFIG_LOG_ENABLED +#define TWI_CONFIG_LOG_ENABLED 0 +#endif +// TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWI_CONFIG_LOG_LEVEL +#define TWI_CONFIG_LOG_LEVEL 3 +#endif + +// TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_INFO_COLOR +#define TWI_CONFIG_INFO_COLOR 0 +#endif + +// TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_DEBUG_COLOR +#define TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef UART_CONFIG_LOG_ENABLED +#define UART_CONFIG_LOG_ENABLED 0 +#endif +// UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef UART_CONFIG_LOG_LEVEL +#define UART_CONFIG_LOG_LEVEL 3 +#endif + +// UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_INFO_COLOR +#define UART_CONFIG_INFO_COLOR 0 +#endif + +// UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_DEBUG_COLOR +#define UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef USBD_CONFIG_LOG_ENABLED +#define USBD_CONFIG_LOG_ENABLED 0 +#endif +// USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef USBD_CONFIG_LOG_LEVEL +#define USBD_CONFIG_LOG_LEVEL 3 +#endif + +// USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_INFO_COLOR +#define USBD_CONFIG_INFO_COLOR 0 +#endif + +// USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_DEBUG_COLOR +#define USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef WDT_CONFIG_LOG_ENABLED +#define WDT_CONFIG_LOG_ENABLED 0 +#endif +// WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef WDT_CONFIG_LOG_LEVEL +#define WDT_CONFIG_LOG_LEVEL 3 +#endif + +// WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_INFO_COLOR +#define WDT_CONFIG_INFO_COLOR 0 +#endif + +// WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_DEBUG_COLOR +#define WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Libraries + +//========================================================== +// APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CDC_ACM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define APP_USBD_CDC_ACM_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#define APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_MSC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_MSC_CONFIG_LOG_ENABLED +#define APP_USBD_MSC_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_MSC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_MSC_CONFIG_LOG_LEVEL +#define APP_USBD_MSC_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_MSC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_INFO_COLOR +#define APP_USBD_MSC_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_MSC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_DEBUG_COLOR +#define APP_USBD_MSC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MEM_MANAGER_ENABLE_LOGS - Enable debug trace in the module. + + +#ifndef MEM_MANAGER_ENABLE_LOGS +#define MEM_MANAGER_ENABLE_LOGS 0 +#endif + +// NRF_BALLOC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_LOG_ENABLED +#define NRF_BALLOC_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_LOG_LEVEL +#define NRF_BALLOC_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_INFO_COLOR +#define NRF_BALLOC_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BALLOC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_DEBUG_COLOR +#define NRF_BALLOC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_BLE_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_CLI_BLE_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_CLI_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_MEMOBJ_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MEMOBJ_CONFIG_LOG_ENABLED +#define NRF_MEMOBJ_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MEMOBJ_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MEMOBJ_CONFIG_LOG_LEVEL +#define NRF_MEMOBJ_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MEMOBJ_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_INFO_COLOR +#define NRF_MEMOBJ_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MEMOBJ_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_DEBUG_COLOR +#define NRF_MEMOBJ_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#define NRF_PWR_MGMT_CONFIG_LOG_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_PWR_MGMT_CONFIG_LOG_LEVEL +#define NRF_PWR_MGMT_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_PWR_MGMT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_INFO_COLOR +#define NRF_PWR_MGMT_CONFIG_INFO_COLOR 0 +#endif + +// NRF_PWR_MGMT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#define NRF_PWR_MGMT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_ANT_LOG_ENABLED - Enable logging in SoftDevice handler (ANT) module. +//========================================================== +#ifndef NRF_SDH_ANT_LOG_ENABLED +#define NRF_SDH_ANT_LOG_ENABLED 1 +#endif +// NRF_SDH_ANT_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_ANT_LOG_LEVEL +#define NRF_SDH_ANT_LOG_LEVEL 3 +#endif + +// NRF_SDH_ANT_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_INFO_COLOR +#define NRF_SDH_ANT_INFO_COLOR 0 +#endif + +// NRF_SDH_ANT_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_DEBUG_COLOR +#define NRF_SDH_ANT_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_BLE_LOG_ENABLED - Enable logging in SoftDevice handler (BLE) module. +//========================================================== +#ifndef NRF_SDH_BLE_LOG_ENABLED +#define NRF_SDH_BLE_LOG_ENABLED 1 +#endif +// NRF_SDH_BLE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_BLE_LOG_LEVEL +#define NRF_SDH_BLE_LOG_LEVEL 3 +#endif + +// NRF_SDH_BLE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_INFO_COLOR +#define NRF_SDH_BLE_INFO_COLOR 0 +#endif + +// NRF_SDH_BLE_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_DEBUG_COLOR +#define NRF_SDH_BLE_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_LOG_ENABLED - Enable logging in SoftDevice handler module. +//========================================================== +#ifndef NRF_SDH_LOG_ENABLED +#define NRF_SDH_LOG_ENABLED 1 +#endif +// NRF_SDH_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_LOG_LEVEL +#define NRF_SDH_LOG_LEVEL 3 +#endif + +// NRF_SDH_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_INFO_COLOR +#define NRF_SDH_INFO_COLOR 0 +#endif + +// NRF_SDH_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_DEBUG_COLOR +#define NRF_SDH_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_SOC_LOG_ENABLED - Enable logging in SoftDevice handler (SoC) module. +//========================================================== +#ifndef NRF_SDH_SOC_LOG_ENABLED +#define NRF_SDH_SOC_LOG_ENABLED 1 +#endif +// NRF_SDH_SOC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_SOC_LOG_LEVEL +#define NRF_SDH_SOC_LOG_LEVEL 3 +#endif + +// NRF_SDH_SOC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_INFO_COLOR +#define NRF_SDH_SOC_INFO_COLOR 0 +#endif + +// NRF_SDH_SOC_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_DEBUG_COLOR +#define NRF_SDH_SOC_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// +//========================================================== + +// +//========================================================== + +// +//========================================================== + +// nRF_NFC + +//========================================================== +// NFC_BLE_OOB_ADVDATA_ENABLED - nfc_ble_oob_advdata - Encoding the advertising data and/or scan response data which is specific for OOB pairing +//========================================================== +#ifndef NFC_BLE_OOB_ADVDATA_ENABLED +#define NFC_BLE_OOB_ADVDATA_ENABLED 0 +#endif +// ADVANCED_ADVDATA_SUPPORT - Non-mandatory AD types for BLE OOB pairing are encoded inside the NDEF message (e.g. service UUIDs) + +// <1=> Enabled +// <0=> Disabled + +#ifndef ADVANCED_ADVDATA_SUPPORT +#define ADVANCED_ADVDATA_SUPPORT 0 +#endif + +// + +// NFC_BLE_PAIR_LIB_ENABLED - nfc_ble_pair_lib - Library parameters +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_ENABLED +#define NFC_BLE_PAIR_LIB_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_LOG_ENABLED +#define NFC_BLE_PAIR_LIB_LOG_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_BLE_PAIR_LIB_LOG_LEVEL +#define NFC_BLE_PAIR_LIB_LOG_LEVEL 3 +#endif + +// NFC_BLE_PAIR_LIB_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_INFO_COLOR +#define NFC_BLE_PAIR_LIB_INFO_COLOR 0 +#endif + +// NFC_BLE_PAIR_LIB_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_DEBUG_COLOR +#define NFC_BLE_PAIR_LIB_DEBUG_COLOR 0 +#endif + +// + +// NFC_BLE_PAIR_LIB_SECURITY_PARAMETERS - Common Peer Manager security parameters. + +//========================================================== +// BLE_NFC_SEC_PARAM_BOND - Enables device bonding. + +// If bonding is enabled at least one of the BLE_NFC_SEC_PARAM_KDIST options must be enabled. +//========================================================== +#ifndef BLE_NFC_SEC_PARAM_BOND +#define BLE_NFC_SEC_PARAM_BOND 1 +#endif +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// + +// BLE_NFC_SEC_PARAM_MIN_KEY_SIZE - Minimal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MIN_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MIN_KEY_SIZE 7 +#endif + +// BLE_NFC_SEC_PARAM_MAX_KEY_SIZE - Maximal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MAX_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MAX_KEY_SIZE 16 +#endif + +// +//========================================================== + +// + +// NFC_NDEF_MSG_ENABLED - nfc_ndef_msg - NFC NDEF Message generator module +//========================================================== +#ifndef NFC_NDEF_MSG_ENABLED +#define NFC_NDEF_MSG_ENABLED 0 +#endif +// NFC_NDEF_MSG_TAG_TYPE - NFC Tag Type + +// <2=> Type 2 Tag +// <4=> Type 4 Tag + +#ifndef NFC_NDEF_MSG_TAG_TYPE +#define NFC_NDEF_MSG_TAG_TYPE 2 +#endif + +// + +// NFC_NDEF_MSG_PARSER_ENABLED - nfc_ndef_msg_parser - NFC NDEF message parser module +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_ENABLED +#define NFC_NDEF_MSG_PARSER_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_LOG_ENABLED +#define NFC_NDEF_MSG_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_MSG_PARSER_LOG_LEVEL +#define NFC_NDEF_MSG_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_MSG_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_MSG_PARSER_INFO_COLOR +#define NFC_NDEF_MSG_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_NDEF_RECORD_PARSER_ENABLED - nfc_ndef_record_parser - NFC NDEF Record parser module +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_ENABLED +#define NFC_NDEF_RECORD_PARSER_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_LOG_ENABLED +#define NFC_NDEF_RECORD_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_RECORD_PARSER_LOG_LEVEL +#define NFC_NDEF_RECORD_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_RECORD_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_RECORD_PARSER_INFO_COLOR +#define NFC_NDEF_RECORD_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_T2T_HAL_ENABLED - nfc_t2t_hal - Hardware Abstraction Layer for NFC library. +//========================================================== +#ifndef NFC_T2T_HAL_ENABLED +#define NFC_T2T_HAL_ENABLED 0 +#endif +// NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NFCT_CONFIG_IRQ_PRIORITY +#define NFCT_CONFIG_IRQ_PRIORITY 7 +#endif + +// HAL_NFC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_LOG_ENABLED +#define HAL_NFC_CONFIG_LOG_ENABLED 0 +#endif +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// HAL_NFC_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_DEBUG_PIN_ENABLED +#define HAL_NFC_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 11 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 12 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 24 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 25 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 28 +#endif + +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// + +// + +// NFC_T4T_HAL_ENABLED - nfc_t4t_hal - Hardware Abstraction Layer for NFC library. +//========================================================== +#ifndef NFC_T4T_HAL_ENABLED +#define NFC_T4T_HAL_ENABLED 0 +#endif +// NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NFCT_CONFIG_IRQ_PRIORITY +#define NFCT_CONFIG_IRQ_PRIORITY 7 +#endif + +// HAL_NFC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_LOG_ENABLED +#define HAL_NFC_CONFIG_LOG_ENABLED 0 +#endif +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// HAL_NFC_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_DEBUG_PIN_ENABLED +#define HAL_NFC_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// + +// + +// +//========================================================== + +// nRF_Segger_RTT + +//========================================================== +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_SoftDevice + +//========================================================== +// NRF_SDH_ANT_ENABLED - nrf_sdh_ant - SoftDevice ANT event handler +//========================================================== +#ifndef NRF_SDH_ANT_ENABLED +#define NRF_SDH_ANT_ENABLED 0 +#endif +// ANT Channels + +//========================================================== +// NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED - Allocated ANT channels. +#ifndef NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED +#define NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED 0 +#endif + +// NRF_SDH_ANT_ENCRYPTED_CHANNELS - Encrypted ANT channels. +#ifndef NRF_SDH_ANT_ENCRYPTED_CHANNELS +#define NRF_SDH_ANT_ENCRYPTED_CHANNELS 0 +#endif + +// +//========================================================== + +// ANT Queues + +//========================================================== +// NRF_SDH_ANT_EVENT_QUEUE_SIZE - Event queue size. +#ifndef NRF_SDH_ANT_EVENT_QUEUE_SIZE +#define NRF_SDH_ANT_EVENT_QUEUE_SIZE 32 +#endif + +// NRF_SDH_ANT_BURST_QUEUE_SIZE - ANT burst queue size. +#ifndef NRF_SDH_ANT_BURST_QUEUE_SIZE +#define NRF_SDH_ANT_BURST_QUEUE_SIZE 128 +#endif + +// +//========================================================== + +// ANT Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_ANT_OBSERVER_PRIO_LEVELS - Total number of priority levels for ANT observers. +// This setting configures the number of priority levels available for the ANT event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_ANT_OBSERVER_PRIO_LEVELS +#define NRF_SDH_ANT_OBSERVER_PRIO_LEVELS 2 +#endif + +// ANT Observers priorities - Invididual priorities + +//========================================================== +// ANT_BPWR_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Bicycle Power Profile. + +#ifndef ANT_BPWR_ANT_OBSERVER_PRIO +#define ANT_BPWR_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_BSC_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Bicycle Speed and Cadence Profile. + +#ifndef ANT_BSC_ANT_OBSERVER_PRIO +#define ANT_BSC_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_ENCRYPT_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Cryptographic ANT stack configuration module. + +#ifndef ANT_ENCRYPT_ANT_OBSERVER_PRIO +#define ANT_ENCRYPT_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_HRM_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Heart Rate Monitor. + +#ifndef ANT_HRM_ANT_OBSERVER_PRIO +#define ANT_HRM_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_SDM_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Stride Based Speed and Distance Monitor Profile. + +#ifndef ANT_SDM_ANT_OBSERVER_PRIO +#define ANT_SDM_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the ANT state indicator module. + +#ifndef ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO +#define ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO 1 +#endif + +// BSP_BTN_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Button Control module. + +#ifndef BSP_BTN_ANT_OBSERVER_PRIO +#define BSP_BTN_ANT_OBSERVER_PRIO 1 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_BLE_ENABLED - nrf_sdh_ble - SoftDevice BLE event handler +//========================================================== +#ifndef NRF_SDH_BLE_ENABLED +#define NRF_SDH_BLE_ENABLED 1 +#endif +// BLE Stack configuration - Stack configuration parameters + +// These values are not used directly by the SoftDevice handler but the application or other libraries might depend on them. +// Keep them up-to-date with the desired configuration. +//========================================================== +// NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links. +#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT +#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 0 +#endif + +// NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links. +#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT +#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0 +#endif + +// NRF_SDH_BLE_TOTAL_LINK_COUNT - Maximum number of total concurrent connections using the default configuration. +#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT +#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1 +#endif + +// NRF_SDH_BLE_GAP_EVENT_LENGTH - The time set aside for this connection on every connection interval in 1.25 ms units. +#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH +#define NRF_SDH_BLE_GAP_EVENT_LENGTH 3 +#endif + +// NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. +#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE +#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23 +#endif + +// NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. +#ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE +#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408 +#endif + +// NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. +#ifndef NRF_SDH_BLE_VS_UUID_COUNT +#define NRF_SDH_BLE_VS_UUID_COUNT 0 +#endif + +// NRF_SDH_BLE_SERVICE_CHANGED - Include the Service Changed characteristic in the Attribute Table. + + +#ifndef NRF_SDH_BLE_SERVICE_CHANGED +#define NRF_SDH_BLE_SERVICE_CHANGED 0 +#endif + +// +//========================================================== + +// BLE Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_BLE_OBSERVER_PRIO_LEVELS - Total number of priority levels for BLE observers. +// This setting configures the number of priority levels available for BLE event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_BLE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_BLE_OBSERVER_PRIO_LEVELS 3 +#endif + +// BLE Observers priorities - Invididual priorities + +//========================================================== +// BLE_ADV_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Advertising module. + +#ifndef BLE_ADV_BLE_OBSERVER_PRIO +#define BLE_ADV_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_ANCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Apple Notification Service Client. + +#ifndef BLE_ANCS_C_BLE_OBSERVER_PRIO +#define BLE_ANCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_ANS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Alert Notification Service Client. + +#ifndef BLE_ANS_C_BLE_OBSERVER_PRIO +#define BLE_ANS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service. + +#ifndef BLE_BAS_BLE_OBSERVER_PRIO +#define BLE_BAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service Client. + +#ifndef BLE_BAS_C_BLE_OBSERVER_PRIO +#define BLE_BAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Blood Pressure Service. + +#ifndef BLE_BPS_BLE_OBSERVER_PRIO +#define BLE_BPS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection parameters module. + +#ifndef BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +#define BLE_CONN_PARAMS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CONN_STATE_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection State module. + +#ifndef BLE_CONN_STATE_BLE_OBSERVER_PRIO +#define BLE_CONN_STATE_BLE_OBSERVER_PRIO 0 +#endif + +// BLE_CSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Cycling Speed and Cadence Service. + +#ifndef BLE_CSCS_BLE_OBSERVER_PRIO +#define BLE_CSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Current Time Service Client. + +#ifndef BLE_CTS_C_BLE_OBSERVER_PRIO +#define BLE_CTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_DB_DISC_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Database Discovery module. + +#ifndef BLE_DB_DISC_BLE_OBSERVER_PRIO +#define BLE_DB_DISC_BLE_OBSERVER_PRIO 1 +#endif + +// BLE_DFU_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_BLE_OBSERVER_PRIO +#define BLE_DFU_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_GLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Glucose Service. + +#ifndef BLE_GLS_BLE_OBSERVER_PRIO +#define BLE_GLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HIDS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Human Interface Device Service. + +#ifndef BLE_HIDS_BLE_OBSERVER_PRIO +#define BLE_HIDS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service. + +#ifndef BLE_HRS_BLE_OBSERVER_PRIO +#define BLE_HRS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service Client. + +#ifndef BLE_HRS_C_BLE_OBSERVER_PRIO +#define BLE_HRS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Health Thermometer Service. + +#ifndef BLE_HTS_BLE_OBSERVER_PRIO +#define BLE_HTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service. + +#ifndef BLE_IAS_BLE_OBSERVER_PRIO +#define BLE_IAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service Client. + +#ifndef BLE_IAS_C_BLE_OBSERVER_PRIO +#define BLE_IAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service. + +#ifndef BLE_LBS_BLE_OBSERVER_PRIO +#define BLE_LBS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service Client. + +#ifndef BLE_LBS_C_BLE_OBSERVER_PRIO +#define BLE_LBS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Link Loss Service. + +#ifndef BLE_LLS_BLE_OBSERVER_PRIO +#define BLE_LLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LNS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Location Navigation Service. + +#ifndef BLE_LNS_BLE_OBSERVER_PRIO +#define BLE_LNS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Service. + +#ifndef BLE_NUS_BLE_OBSERVER_PRIO +#define BLE_NUS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Central Service. + +#ifndef BLE_NUS_C_BLE_OBSERVER_PRIO +#define BLE_NUS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service. + +#ifndef BLE_OTS_BLE_OBSERVER_PRIO +#define BLE_OTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service client. + +#ifndef BLE_OTS_C_BLE_OBSERVER_PRIO +#define BLE_OTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Service. + +#ifndef BLE_RSCS_BLE_OBSERVER_PRIO +#define BLE_RSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Client. + +#ifndef BLE_RSCS_C_BLE_OBSERVER_PRIO +#define BLE_RSCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_TPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the TX Power Service. + +#ifndef BLE_TPS_BLE_OBSERVER_PRIO +#define BLE_TPS_BLE_OBSERVER_PRIO 2 +#endif + +// BSP_BTN_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Button Control module. + +#ifndef BSP_BTN_BLE_OBSERVER_PRIO +#define BSP_BTN_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NRF_BLE_BMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Bond Management Service. + +#ifndef NRF_BLE_BMS_BLE_OBSERVER_PRIO +#define NRF_BLE_BMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_CGMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Contiuon Glucose Monitoring Service. + +#ifndef NRF_BLE_CGMS_BLE_OBSERVER_PRIO +#define NRF_BLE_CGMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT Service Client. + +#ifndef NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +#define NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATT_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT module. + +#ifndef NRF_BLE_GATT_BLE_OBSERVER_PRIO +#define NRF_BLE_GATT_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_QWR_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Queued writes module. + +#ifndef NRF_BLE_QWR_BLE_OBSERVER_PRIO +#define NRF_BLE_QWR_BLE_OBSERVER_PRIO 2 +#endif + +// PM_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Peer Manager module. + +#ifndef PM_BLE_OBSERVER_PRIO +#define PM_BLE_OBSERVER_PRIO 2 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_ENABLED - nrf_sdh - SoftDevice handler +//========================================================== +#ifndef NRF_SDH_ENABLED +#define NRF_SDH_ENABLED 1 +#endif +// Dispatch model + +// This setting configures how Stack events are dispatched to the application. +//========================================================== +// NRF_SDH_DISPATCH_MODEL + + +// NRF_SDH_DISPATCH_MODEL_INTERRUPT: SoftDevice events are passed to the application from the interrupt context. +// NRF_SDH_DISPATCH_MODEL_APPSH: SoftDevice events are scheduled using @ref app_scheduler. +// NRF_SDH_DISPATCH_MODEL_POLLING: SoftDevice events are to be fetched manually. +// <0=> NRF_SDH_DISPATCH_MODEL_INTERRUPT +// <1=> NRF_SDH_DISPATCH_MODEL_APPSH +// <2=> NRF_SDH_DISPATCH_MODEL_POLLING + +#ifndef NRF_SDH_DISPATCH_MODEL +#define NRF_SDH_DISPATCH_MODEL 0 +#endif + +// +//========================================================== + +// Clock - SoftDevice clock configuration + +//========================================================== +// NRF_SDH_CLOCK_LF_SRC - SoftDevice clock source. + +// <0=> NRF_CLOCK_LF_SRC_RC +// <1=> NRF_CLOCK_LF_SRC_XTAL +// <2=> NRF_CLOCK_LF_SRC_SYNTH + +#ifndef NRF_SDH_CLOCK_LF_SRC +#define NRF_SDH_CLOCK_LF_SRC 1 +#endif + +// NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. +#ifndef NRF_SDH_CLOCK_LF_RC_CTIV +#define NRF_SDH_CLOCK_LF_RC_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. +// How often (in number of calibration intervals) the RC oscillator shall be calibrated +// if the temperature has not changed. + +#ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV +#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_XTAL_ACCURACY - External crystal clock accuracy used in the LL to compute timing windows. + +// <0=> NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM +// <1=> NRF_CLOCK_LF_XTAL_ACCURACY_500_PPM +// <2=> NRF_CLOCK_LF_XTAL_ACCURACY_150_PPM +// <3=> NRF_CLOCK_LF_XTAL_ACCURACY_100_PPM +// <4=> NRF_CLOCK_LF_XTAL_ACCURACY_75_PPM +// <5=> NRF_CLOCK_LF_XTAL_ACCURACY_50_PPM +// <6=> NRF_CLOCK_LF_XTAL_ACCURACY_30_PPM +// <7=> NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM + +#ifndef NRF_SDH_CLOCK_LF_XTAL_ACCURACY +#define NRF_SDH_CLOCK_LF_XTAL_ACCURACY 7 +#endif + +// +//========================================================== + +// SDH Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_REQ_OBSERVER_PRIO_LEVELS - Total number of priority levels for request observers. +// This setting configures the number of priority levels available for the SoftDevice request event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_REQ_OBSERVER_PRIO_LEVELS +#define NRF_SDH_REQ_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STATE_OBSERVER_PRIO_LEVELS - Total number of priority levels for state observers. +// This setting configures the number of priority levels available for the SoftDevice state event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STATE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STATE_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STACK_OBSERVER_PRIO_LEVELS - Total number of priority levels for stack event observers. +// This setting configures the number of priority levels available for the SoftDevice stack event handlers (ANT, BLE, SoC). +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STACK_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STACK_OBSERVER_PRIO_LEVELS 2 +#endif + + +// State Observers priorities - Invididual priorities + +//========================================================== +// CLOCK_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_STATE_OBSERVER_PRIO +#define CLOCK_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_STATE_OBSERVER_PRIO +#define POWER_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// RNG_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to this module. + +#ifndef RNG_CONFIG_STATE_OBSERVER_PRIO +#define RNG_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// Stack Event Observers priorities - Invididual priorities + +//========================================================== +// NRF_SDH_ANT_STACK_OBSERVER_PRIO +// This setting configures the priority with which ANT events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have ANT events dispatched before or after other stack events, such as BLE or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_ANT_STACK_OBSERVER_PRIO +#define NRF_SDH_ANT_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_BLE_STACK_OBSERVER_PRIO +// This setting configures the priority with which BLE events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have BLE events dispatched before or after other stack events, such as ANT or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_BLE_STACK_OBSERVER_PRIO +#define NRF_SDH_BLE_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_SOC_STACK_OBSERVER_PRIO +// This setting configures the priority with which SoC events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have SoC events dispatched before or after other stack events, such as ANT or BLE. +// Zero is the highest priority. + +#ifndef NRF_SDH_SOC_STACK_OBSERVER_PRIO +#define NRF_SDH_SOC_STACK_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_SOC_ENABLED - nrf_sdh_soc - SoftDevice SoC event handler +//========================================================== +#ifndef NRF_SDH_SOC_ENABLED +#define NRF_SDH_SOC_ENABLED 0 +#endif +// SoC Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_SOC_OBSERVER_PRIO_LEVELS - Total number of priority levels for SoC observers. +// This setting configures the number of priority levels available for the SoC event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_SOC_OBSERVER_PRIO_LEVELS +#define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS 2 +#endif + +// SoC Observers priorities - Invididual priorities + +//========================================================== +// BLE_ADV_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Advertising module. + +#ifndef BLE_ADV_SOC_OBSERVER_PRIO +#define BLE_ADV_SOC_OBSERVER_PRIO 1 +#endif + +// BLE_DFU_SOC_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_SOC_OBSERVER_PRIO +#define BLE_DFU_SOC_OBSERVER_PRIO 1 +#endif + +// CLOCK_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_SOC_OBSERVER_PRIO +#define CLOCK_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_SOC_OBSERVER_PRIO +#define POWER_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct new file mode 100644 index 0000000000..e69ed0c74f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct @@ -0,0 +1,38 @@ +#! armcc -E + +/* Default to no softdevice */ +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x0 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 0x80000 +#endif + +/* If app_start is 0, do not set aside space for the softdevice */ +#if MBED_APP_START == 0 + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x10000 +#else + #define MBED_RAM_START 0x20003800 + #define MBED_RAM_SIZE 0xC800 +#endif + +#define MBED_RAM0_START MBED_RAM_START +#define MBED_RAM0_SIZE 0xDC +#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE) +#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE) + +LR_IROM1 MBED_APP_START MBED_APP_SIZE { + ER_IROM1 MBED_APP_START MBED_APP_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM0 MBED_RAM0_START UNINIT MBED_RAM0_SIZE { ;no init section + *(*noinit) + } + RW_IRAM1 MBED_RAM1_START MBED_RAM1_SIZE { + .ANY (+RW +ZI) + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/startup_nrf52832.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/startup_nrf52832.S new file mode 100644 index 0000000000..aac3e2c28f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/startup_nrf52832.S @@ -0,0 +1,245 @@ +;/* 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 0x20010000 + + 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 + +__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] +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 + B . + ENDP + ALIGN + END diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld new file mode 100644 index 0000000000..fd78080909 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld @@ -0,0 +1,249 @@ +/* + * 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. */ + +/* Default to no softdevice */ +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x0 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 0x80000 +#endif + +/* If app_start is 0, do not set aside space for the softdevice */ +#if MBED_APP_START == 0 + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x10000 +#else + #define MBED_RAM_START 0x20003800 + #define MBED_RAM_SIZE 0xC800 +#endif + +#define MBED_RAM0_START MBED_RAM_START +#define MBED_RAM0_SIZE 0xDC +#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE) +#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE) + +MEMORY +{ + FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE + RAM_NVIC (rwx) : ORIGIN = MBED_RAM0_START, LENGTH = MBED_RAM0_SIZE + RAM (rwx) : ORIGIN = MBED_RAM1_START, LENGTH = MBED_RAM1_SIZE +} + + +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 + + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > 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 (NOLOAD) : + { + PROVIDE(__start_noinit = .); + KEEP(*(.noinit)) + PROVIDE(__stop_noinit = .); + } > RAM_NVIC + + .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); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/startup_NRF52832.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/startup_NRF52832.S new file mode 100644 index 0000000000..853260b049 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/startup_NRF52832.S @@ -0,0 +1,277 @@ +/* + * 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 DebugMon_Handler + .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 + + + .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 DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_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 + + .end diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf new file mode 100644 index 0000000000..d66a6ab5ab --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf @@ -0,0 +1,75 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ + +/* Default to no softdevice */ +if (!isdefinedsymbol(MBED_APP_START)) { + define symbol MBED_APP_START = 0x0; +} + +if (!isdefinedsymbol(MBED_APP_SIZE)) { + define symbol MBED_APP_SIZE = 0x80000; +} + +/* If app_start is 0, do not set aside space for the softdevice */ +if (MBED_APP_START == 0) { + define symbol MBED_RAM_START = 0x20000000; + define symbol MBED_RAM_SIZE = 0x10000; +} else { + define symbol MBED_RAM_START = 0x20003800; + define symbol MBED_RAM_SIZE = 0xC800; +} + +define symbol MBED_RAM0_START = MBED_RAM_START; +define symbol MBED_RAM0_SIZE = 0xDC; +define symbol MBED_RAM1_START = (MBED_RAM_START + MBED_RAM0_SIZE); +define symbol MBED_RAM1_SIZE = (MBED_RAM_SIZE - MBED_RAM0_SIZE); + +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = MBED_APP_START; + +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = MBED_APP_START; +define symbol __ICFEDIT_region_ROM_end__ = MBED_APP_START + MBED_APP_SIZE - 1; +define symbol __ICFEDIT_region_RAM_NVIC_start__ = MBED_RAM0_START; +define symbol __ICFEDIT_region_RAM_NVIC_end__ = MBED_RAM0_START + MBED_RAM0_SIZE - 1; +define symbol __ICFEDIT_region_RAM_start__ = MBED_RAM1_START; +define symbol __ICFEDIT_region_RAM_end__ = MBED_RAM1_START + MBED_RAM1_SIZE - 1; +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__ = 0x5800; +/**** 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 }; +place at address mem:__ICFEDIT_region_RAM_NVIC_start__ { 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 }; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/startup_NRF52832_IAR.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/startup_NRF52832_IAR.S new file mode 100644 index 0000000000..b27d189e7d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/startup_NRF52832_IAR.S @@ -0,0 +1,381 @@ +;/* 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 + + +__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 . + + + END + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis.h new file mode 100644 index 0000000000..214885742d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.c new file mode 100644 index 0000000000..2efb6da48c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.c @@ -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]; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.h new file mode 100644 index 0000000000..937c497392 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/cmsis_nvic.h @@ -0,0 +1,52 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * 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 + 39) // CORE + MCU Peripherals +#define NVIC_USER_IRQ_OFFSET 16 + +#include "nrf52.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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.c new file mode 100644 index 0000000000..4980feb918 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.c @@ -0,0 +1,365 @@ +/* + +Copyright (c) 2009-2017 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 + + 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. + +NOTICE: This file has been modified by Nordic Semiconductor ASA. + +*/ + +/* NOTE: Template files (including this one) are application specific and therefore expected to + be copied into the application project folder prior to its use! */ + +#include +#include +#include "nrf.h" +#include "system_nrf52.h" +#include "nrf5x_lf_clk_helper.h" + +/*lint ++flb "Enter library region" */ + +#define __SYSTEM_CLOCK_64M (64000000UL) + +static bool errata_12(void); +static bool errata_16(void); +static bool errata_31(void); +static bool errata_32(void); +static bool errata_36(void); +static bool errata_37(void); +static bool errata_57(void); +static bool errata_66(void); +static bool errata_108(void); +static bool errata_136(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) +{ + /* 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_P0->PIN_CNF[18] = (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[14] = (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[15] = (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[16] = (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[18] = (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[20] = (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 + + /* Workaround for Errata 12 "COMP: Reference ladder not correctly calibrated" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_12()){ + *(volatile uint32_t *)0x40013540 = (*(uint32_t *)0x10000324 & 0x00001F00) >> 8; + } + + /* Workaround for Errata 16 "System: RAM may be corrupt on wakeup from CPU IDLE" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_16()){ + *(volatile uint32_t *)0x4007C074 = 3131961357ul; + } + + /* Workaround for Errata 31 "CLOCK: Calibration values are not correctly loaded from FICR at reset" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_31()){ + *(volatile uint32_t *)0x4000053C = ((*(volatile uint32_t *)0x10000244) & 0x0000E000) >> 13; + } + + /* Workaround for Errata 32 "DIF: Debug session automatically enables TracePort pins" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_32()){ + CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; + } + + /* 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 37 "RADIO: Encryption engine is slow by default" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_37()){ + *(volatile uint32_t *)0x400005A0 = 0x3; + } + + /* Workaround for Errata 57 "NFCT: NFC Modulation amplitude" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_57()){ + *(volatile uint32_t *)0x40005610 = 0x00000005; + *(volatile uint32_t *)0x40005688 = 0x00000001; + *(volatile uint32_t *)0x40005618 = 0x00000000; + *(volatile uint32_t *)0x40005614 = 0x0000003F; + } + + /* Workaround for Errata 66 "TEMP: Linearity specification not met with default settings" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_66()){ + NRF_TEMP->A0 = NRF_FICR->TEMP.A0; + NRF_TEMP->A1 = NRF_FICR->TEMP.A1; + NRF_TEMP->A2 = NRF_FICR->TEMP.A2; + NRF_TEMP->A3 = NRF_FICR->TEMP.A3; + NRF_TEMP->A4 = NRF_FICR->TEMP.A4; + NRF_TEMP->A5 = NRF_FICR->TEMP.A5; + NRF_TEMP->B0 = NRF_FICR->TEMP.B0; + NRF_TEMP->B1 = NRF_FICR->TEMP.B1; + NRF_TEMP->B2 = NRF_FICR->TEMP.B2; + NRF_TEMP->B3 = NRF_FICR->TEMP.B3; + NRF_TEMP->B4 = NRF_FICR->TEMP.B4; + NRF_TEMP->B5 = NRF_FICR->TEMP.B5; + NRF_TEMP->T0 = NRF_FICR->TEMP.T0; + NRF_TEMP->T1 = NRF_FICR->TEMP.T1; + NRF_TEMP->T2 = NRF_FICR->TEMP.T2; + NRF_TEMP->T3 = NRF_FICR->TEMP.T3; + NRF_TEMP->T4 = NRF_FICR->TEMP.T4; + } + + /* Workaround for Errata 108 "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_108()){ + *(volatile uint32_t *)0x40000EE4 = *(volatile uint32_t *)0x10000258 & 0x0000004F; + } + + /* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_136()){ + if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){ + NRF_POWER->RESETREAS = ~POWER_RESETREAS_RESETPIN_Msk; + } + } + + /* 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] = 21; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + NRF_UICR->PSELRESET[1] = 21; + 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 + + SystemCoreClockUpdate(); + + // Start the LF oscilator according to the mbed configuration (over the nrf5x_lf_clk_helper.h file) + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_TO_USE << CLOCK_LFCLKSRC_SRC_Pos); + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + // Wait for the external oscillator to start up. + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) { + // Do nothing. + } +} + + +static bool errata_12(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x40){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + +static bool errata_16(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + } + + return false; +} + +static bool errata_31(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x40){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + +static bool errata_32(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + } + + return false; +} + +static bool errata_36(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x40){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + +static bool errata_37(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + } + + return false; +} + +static bool errata_57(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + } + + return false; +} + +static bool errata_66(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + + +static bool errata_108(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x40){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + + +static bool errata_136(void) +{ + if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) && (((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)){ + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x40){ + return true; + } + if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x50){ + return true; + } + } + + return false; +} + + +/*lint --flb "Leave library region" */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.h new file mode 100644 index 0000000000..ee9f40ef66 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/system_nrf52.h @@ -0,0 +1,61 @@ +/* + +Copyright (c) 2009-2017 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 + + 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. + +NOTICE: This file has been modified by Nordic Semiconductor ASA. + +*/ + +#ifndef SYSTEM_NRF52_H +#define SYSTEM_NRF52_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +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_NRF52_H */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralNames.h new file mode 100644 index 0000000000..bcfd647d1a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralNames.h @@ -0,0 +1,82 @@ +/* + * 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 + +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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralPins.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralPins.c new file mode 100644 index 0000000000..aa0813e64a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PeripheralPins.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018 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 "PeripheralPins.h" + +typedef enum { + NRF_SAADC_CHANNEL_0 = 0, + NRF_SAADC_CHANNEL_1 = 1, + NRF_SAADC_CHANNEL_2 = 2, + NRF_SAADC_CHANNEL_3 = 3, + NRF_SAADC_CHANNEL_4 = 4, + NRF_SAADC_CHANNEL_5 = 5, + NRF_SAADC_CHANNEL_6 = 6, + NRF_SAADC_CHANNEL_7 = 7, +} nrf_saadc_channel_t; + +/************ADC***************/ +/* The third "function" value is used to select the correct ADC channel */ +#if DEVICE_ANALOGIN +const PinMap PinMap_ADC[] = { + { p2, ADC0_0, NRF_SAADC_CHANNEL_0 }, + { p3, ADC0_0, NRF_SAADC_CHANNEL_1 }, + { p4, ADC0_0, NRF_SAADC_CHANNEL_2 }, + { p5, ADC0_0, NRF_SAADC_CHANNEL_3 }, + { p28, ADC0_0, NRF_SAADC_CHANNEL_4 }, + { p29, ADC0_0, NRF_SAADC_CHANNEL_5 }, + { p30, ADC0_0, NRF_SAADC_CHANNEL_6 }, + { p31, ADC0_0, NRF_SAADC_CHANNEL_7 }, + { NC, NC, NC } +}; +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PortNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PortNames.h new file mode 100644 index 0000000000..b0162fb1ee --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/PortNames.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h new file mode 100644 index 0000000000..2a5f319abd --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h @@ -0,0 +1,245 @@ +/* + * 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, + STDIO_UART_TX = TX_PIN_NUMBER, + STDIO_UART_RX = RX_PIN_NUMBER, + STDIO_UART_CTS = CTS_PIN_NUMBER, + STDIO_UART_RTS = RTS_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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/device.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/device.h new file mode 100644 index 0000000000..2427e752ea --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/device.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h new file mode 100644 index 0000000000..393d9be522 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h @@ -0,0 +1,8744 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// Board Support + +//========================================================== +// BSP_BTN_BLE_ENABLED - bsp_btn_ble - Button Control for BLE + + +#ifndef BSP_BTN_BLE_ENABLED +#define BSP_BTN_BLE_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_ANT + +//========================================================== +// ANTFS_ENABLED - ant_fs - ANT File Share module. +//========================================================== +#ifndef ANTFS_ENABLED +#define ANTFS_ENABLED 0 +#endif +// ANTFS_CONFIG_NETWORK_NUMBER - ANT-FS network number. +#ifndef ANTFS_CONFIG_NETWORK_NUMBER +#define ANTFS_CONFIG_NETWORK_NUMBER 0 +#endif + +// ANTFS_CONFIG_CHANNEL_NUMBER - ANT-FS channel number. +#ifndef ANTFS_CONFIG_CHANNEL_NUMBER +#define ANTFS_CONFIG_CHANNEL_NUMBER 0 +#endif + +// ANTFS_CONFIG_PAIRING_TIMEOUT - Pairing timeout - how long the UI will wait for a response to a pairing request before switching to the link layer, in seconds. +#ifndef ANTFS_CONFIG_PAIRING_TIMEOUT +#define ANTFS_CONFIG_PAIRING_TIMEOUT 120 +#endif + +// ANTFS_CONFIG_LINK_COMMAND_TIMEOUT - Command timeout - how long the client will wait without receiving any commands before switching to the link layer, in seconds. +#ifndef ANTFS_CONFIG_LINK_COMMAND_TIMEOUT +#define ANTFS_CONFIG_LINK_COMMAND_TIMEOUT 10 +#endif + +// ANTFS_CONFIG_TRANS_TYPE - ANT-FS Transmission Type. +#ifndef ANTFS_CONFIG_TRANS_TYPE +#define ANTFS_CONFIG_TRANS_TYPE 10 +#endif + +// ANTFS_CONFIG_DEVICE_TYPE - ANT device type for channel configuration. +#ifndef ANTFS_CONFIG_DEVICE_TYPE +#define ANTFS_CONFIG_DEVICE_TYPE 1 +#endif + +// ANTFS_CONFIG_BEACON_STATUS_PERIOD - ANT-FS Beacon Message Period. + +// <0=> 0.5 Hz +// <1=> 1 Hz +// <2=> 2 Hz +// <3=> 4 Hz +// <4=> 8 Hz + +#ifndef ANTFS_CONFIG_BEACON_STATUS_PERIOD +#define ANTFS_CONFIG_BEACON_STATUS_PERIOD 3 +#endif + +// ANTFS_CONFIG_TRANSMIT_POWER - ANT Transmit Power. + +// <0=> Lowest ANT Tx power level setting. (-20dBm) +// <1=> ANT Tx power > Lvl 0. (-12dBm) +// <2=> ANT Tx power > Lvl 1. (-4dBm) +// <3=> ANT Tx power > Lvl 2. Default tx power level. (0dBm) +// <4=> ANT Tx power > Lvl 3. (+4dBm) +// <128=> Custom tx power selection + +#ifndef ANTFS_CONFIG_TRANSMIT_POWER +#define ANTFS_CONFIG_TRANSMIT_POWER 3 +#endif + +// ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER - ANT Custom Transmit Power. +#ifndef ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER +#define ANTFS_CONFIG_CUSTOM_TRANSMIT_POWER 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED - Use pairing and key exchange authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PAIRING_ENABLED 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED - Use passkey authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PASSKEY_ENABLED 0 +#endif + +// ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED - Allow host to bypass authentication. + + +#ifndef ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED +#define ANTFS_CONFIG_AUTH_TYPE_PASSTHROUGH_ENABLED 0 +#endif + +// ANTFS_CONFIG_UPLOAD_ENABLED - Support upload operation. + + +#ifndef ANTFS_CONFIG_UPLOAD_ENABLED +#define ANTFS_CONFIG_UPLOAD_ENABLED 0 +#endif + +// ANTFS_CONFIG_DEBUG_LED_ENABLED - Enables LED debug in the module. + + +#ifndef ANTFS_CONFIG_DEBUG_LED_ENABLED +#define ANTFS_CONFIG_DEBUG_LED_ENABLED 0 +#endif + +// + +// ANT_BPWR_ENABLED - ant_bpwr - Bicycle Power Profile +//========================================================== +#ifndef ANT_BPWR_ENABLED +#define ANT_BPWR_ENABLED 0 +#endif +// ANT_BPWR_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_BPWR_LOG_ENABLED +#define ANT_BPWR_LOG_ENABLED 0 +#endif +// ANT_BPWR_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_LOG_LEVEL +#define ANT_BPWR_LOG_LEVEL 3 +#endif + +// ANT_BPWR_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_INFO_COLOR +#define ANT_BPWR_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_COMMON_LOG_ENABLED - Enables logging of BPWR tracing common data. +//========================================================== +#ifndef ANT_BPWR_COMMON_LOG_ENABLED +#define ANT_BPWR_COMMON_LOG_ENABLED 0 +#endif +// ANT_BPWR_COMMON_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_COMMON_LOG_LEVEL +#define ANT_BPWR_COMMON_LOG_LEVEL 3 +#endif + +// ANT_BPWR_COMMON_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_COMMON_INFO_COLOR +#define ANT_BPWR_COMMON_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_TORQUE_LOG_ENABLED - Enables logging of BPWR torque page in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_TORQUE_LOG_ENABLED +#define ANT_BPWR_PAGE_TORQUE_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_TORQUE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_TORQUE_LOG_LEVEL +#define ANT_BPWR_PAGE_TORQUE_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_TORQUE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_TORQUE_INFO_COLOR +#define ANT_BPWR_PAGE_TORQUE_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_1_LOG_ENABLED - Enables logging of BPWR page 1 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_1_LOG_ENABLED +#define ANT_BPWR_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_1_LOG_LEVEL +#define ANT_BPWR_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_1_INFO_COLOR +#define ANT_BPWR_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_16_LOG_ENABLED - Enables logging of BPWR page 16 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_16_LOG_ENABLED +#define ANT_BPWR_PAGE_16_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_16_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_16_LOG_LEVEL +#define ANT_BPWR_PAGE_16_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_16_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_16_INFO_COLOR +#define ANT_BPWR_PAGE_16_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_17_LOG_ENABLED - Enables logging of BPWR page 17 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_17_LOG_ENABLED +#define ANT_BPWR_PAGE_17_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_17_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_17_LOG_LEVEL +#define ANT_BPWR_PAGE_17_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_17_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_17_INFO_COLOR +#define ANT_BPWR_PAGE_17_INFO_COLOR 0 +#endif + +// + +// ANT_BPWR_PAGE_18_LOG_ENABLED - Enables logging of BPWR page 18 in the module. +//========================================================== +#ifndef ANT_BPWR_PAGE_18_LOG_ENABLED +#define ANT_BPWR_PAGE_18_LOG_ENABLED 0 +#endif +// ANT_BPWR_PAGE_18_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BPWR_PAGE_18_LOG_LEVEL +#define ANT_BPWR_PAGE_18_LOG_LEVEL 3 +#endif + +// ANT_BPWR_PAGE_18_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BPWR_PAGE_18_INFO_COLOR +#define ANT_BPWR_PAGE_18_INFO_COLOR 0 +#endif + +// + +// + +// ANT_BSC_ENABLED - ant_bsc - Bicycle Speed and Cadence Profile +//========================================================== +#ifndef ANT_BSC_ENABLED +#define ANT_BSC_ENABLED 0 +#endif +// ANT_BSC_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_BSC_LOG_ENABLED +#define ANT_BSC_LOG_ENABLED 0 +#endif +// ANT_BSC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_LOG_LEVEL +#define ANT_BSC_LOG_LEVEL 3 +#endif + +// ANT_BSC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_INFO_COLOR +#define ANT_BSC_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED - Enables logging of BSC Combined page 0 in the module. +//========================================================== +#ifndef ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED +#define ANT_BSC_COMBINED_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL +#define ANT_BSC_COMBINED_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_BSC_COMBINED_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_COMBINED_PAGE_0_INFO_COLOR +#define ANT_BSC_COMBINED_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_0_LOG_ENABLED - Enables logging of BSC page 0 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_0_LOG_ENABLED +#define ANT_BSC_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_0_LOG_LEVEL +#define ANT_BSC_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_0_INFO_COLOR +#define ANT_BSC_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_1_LOG_ENABLED - Enables logging of BSC page 1 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_1_LOG_ENABLED +#define ANT_BSC_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_1_LOG_LEVEL +#define ANT_BSC_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_1_INFO_COLOR +#define ANT_BSC_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_2_LOG_ENABLED - Enables logging of BSC page 2 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_2_LOG_ENABLED +#define ANT_BSC_PAGE_2_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_2_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_2_LOG_LEVEL +#define ANT_BSC_PAGE_2_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_2_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_2_INFO_COLOR +#define ANT_BSC_PAGE_2_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_3_LOG_ENABLED - Enables logging of BSC page 3 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_3_LOG_ENABLED +#define ANT_BSC_PAGE_3_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_3_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_3_LOG_LEVEL +#define ANT_BSC_PAGE_3_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_3_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_3_INFO_COLOR +#define ANT_BSC_PAGE_3_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_4_LOG_ENABLED - Enables logging of BSC page 4 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_4_LOG_ENABLED +#define ANT_BSC_PAGE_4_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_4_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_4_LOG_LEVEL +#define ANT_BSC_PAGE_4_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_4_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_4_INFO_COLOR +#define ANT_BSC_PAGE_4_INFO_COLOR 0 +#endif + +// + +// ANT_BSC_PAGE_5_LOG_ENABLED - Enables logging of BSC page 5 in the module. +//========================================================== +#ifndef ANT_BSC_PAGE_5_LOG_ENABLED +#define ANT_BSC_PAGE_5_LOG_ENABLED 0 +#endif +// ANT_BSC_PAGE_5_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_BSC_PAGE_5_LOG_LEVEL +#define ANT_BSC_PAGE_5_LOG_LEVEL 3 +#endif + +// ANT_BSC_PAGE_5_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_BSC_PAGE_5_INFO_COLOR +#define ANT_BSC_PAGE_5_INFO_COLOR 0 +#endif + +// + +// + +// ANT_CHANNEL_CONFIG_ENABLED - ant_channel_config - ANT common channel configuration + + +#ifndef ANT_CHANNEL_CONFIG_ENABLED +#define ANT_CHANNEL_CONFIG_ENABLED 0 +#endif + +// ANT_COMMON_PAGE_70_ENABLED - ant_common_page_70 - ANT+ common page 70 +//========================================================== +#ifndef ANT_COMMON_PAGE_70_ENABLED +#define ANT_COMMON_PAGE_70_ENABLED 0 +#endif +// ANT_COMMON_PAGE_70_LOG_ENABLED - Enables logging of common page 70 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_70_LOG_ENABLED +#define ANT_COMMON_PAGE_70_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_70_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_70_LOG_LEVEL +#define ANT_COMMON_PAGE_70_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_70_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_70_INFO_COLOR +#define ANT_COMMON_PAGE_70_INFO_COLOR 0 +#endif + +// + +// + +// ANT_COMMON_PAGE_80_ENABLED - ant_common_page_80 - ANT+ common page 80 +//========================================================== +#ifndef ANT_COMMON_PAGE_80_ENABLED +#define ANT_COMMON_PAGE_80_ENABLED 0 +#endif +// ANT_COMMON_PAGE_80_LOG_ENABLED - Enables logging of common page 80 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_80_LOG_ENABLED +#define ANT_COMMON_PAGE_80_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_80_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_80_LOG_LEVEL +#define ANT_COMMON_PAGE_80_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_80_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_80_INFO_COLOR +#define ANT_COMMON_PAGE_80_INFO_COLOR 0 +#endif + +// + +// + +// ANT_COMMON_PAGE_81_ENABLED - ant_common_page_81 - ANT+ common page 81 +//========================================================== +#ifndef ANT_COMMON_PAGE_81_ENABLED +#define ANT_COMMON_PAGE_81_ENABLED 0 +#endif +// ANT_COMMON_PAGE_81_LOG_ENABLED - Enables logging of common page 81 in the module. +//========================================================== +#ifndef ANT_COMMON_PAGE_81_LOG_ENABLED +#define ANT_COMMON_PAGE_81_LOG_ENABLED 0 +#endif +// ANT_COMMON_PAGE_81_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_COMMON_PAGE_81_LOG_LEVEL +#define ANT_COMMON_PAGE_81_LOG_LEVEL 3 +#endif + +// ANT_COMMON_PAGE_81_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_COMMON_PAGE_81_INFO_COLOR +#define ANT_COMMON_PAGE_81_INFO_COLOR 0 +#endif + +// + +// + +// ANT_ENCRYPT_CONFIG_ENABLED - ant_encrypt_config - Cryptographic ANT stack configuration + + +#ifndef ANT_ENCRYPT_CONFIG_ENABLED +#define ANT_ENCRYPT_CONFIG_ENABLED 0 +#endif + +// ANT_HRM_ENABLED - ant_hrm - Heart Rate Monitor Profile +//========================================================== +#ifndef ANT_HRM_ENABLED +#define ANT_HRM_ENABLED 0 +#endif +// ANT_HRM_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_HRM_LOG_ENABLED +#define ANT_HRM_LOG_ENABLED 0 +#endif +// ANT_HRM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_LOG_LEVEL +#define ANT_HRM_LOG_LEVEL 3 +#endif + +// ANT_HRM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_INFO_COLOR +#define ANT_HRM_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_0_LOG_ENABLED - Enables logging of HRM page 0 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_0_LOG_ENABLED +#define ANT_HRM_PAGE_0_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_0_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_0_LOG_LEVEL +#define ANT_HRM_PAGE_0_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_0_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_0_INFO_COLOR +#define ANT_HRM_PAGE_0_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_1_LOG_ENABLED - Enables logging of HRM page 1 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_1_LOG_ENABLED +#define ANT_HRM_PAGE_1_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_1_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_1_LOG_LEVEL +#define ANT_HRM_PAGE_1_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_1_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_1_INFO_COLOR +#define ANT_HRM_PAGE_1_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_2_LOG_ENABLED - Enables logging of HRM page 2 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_2_LOG_ENABLED +#define ANT_HRM_PAGE_2_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_2_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_2_LOG_LEVEL +#define ANT_HRM_PAGE_2_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_2_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_2_INFO_COLOR +#define ANT_HRM_PAGE_2_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_3_LOG_ENABLED - Enables logging of HRM page 3 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_3_LOG_ENABLED +#define ANT_HRM_PAGE_3_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_3_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_3_LOG_LEVEL +#define ANT_HRM_PAGE_3_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_3_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_3_INFO_COLOR +#define ANT_HRM_PAGE_3_INFO_COLOR 0 +#endif + +// + +// ANT_HRM_PAGE_4_LOG_ENABLED - Enables logging of HRM page 4 in the module. +//========================================================== +#ifndef ANT_HRM_PAGE_4_LOG_ENABLED +#define ANT_HRM_PAGE_4_LOG_ENABLED 0 +#endif +// ANT_HRM_PAGE_4_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_HRM_PAGE_4_LOG_LEVEL +#define ANT_HRM_PAGE_4_LOG_LEVEL 3 +#endif + +// ANT_HRM_PAGE_4_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_HRM_PAGE_4_INFO_COLOR +#define ANT_HRM_PAGE_4_INFO_COLOR 0 +#endif + +// + +// + +// ANT_KEY_MANAGER_ENABLED - ant_key_manager - Software Component + + +#ifndef ANT_KEY_MANAGER_ENABLED +#define ANT_KEY_MANAGER_ENABLED 0 +#endif + +// ANT_REQUEST_CONTROLLER_ENABLED - ant_request_controller - ANT+ request controller + + +#ifndef ANT_REQUEST_CONTROLLER_ENABLED +#define ANT_REQUEST_CONTROLLER_ENABLED 0 +#endif + +// ANT_SDM_ENABLED - ant_sdm - Stride Based Speed and Distance Monitor Profile +//========================================================== +#ifndef ANT_SDM_ENABLED +#define ANT_SDM_ENABLED 0 +#endif +// ANT_SDM_LOG_ENABLED - Enables general logging in the module. +//========================================================== +#ifndef ANT_SDM_LOG_ENABLED +#define ANT_SDM_LOG_ENABLED 0 +#endif +// ANT_SDM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef ANT_SDM_LOG_LEVEL +#define ANT_SDM_LOG_LEVEL 3 +#endif + +// ANT_SDM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef ANT_SDM_INFO_COLOR +#define ANT_SDM_INFO_COLOR 0 +#endif + +// + +// + +// ANT_SEARCH_CONFIG_ENABLED - ant_search_config - ANT common search configuration +//========================================================== +#ifndef ANT_SEARCH_CONFIG_ENABLED +#define ANT_SEARCH_CONFIG_ENABLED 0 +#endif +// ANT_DEFAULT_LOW_PRIORITY_TIMEOUT - Default low priority search time-out. <0-255> + + +#ifndef ANT_DEFAULT_LOW_PRIORITY_TIMEOUT +#define ANT_DEFAULT_LOW_PRIORITY_TIMEOUT 2 +#endif + +// ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT - Default high priority search time-out. <0-255> + + +#ifndef ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT +#define ANT_DEFAULT_HIGH_PRIORITY_TIMEOUT 10 +#endif + +// + +// ANT_STACK_CONFIG_ENABLED - ant_stack_config - Common ANT stack configuration +//========================================================== +#ifndef ANT_STACK_CONFIG_ENABLED +#define ANT_STACK_CONFIG_ENABLED 0 +#endif +// ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED - Allocated ANT channels +#ifndef ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED +#define ANT_CONFIG_TOTAL_CHANNELS_ALLOCATED 0 +#endif + +// ANT_CONFIG_ENCRYPTED_CHANNELS - Encrypted ANT channels +#ifndef ANT_CONFIG_ENCRYPTED_CHANNELS +#define ANT_CONFIG_ENCRYPTED_CHANNELS 0 +#endif + +// ANT_CONFIG_EVENT_QUEUE_SIZE - Event queue size +#ifndef ANT_CONFIG_EVENT_QUEUE_SIZE +#define ANT_CONFIG_EVENT_QUEUE_SIZE 32 +#endif + +// ANT_CONFIG_BURST_QUEUE_SIZE - ANT burst queue size +#ifndef ANT_CONFIG_BURST_QUEUE_SIZE +#define ANT_CONFIG_BURST_QUEUE_SIZE 128 +#endif + +// + +// ANT_STATE_INDICATOR_ENABLED - ant_state_indicator - ANT state indicator using BSP +//========================================================== +#ifndef ANT_STATE_INDICATOR_ENABLED +#define ANT_STATE_INDICATOR_ENABLED 0 +#endif +// ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY - Shutdown observer priority. +#ifndef ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY +#define ANT_STATE_INDICATOR_CONFIG_SHUTDOWN_HANDLER_PRIORITY 1 +#endif + +// + +// +//========================================================== + +// nRF_BLE + +//========================================================== +// BLE_ADVERTISING_ENABLED - ble_advertising - Advertising module + + +#ifndef BLE_ADVERTISING_ENABLED +#define BLE_ADVERTISING_ENABLED 0 +#endif + +// BLE_DTM_ENABLED - ble_dtm - Module for testing RF/PHY using DTM commands + + +#ifndef BLE_DTM_ENABLED +#define BLE_DTM_ENABLED 0 +#endif + +// BLE_RACP_ENABLED - ble_racp - Record Access Control Point library + + +#ifndef BLE_RACP_ENABLED +#define BLE_RACP_ENABLED 0 +#endif + +// NRF_BLE_CONN_PARAMS_ENABLED - ble_conn_params - Initiating and executing a connection parameters negotiation procedure +//========================================================== +#ifndef NRF_BLE_CONN_PARAMS_ENABLED +#define NRF_BLE_CONN_PARAMS_ENABLED 0 +#endif +// NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION - The largest acceptable deviation in slave latency. +// The largest deviation (+ or -) from the requested slave latency that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION 499 +#endif + +// NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION - The largest acceptable deviation (in 10 ms units) in supervision timeout. +// The largest deviation (+ or -, in 10 ms units) from the requested supervision timeout that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION 65535 +#endif + +// + +// NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write) + + +#ifndef NRF_BLE_QWR_ENABLED +#define NRF_BLE_QWR_ENABLED 0 +#endif + +// PEER_MANAGER_ENABLED - peer_manager - Peer Manager +//========================================================== +#ifndef PEER_MANAGER_ENABLED +#define PEER_MANAGER_ENABLED 0 +#endif +// PM_MAX_REGISTRANTS +// Number of event handlers that can be registered. + +#ifndef PM_MAX_REGISTRANTS +#define PM_MAX_REGISTRANTS 3 +#endif + +// PM_FLASH_BUFFERS +// Number of internal buffers for flash operations. +// Decrease this value to lower RAM usage. + +#ifndef PM_FLASH_BUFFERS +#define PM_FLASH_BUFFERS 8 +#endif + +// + +// +//========================================================== + +// nRF_BLE_Services + +//========================================================== +// BLE_ANCS_C_ENABLED - ble_ancs_c - Apple Notification Service Client + + +#ifndef BLE_ANCS_C_ENABLED +#define BLE_ANCS_C_ENABLED 0 +#endif + +// BLE_ANS_C_ENABLED - ble_ans_c - Alert Notification Service Client + + +#ifndef BLE_ANS_C_ENABLED +#define BLE_ANS_C_ENABLED 0 +#endif + +// BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client + + +#ifndef BLE_BAS_C_ENABLED +#define BLE_BAS_C_ENABLED 0 +#endif + +// BLE_BAS_ENABLED - ble_bas - Battery Service + + +#ifndef BLE_BAS_ENABLED +#define BLE_BAS_ENABLED 0 +#endif + +// BLE_CSCS_ENABLED - ble_cscs - Cycling Speed and Cadence Service + + +#ifndef BLE_CSCS_ENABLED +#define BLE_CSCS_ENABLED 0 +#endif + +// BLE_CTS_C_ENABLED - ble_cts_c - Current Time Service Client + + +#ifndef BLE_CTS_C_ENABLED +#define BLE_CTS_C_ENABLED 0 +#endif + +// BLE_DIS_ENABLED - ble_dis - Device Information Service + + +#ifndef BLE_DIS_ENABLED +#define BLE_DIS_ENABLED 0 +#endif + +// BLE_GLS_ENABLED - ble_gls - Glucose Service + + +#ifndef BLE_GLS_ENABLED +#define BLE_GLS_ENABLED 0 +#endif + +// BLE_HIDS_ENABLED - ble_hids - Human Interface Device Service + + +#ifndef BLE_HIDS_ENABLED +#define BLE_HIDS_ENABLED 0 +#endif + +// BLE_HRS_C_ENABLED - ble_hrs_c - Heart Rate Service Client + + +#ifndef BLE_HRS_C_ENABLED +#define BLE_HRS_C_ENABLED 0 +#endif + +// BLE_HRS_ENABLED - ble_hrs - Heart Rate Service + + +#ifndef BLE_HRS_ENABLED +#define BLE_HRS_ENABLED 0 +#endif + +// BLE_HTS_ENABLED - ble_hts - Health Thermometer Service + + +#ifndef BLE_HTS_ENABLED +#define BLE_HTS_ENABLED 0 +#endif + +// BLE_IAS_C_ENABLED - ble_ias_c - Immediate Alert Service Client + + +#ifndef BLE_IAS_C_ENABLED +#define BLE_IAS_C_ENABLED 0 +#endif + +// BLE_IAS_ENABLED - ble_ias - Immediate Alert Service + + +#ifndef BLE_IAS_ENABLED +#define BLE_IAS_ENABLED 0 +#endif + +// BLE_LBS_C_ENABLED - ble_lbs_c - Nordic LED Button Service Client + + +#ifndef BLE_LBS_C_ENABLED +#define BLE_LBS_C_ENABLED 0 +#endif + +// BLE_LBS_ENABLED - ble_lbs - LED Button Service + + +#ifndef BLE_LBS_ENABLED +#define BLE_LBS_ENABLED 0 +#endif + +// BLE_LLS_ENABLED - ble_lls - Link Loss Service + + +#ifndef BLE_LLS_ENABLED +#define BLE_LLS_ENABLED 0 +#endif + +// BLE_NUS_C_ENABLED - ble_nus_c - Nordic UART Central Service + + +#ifndef BLE_NUS_C_ENABLED +#define BLE_NUS_C_ENABLED 0 +#endif + +// BLE_NUS_ENABLED - ble_nus - Nordic UART Service + + +#ifndef BLE_NUS_ENABLED +#define BLE_NUS_ENABLED 0 +#endif + +// BLE_RSCS_C_ENABLED - ble_rscs_c - Running Speed and Cadence Client + + +#ifndef BLE_RSCS_C_ENABLED +#define BLE_RSCS_C_ENABLED 0 +#endif + +// BLE_RSCS_ENABLED - ble_rscs - Running Speed and Cadence Service + + +#ifndef BLE_RSCS_ENABLED +#define BLE_RSCS_ENABLED 0 +#endif + +// BLE_TPS_ENABLED - ble_tps - TX Power Service + + +#ifndef BLE_TPS_ENABLED +#define BLE_TPS_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Core + +//========================================================== +// NRF_MPU_ENABLED - nrf_mpu - Module for MPU +//========================================================== +#ifndef NRF_MPU_ENABLED +#define NRF_MPU_ENABLED 0 +#endif +// NRF_MPU_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_MPU_CLI_CMDS +#define NRF_MPU_CLI_CMDS 1 +#endif + +// + +// NRF_STACK_GUARD_ENABLED - nrf_stack_guard - Module for Protecting Stack +//========================================================== +#ifndef NRF_STACK_GUARD_ENABLED +#define NRF_STACK_GUARD_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_SIZE - Size of stack guard + +// <5=> 32 bytes +// <6=> 64 bytes +// <7=> 128 bytes +// <8=> 256 bytes +// <9=> 512 bytes +// <10=> 1024 bytes +// <11=> 2048 bytes +// <12=> 4096 bytes + +#ifndef NRF_STACK_GUARD_CONFIG_SIZE +#define NRF_STACK_GUARD_CONFIG_SIZE 7 +#endif + +// + +// +//========================================================== + +// nRF_Crypto + +//========================================================== +// NRF_CRYPTO_ENABLED - nrf_crypto - Cryptography library +//========================================================== +#ifndef NRF_CRYPTO_ENABLED +#define NRF_CRYPTO_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_LIB - Enable the ARM Cryptocell CC310 backend + + +// The hardware-accelerated cryptography backend is available only on nRF52840. + +#ifndef NRF_CRYPTO_BACKEND_CC310_LIB +#define NRF_CRYPTO_BACKEND_CC310_LIB 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC - Enable the micro-ecc software backend + +// The micro-ecc library provides a software implementation of ECC cryptography for nRF5 Series devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC +#define NRF_CRYPTO_BACKEND_MICRO_ECC 0 +#endif +// NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 - Enable SHA256 + + +// Enable SHA256 cryptographic hash functionality. +// Enable this setting if you need SHA256 support, for example to verify signatures. + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 +#define NRF_CRYPTO_BACKEND_MICRO_ECC_SHA256 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_RNG - Enable random number generator + + +// Enable random number generation. +// Enable this setting if you need to generate cryptographic keys. +// This setting requires the RNG peripheral driver to be present. + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_RNG +#define NRF_CRYPTO_BACKEND_MICRO_ECC_RNG 0 +#endif + +// + +// + +// +//========================================================== + +// nRF_DFU + +//========================================================== +// ble_dfu - Device Firmware Update + +//========================================================== +// BLE_DFU_ENABLED - Enable DFU Service. + + +#ifndef BLE_DFU_ENABLED +#define BLE_DFU_ENABLED 0 +#endif + +// NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS - Buttonless DFU supports bonds. + + +#ifndef NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS +#define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Drivers + +//========================================================== +// APP_USBD_ENABLED - app_usbd - USB Device library +//========================================================== +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 0 +#endif +// APP_USBD_VID - Vendor ID <0x0000-0xFFFF> + + +// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ + +#ifndef APP_USBD_VID +#define APP_USBD_VID 0 +#endif + +// APP_USBD_PID - Product ID <0x0000-0xFFFF> + + +// Selected Product ID + +#ifndef APP_USBD_PID +#define APP_USBD_PID 0 +#endif + +// APP_USBD_DEVICE_VER_MAJOR - Device version, major part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MAJOR +#define APP_USBD_DEVICE_VER_MAJOR 1 +#endif + +// APP_USBD_DEVICE_VER_MINOR - Device version, minor part <0-99> + + +// Device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MINOR +#define APP_USBD_DEVICE_VER_MINOR 0 +#endif + +// APP_USBD_EVENT_QUEUE_ENABLE - Enable event queue + +// This is the default configuration when all the events are placed into internal queue. +// Disable it when external queue is used like app_scheduler or if you wish to process all events inside interrupts. +// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. +// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable and disable. +//========================================================== +#ifndef APP_USBD_EVENT_QUEUE_ENABLE +#define APP_USBD_EVENT_QUEUE_ENABLE 1 +#endif +// APP_USBD_EVENT_QUEUE_SIZE - The size of event queue <16-64> + + +// The size of the queue for the events that would be processed in the main loop. + +#ifndef APP_USBD_EVENT_QUEUE_SIZE +#define APP_USBD_EVENT_QUEUE_SIZE 32 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CONFIG_LOG_LEVEL +#define APP_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_INFO_COLOR +#define APP_USBD_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_DEBUG_COLOR +#define APP_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver +//========================================================== +#ifndef CLOCK_ENABLED +#define CLOCK_ENABLED 0 +#endif +// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency + +// <0=> Default (64 MHz) + +#ifndef CLOCK_CONFIG_XTAL_FREQ +#define CLOCK_CONFIG_XTAL_FREQ 0 +#endif + +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// COMP_ENABLED - nrf_drv_comp - COMP peripheral driver +//========================================================== +#ifndef COMP_ENABLED +#define COMP_ENABLED 0 +#endif +// COMP_CONFIG_REF - Reference voltage + +// <0=> Internal 1.2V +// <1=> Internal 1.8V +// <2=> Internal 2.4V +// <4=> VDD +// <7=> ARef + +#ifndef COMP_CONFIG_REF +#define COMP_CONFIG_REF 1 +#endif + +// COMP_CONFIG_MAIN_MODE - Main mode + +// <0=> Single ended +// <1=> Differential + +#ifndef COMP_CONFIG_MAIN_MODE +#define COMP_CONFIG_MAIN_MODE 0 +#endif + +// COMP_CONFIG_SPEED_MODE - Speed mode + +// <0=> Low power +// <1=> Normal +// <2=> High speed + +#ifndef COMP_CONFIG_SPEED_MODE +#define COMP_CONFIG_SPEED_MODE 2 +#endif + +// COMP_CONFIG_HYST - Hystheresis + +// <0=> No +// <1=> 50mV + +#ifndef COMP_CONFIG_HYST +#define COMP_CONFIG_HYST 0 +#endif + +// COMP_CONFIG_ISOURCE - Current Source + +// <0=> Off +// <1=> 2.5 uA +// <2=> 5 uA +// <3=> 10 uA + +#ifndef COMP_CONFIG_ISOURCE +#define COMP_CONFIG_ISOURCE 0 +#endif + +// COMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_INPUT +#define COMP_CONFIG_INPUT 0 +#endif + +// COMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_IRQ_PRIORITY +#define COMP_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// EGU_ENABLED - nrf_drv_swi - SWI(EGU) peripheral driver + + +#ifndef EGU_ENABLED +#define EGU_ENABLED 0 +#endif + +// GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver +//========================================================== +#ifndef GPIOTE_ENABLED +#define GPIOTE_ENABLED 1 +#endif +// GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins +#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +// GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef GPIOTE_CONFIG_IRQ_PRIORITY +#define GPIOTE_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// I2S_ENABLED - nrf_drv_i2s - I2S peripheral driver +//========================================================== +#ifndef I2S_ENABLED +#define I2S_ENABLED 0 +#endif +// I2S_CONFIG_SCK_PIN - SCK pin <0-31> + + +#ifndef I2S_CONFIG_SCK_PIN +#define I2S_CONFIG_SCK_PIN 31 +#endif + +// I2S_CONFIG_LRCK_PIN - LRCK pin <1-31> + + +#ifndef I2S_CONFIG_LRCK_PIN +#define I2S_CONFIG_LRCK_PIN 30 +#endif + +// I2S_CONFIG_MCK_PIN - MCK pin +#ifndef I2S_CONFIG_MCK_PIN +#define I2S_CONFIG_MCK_PIN 255 +#endif + +// I2S_CONFIG_SDOUT_PIN - SDOUT pin <0-31> + + +#ifndef I2S_CONFIG_SDOUT_PIN +#define I2S_CONFIG_SDOUT_PIN 29 +#endif + +// I2S_CONFIG_SDIN_PIN - SDIN pin <0-31> + + +#ifndef I2S_CONFIG_SDIN_PIN +#define I2S_CONFIG_SDIN_PIN 28 +#endif + +// I2S_CONFIG_MASTER - Mode + +// <0=> Master +// <1=> Slave + +#ifndef I2S_CONFIG_MASTER +#define I2S_CONFIG_MASTER 0 +#endif + +// I2S_CONFIG_FORMAT - Format + +// <0=> I2S +// <1=> Aligned + +#ifndef I2S_CONFIG_FORMAT +#define I2S_CONFIG_FORMAT 0 +#endif + +// I2S_CONFIG_ALIGN - Alignment + +// <0=> Left +// <1=> Right + +#ifndef I2S_CONFIG_ALIGN +#define I2S_CONFIG_ALIGN 0 +#endif + +// I2S_CONFIG_SWIDTH - Sample width (bits) + +// <0=> 8 +// <1=> 16 +// <2=> 24 + +#ifndef I2S_CONFIG_SWIDTH +#define I2S_CONFIG_SWIDTH 1 +#endif + +// I2S_CONFIG_CHANNELS - Channels + +// <0=> Stereo +// <1=> Left +// <2=> Right + +#ifndef I2S_CONFIG_CHANNELS +#define I2S_CONFIG_CHANNELS 1 +#endif + +// I2S_CONFIG_MCK_SETUP - MCK behavior + +// <0=> Disabled +// <2147483648=> 32MHz/2 +// <1342177280=> 32MHz/3 +// <1073741824=> 32MHz/4 +// <805306368=> 32MHz/5 +// <671088640=> 32MHz/6 +// <536870912=> 32MHz/8 +// <402653184=> 32MHz/10 +// <369098752=> 32MHz/11 +// <285212672=> 32MHz/15 +// <268435456=> 32MHz/16 +// <201326592=> 32MHz/21 +// <184549376=> 32MHz/23 +// <142606336=> 32MHz/30 +// <138412032=> 32MHz/31 +// <134217728=> 32MHz/32 +// <100663296=> 32MHz/42 +// <68157440=> 32MHz/63 +// <34340864=> 32MHz/125 + +#ifndef I2S_CONFIG_MCK_SETUP +#define I2S_CONFIG_MCK_SETUP 536870912 +#endif + +// I2S_CONFIG_RATIO - MCK/LRCK ratio + +// <0=> 32x +// <1=> 48x +// <2=> 64x +// <3=> 96x +// <4=> 128x +// <5=> 192x +// <6=> 256x +// <7=> 384x +// <8=> 512x + +#ifndef I2S_CONFIG_RATIO +#define I2S_CONFIG_RATIO 2000 +#endif + +// I2S_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef I2S_CONFIG_IRQ_PRIORITY +#define I2S_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// LPCOMP_ENABLED - nrf_drv_lpcomp - LPCOMP peripheral driver +//========================================================== +#ifndef LPCOMP_ENABLED +#define LPCOMP_ENABLED 0 +#endif +// LPCOMP_CONFIG_REFERENCE - Reference voltage + +// <0=> Supply 1/8 +// <1=> Supply 2/8 +// <2=> Supply 3/8 +// <3=> Supply 4/8 +// <4=> Supply 5/8 +// <5=> Supply 6/8 +// <6=> Supply 7/8 +// <8=> Supply 1/16 (nRF52) +// <9=> Supply 3/16 (nRF52) +// <10=> Supply 5/16 (nRF52) +// <11=> Supply 7/16 (nRF52) +// <12=> Supply 9/16 (nRF52) +// <13=> Supply 11/16 (nRF52) +// <14=> Supply 13/16 (nRF52) +// <15=> Supply 15/16 (nRF52) +// <7=> External Ref 0 +// <65543=> External Ref 1 + +#ifndef LPCOMP_CONFIG_REFERENCE +#define LPCOMP_CONFIG_REFERENCE 3 +#endif + +// LPCOMP_CONFIG_DETECTION - Detection + +// <0=> Crossing +// <1=> Up +// <2=> Down + +#ifndef LPCOMP_CONFIG_DETECTION +#define LPCOMP_CONFIG_DETECTION 2 +#endif + +// LPCOMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_INPUT +#define LPCOMP_CONFIG_INPUT 0 +#endif + +// LPCOMP_CONFIG_HYST - Hysteresis + + +#ifndef LPCOMP_CONFIG_HYST +#define LPCOMP_CONFIG_HYST 0 +#endif + +// LPCOMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_IRQ_PRIORITY +#define LPCOMP_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// PDM_ENABLED - nrf_drv_pdm - PDM peripheral driver +//========================================================== +#ifndef PDM_ENABLED +#define PDM_ENABLED 0 +#endif +// PDM_CONFIG_MODE - Mode + +// <0=> Stereo +// <1=> Mono + +#ifndef PDM_CONFIG_MODE +#define PDM_CONFIG_MODE 1 +#endif + +// PDM_CONFIG_EDGE - Edge + +// <0=> Left falling +// <1=> Left rising + +#ifndef PDM_CONFIG_EDGE +#define PDM_CONFIG_EDGE 0 +#endif + +// PDM_CONFIG_CLOCK_FREQ - Clock frequency + +// <134217728=> 1000k +// <138412032=> 1032k (default) +// <142606336=> 1067k + +#ifndef PDM_CONFIG_CLOCK_FREQ +#define PDM_CONFIG_CLOCK_FREQ 138412032 +#endif + +// PDM_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PDM_CONFIG_IRQ_PRIORITY +#define PDM_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// PERIPHERAL_RESOURCE_SHARING_ENABLED - nrf_drv_common - Peripheral drivers common module + + +#ifndef PERIPHERAL_RESOURCE_SHARING_ENABLED +#define PERIPHERAL_RESOURCE_SHARING_ENABLED 1 +#endif + +// POWER_ENABLED - nrf_drv_power - POWER peripheral driver +//========================================================== +#ifndef POWER_ENABLED +#define POWER_ENABLED 0 +#endif +// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef POWER_CONFIG_IRQ_PRIORITY +#define POWER_CONFIG_IRQ_PRIORITY 7 +#endif + +// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCEN +#define POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCENHV +#define POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + +// PPI_ENABLED - nrf_drv_ppi - PPI peripheral driver + + +#ifndef PPI_ENABLED +#define PPI_ENABLED 0 +#endif + +// PWM_ENABLED - nrf_drv_pwm - PWM peripheral driver +//========================================================== +#ifndef PWM_ENABLED +#define PWM_ENABLED 1 +#endif +// PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT0_PIN +#define PWM_DEFAULT_CONFIG_OUT0_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT1_PIN - Out1 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT1_PIN +#define PWM_DEFAULT_CONFIG_OUT1_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT2_PIN - Out2 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT2_PIN +#define PWM_DEFAULT_CONFIG_OUT2_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT3_PIN - Out3 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT3_PIN +#define PWM_DEFAULT_CONFIG_OUT3_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_BASE_CLOCK - Base clock + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz + +#ifndef PWM_DEFAULT_CONFIG_BASE_CLOCK +#define PWM_DEFAULT_CONFIG_BASE_CLOCK 4 +#endif + +// PWM_DEFAULT_CONFIG_COUNT_MODE - Count mode + +// <0=> Up +// <1=> Up and Down + +#ifndef PWM_DEFAULT_CONFIG_COUNT_MODE +#define PWM_DEFAULT_CONFIG_COUNT_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_TOP_VALUE - Top value +#ifndef PWM_DEFAULT_CONFIG_TOP_VALUE +#define PWM_DEFAULT_CONFIG_TOP_VALUE 1000 +#endif + +// PWM_DEFAULT_CONFIG_LOAD_MODE - Load mode + +// <0=> Common +// <1=> Grouped +// <2=> Individual +// <3=> Waveform + +#ifndef PWM_DEFAULT_CONFIG_LOAD_MODE +#define PWM_DEFAULT_CONFIG_LOAD_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_STEP_MODE - Step mode + +// <0=> Auto +// <1=> Triggered + +#ifndef PWM_DEFAULT_CONFIG_STEP_MODE +#define PWM_DEFAULT_CONFIG_STEP_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define PWM_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// PWM0_ENABLED - Enable PWM0 instance + + +#ifndef PWM0_ENABLED +#define PWM0_ENABLED 1 +#endif + +// PWM1_ENABLED - Enable PWM1 instance + + +#ifndef PWM1_ENABLED +#define PWM1_ENABLED 1 +#endif + +// PWM2_ENABLED - Enable PWM2 instance + + +#ifndef PWM2_ENABLED +#define PWM2_ENABLED 1 +#endif + +// PWM3_ENABLED - Enable PWM3 instance + + +#ifndef PWM3_ENABLED +#define PWM3_ENABLED 1 +#endif + +// + +// QDEC_ENABLED - nrf_drv_qdec - QDEC peripheral driver +//========================================================== +#ifndef QDEC_ENABLED +#define QDEC_ENABLED 0 +#endif +// QDEC_CONFIG_REPORTPER - Report period + +// <0=> 10 Samples +// <1=> 40 Samples +// <2=> 80 Samples +// <3=> 120 Samples +// <4=> 160 Samples +// <5=> 200 Samples +// <6=> 240 Samples +// <7=> 280 Samples + +#ifndef QDEC_CONFIG_REPORTPER +#define QDEC_CONFIG_REPORTPER 0 +#endif + +// QDEC_CONFIG_SAMPLEPER - Sample period + +// <0=> 128 us +// <1=> 256 us +// <2=> 512 us +// <3=> 1024 us +// <4=> 2048 us +// <5=> 4096 us +// <6=> 8192 us +// <7=> 16384 us + +#ifndef QDEC_CONFIG_SAMPLEPER +#define QDEC_CONFIG_SAMPLEPER 7 +#endif + +// QDEC_CONFIG_PIO_A - A pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_A +#define QDEC_CONFIG_PIO_A 31 +#endif + +// QDEC_CONFIG_PIO_B - B pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_B +#define QDEC_CONFIG_PIO_B 31 +#endif + +// QDEC_CONFIG_PIO_LED - LED pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_LED +#define QDEC_CONFIG_PIO_LED 31 +#endif + +// QDEC_CONFIG_LEDPRE - LED pre +#ifndef QDEC_CONFIG_LEDPRE +#define QDEC_CONFIG_LEDPRE 511 +#endif + +// QDEC_CONFIG_LEDPOL - LED polarity + +// <0=> Active low +// <1=> Active high + +#ifndef QDEC_CONFIG_LEDPOL +#define QDEC_CONFIG_LEDPOL 1 +#endif + +// QDEC_CONFIG_DBFEN - Debouncing enable + + +#ifndef QDEC_CONFIG_DBFEN +#define QDEC_CONFIG_DBFEN 0 +#endif + +// QDEC_CONFIG_SAMPLE_INTEN - Sample ready interrupt enable + + +#ifndef QDEC_CONFIG_SAMPLE_INTEN +#define QDEC_CONFIG_SAMPLE_INTEN 0 +#endif + +// QDEC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QDEC_CONFIG_IRQ_PRIORITY +#define QDEC_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// RNG_ENABLED - nrf_drv_rng - RNG peripheral driver +//========================================================== +#ifndef RNG_ENABLED +#define RNG_ENABLED 1 +#endif +// RNG_CONFIG_ERROR_CORRECTION - Error correction + + +#ifndef RNG_CONFIG_ERROR_CORRECTION +#define RNG_CONFIG_ERROR_CORRECTION 1 +#endif + +// RNG_CONFIG_POOL_SIZE - Pool size +#ifndef RNG_CONFIG_POOL_SIZE +#define RNG_CONFIG_POOL_SIZE 32 +#endif + +// RNG_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RNG_CONFIG_IRQ_PRIORITY +#define RNG_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// RTC_ENABLED - nrf_drv_rtc - RTC peripheral driver +//========================================================== +#ifndef RTC_ENABLED +#define RTC_ENABLED 0 +#endif +// RTC_DEFAULT_CONFIG_FREQUENCY - Frequency <16-32768> + + +#ifndef RTC_DEFAULT_CONFIG_FREQUENCY +#define RTC_DEFAULT_CONFIG_FREQUENCY 32768 +#endif + +// RTC_DEFAULT_CONFIG_RELIABLE - Ensures safe compare event triggering + + +#ifndef RTC_DEFAULT_CONFIG_RELIABLE +#define RTC_DEFAULT_CONFIG_RELIABLE 0 +#endif + +// RTC_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define RTC_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// RTC0_ENABLED - Enable RTC0 instance + + +#ifndef RTC0_ENABLED +#define RTC0_ENABLED 0 +#endif + +// RTC1_ENABLED - Enable RTC1 instance + + +#ifndef RTC1_ENABLED +#define RTC1_ENABLED 0 +#endif + +// RTC2_ENABLED - Enable RTC2 instance + + +#ifndef RTC2_ENABLED +#define RTC2_ENABLED 0 +#endif + +// NRF_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt +#ifndef NRF_MAXIMUM_LATENCY_US +#define NRF_MAXIMUM_LATENCY_US 2000 +#endif + +// + +// SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver +//========================================================== +#ifndef SAADC_ENABLED +#define SAADC_ENABLED 1 +#endif +// SAADC_CONFIG_RESOLUTION - Resolution + +// <0=> 8 bit +// <1=> 10 bit +// <2=> 12 bit +// <3=> 14 bit + +#ifndef SAADC_CONFIG_RESOLUTION +#define SAADC_CONFIG_RESOLUTION 2 +#endif + +// SAADC_CONFIG_OVERSAMPLE - Sample period + +// <0=> Disabled +// <1=> 2x +// <2=> 4x +// <3=> 8x +// <4=> 16x +// <5=> 32x +// <6=> 64x +// <7=> 128x +// <8=> 256x + +#ifndef SAADC_CONFIG_OVERSAMPLE +#define SAADC_CONFIG_OVERSAMPLE 0 +#endif + +// SAADC_CONFIG_LP_MODE - Enabling low power mode + + +#ifndef SAADC_CONFIG_LP_MODE +#define SAADC_CONFIG_LP_MODE 0 +#endif + +// SAADC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SAADC_CONFIG_IRQ_PRIORITY +#define SAADC_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// SPIS_ENABLED - nrf_drv_spis - SPI Slave driver +//========================================================== +#ifndef SPIS_ENABLED +#define SPIS_ENABLED 1 +#endif +// SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// SPIS_DEFAULT_MODE - Mode + +// <0=> MODE_0 +// <1=> MODE_1 +// <2=> MODE_2 +// <3=> MODE_3 + +#ifndef SPIS_DEFAULT_MODE +#define SPIS_DEFAULT_MODE 0 +#endif + +// SPIS_DEFAULT_BIT_ORDER - SPIS default bit order + +// <0=> MSB first +// <1=> LSB first + +#ifndef SPIS_DEFAULT_BIT_ORDER +#define SPIS_DEFAULT_BIT_ORDER 0 +#endif + +// SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef SPIS_DEFAULT_DEF +#define SPIS_DEFAULT_DEF 255 +#endif + +// SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef SPIS_DEFAULT_ORC +#define SPIS_DEFAULT_ORC 255 +#endif + +// SPIS0_ENABLED - Enable SPIS0 instance + + +#ifndef SPIS0_ENABLED +#define SPIS0_ENABLED 1 +#endif + +// SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef SPIS1_ENABLED +#define SPIS1_ENABLED 0 +#endif + +// SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef SPIS2_ENABLED +#define SPIS2_ENABLED 0 +#endif + +// + +// SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver +//========================================================== +#ifndef SPI_ENABLED +#define SPI_ENABLED 1 +#endif +// SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRF_SPI_DRV_MISO_PULLUP_CFG - MISO PIN pull-up configuration. + +// <0=> NRF_GPIO_PIN_NOPULL +// <1=> NRF_GPIO_PIN_PULLDOWN +// <3=> NRF_GPIO_PIN_PULLUP + +#ifndef NRF_SPI_DRV_MISO_PULLUP_CFG +#define NRF_SPI_DRV_MISO_PULLUP_CFG 1 +#endif + +// SPI0_ENABLED - Enable SPI0 instance +//========================================================== +#ifndef SPI0_ENABLED +#define SPI0_ENABLED 1 +#endif +// SPI0_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI0_USE_EASY_DMA +#define SPI0_USE_EASY_DMA 0 +#endif + +// SPI0_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI0_DEFAULT_FREQUENCY +#define SPI0_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// SPI1_ENABLED - Enable SPI1 instance +//========================================================== +#ifndef SPI1_ENABLED +#define SPI1_ENABLED 1 +#endif +// SPI1_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI1_USE_EASY_DMA +#define SPI1_USE_EASY_DMA 0 +#endif + +// SPI1_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI1_DEFAULT_FREQUENCY +#define SPI1_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// SPI2_ENABLED - Enable SPI2 instance +//========================================================== +#ifndef SPI2_ENABLED +#define SPI2_ENABLED 1 +#endif +// SPI2_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI2_USE_EASY_DMA +#define SPI2_USE_EASY_DMA 0 +#endif + +// SPI2_DEFAULT_FREQUENCY - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef SPI2_DEFAULT_FREQUENCY +#define SPI2_DEFAULT_FREQUENCY 1073741824 +#endif + +// + +// + +// TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver +//========================================================== +#ifndef TIMER_ENABLED +#define TIMER_ENABLED 0 +#endif +// TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef TIMER_DEFAULT_CONFIG_FREQUENCY +#define TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef TIMER_DEFAULT_CONFIG_MODE +#define TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef TIMER0_ENABLED +#define TIMER0_ENABLED 0 +#endif + +// TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef TIMER1_ENABLED +#define TIMER1_ENABLED 0 +#endif + +// TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef TIMER2_ENABLED +#define TIMER2_ENABLED 0 +#endif + +// TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef TIMER3_ENABLED +#define TIMER3_ENABLED 0 +#endif + +// TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef TIMER4_ENABLED +#define TIMER4_ENABLED 0 +#endif + +// + +// TWIS_ENABLED - nrf_drv_twis - TWIS peripheral driver +//========================================================== +#ifndef TWIS_ENABLED +#define TWIS_ENABLED 0 +#endif +// TWIS_DEFAULT_CONFIG_ADDR0 - Address0 +#ifndef TWIS_DEFAULT_CONFIG_ADDR0 +#define TWIS_DEFAULT_CONFIG_ADDR0 0 +#endif + +// TWIS_DEFAULT_CONFIG_ADDR1 - Address1 +#ifndef TWIS_DEFAULT_CONFIG_ADDR1 +#define TWIS_DEFAULT_CONFIG_ADDR1 0 +#endif + +// TWIS_DEFAULT_CONFIG_SCL_PULL - SCL pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SCL_PULL +#define TWIS_DEFAULT_CONFIG_SCL_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_SDA_PULL - SDA pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SDA_PULL +#define TWIS_DEFAULT_CONFIG_SDA_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWIS_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TWIS0_ENABLED - Enable TWIS0 instance + + +#ifndef TWIS0_ENABLED +#define TWIS0_ENABLED 0 +#endif + +// TWIS1_ENABLED - Enable TWIS1 instance + + +#ifndef TWIS1_ENABLED +#define TWIS1_ENABLED 0 +#endif + +// TWIS_ASSUME_INIT_AFTER_RESET_ONLY - Assume that any instance would be initialized only once + + +// Optimization flag. Registers used by TWIS are shared by other peripherals. Normally, during initialization driver tries to clear all registers to known state before doing the initialization itself. This gives initialization safe procedure, no matter when it would be called. If you activate TWIS only once and do never uninitialize it - set this flag to 1 what gives more optimal code. + +#ifndef TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +#endif + +// TWIS_NO_SYNC_MODE - Remove support for synchronous mode + + +// Synchronous mode would be used in specific situations. And it uses some additional code and data memory to safely process state machine by polling it in status functions. If this functionality is not required it may be disabled to free some resources. + +#ifndef TWIS_NO_SYNC_MODE +#define TWIS_NO_SYNC_MODE 0 +#endif + +// + +// TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver +//========================================================== +#ifndef TWI_ENABLED +#define TWI_ENABLED 1 +#endif +// TWI_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef TWI_DEFAULT_CONFIG_FREQUENCY +#define TWI_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// TWI_DEFAULT_CONFIG_CLR_BUS_INIT - Enables bus clearing procedure during init + + +#ifndef TWI_DEFAULT_CONFIG_CLR_BUS_INIT +#define TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0 +#endif + +// TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// TWI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// TWI0_ENABLED - Enable TWI0 instance +//========================================================== +#ifndef TWI0_ENABLED +#define TWI0_ENABLED 1 +#endif +// TWI0_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI0_USE_EASY_DMA +#define TWI0_USE_EASY_DMA 0 +#endif + +// + +// TWI1_ENABLED - Enable TWI1 instance +//========================================================== +#ifndef TWI1_ENABLED +#define TWI1_ENABLED 1 +#endif +// TWI1_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI1_USE_EASY_DMA +#define TWI1_USE_EASY_DMA 0 +#endif + +// + +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 1 +#endif +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 1 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 2576384 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 1 +#endif + +// UART0_ENABLED - Enable UART0 instance +//========================================================== +#ifndef UART0_ENABLED +#define UART0_ENABLED 1 +#endif +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// UART1_ENABLED - Enable UART1 instance +//========================================================== +#ifndef UART1_ENABLED +#define UART1_ENABLED 1 +#endif +// UART1_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART1_CONFIG_USE_EASY_DMA +#define UART1_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// + +// USBD_ENABLED - nrf_drv_usbd - USB driver +//========================================================== +#ifndef USBD_ENABLED +#define USBD_ENABLED 0 +#endif +// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef USBD_CONFIG_IRQ_PRIORITY +#define USBD_CONFIG_IRQ_PRIORITY 7 +#endif + +// NRF_DRV_USBD_DMASCHEDULER_MODE - USBD SMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef NRF_DRV_USBD_DMASCHEDULER_MODE +#define NRF_DRV_USBD_DMASCHEDULER_MODE 0 +#endif + +// + +// WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver +//========================================================== +#ifndef WDT_ENABLED +#define WDT_ENABLED 0 +#endif +// WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode + +// <1=> Run in SLEEP, Pause in HALT +// <8=> Pause in SLEEP, Run in HALT +// <9=> Run in SLEEP and HALT +// <0=> Pause in SLEEP and HALT + +#ifndef WDT_CONFIG_BEHAVIOUR +#define WDT_CONFIG_BEHAVIOUR 1 +#endif + +// WDT_CONFIG_RELOAD_VALUE - Reload value <15-4294967295> + + +#ifndef WDT_CONFIG_RELOAD_VALUE +#define WDT_CONFIG_RELOAD_VALUE 2000 +#endif + +// WDT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef WDT_CONFIG_IRQ_PRIORITY +#define WDT_CONFIG_IRQ_PRIORITY 7 +#endif + +// + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_GPIOTE_ENABLED - app_gpiote - GPIOTE events dispatcher + + +#ifndef APP_GPIOTE_ENABLED +#define APP_GPIOTE_ENABLED 0 +#endif + +// APP_PWM_ENABLED - app_pwm - PWM functionality + + +#ifndef APP_PWM_ENABLED +#define APP_PWM_ENABLED 0 +#endif + +// APP_SCHEDULER_ENABLED - app_scheduler - Events scheduler +//========================================================== +#ifndef APP_SCHEDULER_ENABLED +#define APP_SCHEDULER_ENABLED 0 +#endif +// APP_SCHEDULER_WITH_PAUSE - Enabling pause feature + + +#ifndef APP_SCHEDULER_WITH_PAUSE +#define APP_SCHEDULER_WITH_PAUSE 0 +#endif + +// APP_SCHEDULER_WITH_PROFILER - Enabling scheduler profiling + + +#ifndef APP_SCHEDULER_WITH_PROFILER +#define APP_SCHEDULER_WITH_PROFILER 0 +#endif + +// + +// APP_TIMER_ENABLED - app_timer - Application timer functionality +//========================================================== +#ifndef APP_TIMER_ENABLED +#define APP_TIMER_ENABLED 0 +#endif +// APP_TIMER_CONFIG_RTC_FREQUENCY - Configure RTC prescaler. + +// <0=> 32768 Hz +// <1=> 16384 Hz +// <3=> 8192 Hz +// <7=> 4096 Hz +// <15=> 2048 Hz +// <31=> 1024 Hz + +#ifndef APP_TIMER_CONFIG_RTC_FREQUENCY +#define APP_TIMER_CONFIG_RTC_FREQUENCY 0 +#endif + +// APP_TIMER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef APP_TIMER_CONFIG_IRQ_PRIORITY +#define APP_TIMER_CONFIG_IRQ_PRIORITY 7 +#endif + +// APP_TIMER_CONFIG_OP_QUEUE_SIZE - Capacity of timer requests queue. +// Size of the queue depends on how many timers are used +// in the system, how often timers are started and overall +// system latency. If queue size is too small app_timer calls +// will fail. + +#ifndef APP_TIMER_CONFIG_OP_QUEUE_SIZE +#define APP_TIMER_CONFIG_OP_QUEUE_SIZE 10 +#endif + +// APP_TIMER_CONFIG_USE_SCHEDULER - Enable scheduling app_timer events to app_scheduler + + +#ifndef APP_TIMER_CONFIG_USE_SCHEDULER +#define APP_TIMER_CONFIG_USE_SCHEDULER 0 +#endif + +// APP_TIMER_WITH_PROFILER - Enable app_timer profiling + + +#ifndef APP_TIMER_WITH_PROFILER +#define APP_TIMER_WITH_PROFILER 0 +#endif + +// APP_TIMER_KEEPS_RTC_ACTIVE - Enable RTC always on + + +// If option is enabled RTC is kept running even if there is no active timers. +// This option can be used when app_timer is used for timestamping. + +#ifndef APP_TIMER_KEEPS_RTC_ACTIVE +#define APP_TIMER_KEEPS_RTC_ACTIVE 0 +#endif + +// APP_TIMER_CONFIG_SWI_NUMBER - Configure SWI instance used. + +// <0=> 0 +// <1=> 1 + +#ifndef APP_TIMER_CONFIG_SWI_NUMBER +#define APP_TIMER_CONFIG_SWI_NUMBER 0 +#endif + +// + +// NRF_TWI_MNGR_ENABLED - nrf_twi_mngr - TWI transaction manager + + +#ifndef NRF_TWI_MNGR_ENABLED +#define NRF_TWI_MNGR_ENABLED 0 +#endif + +// APP_UART_ENABLED - app_uart - UART driver +//========================================================== +#ifndef APP_UART_ENABLED +#define APP_UART_ENABLED 0 +#endif +// APP_UART_DRIVER_INSTANCE - UART instance used + +// <0=> 0 + +#ifndef APP_UART_DRIVER_INSTANCE +#define APP_UART_DRIVER_INSTANCE 0 +#endif + +// + +// APP_USBD_CLASS_AUDIO_ENABLED - app_usbd_audio - USB AUDIO class + + +#ifndef APP_USBD_CLASS_AUDIO_ENABLED +#define APP_USBD_CLASS_AUDIO_ENABLED 0 +#endif + +// APP_USBD_CLASS_CDC_ACM_ENABLED - app_usbd_cdc_acm - USB CDC ACM class + + +#ifndef APP_USBD_CLASS_CDC_ACM_ENABLED +#define APP_USBD_CLASS_CDC_ACM_ENABLED 0 +#endif + +// APP_USBD_CLASS_HID_ENABLED - app_usbd_hid - USB HID class + + +#ifndef APP_USBD_CLASS_HID_ENABLED +#define APP_USBD_CLASS_HID_ENABLED 0 +#endif + +// APP_USBD_HID_GENERIC_ENABLED - app_usbd_hid_generic - USB HID generic + + +#ifndef APP_USBD_HID_GENERIC_ENABLED +#define APP_USBD_HID_GENERIC_ENABLED 0 +#endif + +// APP_USBD_HID_KBD_ENABLED - app_usbd_hid_kbd - USB HID keyboard + + +#ifndef APP_USBD_HID_KBD_ENABLED +#define APP_USBD_HID_KBD_ENABLED 0 +#endif + +// APP_USBD_HID_MOUSE_ENABLED - app_usbd_hid_mouse - USB HID mouse + + +#ifndef APP_USBD_HID_MOUSE_ENABLED +#define APP_USBD_HID_MOUSE_ENABLED 0 +#endif + +// APP_USBD_MSC_ENABLED - app_usbd_msc - USB MSC class + + +#ifndef APP_USBD_MSC_ENABLED +#define APP_USBD_MSC_ENABLED 0 +#endif + +// BUTTON_ENABLED - app_button - buttons handling module + + +#ifndef BUTTON_ENABLED +#define BUTTON_ENABLED 0 +#endif + +// CRC16_ENABLED - crc16 - CRC16 calculation routines + + +#ifndef CRC16_ENABLED +#define CRC16_ENABLED 0 +#endif + +// CRC32_ENABLED - crc32 - CRC32 calculation routines + + +#ifndef CRC32_ENABLED +#define CRC32_ENABLED 0 +#endif + +// ECC_ENABLED - ecc - Elliptic Curve Cryptography Library + + +#ifndef ECC_ENABLED +#define ECC_ENABLED 0 +#endif + +// FDS_ENABLED - fds - Flash data storage module +//========================================================== +#ifndef FDS_ENABLED +#define FDS_ENABLED 1 +#endif +// Pages - Virtual page settings + +// Configure the number of virtual pages to use and their size. +//========================================================== +// FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. +// One of the virtual pages is reserved by the system for garbage collection. +// Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection. +// The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes. + +#ifndef FDS_VIRTUAL_PAGES +#define FDS_VIRTUAL_PAGES 3 +#endif + +// FDS_VIRTUAL_PAGE_SIZE - The size of a virtual flash page. + + +// Expressed in number of 4-byte words. +// By default, a virtual page is the same size as a physical page. +// The size of a virtual page must be a multiple of the size of a physical page. +// <1024=> 1024 +// <2048=> 2048 + +#ifndef FDS_VIRTUAL_PAGE_SIZE +#define FDS_VIRTUAL_PAGE_SIZE 1024 +#endif + +// +//========================================================== + +// Backend - Backend configuration + +// Configure which nrf_fstorage backend is used by FDS to write to flash. +//========================================================== +// FDS_BACKEND - FDS flash backend. + + +// NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present. +// NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice. +// <1=> NRF_FSTORAGE_NVMC +// <2=> NRF_FSTORAGE_SD + +#ifndef FDS_BACKEND +#define FDS_BACKEND 1 +#endif + +// +//========================================================== + +// Queue - Queue settings + +//========================================================== +// FDS_OP_QUEUE_SIZE - Size of the internal queue. +// Increase this value if you frequently get synchronous FDS_ERR_NO_SPACE_IN_QUEUES errors. + +#ifndef FDS_OP_QUEUE_SIZE +#define FDS_OP_QUEUE_SIZE 4 +#endif + +// +//========================================================== + +// CRC - CRC functionality + +//========================================================== +// FDS_CRC_CHECK_ON_READ - Enable CRC checks. + +// Save a record's CRC when it is written to flash and check it when the record is opened. +// Records with an incorrect CRC can still be 'seen' by the user using FDS functions, but they cannot be opened. +// Additionally, they will not be garbage collected until they are deleted. +//========================================================== +#ifndef FDS_CRC_CHECK_ON_READ +#define FDS_CRC_CHECK_ON_READ 0 +#endif +// FDS_CRC_CHECK_ON_WRITE - Perform a CRC check on newly written records. + + +// Perform a CRC check on newly written records. +// This setting can be used to make sure that the record data was not altered while being written to flash. +// <1=> Enabled +// <0=> Disabled + +#ifndef FDS_CRC_CHECK_ON_WRITE +#define FDS_CRC_CHECK_ON_WRITE 0 +#endif + +// + +// +//========================================================== + +// Users - Number of users + +//========================================================== +// FDS_MAX_USERS - Maximum number of callbacks that can be registered. +#ifndef FDS_MAX_USERS +#define FDS_MAX_USERS 4 +#endif + +// +//========================================================== + +// + +// HARDFAULT_HANDLER_ENABLED - hardfault_default - HardFault default handler for debugging and release +//========================================================== +#ifndef HARDFAULT_HANDLER_ENABLED +#define HARDFAULT_HANDLER_ENABLED 0 +#endif +// HARDFAULT_HANDLER_GDB_PSP_BACKTRACE - Bypass the GDB problem with multiple stack pointers backtrace + + +// There is a known bug in GDB which causes it to incorrectly backtrace the code +// when multiple stack pointers are used (main and process stack pointers). +// This option enables the fix for that problem and allows to see the proper backtrace info. +// It makes it possible to trace the code to the exact point where a HardFault appeared. +// This option requires additional commands and may temporarily switch MSP stack to store data on PSP space. +// This is an optional parameter - enable it while debugging. +// Before a HardFault handler exits, the stack will be reverted to its previous value. + +#ifndef HARDFAULT_HANDLER_GDB_PSP_BACKTRACE +#define HARDFAULT_HANDLER_GDB_PSP_BACKTRACE 1 +#endif + +// + +// HCI_MEM_POOL_ENABLED - hci_mem_pool - memory pool implementation used by HCI +//========================================================== +#ifndef HCI_MEM_POOL_ENABLED +#define HCI_MEM_POOL_ENABLED 0 +#endif +// HCI_TX_BUF_SIZE - TX buffer size in bytes. +#ifndef HCI_TX_BUF_SIZE +#define HCI_TX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_SIZE - RX buffer size in bytes. +#ifndef HCI_RX_BUF_SIZE +#define HCI_RX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_QUEUE_SIZE - RX buffer queue size. +#ifndef HCI_RX_BUF_QUEUE_SIZE +#define HCI_RX_BUF_QUEUE_SIZE 4 +#endif + +// + +// HCI_SLIP_ENABLED - hci_slip - SLIP protocol implementation used by HCI +//========================================================== +#ifndef HCI_SLIP_ENABLED +#define HCI_SLIP_ENABLED 0 +#endif +// HCI_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef HCI_UART_BAUDRATE +#define HCI_UART_BAUDRATE 30801920 +#endif + +// HCI_UART_FLOW_CONTROL - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef HCI_UART_FLOW_CONTROL +#define HCI_UART_FLOW_CONTROL 0 +#endif + +// HCI_UART_RX_PIN - UART RX pin +#ifndef HCI_UART_RX_PIN +#define HCI_UART_RX_PIN 8 +#endif + +// HCI_UART_TX_PIN - UART TX pin +#ifndef HCI_UART_TX_PIN +#define HCI_UART_TX_PIN 6 +#endif + +// HCI_UART_RTS_PIN - UART RTS pin +#ifndef HCI_UART_RTS_PIN +#define HCI_UART_RTS_PIN 5 +#endif + +// HCI_UART_CTS_PIN - UART CTS pin +#ifndef HCI_UART_CTS_PIN +#define HCI_UART_CTS_PIN 7 +#endif + +// + +// HCI_TRANSPORT_ENABLED - hci_transport - HCI transport +//========================================================== +#ifndef HCI_TRANSPORT_ENABLED +#define HCI_TRANSPORT_ENABLED 0 +#endif +// HCI_MAX_PACKET_SIZE_IN_BITS - Maximum size of a single application packet in bits. +#ifndef HCI_MAX_PACKET_SIZE_IN_BITS +#define HCI_MAX_PACKET_SIZE_IN_BITS 8000 +#endif + +// + +// LED_SOFTBLINK_ENABLED - led_softblink - led_softblink module + + +#ifndef LED_SOFTBLINK_ENABLED +#define LED_SOFTBLINK_ENABLED 0 +#endif + +// LOW_POWER_PWM_ENABLED - low_power_pwm - low_power_pwm module + + +#ifndef LOW_POWER_PWM_ENABLED +#define LOW_POWER_PWM_ENABLED 0 +#endif + +// MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator +//========================================================== +#ifndef MEM_MANAGER_ENABLED +#define MEM_MANAGER_ENABLED 0 +#endif +// MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block. <0-255> + + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT 1 +#endif + +// MEMORY_MANAGER_SMALL_BLOCK_SIZE - Size of each memory blocks identified as 'small' block. +// Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE 32 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block. <0-255> + + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_SIZE - Size of each memory blocks identified as 'medium' block. +// Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block. <0-255> + + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_SIZE - Size of each memory blocks identified as 'large' block. +// Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra large' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 1320 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra large' block. +// Size of each memory blocks identified as 'extra extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 3444 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra small' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 64 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra small' block. +// Size of each memory blocks identified as 'extra extra small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 32 +#endif + +// MEM_MANAGER_DISABLE_API_PARAM_CHECK - Disable API parameter checks in the module. + + +#ifndef MEM_MANAGER_DISABLE_API_PARAM_CHECK +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK 0 +#endif + +// + +// NRF_BALLOC_ENABLED - nrf_balloc - Block allocator module +//========================================================== +#ifndef NRF_BALLOC_ENABLED +#define NRF_BALLOC_ENABLED 1 +#endif +// NRF_BALLOC_CONFIG_DEBUG_ENABLED - Enables debug mode in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_CONFIG_DEBUG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS - Number of words used as head guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS +#define NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS - Number of words used as tail guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS +#define NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED - Enables basic checks in this module. + + +#ifndef NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED +#define NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED - Enables double memory free check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED - Enables free memory corruption check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED 0 +#endif + +// + +// + +// NRF_CSENSE_ENABLED - nrf_csense - Capacitive sensor module +//========================================================== +#ifndef NRF_CSENSE_ENABLED +#define NRF_CSENSE_ENABLED 0 +#endif +// NRF_CSENSE_PAD_HYSTERESIS - Minimum value of change required to determine that a pad was touched. +#ifndef NRF_CSENSE_PAD_HYSTERESIS +#define NRF_CSENSE_PAD_HYSTERESIS 15 +#endif + +// NRF_CSENSE_PAD_DEVIATION - Minimum value measured on a pad required to take it into account while calculating the step. +#ifndef NRF_CSENSE_PAD_DEVIATION +#define NRF_CSENSE_PAD_DEVIATION 70 +#endif + +// NRF_CSENSE_MIN_PAD_VALUE - Minimum normalized value on a pad required to take its value into account. +#ifndef NRF_CSENSE_MIN_PAD_VALUE +#define NRF_CSENSE_MIN_PAD_VALUE 20 +#endif + +// NRF_CSENSE_MAX_PADS_NUMBER - Maximum number of pads used for one instance. +#ifndef NRF_CSENSE_MAX_PADS_NUMBER +#define NRF_CSENSE_MAX_PADS_NUMBER 20 +#endif + +// NRF_CSENSE_MAX_VALUE - Maximum normalized value obtained from measurement. +#ifndef NRF_CSENSE_MAX_VALUE +#define NRF_CSENSE_MAX_VALUE 1000 +#endif + +// NRF_CSENSE_OUTPUT_PIN - Output pin used by the low-level module. +// This is used when capacitive sensor does not use COMP. + +#ifndef NRF_CSENSE_OUTPUT_PIN +#define NRF_CSENSE_OUTPUT_PIN 26 +#endif + +// + +// NRF_DRV_CSENSE_ENABLED - nrf_drv_csense - Capacitive sensor low-level module +//========================================================== +#ifndef NRF_DRV_CSENSE_ENABLED +#define NRF_DRV_CSENSE_ENABLED 0 +#endif +// USE_COMP - Use the comparator to implement the capacitive sensor driver. + +// Due to Anomaly 84, COMP I_SOURCE is not functional. It has too high a varation. +//========================================================== +#ifndef USE_COMP +#define USE_COMP 0 +#endif +// TIMER0_FOR_CSENSE - First TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER0_FOR_CSENSE +#define TIMER0_FOR_CSENSE 1 +#endif + +// TIMER1_FOR_CSENSE - Second TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER1_FOR_CSENSE +#define TIMER1_FOR_CSENSE 2 +#endif + +// MEASUREMENT_PERIOD - Single measurement period. +// Time of a single measurement can be calculated as +// T = (1/2)*MEASUREMENT_PERIOD*(1/f_OSC) where f_OSC = I_SOURCE / (2C*(VUP-VDOWN) ). +// I_SOURCE, VUP, and VDOWN are values used to initialize COMP and C is the capacitance of the used pad. + +#ifndef MEASUREMENT_PERIOD +#define MEASUREMENT_PERIOD 20 +#endif + +// + +// + +// NRF_FPRINTF_ENABLED - nrf_fprintf - fprintf function. + + +#ifndef NRF_FPRINTF_ENABLED +#define NRF_FPRINTF_ENABLED 0 +#endif + +// NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library +//========================================================== +#ifndef NRF_FSTORAGE_ENABLED +#define NRF_FSTORAGE_ENABLED 1 +#endif +// nrf_fstorage_sd - Implementation using the SoftDevice. + +// Configuration options for the fstorage implementation using the SoftDevice. +//========================================================== +// NRF_FSTORAGE_SD_QUEUE_SIZE - Size of the internal queue of operations. +// Increase this value if API calls frequently return the error @ref NRF_ERROR_NO_MEM. + +#ifndef NRF_FSTORAGE_SD_QUEUE_SIZE +#define NRF_FSTORAGE_SD_QUEUE_SIZE 4 +#endif + +// NRF_FSTORAGE_SD_MAX_RETRIES - Maximum number of attempts at executing an operation when the SoftDevice is busy. +// Increase this value if events frequently return the @ref NRF_ERROR_TIMEOUT error. +// The SoftDevice might fail to schedule flash access due to high BLE activity. + +#ifndef NRF_FSTORAGE_SD_MAX_RETRIES +#define NRF_FSTORAGE_SD_MAX_RETRIES 8 +#endif + +// NRF_FSTORAGE_SD_MAX_WRITE_SIZE - Maximum number of bytes to be written to flash in a single operation. +// This value must be a multiple of four. +// Lowering this value can increase the chances of the SoftDevice being able to execute flash operations in between radio activity. +// This value is bound by the maximum number of bytes that can be written to flash in a single call to @ref sd_flash_write. +// That is 1024 bytes for nRF51 ICs and 4096 bytes for nRF52 ICs. + +#ifndef NRF_FSTORAGE_SD_MAX_WRITE_SIZE +#define NRF_FSTORAGE_SD_MAX_WRITE_SIZE 4096 +#endif + +// +//========================================================== + +// + +// NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module + + +#ifndef NRF_MEMOBJ_ENABLED +#define NRF_MEMOBJ_ENABLED 0 +#endif + +// NRF_PWR_MGMT_ENABLED - nrf_pwr_mgmt - Power management module +//========================================================== +#ifndef NRF_PWR_MGMT_ENABLED +#define NRF_PWR_MGMT_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. + +// Selected pin will be set when CPU is in sleep mode. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED +#define NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// NRF_PWR_MGMT_SLEEP_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef NRF_PWR_MGMT_SLEEP_DEBUG_PIN +#define NRF_PWR_MGMT_SLEEP_DEBUG_PIN 31 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED - Enables CPU usage monitor. + + +// Module will trace percentage of CPU usage in one second intervals. + +#ifndef NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED +#define NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED 0 +#endif + +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED - Enable standby timeout. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S - Standby timeout (in seconds). +// Shutdown procedure will begin no earlier than after this number of seconds. + +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S 3 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED - Enables FPU event cleaning. + + +#ifndef NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED +#define NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED 1 +#endif + +// NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY - Blocked shutdown procedure will be retried every second. + + +#ifndef NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY +#define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 0 +#endif + +// NRF_PWR_MGMT_CONFIG_USE_SCHEDULER - Module will use @ref app_scheduler. + + +#ifndef NRF_PWR_MGMT_CONFIG_USE_SCHEDULER +#define NRF_PWR_MGMT_CONFIG_USE_SCHEDULER 0 +#endif + +// NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT - The number of priorities for module handlers. +// The number of stages of the shutdown process. + +#ifndef NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT +#define NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT 3 +#endif + +// + +// NRF_QUEUE_ENABLED - nrf_queue - Queue module + + +#ifndef NRF_QUEUE_ENABLED +#define NRF_QUEUE_ENABLED 1 +#endif + +// NRF_SECTION_ITER_ENABLED - nrf_section_iter - Section iterator + + +#ifndef NRF_SECTION_ITER_ENABLED +#define NRF_SECTION_ITER_ENABLED 1 +#endif + +// NRF_STRERROR_ENABLED - nrf_strerror - Library for converting error code to string. + + +#ifndef NRF_STRERROR_ENABLED +#define NRF_STRERROR_ENABLED 0 +#endif + +// SLIP_ENABLED - slip - SLIP encoding and decoding + + +#ifndef SLIP_ENABLED +#define SLIP_ENABLED 0 +#endif + +// TASK_MANAGER_ENABLED - task_manager - Task manager. +//========================================================== +#ifndef TASK_MANAGER_ENABLED +#define TASK_MANAGER_ENABLED 0 +#endif +// TASK_MANAGER_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef TASK_MANAGER_CLI_CMDS +#define TASK_MANAGER_CLI_CMDS 1 +#endif + +// TASK_MANAGER_CONFIG_MAX_TASKS - Maximum number of tasks which can be created +#ifndef TASK_MANAGER_CONFIG_MAX_TASKS +#define TASK_MANAGER_CONFIG_MAX_TASKS 2 +#endif + +// TASK_MANAGER_CONFIG_STACK_SIZE - Stack size for every task (power of 2) +#ifndef TASK_MANAGER_CONFIG_STACK_SIZE +#define TASK_MANAGER_CONFIG_STACK_SIZE 1024 +#endif + +// TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED - Enable stack profiling. + + +#ifndef TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED +#define TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED 1 +#endif + +// TASK_MANAGER_CONFIG_STACK_GUARD - Configures stack guard. + +// <0=> Disabled +// <4=> 32 bytes +// <5=> 64 bytes +// <6=> 128 bytes +// <7=> 256 bytes +// <8=> 512 bytes + +#ifndef TASK_MANAGER_CONFIG_STACK_GUARD +#define TASK_MANAGER_CONFIG_STACK_GUARD 7 +#endif + +// + +// nrf_cli - Command line interface. + +//========================================================== +// NRF_CLI_ENABLED - Enable/disable CLI module. + + +#ifndef NRF_CLI_ENABLED +#define NRF_CLI_ENABLED 0 +#endif + +// NRF_CLI_ARGC_MAX - Maximum number of parameters passed to command handler. +#ifndef NRF_CLI_ARGC_MAX +#define NRF_CLI_ARGC_MAX 12 +#endif + +// NRF_CLI_BUILD_IN_CMDS_ENABLED - CLI build in commands. + + +#ifndef NRF_CLI_BUILD_IN_CMDS_ENABLED +#define NRF_CLI_BUILD_IN_CMDS_ENABLED 1 +#endif + +// NRF_CLI_CMD_BUFF_SIZE - Maximum buffer size for single command. +#ifndef NRF_CLI_CMD_BUFF_SIZE +#define NRF_CLI_CMD_BUFF_SIZE 128 +#endif + +// NRF_CLI_PRINTF_BUFF_SIZE - Maximum print buffer size. +#ifndef NRF_CLI_PRINTF_BUFF_SIZE +#define NRF_CLI_PRINTF_BUFF_SIZE 23 +#endif + +// NRF_CLI_HISTORY_ENABLED - Enable CLI history mode. +//========================================================== +#ifndef NRF_CLI_HISTORY_ENABLED +#define NRF_CLI_HISTORY_ENABLED 1 +#endif +// NRF_CLI_HISTORY_ELEMENT_SIZE - Size of one memory object reserved for CLI history +#ifndef NRF_CLI_HISTORY_ELEMENT_SIZE +#define NRF_CLI_HISTORY_ELEMENT_SIZE 32 +#endif + +// NRF_CLI_HISTORY_ELEMENT_COUNT - Number of history memory objects +#ifndef NRF_CLI_HISTORY_ELEMENT_COUNT +#define NRF_CLI_HISTORY_ELEMENT_COUNT 8 +#endif + +// + +// NRF_CLI_VT100_COLORS_ENABLED - CLI VT100 colors. + + +#ifndef NRF_CLI_VT100_COLORS_ENABLED +#define NRF_CLI_VT100_COLORS_ENABLED 1 +#endif + +// NRF_CLI_LOG_BACKEND - Enable logger backend interface. + + +#ifndef NRF_CLI_LOG_BACKEND +#define NRF_CLI_LOG_BACKEND 1 +#endif + +// NRF_CLI_USES_TASK_MANAGER_ENABLED - Enable CLI to use task_manager + + +#ifndef NRF_CLI_USES_TASK_MANAGER_ENABLED +#define NRF_CLI_USES_TASK_MANAGER_ENABLED 0 +#endif + +// +//========================================================== + +// nrf_cli_rtt - RTT command line interface transport. + +//========================================================== +// NRF_CLI_RTT_ENABLED - Enable/disable CLI RTT module. + + +#ifndef NRF_CLI_RTT_ENABLED +#define NRF_CLI_RTT_ENABLED 0 +#endif + +// NRF_CLI_RTT_TERMINAL_ID - RTT terminal ID for CLI. +#ifndef NRF_CLI_RTT_TERMINAL_ID +#define NRF_CLI_RTT_TERMINAL_ID 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Log + +//========================================================== +// NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend +//========================================================== +#ifndef NRF_LOG_BACKEND_RTT_ENABLED +#define NRF_LOG_BACKEND_RTT_ENABLED 0 +#endif +// NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#endif + +// + +// NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend +//========================================================== +#ifndef NRF_LOG_BACKEND_UART_ENABLED +#define NRF_LOG_BACKEND_UART_ENABLED 0 +#endif +// NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin +#ifndef NRF_LOG_BACKEND_UART_TX_PIN +#define NRF_LOG_BACKEND_UART_TX_PIN 6 +#endif + +// NRF_LOG_BACKEND_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRF_LOG_BACKEND_UART_BAUDRATE +#define NRF_LOG_BACKEND_UART_BAUDRATE 30801920 +#endif + +// NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE 64 +#endif + +// + +// nrf_log - Logging + +//========================================================== +// NRF_LOG_ENABLED - Logging module for nRF5 SDK +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0 +#endif +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 0 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 0 +#endif + +// + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + + +// Log data is buffered and can be processed in idle. + +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 1 +#endif + +// NRF_LOG_BUFSIZE - Size of the buffer for storing logs (in bytes). + + +// Must be power of 2 and multiple of 4. +// If NRF_LOG_DEFERRED = 0 then buffer size can be reduced to minimum. +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 +// <2048=> 2048 +// <4096=> 4096 +// <8192=> 8192 +// <16384=> 16384 + +#ifndef NRF_LOG_BUFSIZE +#define NRF_LOG_BUFSIZE 1024 +#endif + +// NRF_LOG_ALLOW_OVERFLOW - Configures behavior when circular buffer is full. + + +// If set then oldest logs are overwritten. Otherwise a +// marker is injected informing about overflow. + +#ifndef NRF_LOG_ALLOW_OVERFLOW +#define NRF_LOG_ALLOW_OVERFLOW 1 +#endif + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + + +// Function for getting the timestamp is provided by the user + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +// NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. + + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 1 +#endif + +// NRF_LOG_CLI_CMDS - Enable CLI commands for the module. + + +#ifndef NRF_LOG_CLI_CMDS +#define NRF_LOG_CLI_CMDS 1 +#endif + +// Log message pool - Configuration of log message pool + +//========================================================== +// NRF_LOG_MSGPOOL_ELEMENT_SIZE - Size of a single element in the pool of memory objects. +// If a small value is set, then performance of logs processing +// is degraded because data is fragmented. Bigger value impacts +// RAM memory utilization. The size is set to fit a message with +// a timestamp and up to 2 arguments in a single memory object. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_SIZE +#define NRF_LOG_MSGPOOL_ELEMENT_SIZE 20 +#endif + +// NRF_LOG_MSGPOOL_ELEMENT_COUNT - Number of elements in the pool of memory objects +// If a small value is set, then it may lead to a deadlock +// in certain cases if backend has high latency and holds +// multiple messages for long time. Bigger value impacts +// RAM memory usage. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_COUNT +#define NRF_LOG_MSGPOOL_ELEMENT_COUNT 8 +#endif + +// +//========================================================== + +// + +// nrf_log module configuration + +//========================================================== +// nrf_log in nRF_Core + +//========================================================== +// NRF_MPU_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MPU_CONFIG_LOG_ENABLED +#define NRF_MPU_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MPU_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MPU_CONFIG_LOG_LEVEL +#define NRF_MPU_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MPU_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_CONFIG_INFO_COLOR +#define NRF_MPU_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MPU_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_CONFIG_DEBUG_COLOR +#define NRF_MPU_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_STACK_GUARD_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_STACK_GUARD_CONFIG_LOG_ENABLED +#define NRF_STACK_GUARD_CONFIG_LOG_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_STACK_GUARD_CONFIG_LOG_LEVEL +#define NRF_STACK_GUARD_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_STACK_GUARD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_INFO_COLOR +#define NRF_STACK_GUARD_CONFIG_INFO_COLOR 0 +#endif + +// NRF_STACK_GUARD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_DEBUG_COLOR +#define NRF_STACK_GUARD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TASK_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TASK_MANAGER_CONFIG_LOG_ENABLED +#define TASK_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// TASK_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TASK_MANAGER_CONFIG_LOG_LEVEL +#define TASK_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// TASK_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_INFO_COLOR +#define TASK_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// TASK_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_DEBUG_COLOR +#define TASK_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Drivers + +//========================================================== +// CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef CLOCK_CONFIG_LOG_ENABLED +#define CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef CLOCK_CONFIG_LOG_LEVEL +#define CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_INFO_COLOR +#define CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_DEBUG_COLOR +#define CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMMON_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMMON_CONFIG_LOG_ENABLED +#define COMMON_CONFIG_LOG_ENABLED 0 +#endif +// COMMON_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMMON_CONFIG_LOG_LEVEL +#define COMMON_CONFIG_LOG_LEVEL 3 +#endif + +// COMMON_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMMON_CONFIG_INFO_COLOR +#define COMMON_CONFIG_INFO_COLOR 0 +#endif + +// COMMON_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMMON_CONFIG_DEBUG_COLOR +#define COMMON_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMP_CONFIG_LOG_ENABLED +#define COMP_CONFIG_LOG_ENABLED 0 +#endif +// COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMP_CONFIG_LOG_LEVEL +#define COMP_CONFIG_LOG_LEVEL 3 +#endif + +// COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_INFO_COLOR +#define COMP_CONFIG_INFO_COLOR 0 +#endif + +// COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_DEBUG_COLOR +#define COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef GPIOTE_CONFIG_LOG_ENABLED +#define GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef GPIOTE_CONFIG_LOG_LEVEL +#define GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_INFO_COLOR +#define GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_DEBUG_COLOR +#define GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// I2S_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef I2S_CONFIG_LOG_ENABLED +#define I2S_CONFIG_LOG_ENABLED 0 +#endif +// I2S_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef I2S_CONFIG_LOG_LEVEL +#define I2S_CONFIG_LOG_LEVEL 3 +#endif + +// I2S_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_INFO_COLOR +#define I2S_CONFIG_INFO_COLOR 0 +#endif + +// I2S_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_DEBUG_COLOR +#define I2S_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef LPCOMP_CONFIG_LOG_ENABLED +#define LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef LPCOMP_CONFIG_LOG_LEVEL +#define LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_INFO_COLOR +#define LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_DEBUG_COLOR +#define LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PDM_CONFIG_LOG_ENABLED +#define PDM_CONFIG_LOG_ENABLED 0 +#endif +// PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PDM_CONFIG_LOG_LEVEL +#define PDM_CONFIG_LOG_LEVEL 3 +#endif + +// PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_INFO_COLOR +#define PDM_CONFIG_INFO_COLOR 0 +#endif + +// PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_DEBUG_COLOR +#define PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PPI_CONFIG_LOG_ENABLED +#define PPI_CONFIG_LOG_ENABLED 0 +#endif +// PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PPI_CONFIG_LOG_LEVEL +#define PPI_CONFIG_LOG_LEVEL 3 +#endif + +// PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_INFO_COLOR +#define PPI_CONFIG_INFO_COLOR 0 +#endif + +// PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_DEBUG_COLOR +#define PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PWM_CONFIG_LOG_ENABLED +#define PWM_CONFIG_LOG_ENABLED 0 +#endif +// PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PWM_CONFIG_LOG_LEVEL +#define PWM_CONFIG_LOG_LEVEL 3 +#endif + +// PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_INFO_COLOR +#define PWM_CONFIG_INFO_COLOR 0 +#endif + +// PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_DEBUG_COLOR +#define PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef QDEC_CONFIG_LOG_ENABLED +#define QDEC_CONFIG_LOG_ENABLED 0 +#endif +// QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef QDEC_CONFIG_LOG_LEVEL +#define QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_INFO_COLOR +#define QDEC_CONFIG_INFO_COLOR 0 +#endif + +// QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_DEBUG_COLOR +#define QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RNG_CONFIG_LOG_ENABLED +#define RNG_CONFIG_LOG_ENABLED 0 +#endif +// RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RNG_CONFIG_LOG_LEVEL +#define RNG_CONFIG_LOG_LEVEL 3 +#endif + +// RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_INFO_COLOR +#define RNG_CONFIG_INFO_COLOR 0 +#endif + +// RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_DEBUG_COLOR +#define RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED - Enables logging of random numbers. + + +#ifndef RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED +#define RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED 0 +#endif + +// + +// RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RTC_CONFIG_LOG_ENABLED +#define RTC_CONFIG_LOG_ENABLED 0 +#endif +// RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RTC_CONFIG_LOG_LEVEL +#define RTC_CONFIG_LOG_LEVEL 3 +#endif + +// RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_INFO_COLOR +#define RTC_CONFIG_INFO_COLOR 0 +#endif + +// RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_DEBUG_COLOR +#define RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SAADC_CONFIG_LOG_ENABLED +#define SAADC_CONFIG_LOG_ENABLED 0 +#endif +// SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SAADC_CONFIG_LOG_LEVEL +#define SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_INFO_COLOR +#define SAADC_CONFIG_INFO_COLOR 0 +#endif + +// SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_DEBUG_COLOR +#define SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPIS_CONFIG_LOG_ENABLED +#define SPIS_CONFIG_LOG_ENABLED 0 +#endif +// SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPIS_CONFIG_LOG_LEVEL +#define SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_INFO_COLOR +#define SPIS_CONFIG_INFO_COLOR 0 +#endif + +// SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_DEBUG_COLOR +#define SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SWI_CONFIG_LOG_ENABLED +#define SWI_CONFIG_LOG_ENABLED 0 +#endif +// SWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SWI_CONFIG_LOG_LEVEL +#define SWI_CONFIG_LOG_LEVEL 3 +#endif + +// SWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SWI_CONFIG_INFO_COLOR +#define SWI_CONFIG_INFO_COLOR 0 +#endif + +// SWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SWI_CONFIG_DEBUG_COLOR +#define SWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TIMER_CONFIG_LOG_ENABLED +#define TIMER_CONFIG_LOG_ENABLED 0 +#endif +// TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TIMER_CONFIG_LOG_LEVEL +#define TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_INFO_COLOR +#define TIMER_CONFIG_INFO_COLOR 0 +#endif + +// TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_DEBUG_COLOR +#define TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWIS_CONFIG_LOG_ENABLED +#define TWIS_CONFIG_LOG_ENABLED 0 +#endif +// TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWIS_CONFIG_LOG_LEVEL +#define TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_INFO_COLOR +#define TWIS_CONFIG_INFO_COLOR 0 +#endif + +// TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_DEBUG_COLOR +#define TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWI_CONFIG_LOG_ENABLED +#define TWI_CONFIG_LOG_ENABLED 0 +#endif +// TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWI_CONFIG_LOG_LEVEL +#define TWI_CONFIG_LOG_LEVEL 3 +#endif + +// TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_INFO_COLOR +#define TWI_CONFIG_INFO_COLOR 0 +#endif + +// TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_DEBUG_COLOR +#define TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef UART_CONFIG_LOG_ENABLED +#define UART_CONFIG_LOG_ENABLED 0 +#endif +// UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef UART_CONFIG_LOG_LEVEL +#define UART_CONFIG_LOG_LEVEL 3 +#endif + +// UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_INFO_COLOR +#define UART_CONFIG_INFO_COLOR 0 +#endif + +// UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_DEBUG_COLOR +#define UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef USBD_CONFIG_LOG_ENABLED +#define USBD_CONFIG_LOG_ENABLED 0 +#endif +// USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef USBD_CONFIG_LOG_LEVEL +#define USBD_CONFIG_LOG_LEVEL 3 +#endif + +// USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_INFO_COLOR +#define USBD_CONFIG_INFO_COLOR 0 +#endif + +// USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_DEBUG_COLOR +#define USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef WDT_CONFIG_LOG_ENABLED +#define WDT_CONFIG_LOG_ENABLED 0 +#endif +// WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef WDT_CONFIG_LOG_LEVEL +#define WDT_CONFIG_LOG_LEVEL 3 +#endif + +// WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_INFO_COLOR +#define WDT_CONFIG_INFO_COLOR 0 +#endif + +// WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_DEBUG_COLOR +#define WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Libraries + +//========================================================== +// APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CDC_ACM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define APP_USBD_CDC_ACM_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#define APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_MSC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_MSC_CONFIG_LOG_ENABLED +#define APP_USBD_MSC_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_MSC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_MSC_CONFIG_LOG_LEVEL +#define APP_USBD_MSC_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_MSC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_INFO_COLOR +#define APP_USBD_MSC_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_MSC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_DEBUG_COLOR +#define APP_USBD_MSC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MEM_MANAGER_ENABLE_LOGS - Enable debug trace in the module. + + +#ifndef MEM_MANAGER_ENABLE_LOGS +#define MEM_MANAGER_ENABLE_LOGS 0 +#endif + +// NRF_BALLOC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_LOG_ENABLED +#define NRF_BALLOC_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_LOG_LEVEL +#define NRF_BALLOC_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_INFO_COLOR +#define NRF_BALLOC_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BALLOC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_DEBUG_COLOR +#define NRF_BALLOC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_BLE_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_CLI_BLE_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_CLI_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_MEMOBJ_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MEMOBJ_CONFIG_LOG_ENABLED +#define NRF_MEMOBJ_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MEMOBJ_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MEMOBJ_CONFIG_LOG_LEVEL +#define NRF_MEMOBJ_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MEMOBJ_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_INFO_COLOR +#define NRF_MEMOBJ_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MEMOBJ_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_DEBUG_COLOR +#define NRF_MEMOBJ_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#define NRF_PWR_MGMT_CONFIG_LOG_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_PWR_MGMT_CONFIG_LOG_LEVEL +#define NRF_PWR_MGMT_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_PWR_MGMT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_INFO_COLOR +#define NRF_PWR_MGMT_CONFIG_INFO_COLOR 0 +#endif + +// NRF_PWR_MGMT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#define NRF_PWR_MGMT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_ANT_LOG_ENABLED - Enable logging in SoftDevice handler (ANT) module. +//========================================================== +#ifndef NRF_SDH_ANT_LOG_ENABLED +#define NRF_SDH_ANT_LOG_ENABLED 1 +#endif +// NRF_SDH_ANT_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_ANT_LOG_LEVEL +#define NRF_SDH_ANT_LOG_LEVEL 3 +#endif + +// NRF_SDH_ANT_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_INFO_COLOR +#define NRF_SDH_ANT_INFO_COLOR 0 +#endif + +// NRF_SDH_ANT_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_DEBUG_COLOR +#define NRF_SDH_ANT_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_BLE_LOG_ENABLED - Enable logging in SoftDevice handler (BLE) module. +//========================================================== +#ifndef NRF_SDH_BLE_LOG_ENABLED +#define NRF_SDH_BLE_LOG_ENABLED 1 +#endif +// NRF_SDH_BLE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_BLE_LOG_LEVEL +#define NRF_SDH_BLE_LOG_LEVEL 3 +#endif + +// NRF_SDH_BLE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_INFO_COLOR +#define NRF_SDH_BLE_INFO_COLOR 0 +#endif + +// NRF_SDH_BLE_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_DEBUG_COLOR +#define NRF_SDH_BLE_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_LOG_ENABLED - Enable logging in SoftDevice handler module. +//========================================================== +#ifndef NRF_SDH_LOG_ENABLED +#define NRF_SDH_LOG_ENABLED 1 +#endif +// NRF_SDH_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_LOG_LEVEL +#define NRF_SDH_LOG_LEVEL 3 +#endif + +// NRF_SDH_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_INFO_COLOR +#define NRF_SDH_INFO_COLOR 0 +#endif + +// NRF_SDH_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_DEBUG_COLOR +#define NRF_SDH_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_SOC_LOG_ENABLED - Enable logging in SoftDevice handler (SoC) module. +//========================================================== +#ifndef NRF_SDH_SOC_LOG_ENABLED +#define NRF_SDH_SOC_LOG_ENABLED 1 +#endif +// NRF_SDH_SOC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_SOC_LOG_LEVEL +#define NRF_SDH_SOC_LOG_LEVEL 3 +#endif + +// NRF_SDH_SOC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_INFO_COLOR +#define NRF_SDH_SOC_INFO_COLOR 0 +#endif + +// NRF_SDH_SOC_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_DEBUG_COLOR +#define NRF_SDH_SOC_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// +//========================================================== + +// +//========================================================== + +// +//========================================================== + +// nRF_NFC + +//========================================================== +// NFC_BLE_OOB_ADVDATA_ENABLED - nfc_ble_oob_advdata - Encoding the advertising data and/or scan response data which is specific for OOB pairing +//========================================================== +#ifndef NFC_BLE_OOB_ADVDATA_ENABLED +#define NFC_BLE_OOB_ADVDATA_ENABLED 0 +#endif +// ADVANCED_ADVDATA_SUPPORT - Non-mandatory AD types for BLE OOB pairing are encoded inside the NDEF message (e.g. service UUIDs) + +// <1=> Enabled +// <0=> Disabled + +#ifndef ADVANCED_ADVDATA_SUPPORT +#define ADVANCED_ADVDATA_SUPPORT 0 +#endif + +// + +// NFC_BLE_PAIR_LIB_ENABLED - nfc_ble_pair_lib - Library parameters +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_ENABLED +#define NFC_BLE_PAIR_LIB_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_LOG_ENABLED +#define NFC_BLE_PAIR_LIB_LOG_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_BLE_PAIR_LIB_LOG_LEVEL +#define NFC_BLE_PAIR_LIB_LOG_LEVEL 3 +#endif + +// NFC_BLE_PAIR_LIB_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_INFO_COLOR +#define NFC_BLE_PAIR_LIB_INFO_COLOR 0 +#endif + +// NFC_BLE_PAIR_LIB_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_DEBUG_COLOR +#define NFC_BLE_PAIR_LIB_DEBUG_COLOR 0 +#endif + +// + +// NFC_BLE_PAIR_LIB_SECURITY_PARAMETERS - Common Peer Manager security parameters. + +//========================================================== +// BLE_NFC_SEC_PARAM_BOND - Enables device bonding. + +// If bonding is enabled at least one of the BLE_NFC_SEC_PARAM_KDIST options must be enabled. +//========================================================== +#ifndef BLE_NFC_SEC_PARAM_BOND +#define BLE_NFC_SEC_PARAM_BOND 1 +#endif +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// + +// BLE_NFC_SEC_PARAM_MIN_KEY_SIZE - Minimal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MIN_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MIN_KEY_SIZE 7 +#endif + +// BLE_NFC_SEC_PARAM_MAX_KEY_SIZE - Maximal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MAX_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MAX_KEY_SIZE 16 +#endif + +// +//========================================================== + +// + +// NFC_NDEF_MSG_ENABLED - nfc_ndef_msg - NFC NDEF Message generator module +//========================================================== +#ifndef NFC_NDEF_MSG_ENABLED +#define NFC_NDEF_MSG_ENABLED 0 +#endif +// NFC_NDEF_MSG_TAG_TYPE - NFC Tag Type + +// <2=> Type 2 Tag +// <4=> Type 4 Tag + +#ifndef NFC_NDEF_MSG_TAG_TYPE +#define NFC_NDEF_MSG_TAG_TYPE 2 +#endif + +// + +// NFC_NDEF_MSG_PARSER_ENABLED - nfc_ndef_msg_parser - NFC NDEF message parser module +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_ENABLED +#define NFC_NDEF_MSG_PARSER_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_LOG_ENABLED +#define NFC_NDEF_MSG_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_MSG_PARSER_LOG_LEVEL +#define NFC_NDEF_MSG_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_MSG_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_MSG_PARSER_INFO_COLOR +#define NFC_NDEF_MSG_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_NDEF_RECORD_PARSER_ENABLED - nfc_ndef_record_parser - NFC NDEF Record parser module +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_ENABLED +#define NFC_NDEF_RECORD_PARSER_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_LOG_ENABLED +#define NFC_NDEF_RECORD_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_RECORD_PARSER_LOG_LEVEL +#define NFC_NDEF_RECORD_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_RECORD_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_RECORD_PARSER_INFO_COLOR +#define NFC_NDEF_RECORD_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_T2T_HAL_ENABLED - nfc_t2t_hal - Hardware Abstraction Layer for NFC library. +//========================================================== +#ifndef NFC_T2T_HAL_ENABLED +#define NFC_T2T_HAL_ENABLED 0 +#endif +// NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NFCT_CONFIG_IRQ_PRIORITY +#define NFCT_CONFIG_IRQ_PRIORITY 7 +#endif + +// HAL_NFC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_LOG_ENABLED +#define HAL_NFC_CONFIG_LOG_ENABLED 0 +#endif +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// HAL_NFC_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_DEBUG_PIN_ENABLED +#define HAL_NFC_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 11 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 12 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 24 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 25 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 28 +#endif + +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// + +// + +// NFC_T4T_HAL_ENABLED - nfc_t4t_hal - Hardware Abstraction Layer for NFC library. +//========================================================== +#ifndef NFC_T4T_HAL_ENABLED +#define NFC_T4T_HAL_ENABLED 0 +#endif +// NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NFCT_CONFIG_IRQ_PRIORITY +#define NFCT_CONFIG_IRQ_PRIORITY 7 +#endif + +// HAL_NFC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_LOG_ENABLED +#define HAL_NFC_CONFIG_LOG_ENABLED 0 +#endif +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// HAL_NFC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef HAL_NFC_CONFIG_LOG_LEVEL +#define HAL_NFC_CONFIG_LOG_LEVEL 3 +#endif + +// HAL_NFC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_INFO_COLOR +#define HAL_NFC_CONFIG_INFO_COLOR 0 +#endif + +// HAL_NFC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef HAL_NFC_CONFIG_DEBUG_COLOR +#define HAL_NFC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// HAL_NFC_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. +//========================================================== +#ifndef HAL_NFC_CONFIG_DEBUG_PIN_ENABLED +#define HAL_NFC_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_ON_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_ON_DEBUG_PIN +#define HAL_NFC_HCLOCK_ON_DEBUG_PIN 31 +#endif + +// HAL_NFC_HCLOCK_OFF_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_HCLOCK_OFF_DEBUG_PIN +#define HAL_NFC_HCLOCK_OFF_DEBUG_PIN 31 +#endif + +// HAL_NFC_NFC_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_NFC_EVENT_DEBUG_PIN +#define HAL_NFC_NFC_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_DETECT_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_DETECT_EVENT_DEBUG_PIN +#define HAL_NFC_DETECT_EVENT_DEBUG_PIN 31 +#endif + +// HAL_NFC_TIMER4_EVENT_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef HAL_NFC_TIMER4_EVENT_DEBUG_PIN +#define HAL_NFC_TIMER4_EVENT_DEBUG_PIN 31 +#endif + +// + +// + +// +//========================================================== + +// nRF_Segger_RTT + +//========================================================== +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Size of upstream buffer. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_SoftDevice + +//========================================================== +// NRF_SDH_ANT_ENABLED - nrf_sdh_ant - SoftDevice ANT event handler +//========================================================== +#ifndef NRF_SDH_ANT_ENABLED +#define NRF_SDH_ANT_ENABLED 0 +#endif +// ANT Channels + +//========================================================== +// NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED - Allocated ANT channels. +#ifndef NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED +#define NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED 0 +#endif + +// NRF_SDH_ANT_ENCRYPTED_CHANNELS - Encrypted ANT channels. +#ifndef NRF_SDH_ANT_ENCRYPTED_CHANNELS +#define NRF_SDH_ANT_ENCRYPTED_CHANNELS 0 +#endif + +// +//========================================================== + +// ANT Queues + +//========================================================== +// NRF_SDH_ANT_EVENT_QUEUE_SIZE - Event queue size. +#ifndef NRF_SDH_ANT_EVENT_QUEUE_SIZE +#define NRF_SDH_ANT_EVENT_QUEUE_SIZE 32 +#endif + +// NRF_SDH_ANT_BURST_QUEUE_SIZE - ANT burst queue size. +#ifndef NRF_SDH_ANT_BURST_QUEUE_SIZE +#define NRF_SDH_ANT_BURST_QUEUE_SIZE 128 +#endif + +// +//========================================================== + +// ANT Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_ANT_OBSERVER_PRIO_LEVELS - Total number of priority levels for ANT observers. +// This setting configures the number of priority levels available for the ANT event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_ANT_OBSERVER_PRIO_LEVELS +#define NRF_SDH_ANT_OBSERVER_PRIO_LEVELS 2 +#endif + +// ANT Observers priorities - Invididual priorities + +//========================================================== +// ANT_BPWR_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Bicycle Power Profile. + +#ifndef ANT_BPWR_ANT_OBSERVER_PRIO +#define ANT_BPWR_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_BSC_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Bicycle Speed and Cadence Profile. + +#ifndef ANT_BSC_ANT_OBSERVER_PRIO +#define ANT_BSC_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_ENCRYPT_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Cryptographic ANT stack configuration module. + +#ifndef ANT_ENCRYPT_ANT_OBSERVER_PRIO +#define ANT_ENCRYPT_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_HRM_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Heart Rate Monitor. + +#ifndef ANT_HRM_ANT_OBSERVER_PRIO +#define ANT_HRM_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_SDM_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Stride Based Speed and Distance Monitor Profile. + +#ifndef ANT_SDM_ANT_OBSERVER_PRIO +#define ANT_SDM_ANT_OBSERVER_PRIO 1 +#endif + +// ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the ANT state indicator module. + +#ifndef ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO +#define ANT_STATE_INDICATOR_ANT_OBSERVER_PRIO 1 +#endif + +// BSP_BTN_ANT_OBSERVER_PRIO +// Priority with which ANT events are dispatched to the Button Control module. + +#ifndef BSP_BTN_ANT_OBSERVER_PRIO +#define BSP_BTN_ANT_OBSERVER_PRIO 1 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_BLE_ENABLED - nrf_sdh_ble - SoftDevice BLE event handler +//========================================================== +#ifndef NRF_SDH_BLE_ENABLED +#define NRF_SDH_BLE_ENABLED 1 +#endif +// BLE Stack configuration - Stack configuration parameters + +// These values are not used directly by the SoftDevice handler but the application or other libraries might depend on them. +// Keep them up-to-date with the desired configuration. +//========================================================== +// NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links. +#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT +#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 0 +#endif + +// NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links. +#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT +#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0 +#endif + +// NRF_SDH_BLE_TOTAL_LINK_COUNT - Maximum number of total concurrent connections using the default configuration. +#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT +#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1 +#endif + +// NRF_SDH_BLE_GAP_EVENT_LENGTH - The time set aside for this connection on every connection interval in 1.25 ms units. +#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH +#define NRF_SDH_BLE_GAP_EVENT_LENGTH 3 +#endif + +// NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. +#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE +#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23 +#endif + +// NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. +#ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE +#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408 +#endif + +// NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. +#ifndef NRF_SDH_BLE_VS_UUID_COUNT +#define NRF_SDH_BLE_VS_UUID_COUNT 0 +#endif + +// NRF_SDH_BLE_SERVICE_CHANGED - Include the Service Changed characteristic in the Attribute Table. + + +#ifndef NRF_SDH_BLE_SERVICE_CHANGED +#define NRF_SDH_BLE_SERVICE_CHANGED 0 +#endif + +// +//========================================================== + +// BLE Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_BLE_OBSERVER_PRIO_LEVELS - Total number of priority levels for BLE observers. +// This setting configures the number of priority levels available for BLE event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_BLE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_BLE_OBSERVER_PRIO_LEVELS 3 +#endif + +// BLE Observers priorities - Invididual priorities + +//========================================================== +// BLE_ADV_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Advertising module. + +#ifndef BLE_ADV_BLE_OBSERVER_PRIO +#define BLE_ADV_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_ANCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Apple Notification Service Client. + +#ifndef BLE_ANCS_C_BLE_OBSERVER_PRIO +#define BLE_ANCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_ANS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Alert Notification Service Client. + +#ifndef BLE_ANS_C_BLE_OBSERVER_PRIO +#define BLE_ANS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service. + +#ifndef BLE_BAS_BLE_OBSERVER_PRIO +#define BLE_BAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service Client. + +#ifndef BLE_BAS_C_BLE_OBSERVER_PRIO +#define BLE_BAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Blood Pressure Service. + +#ifndef BLE_BPS_BLE_OBSERVER_PRIO +#define BLE_BPS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection parameters module. + +#ifndef BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +#define BLE_CONN_PARAMS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CONN_STATE_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection State module. + +#ifndef BLE_CONN_STATE_BLE_OBSERVER_PRIO +#define BLE_CONN_STATE_BLE_OBSERVER_PRIO 0 +#endif + +// BLE_CSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Cycling Speed and Cadence Service. + +#ifndef BLE_CSCS_BLE_OBSERVER_PRIO +#define BLE_CSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Current Time Service Client. + +#ifndef BLE_CTS_C_BLE_OBSERVER_PRIO +#define BLE_CTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_DB_DISC_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Database Discovery module. + +#ifndef BLE_DB_DISC_BLE_OBSERVER_PRIO +#define BLE_DB_DISC_BLE_OBSERVER_PRIO 1 +#endif + +// BLE_DFU_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_BLE_OBSERVER_PRIO +#define BLE_DFU_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_GLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Glucose Service. + +#ifndef BLE_GLS_BLE_OBSERVER_PRIO +#define BLE_GLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HIDS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Human Interface Device Service. + +#ifndef BLE_HIDS_BLE_OBSERVER_PRIO +#define BLE_HIDS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service. + +#ifndef BLE_HRS_BLE_OBSERVER_PRIO +#define BLE_HRS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service Client. + +#ifndef BLE_HRS_C_BLE_OBSERVER_PRIO +#define BLE_HRS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Health Thermometer Service. + +#ifndef BLE_HTS_BLE_OBSERVER_PRIO +#define BLE_HTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service. + +#ifndef BLE_IAS_BLE_OBSERVER_PRIO +#define BLE_IAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service Client. + +#ifndef BLE_IAS_C_BLE_OBSERVER_PRIO +#define BLE_IAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service. + +#ifndef BLE_LBS_BLE_OBSERVER_PRIO +#define BLE_LBS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service Client. + +#ifndef BLE_LBS_C_BLE_OBSERVER_PRIO +#define BLE_LBS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Link Loss Service. + +#ifndef BLE_LLS_BLE_OBSERVER_PRIO +#define BLE_LLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LNS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Location Navigation Service. + +#ifndef BLE_LNS_BLE_OBSERVER_PRIO +#define BLE_LNS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Service. + +#ifndef BLE_NUS_BLE_OBSERVER_PRIO +#define BLE_NUS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Central Service. + +#ifndef BLE_NUS_C_BLE_OBSERVER_PRIO +#define BLE_NUS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service. + +#ifndef BLE_OTS_BLE_OBSERVER_PRIO +#define BLE_OTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service client. + +#ifndef BLE_OTS_C_BLE_OBSERVER_PRIO +#define BLE_OTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Service. + +#ifndef BLE_RSCS_BLE_OBSERVER_PRIO +#define BLE_RSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Client. + +#ifndef BLE_RSCS_C_BLE_OBSERVER_PRIO +#define BLE_RSCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_TPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the TX Power Service. + +#ifndef BLE_TPS_BLE_OBSERVER_PRIO +#define BLE_TPS_BLE_OBSERVER_PRIO 2 +#endif + +// BSP_BTN_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Button Control module. + +#ifndef BSP_BTN_BLE_OBSERVER_PRIO +#define BSP_BTN_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NRF_BLE_BMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Bond Management Service. + +#ifndef NRF_BLE_BMS_BLE_OBSERVER_PRIO +#define NRF_BLE_BMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_CGMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Contiuon Glucose Monitoring Service. + +#ifndef NRF_BLE_CGMS_BLE_OBSERVER_PRIO +#define NRF_BLE_CGMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT Service Client. + +#ifndef NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +#define NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATT_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT module. + +#ifndef NRF_BLE_GATT_BLE_OBSERVER_PRIO +#define NRF_BLE_GATT_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_QWR_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Queued writes module. + +#ifndef NRF_BLE_QWR_BLE_OBSERVER_PRIO +#define NRF_BLE_QWR_BLE_OBSERVER_PRIO 2 +#endif + +// PM_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Peer Manager module. + +#ifndef PM_BLE_OBSERVER_PRIO +#define PM_BLE_OBSERVER_PRIO 2 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_ENABLED - nrf_sdh - SoftDevice handler +//========================================================== +#ifndef NRF_SDH_ENABLED +#define NRF_SDH_ENABLED 1 +#endif +// Dispatch model + +// This setting configures how Stack events are dispatched to the application. +//========================================================== +// NRF_SDH_DISPATCH_MODEL + + +// NRF_SDH_DISPATCH_MODEL_INTERRUPT: SoftDevice events are passed to the application from the interrupt context. +// NRF_SDH_DISPATCH_MODEL_APPSH: SoftDevice events are scheduled using @ref app_scheduler. +// NRF_SDH_DISPATCH_MODEL_POLLING: SoftDevice events are to be fetched manually. +// <0=> NRF_SDH_DISPATCH_MODEL_INTERRUPT +// <1=> NRF_SDH_DISPATCH_MODEL_APPSH +// <2=> NRF_SDH_DISPATCH_MODEL_POLLING + +#ifndef NRF_SDH_DISPATCH_MODEL +#define NRF_SDH_DISPATCH_MODEL 0 +#endif + +// +//========================================================== + +// Clock - SoftDevice clock configuration + +//========================================================== +// NRF_SDH_CLOCK_LF_SRC - SoftDevice clock source. + +// <0=> NRF_CLOCK_LF_SRC_RC +// <1=> NRF_CLOCK_LF_SRC_XTAL +// <2=> NRF_CLOCK_LF_SRC_SYNTH + +#ifndef NRF_SDH_CLOCK_LF_SRC +#define NRF_SDH_CLOCK_LF_SRC 1 +#endif + +// NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. +#ifndef NRF_SDH_CLOCK_LF_RC_CTIV +#define NRF_SDH_CLOCK_LF_RC_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. +// How often (in number of calibration intervals) the RC oscillator shall be calibrated +// if the temperature has not changed. + +#ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV +#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_XTAL_ACCURACY - External crystal clock accuracy used in the LL to compute timing windows. + +// <0=> NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM +// <1=> NRF_CLOCK_LF_XTAL_ACCURACY_500_PPM +// <2=> NRF_CLOCK_LF_XTAL_ACCURACY_150_PPM +// <3=> NRF_CLOCK_LF_XTAL_ACCURACY_100_PPM +// <4=> NRF_CLOCK_LF_XTAL_ACCURACY_75_PPM +// <5=> NRF_CLOCK_LF_XTAL_ACCURACY_50_PPM +// <6=> NRF_CLOCK_LF_XTAL_ACCURACY_30_PPM +// <7=> NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM + +#ifndef NRF_SDH_CLOCK_LF_XTAL_ACCURACY +#define NRF_SDH_CLOCK_LF_XTAL_ACCURACY 7 +#endif + +// +//========================================================== + +// SDH Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_REQ_OBSERVER_PRIO_LEVELS - Total number of priority levels for request observers. +// This setting configures the number of priority levels available for the SoftDevice request event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_REQ_OBSERVER_PRIO_LEVELS +#define NRF_SDH_REQ_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STATE_OBSERVER_PRIO_LEVELS - Total number of priority levels for state observers. +// This setting configures the number of priority levels available for the SoftDevice state event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STATE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STATE_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STACK_OBSERVER_PRIO_LEVELS - Total number of priority levels for stack event observers. +// This setting configures the number of priority levels available for the SoftDevice stack event handlers (ANT, BLE, SoC). +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STACK_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STACK_OBSERVER_PRIO_LEVELS 2 +#endif + + +// State Observers priorities - Invididual priorities + +//========================================================== +// CLOCK_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_STATE_OBSERVER_PRIO +#define CLOCK_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_STATE_OBSERVER_PRIO +#define POWER_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// RNG_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to this module. + +#ifndef RNG_CONFIG_STATE_OBSERVER_PRIO +#define RNG_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// Stack Event Observers priorities - Invididual priorities + +//========================================================== +// NRF_SDH_ANT_STACK_OBSERVER_PRIO +// This setting configures the priority with which ANT events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have ANT events dispatched before or after other stack events, such as BLE or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_ANT_STACK_OBSERVER_PRIO +#define NRF_SDH_ANT_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_BLE_STACK_OBSERVER_PRIO +// This setting configures the priority with which BLE events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have BLE events dispatched before or after other stack events, such as ANT or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_BLE_STACK_OBSERVER_PRIO +#define NRF_SDH_BLE_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_SOC_STACK_OBSERVER_PRIO +// This setting configures the priority with which SoC events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have SoC events dispatched before or after other stack events, such as ANT or BLE. +// Zero is the highest priority. + +#ifndef NRF_SDH_SOC_STACK_OBSERVER_PRIO +#define NRF_SDH_SOC_STACK_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_SOC_ENABLED - nrf_sdh_soc - SoftDevice SoC event handler +//========================================================== +#ifndef NRF_SDH_SOC_ENABLED +#define NRF_SDH_SOC_ENABLED 0 +#endif +// SoC Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_SOC_OBSERVER_PRIO_LEVELS - Total number of priority levels for SoC observers. +// This setting configures the number of priority levels available for the SoC event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_SOC_OBSERVER_PRIO_LEVELS +#define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS 2 +#endif + +// SoC Observers priorities - Invididual priorities + +//========================================================== +// BLE_ADV_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Advertising module. + +#ifndef BLE_ADV_SOC_OBSERVER_PRIO +#define BLE_ADV_SOC_OBSERVER_PRIO 1 +#endif + +// BLE_DFU_SOC_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_SOC_OBSERVER_PRIO +#define BLE_DFU_SOC_OBSERVER_PRIO 1 +#endif + +// CLOCK_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_SOC_OBSERVER_PRIO +#define CLOCK_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_SOC_OBSERVER_PRIO +#define POWER_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct new file mode 100644 index 0000000000..6849dc2239 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct @@ -0,0 +1,38 @@ +#! armcc -E + +/* Default to no softdevice */ +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x0 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 0x100000 +#endif + +/* If app_start is 0, do not set aside space for the softdevice */ +#if MBED_APP_START == 0 + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x40000 +#else + #define MBED_RAM_START 0x20003700 + #define MBED_RAM_SIZE 0x3C900 +#endif + +#define MBED_RAM0_START MBED_RAM_START +#define MBED_RAM0_SIZE 0x100 +#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE) +#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE) + +LR_IROM1 MBED_APP_START MBED_APP_SIZE { + ER_IROM1 MBED_APP_START MBED_APP_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM0 MBED_RAM0_START UNINIT MBED_RAM0_SIZE { ;no init section + *(*noinit) + } + RW_IRAM1 MBED_RAM1_START MBED_RAM1_SIZE { + .ANY (+RW +ZI) + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/startup_nrf52840.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/startup_nrf52840.S new file mode 100644 index 0000000000..59e6c0ad01 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/startup_nrf52840.S @@ -0,0 +1,268 @@ +;/* 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 0 ; Reserved + DCD 0 ; Reserved + DCD PWM3_IRQHandler_v + DCD 0 ; Reserved + DCD SPIM3_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 +PWM3_IRQHandler_v +SPIM3_IRQHandler_v + + B . + ENDP + ALIGN + END diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld new file mode 100644 index 0000000000..55f39e9c4f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld @@ -0,0 +1,248 @@ +/* + * 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. */ + +/* Default to no softdevice */ +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x0 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 0x100000 +#endif + +/* If app_start is 0, do not set aside space for the softdevice */ +#if MBED_APP_START == 0 + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x40000 +#else + #define MBED_RAM_START 0x20003700 + #define MBED_RAM_SIZE 0x3C900 +#endif + +#define MBED_RAM0_START MBED_RAM_START +#define MBED_RAM0_SIZE 0x100 +#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE) +#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE) + +MEMORY +{ + FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE + RAM_NVIC (rwx) : ORIGIN = MBED_RAM0_START, LENGTH = MBED_RAM0_SIZE + RAM (rwx) : ORIGIN = MBED_RAM1_START, LENGTH = MBED_RAM1_SIZE +} + + +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 + + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > 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 (NOLOAD) : + { + PROVIDE(__start_noinit = .); + KEEP(*(.noinit)) + PROVIDE(__stop_noinit = .); + } > RAM_NVIC + + .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); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/startup_NRF52840.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/startup_NRF52840.S new file mode 100644 index 0000000000..ff772b1aa7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/startup_NRF52840.S @@ -0,0 +1,292 @@ +/* + * 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 DebugMon_Handler + .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 0 /*Reserved */ + .long 0 /*Reserved */ + .long PWM3_IRQHandler_v + .long 0 /*Reserved */ + .long SPIM3_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 DebugMon_Handler + .type DebugMon_Handler, %function +DebugMon_Handler: + b . + .size DebugMon_Handler, . - DebugMon_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 PWM3_IRQHandler_v + IRQ SPIM3_IRQHandler_v + + .end diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf new file mode 100644 index 0000000000..2605356911 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf @@ -0,0 +1,75 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ + +/* Default to no softdevice */ +if (!isdefinedsymbol(MBED_APP_START)) { + define symbol MBED_APP_START = 0x0; +} + +if (!isdefinedsymbol(MBED_APP_SIZE)) { + define symbol MBED_APP_SIZE = 0x100000; +} + +/* If app_start is 0, do not set aside space for the softdevice */ +if (MBED_APP_START == 0) { + define symbol MBED_RAM_START = 0x20000000; + define symbol MBED_RAM_SIZE = 0x40000; +} else { + define symbol MBED_RAM_START = 0x20003700; + define symbol MBED_RAM_SIZE = 0x3C900; +} + +define symbol MBED_RAM0_START = MBED_RAM_START; +define symbol MBED_RAM0_SIZE = 0x100; +define symbol MBED_RAM1_START = (MBED_RAM_START + MBED_RAM0_SIZE); +define symbol MBED_RAM1_SIZE = (MBED_RAM_SIZE - MBED_RAM0_SIZE); + +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = MBED_APP_START; + +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = MBED_APP_START; +define symbol __ICFEDIT_region_ROM_end__ = MBED_APP_START + MBED_APP_SIZE - 1; +define symbol __ICFEDIT_region_RAM_NVIC_start__ = MBED_RAM0_START; +define symbol __ICFEDIT_region_RAM_NVIC_end__ = MBED_RAM0_START + MBED_RAM0_SIZE - 1; +define symbol __ICFEDIT_region_RAM_start__ = MBED_RAM1_START; +define symbol __ICFEDIT_region_RAM_end__ = MBED_RAM1_START + MBED_RAM1_SIZE - 1; +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__ = 0x17800; +/**** 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 }; +place at address mem:__ICFEDIT_region_RAM_NVIC_start__ { 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 }; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/startup_NRF52840_IAR.S b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/startup_NRF52840_IAR.S new file mode 100644 index 0000000000..86b3d77ecb --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/startup_NRF52840_IAR.S @@ -0,0 +1,419 @@ +;/* 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 0 ; Reserved + DCD 0 ; Reserved + DCD PWM3_IRQHandler_v + DCD 0 ; Reserved + DCD SPIM3_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 + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis.h new file mode 100644 index 0000000000..214885742d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.c new file mode 100644 index 0000000000..2efb6da48c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.c @@ -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]; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.h new file mode 100644 index 0000000000..6cc327e851 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/cmsis_nvic.h @@ -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 + 48) // 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.c new file mode 100644 index 0000000000..55b171bf2d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.c @@ -0,0 +1,267 @@ +/* + +Copyright (c) 2009-2017 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 + + 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. + +NOTICE: This file has been modified by Nordic Semiconductor ASA. + +*/ + +/* NOTE: Template files (including this one) are application specific and therefore expected to + be copied into the application project folder prior to its use! */ + +#include +#include +#include "nrf.h" +#include "system_nrf52840.h" +#include "nrf5x_lf_clk_helper.h" + +/*lint ++flb "Enter library region" */ + +#define __SYSTEM_CLOCK_64M (64000000UL) + +static bool errata_36(void); +static bool errata_66(void); +static bool errata_98(void); +static bool errata_103(void); +static bool errata_115(void); +static bool errata_120(void); +static bool errata_136(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) +{ + /* 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 + + /* 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 66 "TEMP: Linearity specification not met with default settings" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_66()){ + NRF_TEMP->A0 = NRF_FICR->TEMP.A0; + NRF_TEMP->A1 = NRF_FICR->TEMP.A1; + NRF_TEMP->A2 = NRF_FICR->TEMP.A2; + NRF_TEMP->A3 = NRF_FICR->TEMP.A3; + NRF_TEMP->A4 = NRF_FICR->TEMP.A4; + NRF_TEMP->A5 = NRF_FICR->TEMP.A5; + NRF_TEMP->B0 = NRF_FICR->TEMP.B0; + NRF_TEMP->B1 = NRF_FICR->TEMP.B1; + NRF_TEMP->B2 = NRF_FICR->TEMP.B2; + NRF_TEMP->B3 = NRF_FICR->TEMP.B3; + NRF_TEMP->B4 = NRF_FICR->TEMP.B4; + NRF_TEMP->B5 = NRF_FICR->TEMP.B5; + NRF_TEMP->T0 = NRF_FICR->TEMP.T0; + NRF_TEMP->T1 = NRF_FICR->TEMP.T1; + NRF_TEMP->T2 = NRF_FICR->TEMP.T2; + NRF_TEMP->T3 = NRF_FICR->TEMP.T3; + NRF_TEMP->T4 = NRF_FICR->TEMP.T4; + } + + /* 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; + } + + /* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document + for your device located at https://infocenter.nordicsemi.com/ */ + if (errata_136()){ + if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){ + NRF_POWER->RESETREAS = ~POWER_RESETREAS_RESETPIN_Msk; + } + } + + /* 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 + + SystemCoreClockUpdate(); + + // Start the LF oscilator according to the mbed configuration (over the nrf5x_lf_clk_helper.h file) + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_TO_USE << CLOCK_LFCLKSRC_SRC_Pos); + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + // Wait for the external oscillator to start up. + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) { + // Do nothing. + } +} + + +static bool errata_36(void) +{ + if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){ + return true; + } + + return false; +} + + +static bool errata_66(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; +} + + +static bool errata_136(void) +{ + if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){ + return true; + } + + return false; +} + +/*lint --flb "Leave library region" */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.h new file mode 100644 index 0000000000..5a1e794962 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/system_nrf52840.h @@ -0,0 +1,61 @@ +/* + +Copyright (c) 2009-2017 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 + + 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. + +NOTICE: This file has been modified by Nordic Semiconductor ASA. + +*/ + +#ifndef SYSTEM_NRF52840_H +#define SYSTEM_NRF52840_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +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 */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/README.md new file mode 100644 index 0000000000..61aa551ec4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/README.md @@ -0,0 +1,21 @@ +# Folder origin + +components/ble +components/softdevice +components/libraries/fstorage/nrf_fstorage_sd.* + +# Modifications + +Removed: + * common/nrf_sdh_freertos.c + * common/nrf_sdh_freertos.h + * s212/* + * s332/* + +Moved: + * s112/ to ../TARGET_SOFTDEVICE_S112 + * s132/ to ../TARGET_SOFTDEVICE_s132 + * s140/ to ../TARGET_SOFTDEVICE_s140 + +Renamed: + * ble.h to nrf_ble.h diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md new file mode 100644 index 0000000000..c9f238a697 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md @@ -0,0 +1,12 @@ +# Folder origin + +components/ble + +# Modifications + +Removed + * ble_services/* + * ble_dtm/ble_dtm_hw_nrf51.c + +Renamed + * #include "ble.h" -> #include "nrf_ble.h" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c new file mode 100644 index 0000000000..1cb77cd6c8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c @@ -0,0 +1,695 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "nrf_fstorage.h" +#include "sdk_errors.h" +#include "nrf_sdh_ble.h" +#include "nrf_sdh_soc.h" + +#define BLE_ADV_MODES (5) /**< Total number of possible advertising modes. */ + + +#if (NRF_SD_BLE_API_VERSION <= 2) + + static bool whitelist_has_entries(ble_advertising_t * const p_advertising) + { + return ((p_advertising->whitelist.addr_count != 0) || (p_advertising->whitelist.irk_count != 0)); + } + +#else + + static bool whitelist_has_entries(ble_advertising_t * const p_advertising) + { + return p_advertising->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_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) +{ + if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) + { + p_advertising->current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + } +} + + +/**@brief Function for handling the Disconnected event. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) +{ + uint32_t ret; + + p_advertising->whitelist_temporarily_disabled = false; + + if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle && + p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false) + { + ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED); + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + } +} + + +/**@brief Function for handling the Timeout event. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_timeout(ble_advertising_t * const p_advertising, 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(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current)); + + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->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() +{ + return nrf_fstorage_is_busy(NULL); +} + + +/**@brief Get the next available advertising mode. + * + * @param[in] p_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + ble_adv_mode_t adv_mode) +{ + bool peer_addr_is_valid = addr_is_valid(p_advertising->peer_address.addr); + + // If a mode is disabled, continue to the next mode. + + switch (adv_mode) + { + case BLE_ADV_MODE_DIRECTED: + if ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid) + { + return BLE_ADV_MODE_DIRECTED; + } + // Fallthrough. + + case BLE_ADV_MODE_DIRECTED_SLOW: + if ((p_advertising->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 (p_advertising->adv_modes_config.ble_adv_fast_enabled) + { + return BLE_ADV_MODE_FAST; + } + // Fallthrough. + + case BLE_ADV_MODE_SLOW: + if (p_advertising->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[in] p_advertising Advertising instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS + */ +static ret_code_t set_adv_mode_directed(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED; + + p_adv_params->p_peer_addr = &(p_advertising->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[in] p_advertising Advertising module instance. + * @param[out] p_adv_params Advertising parameters. + * + * @return NRF_SUCCESS + */ +static ret_code_t set_adv_mode_directed_slow(ble_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED_SLOW; + + p_adv_params->p_peer_addr = &p_advertising->peer_address; + p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; + p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_directed_slow_timeout; + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_directed_slow_interval; + + return NRF_SUCCESS; +} + + +/**@brief Function for starting fast advertising. + * + * @param[in] p_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + ret_code_t ret; + + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_fast_interval; + p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_fast_timeout; + + if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && + (!p_advertising->whitelist_temporarily_disabled) && + (whitelist_has_entries(p_advertising))) + { + #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; + p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + + ret = ble_advdata_set(&(p_advertising->advdata), NULL); + if (ret != NRF_SUCCESS) + { + return ret; + } + + p_advertising->adv_evt = BLE_ADV_EVT_FAST_WHITELIST; + } + else + { + p_advertising->adv_evt = BLE_ADV_EVT_FAST; + } + + return NRF_SUCCESS; +} + + +/**@brief Function for starting slow advertising. + * + * @param[in] p_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + ble_gap_adv_params_t * p_adv_params) +{ + ret_code_t ret; + + p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_slow_interval; + p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_slow_timeout; + + if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && + (!p_advertising->whitelist_temporarily_disabled) && + (whitelist_has_entries(p_advertising))) + { + #if (NRF_SD_BLE_API_VERSION <= 2) + { + p_adv_params->p_whitelist = &p_advertising->whitelist; + } + #endif + + p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; + p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + + ret = ble_advdata_set(&(p_advertising->advdata), NULL); + if (ret != NRF_SUCCESS) + { + return ret; + } + + p_advertising->adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; + } + else + { + p_advertising->adv_evt = BLE_ADV_EVT_SLOW; + } + + return NRF_SUCCESS; +} + + +void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, + uint8_t ble_cfg_tag) +{ + p_advertising->conn_cfg_tag = ble_cfg_tag; +} + + +uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, + ble_advertising_init_t const * const p_init) +{ + uint32_t ret; + if ((p_init == NULL) || (p_advertising == NULL)) + { + return NRF_ERROR_NULL; + } + + p_advertising->initialized = true; + p_advertising->adv_mode_current = BLE_ADV_MODE_IDLE; + p_advertising->adv_modes_config = p_init->config; + p_advertising->conn_cfg_tag = BLE_CONN_CFG_TAG_DEFAULT; + p_advertising->evt_handler = p_init->evt_handler; + p_advertising->error_handler = p_init->error_handler; + p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; + + memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); + memset(&p_advertising->advdata, 0, sizeof(p_advertising->advdata)); + + // Copy advertising data. + p_advertising->advdata.name_type = p_init->advdata.name_type; + p_advertising->advdata.include_appearance = p_init->advdata.include_appearance; + p_advertising->advdata.flags = p_init->advdata.flags; + p_advertising->advdata.short_name_len = p_init->advdata.short_name_len; + + p_advertising->advdata.uuids_complete = p_init->advdata.uuids_complete; + p_advertising->advdata.uuids_more_available = p_init->advdata.uuids_more_available; + p_advertising->advdata.uuids_solicited = p_init->advdata.uuids_solicited; + p_advertising->advdata.include_ble_device_addr = p_init->advdata.include_ble_device_addr; + + if (p_init->advdata.p_manuf_specific_data != NULL) + { + p_advertising->advdata.p_manuf_specific_data = &(p_advertising->manuf_specific_data); + p_advertising->manuf_specific_data.data.p_data = p_advertising->manuf_data_array; + p_advertising->advdata.p_manuf_specific_data->company_identifier = + p_init->advdata.p_manuf_specific_data->company_identifier; + p_advertising->advdata.p_manuf_specific_data->data.size = p_init->advdata.p_manuf_specific_data->data.size; + + for (uint32_t i = 0; i < p_advertising->advdata.p_manuf_specific_data->data.size; i++) + { + p_advertising->manuf_data_array[i] = p_init->advdata.p_manuf_specific_data->data.p_data[i]; + } + } + + if (p_init->advdata.p_service_data_array != NULL) + { + p_advertising->service_data.data.p_data = p_advertising->service_data_array; + p_advertising->advdata.p_service_data_array = &(p_advertising->service_data); + p_advertising->advdata.p_service_data_array->data.p_data = p_advertising->service_data_array; + p_advertising->advdata.p_service_data_array->data.size = p_init->advdata.p_service_data_array->data.size; + p_advertising->advdata.p_service_data_array->service_uuid = p_init->advdata.p_service_data_array->service_uuid; + + for (uint32_t i = 0; i < p_advertising->advdata.p_service_data_array->data.size; i++) + { + p_advertising->service_data_array[i] = p_init->advdata.p_service_data_array->data.p_data[i]; + } + + p_advertising->advdata.service_data_count = p_init->advdata.service_data_count; + } + + if (p_init->advdata.p_slave_conn_int != NULL) + { + p_advertising->advdata.p_slave_conn_int = &(p_advertising->slave_conn_int); + p_advertising->advdata.p_slave_conn_int->max_conn_interval = p_init->advdata.p_slave_conn_int->max_conn_interval; + p_advertising->advdata.p_slave_conn_int->min_conn_interval = p_init->advdata.p_slave_conn_int->min_conn_interval; + } + + if (p_init->advdata.p_tx_power_level != NULL) + { + p_advertising->advdata.p_tx_power_level = p_init->advdata.p_tx_power_level; + } + +#if (NRF_SD_BLE_API_VERSION <= 2) + for (int i = 0; i whitelist.pp_addrs[i] = &p_advertising->whitelist_addrs[i]; + } + + for (int i = 0; i whitelist.pp_irks[i] = &p_advertising->whitelist_irks[i]; + } +#endif + ret = ble_advdata_set(&(p_advertising->advdata), &(p_init->srdata)); + return ret; +} + + +uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, + ble_adv_mode_t advertising_mode) +{ + uint32_t ret; + ble_gap_adv_params_t adv_params; + + if (p_advertising->initialized == false) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->adv_mode_current = advertising_mode; + + // Delay starting advertising until the flash operations are complete. + if (flash_access_in_progress()) + { + p_advertising->advertising_start_pending = true; + return NRF_SUCCESS; + } + + memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); + + if ( ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) + ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) + ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW)) + ) + { + if (p_advertising->evt_handler != NULL) + { + p_advertising->peer_addr_reply_expected = true; + p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); + } + else + { + p_advertising->peer_addr_reply_expected = false; + } + } + + p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode); + + // Fetch the whitelist. + if ((p_advertising->evt_handler != NULL) && + (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) && + (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && + (!p_advertising->whitelist_temporarily_disabled)) + { + #if (NRF_SD_BLE_API_VERSION >= 3) + p_advertising->whitelist_in_use = false; + #endif + p_advertising->whitelist_reply_expected = true; + p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); + } + else + { + p_advertising->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 (p_advertising->adv_mode_current) + { + case BLE_ADV_MODE_DIRECTED: + ret = set_adv_mode_directed(p_advertising, &adv_params); + break; + + case BLE_ADV_MODE_DIRECTED_SLOW: + ret = set_adv_mode_directed_slow(p_advertising, &adv_params); + break; + + case BLE_ADV_MODE_FAST: + ret = set_adv_mode_fast(p_advertising, &adv_params); + break; + + case BLE_ADV_MODE_SLOW: + ret = set_adv_mode_slow(p_advertising, &adv_params); + break; + + case BLE_ADV_MODE_IDLE: + p_advertising->adv_evt = BLE_ADV_EVT_IDLE; + break; + + default: + break; + } + + if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE) + { + ret = sd_ble_gap_adv_start(&adv_params, p_advertising->conn_cfg_tag); + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + if (p_advertising->evt_handler != NULL) + { + p_advertising->evt_handler(p_advertising->adv_evt); + } + + return NRF_SUCCESS; +} + + +void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connected(p_advertising, p_ble_evt); + break; + + // Upon disconnection, whitelist will be activated and direct advertising is started. + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected(p_advertising, p_ble_evt); + break; + + // Upon time-out, the next advertising mode is started. + case BLE_GAP_EVT_TIMEOUT: + on_timeout(p_advertising, p_ble_evt); + break; + + default: + break; + } +} + + +void ble_advertising_on_sys_evt(uint32_t evt_id, void * p_context) +{ + ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; + + switch (evt_id) + { + //When a flash operation finishes, re-attempt to start advertising operations. + case NRF_EVT_FLASH_OPERATION_SUCCESS: + case NRF_EVT_FLASH_OPERATION_ERROR: + { + if (p_advertising->advertising_start_pending) + { + p_advertising->advertising_start_pending = false; + ret_code_t ret = ble_advertising_start(p_advertising, + p_advertising->adv_mode_current); + + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + } + } break; + + default: + // No implementation needed. + break; + } +} + + +uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, + ble_gap_addr_t * p_peer_address) +{ + if (!p_advertising->peer_addr_reply_expected) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->peer_addr_reply_expected = false; + + memcpy(&p_advertising->peer_address, p_peer_address, sizeof(p_advertising->peer_address)); + + return NRF_SUCCESS; +} + + +uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, + 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 (!p_advertising->whitelist_reply_expected) + { + return NRF_ERROR_INVALID_STATE; + } + + p_advertising->whitelist_reply_expected = false; + + #if (NRF_SD_BLE_API_VERSION <= 2) + + p_advertising->whitelist.addr_count = addr_cnt; + p_advertising->whitelist.irk_count = irk_cnt; + + for (uint32_t i = 0; i < addr_cnt; i++) + { + *p_advertising->whitelist.pp_addrs[i] = p_gap_addrs[i]; + } + + for (uint32_t i = 0; i < irk_cnt; i++) + { + *p_advertising->whitelist.pp_irks[i] = p_gap_irks[i]; + } + + #else + + p_advertising->whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0)); + + #endif + + return NRF_SUCCESS; +} + + +uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising) +{ + uint32_t ret; + + (void) sd_ble_gap_adv_stop(); + + p_advertising->whitelist_temporarily_disabled = true; + + #if (NRF_SD_BLE_API_VERSION >= 3) + p_advertising->whitelist_in_use = false; + #endif + + p_advertising->advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + ret = ble_advdata_set(&(p_advertising->advdata), NULL); + if (ret != NRF_SUCCESS) + { + return ret; + } + + ret = ble_advertising_start(p_advertising, p_advertising->adv_mode_current); + if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) + { + p_advertising->error_handler(ret); + } + + return NRF_SUCCESS; +} + + +void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, + ble_adv_modes_config_t const * const p_adv_modes_config) +{ + p_advertising->adv_modes_config = *p_adv_modes_config; +} + + +#endif // NRF_MODULE_ENABLED(BLE_ADVERTISING) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h new file mode 100644 index 0000000000..61bbb7b0b6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ + +#ifndef BLE_ADVERTISING_H__ +#define BLE_ADVERTISING_H__ + +#include +#include "nrf_error.h" +#include "nrf_ble.h" +#include "ble_gattc.h" +#include "ble_advdata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_advertising instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define BLE_ADVERTISING_DEF(_name) \ +static ble_advertising_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ + BLE_ADV_BLE_OBSERVER_PRIO, \ + ble_advertising_on_ble_evt, &_name); \ +NRF_SDH_SOC_OBSERVER(_name ## _soc_obs, \ + BLE_ADV_SOC_OBSERVER_PRIO, \ + ble_advertising_on_sys_evt, &_name) + + +/**@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_on_disconnect_disabled; /**< Enable or disable automatic return to advertising upon disconnecting.*/ + 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; + +/**@brief BLE advertising event handler type. */ +typedef void (*ble_adv_evt_handler_t) (ble_adv_evt_t const adv_evt); + +/**@brief BLE advertising error handler type. */ +typedef void (*ble_adv_error_handler_t) (uint32_t nrf_error); + +typedef struct +{ + bool initialized; + bool advertising_start_pending; /**< Flag to keep track of ongoing operations in flash. */ + + ble_adv_evt_t 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. */ + + ble_adv_mode_t adv_mode_current; /**< Variable to keep track of the current advertising mode. */ + ble_adv_modes_config_t adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/ + uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if the advertising results in a connection. */ + + ble_gap_addr_t peer_address; /**< Address of the most recently connected peer, used for direct advertising. */ + bool peer_addr_reply_expected; /**< Flag to verify that peer address is only set when requested. */ + + ble_advdata_t advdata; /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */ + ble_advdata_manuf_data_t manuf_specific_data; /**< Manufacturer specific data structure*/ + uint8_t manuf_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the Manufacturer specific data*/ + ble_advdata_service_data_t service_data; /**< Service data structure. */ + uint8_t service_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the service data. */ + ble_advdata_conn_int_t slave_conn_int; /**< Connection interval range structure.*/ + uint16_t current_slave_link_conn_handle; /**< Connection handle for the active link. */ + + ble_adv_evt_handler_t evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */ + ble_adv_error_handler_t error_handler; /**< Handler for the advertising error events. */ + + bool whitelist_temporarily_disabled; /**< Flag to keep track of temporary disabling of the whitelist. */ + bool 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(). + ble_gap_addr_t * p_whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_irk_t * p_whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; + ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; + + ble_gap_whitelist_t m_whitelist = + { + .pp_addrs = p_whitelist_addrs, + .pp_irks = 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). + bool whitelist_in_use; +#endif +} ble_advertising_t; + +typedef struct +{ + uint32_t interval; + uint32_t timeout; + bool enabled; +} ble_adv_mode_config_t; + +/**@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_advdata_t advdata; /**< Advertising data: name, appearance, discovery flags, and more. */ + ble_advdata_t srdata; /**< Scan response data: Supplement to advertising data. */ + ble_adv_modes_config_t config; /**< Select which advertising modes and intervals will be utilized.*/ + ble_adv_evt_handler_t evt_handler; /**< Event handler that will be called upon advertising events. */ + ble_adv_error_handler_t error_handler; /**< Error handler that will propogate internal errors to the main applications. */ +} ble_advertising_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. + * @param[in] p_adv Advertising module instance. + */ +void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_adv); + + +/**@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. + * @param[in] p_adv Advertising module instance. + */ +void ble_advertising_on_sys_evt(uint32_t sys_evt, void * p_adv); + + +/**@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[out] p_advertising Advertising module instance. This structure must be supplied by + * the application. It is initialized by this function and will later + * be used to identify this particular module instance. + * @param[in] p_init Information needed to initialize the module. + * + * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. + */ +uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, + ble_advertising_init_t const * const p_init); + + + /**@brief Function for changing the connection settings tag that will be used for upcoming connections. + * + * @details See @ref sd_ble_cfg_set for more details about changing connection settings. If this + * function is never called, @ref BLE_CONN_CFG_TAG_DEFAULT will be used. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] ble_cfg_tag Configuration for the connection settings (see @ref sd_ble_cfg_set). + */ +void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, uint8_t ble_cfg_tag); + +/**@brief Function for starting advertising. + * + * @details You can start advertising in any of the advertising modes that you enabled + * during initialization. + * + * @param[in] p_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + 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_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + 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_advertising Advertising module instance. + * @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_advertising_t * const p_advertising, + 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. + * + * @param[in] p_advertising Advertising module instance. + * + * @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice. + */ +uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising); + + +/**@brief Function for changing advertising modes configuration. + * + * @details This function can be called if you wish to reconfigure the advertising modes that the + * advertising module will cycle through. Enable or disable modes as listed in + * @ref ble_adv_mode_t; or change the duration of the advertising and use of whitelist. + * + * Keep in mind that @ref ble_adv_modes_config_t is also supplied when calling + * @ref ble_advertising_init. Calling @ref ble_advertising_modes_config_set + * is only necessary if your application requires this behaviour to change. + * + * @param[in] p_advertising Advertising module instance. + * @param[in] p_adv_modes_config Struct to keep track of disabled and enabled advertising modes, + * as well as time-outs and intervals. + */ +void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, + ble_adv_modes_config_t const * const p_adv_modes_config); +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_ADVERTISING_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c new file mode 100644 index 0000000000..d54d6ef773 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c @@ -0,0 +1,986 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "ble_srv_common.h" +#define NRF_LOG_MODULE_NAME ble_db_disc +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#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(ble_uuid_t const * p_srv_uuid) +{ + for (uint32_t 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(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) +{ + for (uint32_t 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 * p_db_discovery, + uint32_t err_code, + uint16_t 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 = + { + .conn_handle = conn_handle, + .evt_type = BLE_DB_DISCOVERY_ERROR, + .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 * p_db_discovery, + bool is_srv_found, + uint16_t 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 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_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", + 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; + + 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; + } +} + + +/**@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 * 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 * p_db_discovery, + uint16_t 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 * p_db_discovery, + bool * p_raise_discov_complete, + uint16_t 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 * p_db_discovery, + 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; + ble_gattc_evt_prim_srvc_disc_rsp_t const * p_prim_srvc_disc_rsp_evt; + + NRF_LOG_DEBUG("Found service UUID 0x%x.", 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; + } + } + else + { + NRF_LOG_DEBUG("Service UUID 0x%x not found.", 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 * p_db_discovery, + 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) + { + ble_gattc_evt_char_disc_rsp_t const * 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; + + 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; + + 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_DEBUG("Discovery of service with UUID 0x%x completed with success" + " on connection handle 0x%x.", + 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_DEBUG("Discovery of service with UUID 0x%x completed with success" + " on connection handle 0x%x.", + 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(ble_uuid_t const * p_uuid) +{ + VERIFY_PARAM_NOT_NULL(p_uuid); + VERIFY_MODULE_INITIALIZED(); + + return registered_handler_set(p_uuid, m_evt_handler); +} + + +static uint32_t discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) +{ + uint32_t err_code; + ble_gatt_db_srv_t * p_srv_being_discovered; + + memset(p_db_discovery, 0x00, sizeof(ble_db_discovery_t)); + + p_db_discovery->conn_handle = conn_handle; + + 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_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", + p_srv_being_discovered->srv_uuid.uuid, conn_handle); + + err_code = sd_ble_gattc_primary_services_discover(conn_handle, + SRV_DISC_START_HANDLE, + &(p_srv_being_discovered->srv_uuid)); + if (err_code != NRF_ERROR_BUSY) + { + VERIFY_SUCCESS(err_code); + p_db_discovery->discovery_in_progress = true; + p_db_discovery->discovery_pending = false; + } + else + { + p_db_discovery->discovery_in_progress = true; + p_db_discovery->discovery_pending = true; + } + + return NRF_SUCCESS; +} + + +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; + } + + return discovery_start(p_db_discovery, conn_handle); +} + + +/**@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 * p_db_discovery, + ble_gap_evt_t const * p_evt) +{ + if (p_evt->conn_handle == p_db_discovery->conn_handle) + { + p_db_discovery->discovery_in_progress = false; + p_db_discovery->discovery_pending = false; + p_db_discovery->conn_handle = BLE_CONN_HANDLE_INVALID; + } +} + + +void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, + void * p_context) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); + VERIFY_PARAM_NOT_NULL_VOID(p_context); + VERIFY_MODULE_INITIALIZED_VOID(); + + ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context; + + 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; + } + + if ( (p_db_discovery->discovery_pending) + && (p_ble_evt->header.evt_id >= BLE_GATTC_EVT_BASE) + && (p_ble_evt->header.evt_id <= BLE_GATTC_EVT_LAST) + && (p_ble_evt->evt.gattc_evt.conn_handle == p_db_discovery->conn_handle)) + { + (void)discovery_start(p_db_discovery, p_db_discovery->conn_handle); + } +} +#endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h new file mode 100644 index 0000000000..e1fe1f554e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h @@ -0,0 +1,235 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include +#include "nrf_error.h" +#include "nrf_ble.h" +#include "ble_gattc.h" +#include "ble_gatt_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_db_discovery instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define BLE_DB_DISCOVERY_DEF(_name) \ +static ble_db_discovery_t _name = {.discovery_in_progress = 0, \ + .discovery_pending = 0, \ + .conn_handle = BLE_CONN_HANDLE_INVALID}; \ +NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + BLE_DB_DISC_BLE_OBSERVER_PRIO, \ + ble_db_discovery_on_ble_evt, &_name) + +/** @brief Macro for defining multiple ble_db_discovery instances. + * + * @param _name Name of the array of instances. + * @param _cnt Number of instances to define. + */ +#define BLE_DB_DISCOVERY_ARRAY_DEF(_name, _cnt) \ +static ble_db_discovery_t _name[_cnt] = {{.discovery_in_progress = 0, \ + .discovery_pending = 0, \ + .conn_handle = BLE_CONN_HANDLE_INVALID}}; \ +NRF_SDH_BLE_OBSERVERS(_name ## _obs, \ + BLE_DB_DISC_BLE_OBSERVER_PRIO, \ + ble_db_discovery_on_ble_evt, &_name, _cnt) + +#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 DB Discovery event type. */ +typedef enum +{ + BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the discovery of one service 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 instance 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. */ + bool discovery_pending; /**< Discovery was requested, but could not start because the SoftDevice was busy. */ + 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. The UUID field of this will be filled when the event type is @ref BLE_DB_DISCOVERY_SRV_NOT_FOUND. */ + 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. + * + * @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 using + * @p p_db_discovery. Use a different @ref ble_db_discovery_t + * structure, or wait for a DB Discovery event before retrying. + * + * @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 * p_db_discovery, + uint16_t conn_handle); + + +/**@brief Function for handling the Application's BLE Stack events. + * + * @param[in] p_ble_evt Pointer to the BLE event received. + * @param[in,out] p_context Pointer to the DB Discovery structure. + */ +void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, + void * p_context); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DB_DISCOVERY_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c new file mode 100644 index 0000000000..3aa8f1c587 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c @@ -0,0 +1,942 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DTM) +#include "ble_dtm.h" +#include "ble_dtm_hw.h" +#include +#include +#include "nrf.h" + +#define DTM_HEADER_OFFSET 0 /**< Index where the header of the pdu is located. */ +#define DTM_HEADER_SIZE 2 /**< Size of PDU header. */ +#define DTM_PAYLOAD_MAX_SIZE 255 /**< Maximum payload size allowed during dtm execution. */ +#define DTM_LENGTH_OFFSET (DTM_HEADER_OFFSET + 1) /**< Index where the length of the payload is encoded. */ +#define DTM_PDU_MAX_MEMORY_SIZE (DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE) /**< Maximum PDU size allowed during dtm execution. */ +#define DTM_ON_AIR_OVERHEAD_SIZE 10 /**< Size of the packet on air without the payload (preamble + sync word + type + RFU + length + CRC). */ + +#define RX_MODE true /**< Constant defining RX mode for radio during dtm test. */ +#define TX_MODE false /**< Constant defining TX mode for radio during dtm test. */ + +#define PHYS_CH_MAX 39 /**< Maximum number of valid channels in BLE. */ + +// Values that for now are "constants" - they could be configured by a function setting them, +// but most of these are set by the BLE DTM standard, so changing them is not relevant. +#define RFPHY_TEST_0X0F_REF_PATTERN 0x0f /**< RF-PHY test packet patterns, for the repeated octet packets. */ +#define RFPHY_TEST_0X55_REF_PATTERN 0x55 /**< RF-PHY test packet patterns, for the repeated octet packets. */ +#define RFPHY_TEST_0XFF_REF_PATTERN 0xFF /**< RF-PHY test packet patterns, for the repeated octet packets. */ + +#define PRBS9_CONTENT {0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, \ + 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, \ + 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, \ + 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, \ + 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, \ + 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, \ + 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, \ + 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, \ + 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, \ + 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, \ + 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, \ + 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, \ + 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, \ + 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, \ + 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, \ + 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, \ + 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, \ + 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, \ + 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, \ + 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, \ + 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, \ + 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, \ + 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, \ + 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, \ + 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, \ + 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, \ + 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, \ + 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, \ + 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, \ + 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, \ + 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, \ + 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7} /**< The PRBS9 sequence used as packet payload. + The bytes in the sequence is in the right order, but the bits of each byte in the array is reverse. + of that found by running the PRBS9 algorithm. This is because of the endianess of the nRF5 radio. */ + +/**@brief Structure holding the PDU used for transmitting/receiving a PDU. + */ +typedef struct +{ + uint8_t content[DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE]; /**< PDU packet content. */ +} pdu_type_t; + +/**@brief States used for the DTM test implementation. + */ +typedef enum +{ + STATE_UNINITIALIZED, /**< The DTM is uninitialized. */ + STATE_IDLE, /**< State when system has just initialized, or current test has completed. */ + STATE_TRANSMITTER_TEST, /**< State used when a DTM Transmission test is running. */ + STATE_CARRIER_TEST, /**< State used when a DTM Carrier test is running (Vendor specific test). */ + STATE_RECEIVER_TEST /**< State used when a DTM Receive test is running. */ +} state_t; + + +// Internal variables set as side effects of commands or events. +static state_t m_state = STATE_UNINITIALIZED; /**< Current machine state. */ +static uint16_t m_rx_pkt_count; /**< Number of valid packets received. */ +static pdu_type_t m_pdu; /**< PDU to be sent. */ +static uint16_t m_event; /**< current command status - initially "ok", may be set if error detected, or to packet count. */ +static bool m_new_event; /**< Command has been processed - number of not yet reported event bytes. */ +static uint32_t m_packet_length; /**< Payload length of transmitted PDU, bits 2:7 of 16-bit dtm command. */ +static dtm_pkt_type_t m_packet_type; /**< Bits 0..1 of 16-bit transmit command, or 0xFFFFFFFF. */ +static dtm_freq_t m_phys_ch; /**< 0..39 physical channel number (base 2402 MHz, Interval 2 MHz), bits 8:13 of 16-bit dtm command. */ +static uint32_t m_current_time = 0; /**< Counter for interrupts from timer to ensure that the 2 bytes forming a DTM command are received within the time window. */ + +// Nordic specific configuration values (not defined by BLE standard). +// Definition of initial values found in ble_dtm.h +static int32_t m_tx_power = DEFAULT_TX_POWER; /**< TX power for transmission test, default to maximum value (+4 dBm). */ +static NRF_TIMER_Type * mp_timer = DEFAULT_TIMER; /**< Timer to be used. */ +static IRQn_Type m_timer_irq = DEFAULT_TIMER_IRQn; /**< which interrupt line to clear on every timeout */ + +static uint8_t const m_prbs_content[] = PRBS9_CONTENT; /**< Pseudo-random bit sequence defined by the BLE standard. */ +static uint8_t m_packetHeaderLFlen = 8; /**< Length of length field in packet Header (in bits). */ +static uint8_t m_packetHeaderS0len = 1; /**< Length of S0 field in packet Header (in bytes). */ +static uint8_t m_packetHeaderS1len = 0; /**< Length of S1 field in packet Header (in bits). */ +static uint8_t m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; /**< Length of the preamble. */ + +static uint8_t m_crcConfSkipAddr = 1; /**< Leave packet address field out of CRC calculation. */ +static uint8_t m_static_length = 0; /**< Number of bytes sent in addition to the var.length payload. */ +static uint32_t m_balen = 3; /**< Base address length in bytes. */ +static uint32_t m_endian = RADIO_PCNF1_ENDIAN_Little; /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */ +static uint32_t m_whitening = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */ +static uint8_t m_crcLength = RADIO_CRCCNF_LEN_Three; /**< CRC Length (in bytes). */ +static uint32_t m_address = 0x71764129; /**< Address. */ +static uint32_t m_crc_poly = 0x0000065B; /**< CRC polynomial. */ +static uint32_t m_crc_init = 0x00555555; /**< Initial value for CRC calculation. */ +static uint8_t m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; /**< nRF51 specific radio mode value. */ +static uint32_t m_txIntervaluS = 2500; /**< Time between start of Tx packets (in uS). */ + + +/**@brief Function for verifying that a received PDU has the expected structure and content. + */ +static bool check_pdu(void) +{ + uint8_t k; // Byte pointer for running through PDU payload + uint8_t pattern; // Repeating octet value in payload + dtm_pkt_type_t pdu_packet_type; // Note: PDU packet type is a 4-bit field in HCI, but 2 bits in BLE DTM + uint32_t length = 0; + + pdu_packet_type = (dtm_pkt_type_t)(m_pdu.content[DTM_HEADER_OFFSET] & 0x0F); + length = m_pdu.content[DTM_LENGTH_OFFSET]; + + // Check that the length is valid. + if (length > DTM_PAYLOAD_MAX_SIZE) + { + return false; + } + + // If the 1Mbit or 2Mbit radio mode is active, check that one of the three valid uncoded DTM packet types are selected. + if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0X55)) + { + return false; + } + +#ifdef NRF52840_XXAA + // If a long range radio mode is active, check that one of the four valid coded DTM packet types are selected. + if ((m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0XFF)) + { + return false; + } +#endif + + if (pdu_packet_type == DTM_PKT_PRBS9) + { + // Payload does not consist of one repeated octet; must compare ir with entire block into + return (memcmp(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, length) == 0); + } + + if (pdu_packet_type == DTM_PKT_0X0F) + { + pattern = RFPHY_TEST_0X0F_REF_PATTERN; + } + else if (pdu_packet_type == DTM_PKT_0X55) + { + pattern = RFPHY_TEST_0X55_REF_PATTERN; + } + else if (pdu_packet_type == DTM_PKT_0XFF) + { + pattern = RFPHY_TEST_0XFF_REF_PATTERN; + } + else + { + // No valid packet type set. + return false; + } + + for (k = 0; k < length; k++) + { + // Check repeated pattern filling the PDU payload + if (m_pdu.content[k + 2] != pattern) + { + return false; + } + } + return true; +} + + +/**@brief Function for turning off the radio after a test. + * Also called after test done, to be ready for next test. + */ +static void radio_reset(void) +{ + NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk | PPI_CHENCLR_CH1_Msk; + + NRF_RADIO->SHORTS = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->TASKS_DISABLE = 1; + + while (NRF_RADIO->EVENTS_DISABLED == 0) + { + // Do nothing + } + + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->TASKS_RXEN = 0; + NRF_RADIO->TASKS_TXEN = 0; + + m_rx_pkt_count = 0; +} + + +/**@brief Function for initializing the radio for DTM. + */ +static uint32_t radio_init(void) +{ + if (dtm_radio_validate(m_tx_power, m_radio_mode) != DTM_SUCCESS) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + + // Turn off radio before configuring it + radio_reset(); + + NRF_RADIO->TXPOWER = m_tx_power; + NRF_RADIO->MODE = m_radio_mode << RADIO_MODE_MODE_Pos; + + // Set the access address, address0/prefix0 used for both Rx and Tx address + NRF_RADIO->PREFIX0 &= ~RADIO_PREFIX0_AP0_Msk; + NRF_RADIO->PREFIX0 |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk; + NRF_RADIO->BASE0 = m_address << 8; + NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos; + NRF_RADIO->TXADDRESS = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk; + + // Configure CRC calculation + NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) | + (m_crcLength << RADIO_CRCCNF_LEN_Pos); + + if (m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) + { + // Non-coded PHY + NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | + (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | + (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | + (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); + } +#ifdef NRF52840_XXAA + else + { + // Coded PHY (Long range) + NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | + (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | + (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | + (3 << RADIO_PCNF0_TERMLEN_Pos) | + (2 << RADIO_PCNF0_CILEN_Pos) | + (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); + } +#endif + + NRF_RADIO->PCNF1 = (m_whitening << RADIO_PCNF1_WHITEEN_Pos) | + (m_endian << RADIO_PCNF1_ENDIAN_Pos) | + (m_balen << RADIO_PCNF1_BALEN_Pos) | + (m_static_length << RADIO_PCNF1_STATLEN_Pos) | + (DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos); + + return DTM_SUCCESS; +} + + +/**@brief Function for preparing the radio. At start of each test: Turn off RF, clear interrupt flags of RF, initialize the radio + * at given RF channel. + * + *@param[in] rx boolean indicating if radio should be prepared in rx mode (true) or tx mode. + */ +static void radio_prepare(bool rx) +{ + dtm_turn_off_test(); + NRF_RADIO->CRCPOLY = m_crc_poly; + NRF_RADIO->CRCINIT = m_crc_init; + NRF_RADIO->FREQUENCY = (m_phys_ch << 1) + 2; // Actual frequency (MHz): 2400 + register value + NRF_RADIO->PACKETPTR = (uint32_t)&m_pdu; // Setting packet pointer will start the radio + NRF_RADIO->EVENTS_READY = 0; + NRF_RADIO->SHORTS = (1 << RADIO_SHORTS_READY_START_Pos) | // Shortcut between READY event and START task + (1 << RADIO_SHORTS_END_DISABLE_Pos); // Shortcut between END event and DISABLE task + + if (rx) + { + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->TASKS_RXEN = 1; // shorts will start radio in RX mode when it is ready + } + else // tx + { + NRF_RADIO->TXPOWER = m_tx_power; + } +} + + +/**@brief Function for terminating the ongoing test (if any) and closing down the radio. + */ +static void dtm_test_done(void) +{ + dtm_turn_off_test(); + NRF_PPI->CHENCLR = 0x01; + NRF_PPI->CH[0].EEP = 0; // Break connection from timer to radio to stop transmit loop + NRF_PPI->CH[0].TEP = 0; + + radio_reset(); + m_state = STATE_IDLE; +} + + +/**@brief Function for configuring the timer for 625us cycle time. + */ +static uint32_t timer_init(void) +{ + // Use 16MHz from external crystal + // This could be customized for RC/Xtal, or even to use a 32 kHz crystal + NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; + NRF_CLOCK->TASKS_HFCLKSTART = 1; + + while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) + { + // Do nothing while waiting for the clock to start + } + + mp_timer->TASKS_STOP = 1; // Stop timer, if it was running + mp_timer->TASKS_CLEAR = 1; + mp_timer->MODE = TIMER_MODE_MODE_Timer; // Timer mode (not counter) + mp_timer->EVENTS_COMPARE[0] = 0; // clean up possible old events + mp_timer->EVENTS_COMPARE[1] = 0; + mp_timer->EVENTS_COMPARE[2] = 0; + mp_timer->EVENTS_COMPARE[3] = 0; + + // Timer is polled, but enable the compare0 interrupt in order to wakeup from CPU sleep + mp_timer->INTENSET = TIMER_INTENSET_COMPARE0_Msk; + mp_timer->SHORTS = 1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos; // Clear the count every time timer reaches the CCREG0 count + mp_timer->PRESCALER = 4; // Input clock is 16MHz, timer clock = 2 ^ prescale -> interval 1us + mp_timer->CC[0] = m_txIntervaluS; // 625uS with 1MHz clock to the timer + mp_timer->CC[1] = UART_POLL_CYCLE; // Depends on the baud rate of the UART. Default baud rate of 19200 will result in a 260uS time with 1MHz clock to the timer + mp_timer->TASKS_START = 1; // Start the timer - it will be running continuously + m_current_time = 0; + return DTM_SUCCESS; +} + + +/**@brief Function for handling vendor specific commands. + * Used when packet type is set to Vendor specific. + * The length field is used for encoding vendor specific command. + * The frequency field is used for encoding vendor specific options to the command. + * + * @param[in] vendor_cmd Vendor specific command to be executed. + * @param[in] vendor_option Vendor specific option to the vendor command. + * + * @return DTM_SUCCESS or one of the DTM_ERROR_ values + */ +static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd, dtm_freq_t vendor_option) +{ + switch (vendor_cmd) + { + // nRFgo Studio uses CARRIER_TEST_STUDIO to indicate a continuous carrier without + // a modulated signal. + case CARRIER_TEST: + case CARRIER_TEST_STUDIO: + // Not a packet type, but used to indicate that a continuous carrier signal + // should be transmitted by the radio. + radio_prepare(TX_MODE); + + dtm_constant_carrier(); + + // Shortcut between READY event and START task + NRF_RADIO->SHORTS = 1 << RADIO_SHORTS_READY_START_Pos; + + // Shortcut will start radio in Tx mode when it is ready + NRF_RADIO->TASKS_TXEN = 1; + m_state = STATE_CARRIER_TEST; + break; + + case SET_TX_POWER: + if (!dtm_set_txpower(vendor_option)) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + break; + + case SELECT_TIMER: + if (!dtm_set_timer(vendor_option)) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + break; + } + // Event code is unchanged, successful + return DTM_SUCCESS; +} + + +static uint32_t dtm_packet_interval_calculate(uint32_t test_payload_length, uint32_t mode) +{ + uint32_t test_packet_length = 0; // [us] NOTE: bits are us at 1Mbit + uint32_t packet_interval = 0; // us + uint32_t overhead_bits = 0; // bits + + /* packet overhead + * see BLE [Vol 6, Part F] page 213 + * 4.1 LE TEST PACKET FORMAT */ + if (mode == RADIO_MODE_MODE_Ble_2Mbit) + { + // 16 preamble + // 32 sync word + // 8 PDU header, actually packetHeaderS0len * 8 + // 8 PDU length, actually packetHeaderLFlen + // 24 CRC + overhead_bits = 88; // 11 bytes + } + else if (mode == RADIO_MODE_MODE_Ble_1Mbit) + { + // 8 preamble + // 32 sync word + // 8 PDU header, actually packetHeaderS0len * 8 + // 8 PDU length, actually packetHeaderLFlen + // 24 CRC + overhead_bits = 80; // 10 bytes + } +#ifdef NRF52840_XXAA + else if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) + { + // 80 preamble + // 32 * 8 sync word coding=8 + // 2 * 8 Coding indicator, coding=8 + // 3 * 8 TERM1 coding=8 + // 8 * 8 PDU header, actually packetHeaderS0len * 8 coding=8 + // 8 * 8 PDU length, actually packetHeaderLFlen coding=8 + // 24 * 8 CRC coding=8 + // 3 * 8 TERM2 coding=8 + overhead_bits = 720; // 90 bytes + } + else if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) + { + // 80 preamble + // 32 * 8 sync word coding=8 + // 2 * 8 Coding indicator, coding=8 + // 3 * 8 TERM 1 coding=8 + // 8 * 2 PDU header, actually packetHeaderS0len * 8 coding=2 + // 8 * 2 PDU length, actually packetHeaderLFlen coding=2 + // 24 * 2 CRC coding=2 + // 3 * 2 TERM2 coding=2 + // NOTE: this makes us clock out 46 bits for CI + TERM1 + TERM2 + // assumption the radio will handle this + overhead_bits = 462; // 57.75 bytes + } +#endif + /* add PDU payload test_payload length */ + test_packet_length = (test_payload_length * 8); // in bits +#ifdef NRF52840_XXAA + // account for the encoding of PDU + if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) + { + test_packet_length *= 8; // 1 to 8 encoding + } + if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) + { + test_packet_length *= 2; // 1 to 2 encoding + } +#endif + // add overhead calculated above + test_packet_length += overhead_bits; + // we remember this bits are us in 1Mbit + if (mode == RADIO_MODE_MODE_Ble_2Mbit) + { + test_packet_length /= 2; // double speed + } + + /* + * packet_interval = ceil((test_packet_length+249)/625)*625 + * NOTE: To avoid floating point an equivalent calculation is used. + */ + uint32_t i = 0; + uint32_t timeout = 0; + do + { + i++; + timeout = i * 625; + } while (test_packet_length + 249 > timeout); + packet_interval = i * 625; + + return packet_interval; +} + + +uint32_t dtm_init(void) +{ + if ((timer_init() != DTM_SUCCESS) || (radio_init() != DTM_SUCCESS)) + { + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + m_new_event = false; + m_state = STATE_IDLE; + m_packet_length = 0; + + // Enable wake-up on event + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + + return DTM_SUCCESS; +} + + +uint32_t dtm_wait(void) +{ + // Enable wake-up on event + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + + for (;;) + { + // Event may be the reception of a packet - + // handle radio first, to give it highest priority: + if (NRF_RADIO->EVENTS_END != 0) + { + NRF_RADIO->EVENTS_END = 0; + NVIC_ClearPendingIRQ(RADIO_IRQn); + + if (m_state == STATE_RECEIVER_TEST) + { + NRF_RADIO->TASKS_RXEN = 1; + if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu()) + { + // Count the number of successfully received packets + m_rx_pkt_count++; + } + // Note that failing packets are simply ignored (CRC or contents error). + + // Zero fill all pdu fields to avoid stray data + memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); + } + // If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!) + } + + // Check for timeouts: + if (mp_timer->EVENTS_COMPARE[0] != 0) + { + mp_timer->EVENTS_COMPARE[0] = 0; + } + else if (mp_timer->EVENTS_COMPARE[1] != 0) + { + // Reset timeout event flag for next iteration. + mp_timer->EVENTS_COMPARE[1] = 0; + NVIC_ClearPendingIRQ(m_timer_irq); + return ++m_current_time; + } + + // Other events: No processing + } +} + +uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload) +{ + // Save specified packet in static variable for tx/rx functions to use. + // Note that BLE conformance testers always use full length packets. + m_packet_length = (m_packet_length & 0xC0) | ((uint8_t)length & 0x3F); + m_packet_type = payload; + m_phys_ch = freq; + + // If 1 Mbit or 2 Mbit radio mode is in use check for Vendor Specific payload. + if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && payload == DTM_PKT_VENDORSPECIFIC) + { + /* Note that in a HCI adaption layer, as well as in the DTM PDU format, + the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not + support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC, + to avoid the risk of confusion, should the code be extended to greater coverage. + */ + m_packet_type = DTM_PKT_TYPE_VENDORSPECIFIC; + } + + // Clean out any non-retrieved event that might linger from an earlier test + m_new_event = true; + + // Set default event; any error will set it to LE_TEST_STATUS_EVENT_ERROR + m_event = LE_TEST_STATUS_EVENT_SUCCESS; + + if (m_state == STATE_UNINITIALIZED) + { + // Application has not explicitly initialized DTM, + return DTM_ERROR_UNINITIALIZED; + } + + if (cmd == LE_TEST_SETUP) + { + // Note that timer will continue running after a reset + dtm_test_done(); + if (freq == LE_TEST_SETUP_RESET) + { + if (length != 0x00) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + // Reset the packet length upper bits. + m_packet_length = 0; + + // Reset the selected PHY to 1Mbit + m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; + m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; + +#ifdef NRF52840_XXAA + // Workaround for Errata ID 164 + *(volatile uint32_t *)0x4000173C &= ~0x80000000; +#endif + } + else if (freq == LE_TEST_SETUP_SET_UPPER) + { + if (length > 0x03) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + m_packet_length = length << 6; + } + else if (freq == LE_TEST_SETUP_SET_PHY) + { + switch (length) + { + case LE_PHY_1M: + m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; + m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; + +#ifdef NRF52840_XXAA + // Workaround for Errata ID 164 + *(volatile uint32_t *)0x4000173C &= ~0x80000000; +#endif + + return radio_init(); + + case LE_PHY_2M: + m_radio_mode = RADIO_MODE_MODE_Ble_2Mbit; + m_packetHeaderPlen = RADIO_PCNF0_PLEN_16bit; + +#ifdef NRF52840_XXAA + // Workaround for Errata ID 164 + *(volatile uint32_t *)0x4000173C &= ~0x80000000; +#endif + + return radio_init(); + + case LE_PHY_LE_CODED_S8: +#ifdef NRF52840_XXAA + m_radio_mode = RADIO_MODE_MODE_Ble_LR125Kbit; + m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; + + // Workaround for Errata ID 164 + *(volatile uint32_t *)0x4000173C |= 0x80000000; + *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); + + return radio_init(); +#else + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; +#endif // NRF52840_XXAA + case LE_PHY_LE_CODED_S2: +#ifdef NRF52840_XXAA + m_radio_mode = RADIO_MODE_MODE_Ble_LR500Kbit; + m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; + + // Workaround for Errata ID 164 + *(volatile uint32_t *)0x4000173C |= 0x80000000; + *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); + + return radio_init(); +#else + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; +#endif + default: + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + } + else if(freq == LE_TEST_SETUP_SELECT_MODULATION) + { + if (length > 0x01) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + // Only standard modulation is supported. + } + else if (freq == LE_TEST_SETUP_READ_SUPPORTED) + { + if (length != 0x00) + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + // 0XXXXXXXXXXX0110 indicate that 2Mbit and DLE is supported and stable modulation is not supported (No nRF5 device supports this). + m_event = 0x0006; + } + else if (freq == LE_TEST_SETUP_READ_MAX) + { + // Read max supported value. + switch (length) + { + case 0x00: + // Read supportedMaxTxOctets + m_event = 0x01FE; + break; + + case 0x01: + // Read supportedMaxTxTime + m_event = 0x4290; + break; + + case 0x02: + // Read supportedMaxRxOctets + m_event = 0x01FE; + break; + + case 0x03: + // Read supportedMaxRxTime + m_event = 0x4290; + break; + + default: + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + } + else + { + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + return DTM_SUCCESS; + } + + if (cmd == LE_TEST_END) + { + if (m_state == STATE_IDLE) + { + // Sequencing error - only rx or tx test may be ended! + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_INVALID_STATE; + } + m_event = LE_PACKET_REPORTING_EVENT | m_rx_pkt_count; + dtm_test_done(); + return DTM_SUCCESS; + } + + if (m_state != STATE_IDLE) + { + // Sequencing error - only TEST_END/RESET are legal while test is running + // Note: State is unchanged; ongoing test not affected + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_INVALID_STATE; + } + + // Check for illegal values of m_phys_ch. Skip the check if the packet is vendor spesific. + if (payload != DTM_PKT_VENDORSPECIFIC && m_phys_ch > PHYS_CH_MAX) + { + // Parameter error + // Note: State is unchanged; ongoing test not affected + m_event = LE_TEST_STATUS_EVENT_ERROR; + + return DTM_ERROR_ILLEGAL_CHANNEL; + } + + m_rx_pkt_count = 0; + + if (cmd == LE_RECEIVER_TEST) + { + // Zero fill all pdu fields to avoid stray data from earlier test run + memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); + radio_prepare(RX_MODE); // Reinitialize "everything"; RF interrupts OFF + m_state = STATE_RECEIVER_TEST; + return DTM_SUCCESS; + } + + if (cmd == LE_TRANSMITTER_TEST) + { + // Check for illegal values of m_packet_length. Skip the check if the packet is vendor spesific. + if (m_packet_type != DTM_PKT_TYPE_VENDORSPECIFIC && m_packet_length > DTM_PAYLOAD_MAX_SIZE) + { + // Parameter error + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_LENGTH; + } + + + m_pdu.content[DTM_LENGTH_OFFSET] = m_packet_length; + // Note that PDU uses 4 bits even though BLE DTM uses only 2 (the HCI SDU uses all 4) + switch (m_packet_type) + { + case DTM_PKT_PRBS9: + m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_PRBS9; + // Non-repeated, must copy entire pattern to PDU + memcpy(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, m_packet_length); + break; + + case DTM_PKT_0X0F: + m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X0F; + // Bit pattern 00001111 repeated + memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X0F_REF_PATTERN, m_packet_length); + break; + + case DTM_PKT_0X55: + m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X55; + // Bit pattern 01010101 repeated + memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X55_REF_PATTERN, m_packet_length); + break; + + case DTM_PKT_0XFF: + m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0XFF; + // Bit pattern 11111111 repeated. Only available in coded PHY (Long range). + memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0XFF_REF_PATTERN, m_packet_length); + break; + + case DTM_PKT_TYPE_VENDORSPECIFIC: + // The length field is for indicating the vendor specific command to execute. + // The frequency field is used for vendor specific options to the command. + return dtm_vendor_specific_pkt(length, freq); + + default: + // Parameter error + m_event = LE_TEST_STATUS_EVENT_ERROR; + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + + // Initialize CRC value, set channel: + radio_prepare(TX_MODE); + + // Set the timer to the correct period. The delay between each packet is described in the + // Bluetooth Core Spsification version 4.2 Vol. 6 Part F Section 4.1.6. + mp_timer->CC[0] = dtm_packet_interval_calculate(m_packet_length, m_radio_mode); + + // Configure PPI so that timer will activate radio every 625 us + NRF_PPI->CH[0].EEP = (uint32_t)&mp_timer->EVENTS_COMPARE[0]; + NRF_PPI->CH[0].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; + NRF_PPI->CHENSET = 0x01; + m_state = STATE_TRANSMITTER_TEST; + } + return DTM_SUCCESS; +} + + +bool dtm_event_get(dtm_event_t *p_dtm_event) +{ + bool was_new = m_new_event; + // mark the current event as retrieved + m_new_event = false; + *p_dtm_event = m_event; + // return value indicates whether this value was already retrieved. + return was_new; +} + + +// ================================================================================================= +// Configuration functions (only for parameters not definitely determined by the BLE DTM standard). +// These functions return true if successful, false if value could not be set + + +/**@brief Function for configuring the output power for transmitter test. + This function may be called directly, or through dtm_cmd() specifying + DTM_PKT_VENDORSPECIFIC as payload, SET_TX_POWER as length, and the dBm value as frequency. + */ +bool dtm_set_txpower(uint32_t new_tx_power) +{ + // radio->TXPOWER register is 32 bits, low octet a signed value, upper 24 bits zeroed + int8_t new_power8 = (int8_t)(new_tx_power & 0xFF); + + // The two most significant bits are not sent in the 6 bit field of the DTM command. + // These two bits are 1's if and only if the tx_power is a negative number. + // All valid negative values have the fourth most significant bit as 1. + // All valid positive values have the fourth most significant bit as 0. + // By checking this bit, the two most significant bits can be determined. + new_power8 = (new_power8 & 0x30) != 0 ? (new_power8 | 0xC0) : new_power8; + + if (m_state > STATE_IDLE) + { + // radio must be idle to change the tx power + return false; + } + + m_tx_power = new_power8; + + return true; +} + + +/**@brief Function for selecting a timer resource. + * This function may be called directly, or through dtm_cmd() specifying + * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq + * + * @param[in] new_timer Timer id for the timer to use: 0, 1, or 2. + * + * @return true if the timer was successfully changed, false otherwise. + */ +bool dtm_set_timer(uint32_t new_timer) +{ + if (m_state > STATE_IDLE) + { + return false; + } + return dtm_hw_set_timer(&mp_timer, &m_timer_irq, new_timer); +} + +/// @} +#endif // NRF_MODULE_ENABLED(BLE_DTM) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h new file mode 100644 index 0000000000..04066cbc2e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_dtm DTM - Direct Test Mode + * @{ + * @ingroup ble_sdk_lib + * @brief Module for testing RF/PHY using DTM commands. + */ + +#ifndef BLE_DTM_H__ +#define BLE_DTM_H__ + +#include +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Configuration parameters. */ +#define DTM_BITRATE UARTE_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */ +#define DEFAULT_TX_POWER RADIO_TXPOWER_TXPOWER_0dBm /**< Default Transmission power using in the DTM module. */ +#define DEFAULT_TIMER NRF_TIMER0 /**< Default timer used for timing. */ +#define DEFAULT_TIMER_IRQn TIMER0_IRQn /**< IRQ used for timer. NOTE: MUST correspond to DEFAULT_TIMER. */ + +/**@brief BLE DTM command codes. */ +typedef uint32_t dtm_cmd_t; /**< DTM command type. */ + +#define LE_TEST_SETUP 0 /**< DTM command: Set PHY or modulation, configure upper two bits of length, + request matrix of supported features or request max values of parameters. */ +#define LE_RECEIVER_TEST 1 /**< DTM command: Start receive test. */ +#define LE_TRANSMITTER_TEST 2 /**< DTM command: Start transmission test. */ +#define LE_TEST_END 3 /**< DTM command: End test and send packet report. */ + +#define LE_TEST_SETUP_RESET 0 /**< DTM command parameter: Stop TX/RX, reset the packet length upper bits and set the PHY to 1Mbit. */ +#define LE_TEST_SETUP_SET_UPPER 1 /**< DTM command parameter: Set the upper two bits of the length field. */ +#define LE_TEST_SETUP_SET_PHY 2 /**< DTM command parameter: Select the PHY to be used for packets. */ +#define LE_TEST_SETUP_SELECT_MODULATION 3 /**< DTM command parameter: Select standard or stable modulation index. Stable modulation index is not supported. */ +#define LE_TEST_SETUP_READ_SUPPORTED 4 /**< DTM command parameter: Read the supported test case features. */ +#define LE_TEST_SETUP_READ_MAX 5 /**< DTM command parameter: Read the max supported time and length for packets. */ + +#define LE_PHY_1M 1 /**< DTM command parameter: Set PHY for future packets to use 1MBit PHY. */ +#define LE_PHY_2M 2 /**< DTM command parameter: Set PHY for future packets to use 2MBit PHY. */ +#define LE_PHY_LE_CODED_S8 3 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=8. */ +#define LE_PHY_LE_CODED_S2 4 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=2 */ + +// Configuration options used as parameter 2 +// when cmd == LE_TRANSMITTER_TEST and payload == DTM_PKT_VENDORSPECIFIC +// Configuration value, if any, is supplied in parameter 3 + +#define CARRIER_TEST 0 /**< Length=0 indicates a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ +#define CARRIER_TEST_STUDIO 1 /**< nRFgo Studio uses value 1 in length field, to indicate a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ +#define SET_TX_POWER 2 /**< Set transmission power, value -40..+4 dBm in steps of 4 */ +#define SELECT_TIMER 3 /**< Select on of the 16 MHz timers 0, 1 or 2 */ + +#define LE_PACKET_REPORTING_EVENT 0x8000 /**< DTM Packet reporting event, returned by the device to the tester. */ +#define LE_TEST_STATUS_EVENT_SUCCESS 0x0000 /**< DTM Status event, indicating success. */ +#define LE_TEST_STATUS_EVENT_ERROR 0x0001 /**< DTM Status event, indicating an error. */ + +#define DTM_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */ +#define DTM_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */ +#define DTM_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */ +#define DTM_PKT_0XFF 0x03 /**< Bit pattern 11111111 (Used only for coded PHY). */ +#define DTM_PKT_VENDORSPECIFIC 0x03 /**< Vendor specific PKT field value. Nordic: Continuous carrier test, or configuration. */ +#define DTM_PKT_TYPE_VENDORSPECIFIC 0xFF /**< Vendor specific packet type for internal use. */ + +// The pdu payload type for each bit pattern. Identical to the PKT value except pattern 0xFF which is 0x04. +#define DTM_PDU_TYPE_PRBS9 0x00 /**< PDU payload type for bit pattern PRBS9. */ +#define DTM_PDU_TYPE_0X0F 0x01 /**< PDU payload type for bit pattern 11110000 (LSB is the leftmost bit). */ +#define DTM_PDU_TYPE_0X55 0x02 /**< PDU payload type for bit pattern 10101010 (LSB is the leftmost bit). */ +#define DTM_PDU_TYPE_0XFF 0x04 /**< PDU payload type for bit pattern 11111111 (Used only for coded PHY). */ + +/**@brief Return codes from dtm_cmd(). */ +#define DTM_SUCCESS 0x00 /**< Indicate that the DTM function completed with success. */ +#define DTM_ERROR_ILLEGAL_CHANNEL 0x01 /**< Physical channel number must be in the range 0..39. */ +#define DTM_ERROR_INVALID_STATE 0x02 /**< Sequencing error: Command is not valid now. */ +#define DTM_ERROR_ILLEGAL_LENGTH 0x03 /**< Payload size must be in the range 0..37. */ +#define DTM_ERROR_ILLEGAL_CONFIGURATION 0x04 /**< Parameter out of range (legal range is function dependent). */ +#define DTM_ERROR_UNINITIALIZED 0x05 /**< DTM module has not been initialized by the application. */ + +/**@details The UART poll cycle in micro seconds. + * A baud rate of e.g. 19200 bits / second, and 8 data bits, 1 start/stop bit, no flow control, + * give the time to transmit a byte: 10 bits * 1/19200 = approx: 520 us. + * To ensure no loss of bytes, the UART should be polled every 260 us. + */ +#if DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud9600 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/9600/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud14400 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/14400/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud19200 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/19200/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud28800 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/28800/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud38400 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/38400/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud57600 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/57600/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud76800 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/768000/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud115200 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/115200/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud230400 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/230400/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud250000 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/250000/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud460800 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/460800/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud921600 +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/921600/2)) +#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud1M +#define UART_POLL_CYCLE ((uint32_t)(10*1e6/1e6/2)) +#else +// It is possible to find values that work for other baud rates, but the formula above is not +// guaranteed to work for all values. Suitable values may have to be found by trial and error. +#error "Unsupported baud rate set." +#endif + +// Note: DTM_PKT_VENDORSPECIFIC, is not a packet type +#define PACKET_TYPE_MAX DTM_PKT_0XFF /**< Highest value allowed as DTM Packet type. */ + +/** @brief BLE DTM event type. */ +typedef uint32_t dtm_event_t; /**< Type for handling DTM event. */ + +/** @brief BLE DTM frequency type. */ +typedef uint32_t dtm_freq_t; /**< Physical channel, valid range: 0..39. */ + +/**@brief BLE DTM packet types. */ +typedef uint32_t dtm_pkt_type_t; /**< Type for holding the requested DTM payload type.*/ + + +/**@brief Function for initializing or re-initializing DTM module + * + * @return DTM_SUCCESS on successful initialization of the DTM module. +*/ +uint32_t dtm_init(void); + + +/**@brief Function for giving control to dtmlib for handling timer and radio events. + * Will return to caller at 625us intervals or whenever another event than radio occurs + * (such as UART input). Function will put MCU to sleep between events. + * + * @return Time counter, incremented every 625 us. + */ +uint32_t dtm_wait(void); + + +/**@brief Function for calling when a complete command has been prepared by the Tester. + * + * @param[in] cmd One of the DTM_CMD values (bits 14:15 in the 16-bit UART format). + * @param[in] freq Phys. channel no - actual frequency = (2402 + freq * 2) MHz (bits 8:13 in + * the 16-bit UART format). + * @param[in] length Payload length, 0..37 (bits 2:7 in the 16-bit UART format). + * @param[in] payload One of the DTM_PKT values (bits 0:1 in the 16-bit UART format). + * + * @return DTM_SUCCESS or one of the DTM_ERROR_ values + */ +uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload); + + +/**@brief Function for reading the result of a DTM command + * + * @param[out] p_dtm_event Pointer to buffer for 16 bit event code according to DTM standard. + * + * @return true: new event, false: no event since last call, this event has been read earlier + */ +bool dtm_event_get(dtm_event_t * p_dtm_event); + + +/**@brief Function for configuring the timer to use. + * + * @note Must be called when no DTM test is running. + * + * @param[in] new_timer Index (0..2) of timer to be used by the DTM library + * + * @return true: success, new timer was selected, false: parameter error + */ +bool dtm_set_timer(uint32_t new_timer); + + +/**@brief Function for configuring the transmit power. + * + * @note Must be called when no DTM test is running. + * + * @param[in] new_tx_power New output level, +4..-40, in steps of 4. + * + * @return true: tx power setting changed, false: parameter error + */ +bool dtm_set_txpower(uint32_t new_tx_power); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DTM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h new file mode 100644 index 0000000000..c63d155cc8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_dtm_hw Direct Test Mode HW + * @{ + * @ingroup ble_sdk_lib + * @brief Module contains hardware related function for testing RF/PHY using DTM commands. + */ + +#ifndef BLE_DTM_HW_H__ +#define BLE_DTM_HW_H__ + +#include +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Function for selecting a timer resource. + * This function may be called directly, or through dtm_cmd() specifying + * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq + * + * @param[out] mp_timer Pointer to timer instance used in dtm source file. + * @param[out] m_timer_irq Pointer to timer interrupt related to mp_timer. + * @param[in] new_timer Timer id for the timer to use. + * + * @retval true if the timer was successfully changed. + * @retval false if the error occurs. + */ + +bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer); + + +/**@brief Function for turning off radio test. + * This function is platform depending. For now only nRF51 requieres this special function. + */ +void dtm_turn_off_test(void); + + +/**@brief Function for setting constant carrier in radio settings. + * This function is used to handle vendor specific command testing continous carrier without + * a modulated signal. + */ +void dtm_constant_carrier(void); + + +/**@brief Function for validating tx power and radio move settings. + * @param[in] m_tx_power TX power for transmission test. + * @param[in] m_radio_mode Radio mode value. + * + * @retval DTM_SUCCESS if input parameters values are correct. + * @retval DTM_ERROR_ILLEGAL_CONFIGURATION if input parameters values are not correct. + */ +uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode); + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DTM_HW_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c new file mode 100644 index 0000000000..9f5f4b4d34 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_dtm_hw.h" +#include "ble_dtm.h" +#include +#include +#include "nrf.h" + + +void dtm_turn_off_test() +{ +} + + +void dtm_constant_carrier() +{ +NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) | + (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos); +} + + +uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode) +{ + // Initializing code below is quite generic - for BLE, the values are fixed, and expressions + // are constant. Non-constant values are essentially set in radio_prepare(). + if (!(m_tx_power == RADIO_TXPOWER_TXPOWER_0dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Pos4dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg30dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg20dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg16dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg12dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg8dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg4dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Pos3dBm || + m_tx_power == RADIO_TXPOWER_TXPOWER_Neg40dBm + ) || + + !( +#ifdef NRF52840_XXAA + m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit || + m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || +#endif //NRF52840_XXAA + m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || + m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit + ) + ) + { + return DTM_ERROR_ILLEGAL_CONFIGURATION; + } + + return DTM_SUCCESS; +} + + +bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer) +{ + if (new_timer == 0) + { + *mp_timer = NRF_TIMER0; + *m_timer_irq = TIMER0_IRQn; + } + else if (new_timer == 1) + { + *mp_timer = NRF_TIMER1; + *m_timer_irq = TIMER1_IRQn; + } + else if (new_timer == 2) + { + *mp_timer = NRF_TIMER2; + *m_timer_irq = TIMER2_IRQn; + } +#ifndef NRF52810_XXAA + else if (new_timer == 3) + { + *mp_timer = NRF_TIMER3; + *m_timer_irq = TIMER3_IRQn; + } + else if (new_timer == 4) + { + *mp_timer = NRF_TIMER4; + *m_timer_irq = TIMER4_IRQn; + } +#endif //NRF52810_XXAA + else + { + // Parameter error: Only TIMER 0, 1, 2, 3 and 4 provided by nRF52 + return false; + } + // New timer has been selected: + return true; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c new file mode 100644 index 0000000000..41a4ccb4f6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_RACP) +#include "ble_racp.h" +#include + + +void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val) +{ + p_racp_val->opcode = 0xFF; + p_racp_val->operator = 0xFF; + p_racp_val->operand_len = 0; + p_racp_val->p_operand = NULL; + + if (data_len > 0) + { + p_racp_val->opcode = p_data[0]; + } + if (data_len > 1) + { + p_racp_val->operator = p_data[1]; //lint !e415 + } + if (data_len > 2) + { + p_racp_val->operand_len = data_len - 2; + p_racp_val->p_operand = (uint8_t*)&p_data[2]; //lint !e416 + } +} + + +uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data) +{ + uint8_t len = 0; + int i; + + if (p_data != NULL) + { + p_data[len++] = p_racp_val->opcode; + p_data[len++] = p_racp_val->operator; + + for (i = 0; i < p_racp_val->operand_len; i++) + { + p_data[len++] = p_racp_val->p_operand[i]; + } + } + + return len; +} +#endif // NRF_MODULE_ENABLED(BLE_RACP) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h new file mode 100644 index 0000000000..14da8b281b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_racp Record Access Control Point + * @{ + * @ingroup ble_sdk_lib + * @brief Record Access Control Point library. + */ + +#ifndef BLE_RACP_H__ +#define BLE_RACP_H__ + +#include +#include +#include "nrf_ble.h" +#include "ble_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Record Access Control Point opcodes. */ +#define RACP_OPCODE_RESERVED 0 /**< Record Access Control Point opcode - Reserved for future use. */ +#define RACP_OPCODE_REPORT_RECS 1 /**< Record Access Control Point opcode - Report stored records. */ +#define RACP_OPCODE_DELETE_RECS 2 /**< Record Access Control Point opcode - Delete stored records. */ +#define RACP_OPCODE_ABORT_OPERATION 3 /**< Record Access Control Point opcode - Abort operation. */ +#define RACP_OPCODE_REPORT_NUM_RECS 4 /**< Record Access Control Point opcode - Report number of stored records. */ +#define RACP_OPCODE_NUM_RECS_RESPONSE 5 /**< Record Access Control Point opcode - Number of stored records response. */ +#define RACP_OPCODE_RESPONSE_CODE 6 /**< Record Access Control Point opcode - Response code. */ + +/**@brief Record Access Control Point operators. */ +#define RACP_OPERATOR_NULL 0 /**< Record Access Control Point operator - Null. */ +#define RACP_OPERATOR_ALL 1 /**< Record Access Control Point operator - All records. */ +#define RACP_OPERATOR_LESS_OR_EQUAL 2 /**< Record Access Control Point operator - Less than or equal to. */ +#define RACP_OPERATOR_GREATER_OR_EQUAL 3 /**< Record Access Control Point operator - Greater than or equal to. */ +#define RACP_OPERATOR_RANGE 4 /**< Record Access Control Point operator - Within range of (inclusive). */ +#define RACP_OPERATOR_FIRST 5 /**< Record Access Control Point operator - First record (i.e. oldest record). */ +#define RACP_OPERATOR_LAST 6 /**< Record Access Control Point operator - Last record (i.e. most recent record). */ +#define RACP_OPERATOR_RFU_START 7 /**< Record Access Control Point operator - Start of Reserved for Future Use area. */ + +/**@brief Record Access Control Point Operand Filter Type Value. */ +#define RACP_OPERAND_FILTER_TYPE_TIME_OFFSET 1 /**< Record Access Control Point Operand Filter Type Value - Time Offset- */ + +/**@brief Record Access Control Point response codes. */ +#define RACP_RESPONSE_RESERVED 0 /**< Record Access Control Point response code - Reserved for future use. */ +#define RACP_RESPONSE_SUCCESS 1 /**< Record Access Control Point response code - Successful operation. */ +#define RACP_RESPONSE_OPCODE_UNSUPPORTED 2 /**< Record Access Control Point response code - Unsupported op code received. */ +#define RACP_RESPONSE_INVALID_OPERATOR 3 /**< Record Access Control Point response code - Operator not valid for service. */ +#define RACP_RESPONSE_OPERATOR_UNSUPPORTED 4 /**< Record Access Control Point response code - Unsupported operator. */ +#define RACP_RESPONSE_INVALID_OPERAND 5 /**< Record Access Control Point response code - Operand not valid for service. */ +#define RACP_RESPONSE_NO_RECORDS_FOUND 6 /**< Record Access Control Point response code - No matching records found. */ +#define RACP_RESPONSE_ABORT_FAILED 7 /**< Record Access Control Point response code - Abort could not be completed. */ +#define RACP_RESPONSE_PROCEDURE_NOT_DONE 8 /**< Record Access Control Point response code - Procedure could not be completed. */ +#define RACP_RESPONSE_OPERAND_UNSUPPORTED 9 /**< Record Access Control Point response code - Unsupported operand. */ + +/**@brief Record Access Control Point value structure. */ +typedef struct +{ + uint8_t opcode; /**< Op Code. */ + uint8_t operator; /**< Operator. */ + uint8_t operand_len; /**< Length of the operand. */ + uint8_t * p_operand; /**< Pointer to the operand. */ +} ble_racp_value_t; + +/**@brief Function for decoding a Record Access Control Point write. + * + * @details This call decodes a write to the Record Access Control Point. + * + * @param[in] data_len Length of data in received write. + * @param[in] p_data Pointer to received data. + * @param[out] p_racp_val Pointer to decoded Record Access Control Point write. + * @note This does not do a data copy. It assumes the data pointed to by + * p_data is persistant until no longer needed. + */ +void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val); + +/**@brief Function for encoding a Record Access Control Point response. + * + * @details This call encodes a response from the Record Access Control Point response. + * + * @param[in] p_racp_val Pointer to Record Access Control Point to encode. + * @param[out] p_data Pointer to where encoded data is written. + * NOTE! It is calling routines respsonsibility to make sure. + * + * @return Length of encoded data. + */ +uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_RACP_H__ + +/** @} */ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.c new file mode 100644 index 0000000000..a9f81e7692 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.c @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_radio_notification.h" +#include + +#include "nrf_nvic.h" + +static bool m_radio_active = false; /**< Current radio state. */ +static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */ + + +void SWI1_IRQHandler(void) +{ + m_radio_active = !m_radio_active; + if (m_evt_handler != NULL) + { + m_evt_handler(m_radio_active); + } +} + + +uint32_t ble_radio_notification_init(uint32_t irq_priority, + uint8_t distance, + ble_radio_notification_evt_handler_t evt_handler) +{ + uint32_t err_code; + + m_evt_handler = evt_handler; + + // Initialize Radio Notification software interrupt + err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + err_code = sd_nvic_EnableIRQ(SWI1_IRQn); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Configure the event + return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.h new file mode 100644 index 0000000000..43e7946f3e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_radio_notification/ble_radio_notification.h @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_radio_notification Radio Notification Event Handler + * @{ + * @ingroup ble_sdk_lib + * @brief Module for propagating Radio Notification events to the application. + */ + +#ifndef BLE_RADIO_NOTIFICATION_H__ +#define BLE_RADIO_NOTIFICATION_H__ + +#include +#include +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Application radio notification event handler type. */ +typedef void (*ble_radio_notification_evt_handler_t) (bool radio_active); + +/**@brief Function for initializing the Radio Notification module. + * + * @param[in] irq_priority Interrupt priority for the Radio Notification interrupt handler. + * @param[in] distance The time from an Active event until the radio is activated. + * @param[in] evt_handler Handler to be executed when a radio notification event has been + * received. + * + * @return NRF_SUCCESS on successful initialization, otherwise an error code. + */ +uint32_t ble_radio_notification_init(uint32_t irq_priority, + uint8_t distance, + ble_radio_notification_evt_handler_t evt_handler); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_RADIO_NOTIFICATION_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c new file mode 100644 index 0000000000..dd0c43c97f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c @@ -0,0 +1,706 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_advdata.h" +#include "ble_gap.h" +#include "ble_srv_common.h" +#include "sdk_common.h" + +// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. + +#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ +#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ +#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ + +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ + AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ +#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ +#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ +#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ +#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ + +// Types of LE Bluetooth Device Address AD type +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL + +static uint32_t ble_device_addr_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + ble_gap_addr_t device_addr; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get BLE address. + #if (NRF_SD_BLE_API_VERSION >= 3) + err_code = sd_ble_gap_addr_get(&device_addr); + #else + err_code = sd_ble_gap_address_get(&device_addr); + #endif + VERIFY_SUCCESS(err_code); + + // Encode LE Bluetooth Device Address. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; + *p_offset += AD_TYPE_FIELD_SIZE; + memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); + *p_offset += BLE_GAP_ADDR_LEN; + if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; + } + else + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; + } + *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; + + return NRF_SUCCESS; +} + +static uint32_t name_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + uint16_t rem_adv_data_len; + uint16_t actual_length; + uint8_t adv_data_format; + + + // Validate parameters + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check for buffer overflow. + if ( (((*p_offset) + AD_DATA_OFFSET) > max_size) || + ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (((*p_offset) + AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) + { + return NRF_ERROR_DATA_SIZE; + } + + rem_adv_data_len = max_size - (*p_offset) - AD_DATA_OFFSET; + actual_length = rem_adv_data_len; + + // Get GAP device name and length + err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + AD_DATA_OFFSET], + &actual_length); + VERIFY_SUCCESS(err_code); + + // Check if device intend to use short name and it can fit available data size. + if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len)) + { + // Complete device name can fit, setting Complete Name in Adv Data. + adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + } + else + { + // Else short name needs to be used. Or application has requested use of short name. + adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; + + // If application has set a preference on the short name size, it needs to be considered, + // else fit what can be fit. + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (p_advdata->short_name_len <= rem_adv_data_len)) + { + // Short name fits available size. + actual_length = p_advdata->short_name_len; + } + // Else whatever can fit the data buffer will be packed. + else + { + actual_length = rem_adv_data_len; + } + } + + // There is only 1 byte intended to encode length which is (actual_length + AD_TYPE_FIELD_SIZE) + if (actual_length > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Complete name field in encoded data. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + actual_length); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_data_format; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += actual_length; + + return NRF_SUCCESS; +} + + +static uint32_t appearance_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + uint16_t appearance; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get GAP appearance field. + err_code = sd_ble_gap_appearance_get(&appearance); + VERIFY_SUCCESS(err_code); + + // Encode Length, AD Type and Appearance. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; + *p_offset += AD_TYPE_FIELD_SIZE; + *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + +static uint32_t flags_encode(int8_t flags, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode flags. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = flags; + *p_offset += AD_TYPE_FLAGS_DATA_SIZE; + + return NRF_SUCCESS; +} + +static uint32_t tx_power_level_encode(int8_t tx_power_level, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode TX Power Level. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; + *p_offset += AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = tx_power_level; + *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; + + return NRF_SUCCESS; +} + + +static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type, + uint8_t uuid_size, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + int i; + bool is_heading_written = false; + uint16_t start_pos = *p_offset; + uint16_t length; + + for (i = 0; i < p_uuid_list->uuid_cnt; i++) + { + uint32_t err_code; + uint8_t encoded_size; + ble_uuid_t uuid = p_uuid_list->p_uuids[i]; + + // Find encoded uuid size. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); + VERIFY_SUCCESS(err_code); + + // Check size. + if (encoded_size == uuid_size) + { + uint8_t heading_bytes = (is_heading_written) ? 0 : AD_DATA_OFFSET; + + // Check for buffer overflow + if (((*p_offset) + encoded_size + heading_bytes) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + if (!is_heading_written) + { + // Write AD structure heading. + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_type; + *p_offset += AD_TYPE_FIELD_SIZE; + is_heading_written = true; + } + + // Write UUID. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); + VERIFY_SUCCESS(err_code); + *p_offset += encoded_size; + } + } + + if (is_heading_written) + { + // Write length. + length = (*p_offset) - (start_pos + AD_LENGTH_FIELD_SIZE); + // There is only 1 byte intended to encode length + if (length > 0x00FF) + { + return NRF_ERROR_DATA_SIZE; + } + p_encoded_data[start_pos] = (uint8_t)length; + } + + return NRF_SUCCESS; +} + + +static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type_16, + uint8_t adv_type_128, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + + // Encode 16 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_16, + sizeof(uint16_le_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + // Encode 128 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_128, + sizeof(ble_uuid128_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) +{ + // Check Minimum Connection Interval. + if ((p_conn_int->min_conn_interval < 0x0006) || + ( + (p_conn_int->min_conn_interval > 0x0c80) && + (p_conn_int->min_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check Maximum Connection Interval. + if ((p_conn_int->max_conn_interval < 0x0006) || + ( + (p_conn_int->max_conn_interval > 0x0c80) && + (p_conn_int->max_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. + if ((p_conn_int->min_conn_interval != 0xffff) && + (p_conn_int->max_conn_interval != 0xffff) && + (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Check parameters. + err_code = conn_int_check(p_conn_int); + VERIFY_SUCCESS(err_code); + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Minimum and Maximum Connection Intervals. + *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); + *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + + +static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; + + // Check for buffer overflow. + if (((*p_offset) + AD_DATA_OFFSET + data_size) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode Company Identifier. + *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); + + // Encode additional manufacturer specific data. + if (p_manuf_sp_data->data.size > 0) + { + if (p_manuf_sp_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); + *p_offset += p_manuf_sp_data->data.size; + } + + return NRF_SUCCESS; +} + +// Implemented only for 16-bit UUIDs +static uint32_t service_data_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint8_t i; + + // Check parameter consistency. + if (p_advdata->p_service_data_array == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + for (i = 0; i < p_advdata->service_data_count; i++) + { + ble_advdata_service_data_t * p_service_data; + uint32_t data_size; + + p_service_data = &p_advdata->p_service_data_array[i]; + // For now implemented only for 16-bit UUIDs + data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; + + // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); + *p_offset += AD_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; + *p_offset += AD_TYPE_FIELD_SIZE; + + // Encode service 16-bit UUID. + *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); + + // Encode additional service data. + if (p_service_data->data.size > 0) + { + if (p_service_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); + *p_offset += p_service_data->data.size; + } + } + + return NRF_SUCCESS; +} + +uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len) +{ + uint32_t err_code = NRF_SUCCESS; + uint16_t max_size = *p_len; + *p_len = 0; + + // Encode LE Bluetooth Device Address + if (p_advdata->include_ble_device_addr) + { + err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode appearance. + if (p_advdata->include_appearance) + { + err_code = appearance_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + //Encode Flags + if (p_advdata->flags != 0 ) + { + err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode TX power level. + if (p_advdata->p_tx_power_level != NULL) + { + err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'more available' uuid list. + if (p_advdata->uuids_more_available.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_more_available, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'complete' uuid list. + if (p_advdata->uuids_complete.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_complete, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'solicited service' uuid list. + if (p_advdata->uuids_solicited.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_solicited, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Slave Connection Interval Range. + if (p_advdata->p_slave_conn_int != NULL) + { + err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Manufacturer Specific Data. + if (p_advdata->p_manuf_specific_data != NULL) + { + err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Service Data. + if (p_advdata->service_data_count > 0) + { + err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. + if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) + { + err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + return err_code; +} + + +static uint32_t advdata_check(const ble_advdata_t * p_advdata) +{ + // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. + if ( + ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +static uint32_t srdata_check(const ble_advdata_t * p_srdata) +{ + // Flags shall not be included in the scan response data. + if (p_srdata->flags) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) +{ + uint32_t err_code; + uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE; + uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE; + uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; + uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; + uint8_t * p_encoded_advdata; + uint8_t * p_encoded_srdata; + + // Encode advertising data (if supplied). + if (p_advdata != NULL) + { + err_code = advdata_check(p_advdata); + VERIFY_SUCCESS(err_code); + + err_code = ble_advdata_encode(p_advdata, encoded_advdata, &len_advdata); + VERIFY_SUCCESS(err_code); + p_encoded_advdata = encoded_advdata; + } + else + { + p_encoded_advdata = NULL; + len_advdata = 0; + } + + // Encode scan response data (if supplied). + if (p_srdata != NULL) + { + err_code = srdata_check(p_srdata); + VERIFY_SUCCESS(err_code); + + err_code = ble_advdata_encode(p_srdata, encoded_srdata, &len_srdata); + VERIFY_SUCCESS(err_code); + p_encoded_srdata = encoded_srdata; + } + else + { + p_encoded_srdata = NULL; + len_srdata = 0; + } + + // Pass encoded advertising data and/or scan response data to the stack. + return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h new file mode 100644 index 0000000000..bf7d862497 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_sdk_lib_advdata Advertising and Scan Response Data Encoder + * @{ + * @ingroup ble_sdk_lib + * @brief Functions for encoding data in the Advertising and Scan Response Data format, + * and for passing the data to the stack. + */ + +#ifndef BLE_ADVDATA_H__ +#define BLE_ADVDATA_H__ + +#include +#include +#include +#include "nrf_ble.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ +#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ +#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ + +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ + AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ +#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ +#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ +#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ +#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ +#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ + AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ +#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ +#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ + + +/**@brief Security Manager TK value. */ +typedef struct +{ + uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value in little-endian format. */ +} ble_advdata_tk_value_t; + +/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */ + BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */ + BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */ + BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ + BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ +} ble_advdata_le_role_t; + +/**@brief Advertising data name type. This enumeration contains the options available for the device name inside + * the advertising data. */ +typedef enum +{ + BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */ + BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */ + BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */ +} ble_advdata_name_type_t; + +/**@brief UUID list type. */ +typedef struct +{ + uint16_t uuid_cnt; /**< Number of UUID entries. */ + ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */ +} ble_advdata_uuid_list_t; + +/**@brief Connection interval range structure. */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */ + uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */ +} ble_advdata_conn_int_t; + +/**@brief Manufacturer specific data structure. */ +typedef struct +{ + uint16_t company_identifier; /**< Company identifier code. */ + uint8_array_t data; /**< Additional manufacturer specific data. */ +} ble_advdata_manuf_data_t; + +/**@brief Service data structure. */ +typedef struct +{ + uint16_t service_uuid; /**< Service UUID. */ + uint8_array_t data; /**< Additional service data. */ +} ble_advdata_service_data_t; + +/**@brief Advertising data structure. This structure contains all options and data needed for encoding and + * setting the advertising data. */ +typedef struct +{ + ble_advdata_name_type_t name_type; /**< Type of device name. */ + uint8_t short_name_len; /**< Length of short device name (if short type is specified). */ + bool include_appearance; /**< Determines if Appearance shall be included. */ + uint8_t flags; /**< Advertising data Flags field. */ + int8_t * p_tx_power_level; /**< TX Power Level field. */ + ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */ + ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */ + ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */ + ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */ + ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */ + ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */ + uint8_t service_data_count; /**< Number of Service data structures. */ + bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */ + ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */ + ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ + uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ +#if (NRF_SD_BLE_API_VERSION > 1) + ble_gap_lesc_oob_data_t * p_lesc_data; /**< LE Secure Connections OOB data. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ +#endif +} ble_advdata_t; + +/**@brief Function for encoding data in the Advertising and Scan Response data format + * (AD structures). + * + * @details This function encodes data into the Advertising and Scan Response data format + * (AD structures) based on the selections in the supplied structures. This function can be used to + * create a payload of Advertising packet or Scan Response packet, or a payload of NFC + * message intended for initiating the Out-of-Band pairing. + * + * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. + * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. + * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. + * \c out: Length of encoded data. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the + * provided buffer or some encoded AD structure is too long and its + * length cannot be encoded with one octet. + * + * @warning This API may override the application's request to use the long name and use a short name + * instead. This truncation will occur in case the long name does not fit the provided buffer size. + * The application can specify a preferred short name length if truncation is required. + * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name + * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni + * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. + * However, it should be noted that this is just a preference that the application can specify, and + * if the preference is too large to fit in the provided buffer, the name can be truncated further. + */ +uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len); + +/**@brief Function for encoding and setting the advertising data and/or scan response data. + * + * @details This function encodes advertising data and/or scan response data based on the selections + * in the supplied structures, and passes the encoded data to the stack. + * + * @param[in] p_advdata Structure for specifying the content of the advertising data. + * Set to NULL if advertising data is not to be set. + * @param[in] p_srdata Structure for specifying the content of the scan response data. + * Set to NULL if scan response data is not to be set. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. + * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the + * advertising packet. The maximum size of the advertisement packet + * is @ref BLE_GAP_ADV_MAX_SIZE. + * + * @warning This API may override the application's request to use the long name and use a short name + * instead. This truncation will occur in case the long name does not fit the provided buffer size. + * The application can specify a preferred short name length if truncation is required. + * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name + * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni + * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. + * However, it should be noted that this is just a preference that the application can specify, and + * if the preference is too large to fit in the provided buffer, the name can be truncated further. + */ +uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_ADVDATA_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c new file mode 100644 index 0000000000..3229571b31 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c @@ -0,0 +1,572 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_BLE_CONN_PARAMS) +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "ble_hci.h" +#include "ble_err.h" +#include "ble_conn_params.h" +#include "ble_srv_common.h" +#include "ble_conn_state.h" +#include "nrf_sdh_ble.h" +#include "app_timer.h" +#include "app_util.h" + + +#define NRF_BLE_CONN_PARAMS_N_INSTANCES NRF_SDH_BLE_PERIPHERAL_LINK_COUNT //!< The number of @ref ble_conn_params_instance_t instances kept by the conn_params module. + +#if (NRF_BLE_CONN_PARAMS_N_INSTANCES < 1) +#error Invalid NRF_SDH_BLE_PERIPHERAL_LINK_COUNT value. Set it in SDK config (nrf_sdh_ble). +#endif + +/** @brief Each peripheral link has such an instance associated with it. + */ +typedef struct +{ + uint16_t conn_handle; //!< The connection handle of this link. If this is @ref BLE_CONN_HANDLE_INVALID, the instance is free. + app_timer_id_t timer_id; //!< The ID of the timer associated with this link. + uint8_t update_count; //!< The number of times the connection parameters have been attempted negotiated on this link. + uint8_t params_ok; //!< Whether the current connection parameters on this link are acceptable according to the @p preferred_conn_params, and configured maximum deviations. + ble_gap_conn_params_t preferred_conn_params; //!< The desired connection parameters for this link. +} ble_conn_params_instance_t; + +static app_timer_t m_timer_data[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{{0}}}; //!< Data needed for timers. +static ble_conn_params_instance_t m_conn_params_instances[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{0}}; //!< Configuration data for each connection. +static ble_conn_params_init_t m_conn_params_config; //!< Configuration as provided by the application during intialization. +static ble_gap_conn_params_t m_preferred_conn_params; //!< The preferred connection parameters as specified during initialization. +//lint -esym(551, m_preferred_conn_params) "Not accessed" + + +/**@brief Function for retrieving the conn_params instance belonging to a conn_handle + * + * @params[in] conn_handle The connection handle to retrieve the instance of. + * + * @return A pointer to the instance, or NULL if no instance was found with that conn_handle. + */ +static ble_conn_params_instance_t * instance_get(uint16_t conn_handle) +{ + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) + { + if (m_conn_params_instances[i].conn_handle == conn_handle) + { + return &m_conn_params_instances[i]; + } + } + //lint -restore + return NULL; +} + + +/**@brief Function for initializing an instance, and associating it with a conn_handle. + * + * @params[in] p_instance The instance to initialize and associate. + * @params[in] conn_handle The connection handle to associate with. + */ +static __INLINE void instance_claim(ble_conn_params_instance_t * p_instance, uint16_t conn_handle) +{ + p_instance->conn_handle = conn_handle; + p_instance->update_count = 0; + p_instance->preferred_conn_params = m_preferred_conn_params; +} + + +/**@brief Function for freeing an instance. + * + * @params[in] p_instance The instance to free. + */ +static __INLINE void instance_free(ble_conn_params_instance_t * p_instance) +{ + p_instance->conn_handle = BLE_CONN_HANDLE_INVALID; +} + + +/**@brief Function for validating a set of connection parameters against the preferred parameters. + * + * @param[in] p_preferred_conn_params The desired parameters. + * @param[in] p_actual_conn_params The parameters to validate. + * @param[in] max_slave_latency_err The amount of discrepancy in slave latency, in number of + * connection intervals, that will be accepted. + * @param[in] max_sup_timeout_err The amount of discrepancy in supervision timeout, in tens of + * milliseconds, that will be accepted. + * + * @return Whether the params in @p p_actual_conn_params are acceptable given the other parameters. + */ +static bool is_conn_params_ok(ble_gap_conn_params_t const * p_preferred_conn_params, + ble_gap_conn_params_t const * p_actual_conn_params, + uint16_t max_slave_latency_err, + uint16_t max_sup_timeout_err) +{ + uint32_t max_allowed_sl = p_preferred_conn_params->slave_latency + max_slave_latency_err; + uint32_t min_allowed_sl = p_preferred_conn_params->slave_latency + - MIN(max_slave_latency_err, p_preferred_conn_params->slave_latency); + uint32_t max_allowed_to = p_preferred_conn_params->conn_sup_timeout + max_sup_timeout_err; + uint32_t min_allowed_to = p_preferred_conn_params->conn_sup_timeout + - MIN(max_sup_timeout_err, p_preferred_conn_params->conn_sup_timeout); + + // Check if interval is within the acceptable range. + // NOTE: Using max_conn_interval in the received event data because this contains + // the client's connection interval. + if ((p_actual_conn_params->max_conn_interval < p_preferred_conn_params->min_conn_interval) + || (p_actual_conn_params->max_conn_interval > p_preferred_conn_params->max_conn_interval)) + { + return false; + } + + // Check if slave latency is within the acceptable deviation. + if ((p_actual_conn_params->slave_latency < min_allowed_sl) + || (p_actual_conn_params->slave_latency > max_allowed_sl)) + { + return false; + } + + // Check if supervision timeout is within the acceptable deviation. + if ((p_actual_conn_params->conn_sup_timeout < min_allowed_to) + || (p_actual_conn_params->conn_sup_timeout > max_allowed_to)) + { + return false; + } + + return true; +} + + +static void send_error_evt(ret_code_t err_code) +{ + if (m_conn_params_config.error_handler != NULL) + { + m_conn_params_config.error_handler(err_code); + } +} + + +/**@brief Function for sending a conn_param_update request on-air, and handling errors. + * + * @param[in] conn_handle Connection to send request on. + * @param[in] p_new_conn_params Connection parameters to request. + * + * @return Whether the request was successfully sent. + */ +static bool send_update_request(uint16_t conn_handle, ble_gap_conn_params_t * p_new_conn_params) +{ + ret_code_t err_code; + + err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_conn_params); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) // NRF_ERROR_BUSY means another conn_param_update request is pending. + { + send_error_evt(err_code); + } + + return (err_code == NRF_SUCCESS); +} + + +/**@brief Function called after conn_params_update_delay has happened. This is triggered by app_timer. + * + * @param[in] p_context Context identifying which connection this is for. + */ +static void update_timeout_handler(void * p_context) +{ + uint32_t conn_handle = (uint32_t)p_context; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Check if we have reached the maximum number of attempts + if (p_instance->update_count < m_conn_params_config.max_conn_params_update_count) + { + bool update_sent = send_update_request(conn_handle, &p_instance->preferred_conn_params); + if (update_sent) + { + p_instance->update_count++; + } + } + else + { + p_instance->update_count = 0; + + // Negotiation failed, disconnect automatically if this has been configured + if (m_conn_params_config.disconnect_on_fail) + { + ret_code_t err_code; + + err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) // NRF_ERROR_INVALID_STATE means disconnect is already in progress. + { + send_error_evt(err_code); + } + } + + // Notify the application that the procedure has failed + if (m_conn_params_config.evt_handler != NULL) + { + ble_conn_params_evt_t evt; + + evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED; + evt.conn_handle = conn_handle; + m_conn_params_config.evt_handler(&evt); + } + } + } +} + + +ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init) +{ + ret_code_t err_code; + + VERIFY_PARAM_NOT_NULL(p_init); + + m_conn_params_config = *p_init; + m_conn_params_config.p_conn_params = &m_preferred_conn_params; + + if (p_init->p_conn_params != NULL) + { + // Set the connection params in stack. + err_code = sd_ble_gap_ppcp_set(p_init->p_conn_params); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + m_preferred_conn_params = *p_init->p_conn_params; + } + else + { + // Get the (default) connection params from stack. + err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + } + + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) + { + ble_conn_params_instance_t * p_instance = &m_conn_params_instances[i]; + + instance_free(p_instance); + p_instance->timer_id = &m_timer_data[i]; + + err_code = app_timer_create(&p_instance->timer_id, + APP_TIMER_MODE_SINGLE_SHOT, + update_timeout_handler); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + } + //lint -restore + + return NRF_SUCCESS; +} + + +ret_code_t ble_conn_params_stop(void) +{ + ret_code_t err_code; + + //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 + for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) + { + err_code = app_timer_stop(m_conn_params_instances[i].timer_id); + switch (err_code) + { + case NRF_SUCCESS: + /* do nothing */ + break; + + case NRF_ERROR_INVALID_STATE: + /* do nothing */ + break; + + case NRF_ERROR_NO_MEM: + return NRF_ERROR_BUSY; + + case NRF_ERROR_INVALID_PARAM: + /* fallthrough */ + default: + return NRF_ERROR_INTERNAL; + } + } + //lint -restore + return NRF_SUCCESS; +} + + +/**@brief Function for taking appropriate action based on the current state of connection parameters. + * + * @param[in] conn_handle Connection to handle. + * @param[in] p_instance Configuration for the connection. + */ +static void conn_params_negotiation(uint16_t conn_handle, ble_conn_params_instance_t * p_instance) + { + // Start negotiation if the received connection parameters are not acceptable + if (!p_instance->params_ok) + { + ret_code_t err_code; + uint32_t timeout_ticks; + + if (p_instance->update_count == 0) + { + // First connection parameter update + timeout_ticks = m_conn_params_config.first_conn_params_update_delay; + } + else + { + timeout_ticks = m_conn_params_config.next_conn_params_update_delay; + } + + err_code = app_timer_start(p_instance->timer_id, timeout_ticks, (void *)(uint32_t)conn_handle); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + } + else + { + p_instance->update_count = 0; + + // Notify the application that the procedure has succeeded + if (m_conn_params_config.evt_handler != NULL) + { + ble_conn_params_evt_t evt; + + evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED; + evt.conn_handle = conn_handle; + m_conn_params_config.evt_handler(&evt); + } + } +} + + +/**@brief Function for handling a connection event from the SoftDevice. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_connect(ble_evt_t const * p_ble_evt) +{ + uint8_t role = p_ble_evt->evt.gap_evt.params.connected.role; + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + + if (role != BLE_GAP_ROLE_PERIPH) + { + return; + } + + ble_conn_params_instance_t * p_instance = instance_get(BLE_CONN_HANDLE_INVALID); + + if (p_instance == NULL) + { + send_error_evt(NRF_ERROR_NO_MEM); + return; + } + + instance_claim(p_instance, conn_handle); + p_instance->params_ok = is_conn_params_ok(&p_instance->preferred_conn_params, + &p_ble_evt->evt.gap_evt.params.connected.conn_params, + NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, + NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); + + // Check if we shall handle negotiation on connect + if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID) + { + conn_params_negotiation(conn_handle, p_instance); + } +} + + +/**@brief Function for handling a disconnection event from the SoftDevice. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_disconnect(ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Stop timer if running + err_code = app_timer_stop(p_instance->timer_id); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + + instance_free(p_instance); + } +} + + +/**@brief Function for handling a GATT write event from the SoftDevice. + * + * @details To provide the start_on_notify_cccd_handle functionality. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_write(ble_evt_t const * p_ble_evt) +{ + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + // Check if this is the correct CCCD + if ( + (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle) + && + (p_evt_write->len == 2) + ) + { + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + // Check if this is a 'start notification' + if (ble_srv_is_notification_enabled(p_evt_write->data)) + { + // Do connection parameter negotiation if necessary + conn_params_negotiation(conn_handle, p_instance); + } + else + { + ret_code_t err_code; + + // Stop timer if running + err_code = app_timer_stop(p_instance->timer_id); + if (err_code != NRF_SUCCESS) + { + send_error_evt(err_code); + } + } + } + } +} + + +/**@brief Function for handling a connection parameter update event from the SoftDevice. + * + * @details This event means the peer central has changed the connection parameters or declined our + * request. + * + * @param[in] p_ble_evt Event from the SoftDevice. + */ +static void on_conn_params_update(ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_instance != NULL) + { + p_instance->params_ok = is_conn_params_ok( + &p_instance->preferred_conn_params, + &p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params, + NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, + NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); + + conn_params_negotiation(conn_handle, p_instance); + } +} + + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnect(p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_ble_evt); + break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE: + on_conn_params_update(p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + + +ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, + ble_gap_conn_params_t * p_new_params) +{ + ret_code_t err_code = BLE_ERROR_INVALID_CONN_HANDLE; + ble_conn_params_instance_t * p_instance = instance_get(conn_handle); + + if (p_new_params == NULL) + { + p_new_params = &m_preferred_conn_params; + } + + if (p_instance != NULL) + { + // Send request to central. + err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_params); + if (err_code == NRF_SUCCESS) + { + p_instance->params_ok = false; + p_instance->update_count = 1; + p_instance->preferred_conn_params = *p_new_params; + } + } + + return err_code; +} + +NRF_SDH_BLE_OBSERVER(m_ble_observer, BLE_CONN_PARAMS_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + +#endif //ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h new file mode 100644 index 0000000000..0e2024c0eb --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_conn_params Connection Parameters Negotiation + * @{ + * @ingroup ble_sdk_lib + * @brief Module for initiating and executing a connection parameters negotiation procedure. + */ + +#ifndef BLE_CONN_PARAMS_H__ +#define BLE_CONN_PARAMS_H__ + +#include +#include "nrf_ble.h" +#include "ble_srv_common.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Connection Parameters Module event type. */ +typedef enum +{ + BLE_CONN_PARAMS_EVT_FAILED, //!< Negotiation procedure failed. + BLE_CONN_PARAMS_EVT_SUCCEEDED //!< Negotiation procedure succeeded. +} ble_conn_params_evt_type_t; + +/**@brief Connection Parameters Module event. */ +typedef struct +{ + ble_conn_params_evt_type_t evt_type; //!< Type of event. + uint16_t conn_handle; //!< Connection the event refers to. +} ble_conn_params_evt_t; + +/**@brief Connection Parameters Module event handler type. */ +typedef void (*ble_conn_params_evt_handler_t) (ble_conn_params_evt_t * p_evt); + +/**@brief Connection Parameters Module init structure. This contains all options and data needed for + * initialization of the connection parameters negotiation module. */ +typedef struct +{ + ble_gap_conn_params_t * p_conn_params; //!< Pointer to the connection parameters desired by the application. When calling ble_conn_params_init, if this parameter is set to NULL, the connection parameters will be fetched from host. + uint32_t first_conn_params_update_delay; //!< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (in number of timer ticks). + uint32_t next_conn_params_update_delay; //!< Time between each call to sd_ble_gap_conn_param_update after the first (in number of timer ticks). Recommended value 30 seconds as per BLUETOOTH SPECIFICATION Version 4.0. + uint8_t max_conn_params_update_count; //!< Number of attempts before giving up the negotiation. + uint16_t start_on_notify_cccd_handle; //!< If procedure is to be started when notification is started, set this to the handle of the corresponding CCCD. Set to BLE_GATT_HANDLE_INVALID if procedure is to be started on connect event. + bool disconnect_on_fail; //!< Set to TRUE if a failed connection parameters update shall cause an automatic disconnection, set to FALSE otherwise. + ble_conn_params_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Connection Parameters. + ble_srv_error_handler_t error_handler; //!< Function to be called in case of an error. +} ble_conn_params_init_t; + + +/**@brief Function for initializing the Connection Parameters module. + * + * @note If the negotiation procedure should be triggered when notification/indication of + * any characteristic is enabled by the peer, then this function must be called after + * having initialized the services. + * + * @param[in] p_init This contains information needed to initialize this module. + * + * @retval NRF_SUCCESS Successful initialization. + * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. + * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. + * @retval NRF_ERROR_NULL @p p_init was NULL. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init); + +/**@brief Function for stopping the Connection Parameters module. + * + * @details This function is intended to be used by the application to clean up the connection + * parameters update module. This will stop the connection parameters update timer if + * running, thereby preventing any impending connection parameters update procedure. This + * function must be called by the application when it needs to clean itself up (for + * example, before disabling the bluetooth SoftDevice) so that an unwanted timer expiry + * event can be avoided. + * + * @retval NRF_SUCCESS Successfully stopped module. + * @retval NRF_ERROR_BUSY Could not complete operation at this time. Try again later. + Note that some timers may have been disabled. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t ble_conn_params_stop(void); + +/**@brief Function for changing the current connection parameters to a new set. + * + * @details Use this function to change the connection parameters to a new set of parameter + * (ie different from the ones given at init of the module). + * This function is useful for scenario where most of the time the application + * needs a relatively big connection interval, and just sometimes, for a temporary + * period requires shorter connection interval, for example to transfer a higher + * amount of data. + * If the given parameters does not match the current connection's parameters + * this function initiates a new negotiation. + * + * @param[in] conn_handle The connection to change connection parameters on. + * @param[in] p_new_params This contains the new connections parameters to setup. + * + * @retval NRF_SUCCESS Successfully started Connection Parameter update procedure. + * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. + * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. + * @retval BLE_ERROR_INVALID_CONN_HANDLE The provided connection handle is invalid. + * @retval NRF_ERROR_INVALID_STATE The connection is not in a state where this operation can + * performed. + * @retval NRF_ERROR_BUSY Could not start operation at this time. Try again later. + * @retval NRF_ERROR_NO_MEM The SoftDevice lacks the memory to perform the action. + */ +ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, + ble_gap_conn_params_t * p_new_params); + +#ifdef __cplusplus +} +#endif + +#endif // BLE_CONN_PARAMS_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c new file mode 100644 index 0000000000..47f1d7c9e6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c @@ -0,0 +1,444 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_conn_state.h" +#include +#include +#include +#include "nrf_ble.h" +#include "sdk_mapped_flags.h" +#include "app_error.h" +#include "nrf_sdh_ble.h" + + +#if defined(__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined(__ICCARM__) + #pragma language=extended +#elif defined(__GNUC__) + /* anonymous unions are enabled by default */ +#endif + + +#define BLE_CONN_STATE_N_DEFAULT_FLAGS 5 /**< The number of flags kept for each connection, excluding user flags. */ +#define BLE_CONN_STATE_N_FLAGS (BLE_CONN_STATE_N_DEFAULT_FLAGS + BLE_CONN_STATE_N_USER_FLAGS) /**< The number of flags kept for each connection, including user flags. */ + +/**@brief Structure containing all the flag collections maintained by the Connection State module. + */ +typedef struct +{ + sdk_mapped_flags_t valid_flags; /**< Flags indicating which connection handles are valid. */ + sdk_mapped_flags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */ + sdk_mapped_flags_t central_flags; /**< Flags indicating in which connections the local device is the central. */ + sdk_mapped_flags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */ + sdk_mapped_flags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */ + sdk_mapped_flags_t user_flags[BLE_CONN_STATE_N_USER_FLAGS]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */ +} ble_conn_state_flag_collections_t; + + +/**@brief Structure containing the internal state of the Connection State module. + */ +typedef struct +{ + uint32_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */ + uint16_t valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */ + union + { + ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */ + sdk_mapped_flags_t flag_array[BLE_CONN_STATE_N_FLAGS]; /**< Flag collections as array to allow use of @ref sdk_mapped_flags_bulk_update_by_key() when setting all flags. */ + }; +} ble_conn_state_t; + + +#if defined(__CC_ARM) + #pragma pop +#elif defined(__ICCARM__) + /* leave anonymous unions enabled */ +#elif defined(__GNUC__) + /* anonymous unions are enabled by default */ +#endif + + +static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */ + + +/**@brief Function for resetting all internal memory to the values it had at initialization. + */ +void bcs_internal_state_reset(void) +{ + memset( &m_bcs, 0, sizeof(ble_conn_state_t) ); +} + + +/**@brief Function for activating a connection record. + * + * @param p_record The record to activate. + * @param conn_handle The connection handle to copy into the record. + * @param role The role of the connection. + * + * @return whether the record was activated successfully. + */ +static bool record_activate(uint16_t conn_handle) +{ + uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags); + + if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX) + { + m_bcs.valid_conn_handles[available_index] = conn_handle; + sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, + &m_bcs.flags.connected_flags, + conn_handle, + 1); + sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, + &m_bcs.flags.valid_flags, + conn_handle, + 1); + + return true; + } + + return false; +} + + +/**@brief Function for marking a connection record as invalid and resetting the values. + * + * @param p_record The record to invalidate. + */ +static void record_invalidate(uint16_t conn_handle) +{ + sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles, + m_bcs.flag_array, + BLE_CONN_STATE_N_FLAGS, + conn_handle, + 0); +} + + +/**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED. + * + * @param p_record The record of the connection to set as disconnected. + */ +static void record_set_disconnected(uint16_t conn_handle) +{ + sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, + &m_bcs.flags.connected_flags, + conn_handle, + 0); +} + + +/**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED + * connection status + */ +static void record_purge_disconnected() +{ + sdk_mapped_flags_key_list_t disconnected_list; + + disconnected_list = sdk_mapped_flags_key_list_get( + m_bcs.valid_conn_handles, + (~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags)); + + for (uint32_t i = 0; i < disconnected_list.len; i++) + { + record_invalidate(disconnected_list.flag_keys[i]); + } +} + + +/**@brief Function for checking if a user flag has been acquired. + * + * @param[in] flag_id Which flag to check. + * + * @return Whether the flag has been acquired. + */ +static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id) +{ + return ((m_bcs.acquired_flags & (1 << flag_id)) != 0); +} + + +/**@brief Function for marking a user flag as acquired. + * + * @param[in] flag_id Which flag to mark. + */ +static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id) +{ + m_bcs.acquired_flags |= (1 << flag_id); +} + + +void ble_conn_state_init(void) +{ + bcs_internal_state_reset(); +} + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + record_purge_disconnected(); + + if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) ) + { + // No more records available. Should not happen. + APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + } +#if !defined (S112) + else + { + bool is_central = + (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL); + + sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, + &m_bcs.flags.central_flags, + p_ble_evt->evt.gap_evt.conn_handle, + is_central); + } +#endif // !defined (S112) + + break; + + case BLE_GAP_EVT_DISCONNECTED: + record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle); + break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + sdk_mapped_flags_update_by_key( + m_bcs.valid_conn_handles, + &m_bcs.flags.encrypted_flags, + p_ble_evt->evt.gap_evt.conn_handle, + (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1)); + sdk_mapped_flags_update_by_key( + m_bcs.valid_conn_handles, + &m_bcs.flags.mitm_protected_flags, + p_ble_evt->evt.gap_evt.conn_handle, + (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2)); + break; + } +} + +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_CONN_STATE_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + + +bool ble_conn_state_valid(uint16_t conn_handle) +{ + return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.valid_flags, + conn_handle); +} + + +uint8_t ble_conn_state_role(uint16_t conn_handle) +{ + uint8_t role = BLE_GAP_ROLE_INVALID; + + if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) ) + { + bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.central_flags, + conn_handle); +#if !defined (S112) + role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH; +#else + role = BLE_GAP_ROLE_PERIPH; + UNUSED_VARIABLE(central); +#endif // !defined (S112) + } + + return role; +} + + +ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle) +{ + ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID; + bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.valid_flags, + conn_handle); + + if (valid) + { + bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.connected_flags, + conn_handle); + + conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED; + } + + return conn_status; +} + + +bool ble_conn_state_encrypted(uint16_t conn_handle) +{ + return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.encrypted_flags, + conn_handle); +} + + +bool ble_conn_state_mitm_protected(uint16_t conn_handle) +{ + return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.mitm_protected_flags, + conn_handle); +} + + +uint32_t ble_conn_state_n_connections(void) +{ + return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags); +} + + +uint32_t ble_conn_state_n_centrals(void) +{ + return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); +} + + +uint32_t ble_conn_state_n_peripherals(void) +{ + return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); +} + + +sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void) +{ + return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags); +} + + +sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void) +{ + return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, + (m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); +} + + +sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void) +{ + return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, + (~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); +} + + +uint8_t ble_conn_state_conn_idx(uint16_t conn_handle) +{ + uint8_t index; + if (sdk_mapped_flags_get_by_key_w_idx(m_bcs.valid_conn_handles, + m_bcs.flags.valid_flags, + conn_handle, + &index)) + { + return index; + } + else + { + return BLE_CONN_STATE_MAX_CONNECTIONS; + } +} + + +ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void) +{ + for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0; + i < BLE_CONN_STATE_N_USER_FLAGS; + i++) + { + if ( !user_flag_is_acquired(i) ) + { + user_flag_acquire(i); + return i; + } + } + + return BLE_CONN_STATE_USER_FLAG_INVALID; +} + + +bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id) +{ + if (user_flag_is_acquired(flag_id)) + { + return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, + m_bcs.flags.user_flags[flag_id], + conn_handle); + } + else + { + return false; + } +} + + +void ble_conn_state_user_flag_set(uint16_t conn_handle, + ble_conn_state_user_flag_id_t flag_id, + bool value) +{ + if (user_flag_is_acquired(flag_id)) + { + sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, + &m_bcs.flags.user_flags[flag_id], + conn_handle, + value); + } +} + + +sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id) +{ + if ( user_flag_is_acquired(flag_id) ) + { + return m_bcs.flags.user_flags[flag_id]; + } + else + { + return 0; + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h new file mode 100644 index 0000000000..878b8d838a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h @@ -0,0 +1,317 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_conn_state Connection state + * @ingroup ble_sdk_lib + * @{ + * @brief Module for storing data on BLE connections. + * + * @details This module stores certain states for each connection, which can be queried by + * connection handle. The module uses BLE events to keep the states updated. + * + * In addition to the preprogrammed states, this module can also keep track of a number of + * binary user states, or user flags. These are reset to 0 for new connections, but + * otherwise not touched by this module. + * + * This module uses the @ref sdk_mapped_flags module, with connection handles as keys and + * the connection states as flags. + * + * @note A connection handle is not immediately invalidated when it is disconnected. Certain states, + * such as the role, can still be queried until the next time a new connection is established + * to any device. + * + */ + +#ifndef BLE_CONN_STATE_H__ +#define BLE_CONN_STATE_H__ + +#include +#include +#include "nrf_ble.h" +#include "sdk_mapped_flags.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Connection handle statuses. + */ +typedef enum +{ + BLE_CONN_STATUS_INVALID, /**< The connection handle is invalid. */ + BLE_CONN_STATUS_DISCONNECTED, /**< The connection handle refers to a connection that has been disconnected, but not yet invalidated. */ + BLE_CONN_STATUS_CONNECTED, /**< The connection handle refers to an active connection. */ +} ble_conn_state_status_t; + +#define BLE_CONN_STATE_MAX_CONNECTIONS 20 /**< The maximum number of connections supported. */ +#define BLE_CONN_STATE_N_USER_FLAGS 24 /**< The number of available user flags. */ + + +/**@brief One ID for each user flag collection. + * + * @details These IDs are used to identify user flag collections in the API calls. + */ +typedef enum +{ + BLE_CONN_STATE_USER_FLAG0 = 0, + BLE_CONN_STATE_USER_FLAG1, + BLE_CONN_STATE_USER_FLAG2, + BLE_CONN_STATE_USER_FLAG3, + BLE_CONN_STATE_USER_FLAG4, + BLE_CONN_STATE_USER_FLAG5, + BLE_CONN_STATE_USER_FLAG6, + BLE_CONN_STATE_USER_FLAG7, + BLE_CONN_STATE_USER_FLAG8, + BLE_CONN_STATE_USER_FLAG9, + BLE_CONN_STATE_USER_FLAG10, + BLE_CONN_STATE_USER_FLAG11, + BLE_CONN_STATE_USER_FLAG12, + BLE_CONN_STATE_USER_FLAG13, + BLE_CONN_STATE_USER_FLAG14, + BLE_CONN_STATE_USER_FLAG15, + BLE_CONN_STATE_USER_FLAG16, + BLE_CONN_STATE_USER_FLAG17, + BLE_CONN_STATE_USER_FLAG18, + BLE_CONN_STATE_USER_FLAG19, + BLE_CONN_STATE_USER_FLAG20, + BLE_CONN_STATE_USER_FLAG21, + BLE_CONN_STATE_USER_FLAG22, + BLE_CONN_STATE_USER_FLAG23, + BLE_CONN_STATE_USER_FLAG_INVALID, +} ble_conn_state_user_flag_id_t; + + +/** + * @defgroup ble_conn_state_functions BLE connection state functions + * @{ + */ + + +/**@brief Function for initializing or resetting the module. + * + * @details This function sets all states to their default, removing all records of connection handles. + */ +void ble_conn_state_init(void); + + +/**@brief Function for querying whether a connection handle represents a valid connection. + * + * @details A connection might be valid and have a BLE_CONN_STATUS_DISCONNECTED status. + * Those connections are invalidated after a new connection occurs. + * + * @param[in] conn_handle Handle of the connection. + * + * @retval true If conn_handle represents a valid connection, thus a connection for which + we have a record. + * @retval false If conn_handle is @ref BLE_GAP_ROLE_INVALID, or if it has never been recorded. + */ +bool ble_conn_state_valid(uint16_t conn_handle); + + +/**@brief Function for querying the role of the local device in a connection. + * + * @param[in] conn_handle Handle of the connection to get the role for. + * + * @return The role of the local device in the connection (see @ref BLE_GAP_ROLES). + * If conn_handle is not valid, the function returns BLE_GAP_ROLE_INVALID. + */ +uint8_t ble_conn_state_role(uint16_t conn_handle); + + +/**@brief Function for querying the status of a connection. + * + * @param[in] conn_handle Handle of the connection. + * + * @return The status of the connection. + * If conn_handle is not valid, the function returns BLE_CONN_STATE_INVALID. + */ +ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle); + + +/**@brief Function for querying whether a connection is encrypted. + * + * @param[in] conn_handle Handle of connection to get the encryption state for. + * + * @retval true If the connection is encrypted. + * @retval false If the connection is not encrypted or conn_handle is invalid. + */ +bool ble_conn_state_encrypted(uint16_t conn_handle); + + +/**@brief Function for querying whether a connection encryption is protected from Man in the Middle + * attacks. + * + * @param[in] conn_handle Handle of connection to get the MITM state for. + * + * @retval true If the connection is encrypted with MITM protection. + * @retval false If the connection is not encrypted, or encryption is not MITM protected, or + * conn_handle is invalid. + */ +bool ble_conn_state_mitm_protected(uint16_t conn_handle); + + +/**@brief Function for querying the total number of connections. + * + * @return The total number of valid connections for which the module has a record. + */ +uint32_t ble_conn_state_n_connections(void); + + +/**@brief Function for querying the total number of connections in which the role of the local + * device is @ref BLE_GAP_ROLE_CENTRAL. + * + * @return The number of connections in which the role of the local device is + * @ref BLE_GAP_ROLE_CENTRAL. + */ +uint32_t ble_conn_state_n_centrals(void); + + +/**@brief Function for querying the total number of connections in which the role of the local + * device is @ref BLE_GAP_ROLE_PERIPH. + * + * @return The number of connections in which the role of the local device is + * @ref BLE_GAP_ROLE_PERIPH. + */ +uint32_t ble_conn_state_n_peripherals(void); + + +/**@brief Function for obtaining a list of all connection handles for which the module has a record. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record. + */ +sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void); + + +/**@brief Function for obtaining a list of connection handles in which the role of the local + * device is @ref BLE_GAP_ROLE_CENTRAL. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record and in which + * the role of local device is @ref BLE_GAP_ROLE_CENTRAL. + */ +sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void); + + +/**@brief Function for obtaining the handle for the connection in which the role of the local device + * is @ref BLE_GAP_ROLE_PERIPH. + * + * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. + * + * @return A list of all valid connection handles for which the module has a record and in which + * the role of local device is @ref BLE_GAP_ROLE_PERIPH. + */ +sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void); + + +/**@brief Function for translating a connection handle to a value that can be used as an array index. + * + * @details Function for mapping connection handles onto the range <0 - MAX_CONNECTIONS>. + * + * @note The index will be the same as long as a connection is invalid. A subsequent connection with + * the same connection handle might have a different index. + * + * @param[in] conn_handle The connection for which to retrieve an index. + * + * @return An index unique to this connection. Or @ref BLE_CONN_STATE_MAX_CONNECTIONS if + * @p conn_handle refers to an invalid connection. + */ +uint8_t ble_conn_state_conn_idx(uint16_t conn_handle); + + +/**@brief Function for obtaining exclusive access to one of the user flag collections. + * + * @details The acquired collection contains one flag for each connection. These flags can be set + * and read individually for each connection. + * + * The state of user flags will not be modified by the connection state module, except to + * set it to 0 for a connection when that connection is invalidated. + * + * @return The ID of the acquired flag, or BLE_CONN_STATE_USER_FLAG_INVALID if none are available. + */ +ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void); + + +/**@brief Function for reading the value of a user flag. + * + * @param[in] conn_handle Handle of connection to get the flag state for. + * @param[in] flag_id Which flag to get the state for. + * + * @return The state of the flag. If conn_handle is invalid, the function returns false. + */ +bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id); + + +/**@brief Function for setting the value of a user flag. + * + * @param[in] conn_handle Handle of connection to set the flag state for. + * @param[in] flag_id Which flag to set the state for. + * @param[in] value Value to set the flag state to. + */ +void ble_conn_state_user_flag_set(uint16_t conn_handle, + ble_conn_state_user_flag_id_t flag_id, + bool value); + + +/**@brief Function for getting the state of a user flag for all connection handles. + * + * @details The returned collection can be used with the @ref sdk_mapped_flags API. The returned + * collection is a copy, so modifying it has no effect on the conn_state module. + * + * @param[in] flag_id Which flag to get states for. + * + * @return The collection of flag states. The collection is always all zeros when the flag_id is + * unregistered. + */ +sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id); + +/** @} */ +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_CONN_STATE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h new file mode 100644 index 0000000000..762784c11a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/* Attention! +* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile +* qualification listings, this section of source code must not be modified. +*/ + +/** @file + * @brief Contains definition of ble_date_time structure. + */ + +/** @file + * + * @defgroup ble_sdk_srv_date_time BLE Date Time characteristic type + * @{ + * @ingroup ble_sdk_lib + * @brief Definition of ble_date_time_t type. + */ + +#ifndef BLE_DATE_TIME_H__ +#define BLE_DATE_TIME_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Date and Time structure. */ +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} ble_date_time_t; + +static __INLINE uint8_t ble_date_time_encode(const ble_date_time_t * p_date_time, + uint8_t * p_encoded_data) +{ + uint8_t len = uint16_encode(p_date_time->year, p_encoded_data); + + p_encoded_data[len++] = p_date_time->month; + p_encoded_data[len++] = p_date_time->day; + p_encoded_data[len++] = p_date_time->hours; + p_encoded_data[len++] = p_date_time->minutes; + p_encoded_data[len++] = p_date_time->seconds; + + return len; +} + +static __INLINE uint8_t ble_date_time_decode(ble_date_time_t * p_date_time, + const uint8_t * p_encoded_data) +{ + uint8_t len = sizeof(uint16_t); + + p_date_time->year = uint16_decode(p_encoded_data); + p_date_time->month = p_encoded_data[len++]; + p_date_time->day = p_encoded_data[len++]; + p_date_time->hours = p_encoded_data[len++]; + p_date_time->minutes = p_encoded_data[len++]; + p_date_time->seconds = p_encoded_data[len++]; + + return len; +} + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_DATE_TIME_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h new file mode 100644 index 0000000000..3b35773e0b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_sdk_lib_gatt_db GATT Database Service Structure + * @{ + * @ingroup ble_sdk_lib + */ + +#ifndef BLE_GATT_DB_H__ +#define BLE_GATT_DB_H__ + +#include +#include "nrf_ble.h" +#include "ble_gattc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_GATT_DB_MAX_CHARS 6 /**< The maximum number of characteristics present in a service record. */ + +/**@brief Structure for holding the characteristic and the handle of its CCCD present on a server. + */ +typedef struct +{ + ble_gattc_char_t characteristic; /**< Structure containing information about the characteristic. */ + uint16_t cccd_handle; /**< CCCD Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a CCCD is not present at the server. */ + uint16_t ext_prop_handle; /**< Extended Properties Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if an Extended Properties descriptor is not present at the server. */ + uint16_t user_desc_handle; /**< User Description Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a User Description descriptor is not present at the server. */ + uint16_t report_ref_handle; /**< Report Reference Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a Report Reference descriptor is not present at the server. */ +} ble_gatt_db_char_t; + +/**@brief Structure for holding information about the service and the characteristics present on a + * server. + */ +typedef struct +{ + ble_uuid_t srv_uuid; /**< UUID of the service. */ + uint8_t char_count; /**< Number of characteristics present in the service. */ + ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ + ble_gatt_db_char_t charateristics[BLE_GATT_DB_MAX_CHARS]; /**< Array of information related to the characteristics present in the service. This list can extend further than one. */ +} ble_gatt_db_srv_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* BLE_GATT_DB_H__ */ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h new file mode 100644 index 0000000000..ca259f1450 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/* Attention! +* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile +* qualification listings, this section of source code must not be modified. +*/ + +#ifndef BLE_SENSOR_LOCATION_H__ +#define BLE_SENSOR_LOCATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BLE_SENSOR_LOCATION_OTHER = 0 , /**<-- Other */ + BLE_SENSOR_LOCATION_TOP_OF_SHOE = 1 , /**<-- Top of shoe */ + BLE_SENSOR_LOCATION_IN_SHOE = 2 , /**<-- In shoe */ + BLE_SENSOR_LOCATION_HIP = 3 , /**<-- Hip */ + BLE_SENSOR_LOCATION_FRONT_WHEEL = 4 , /**<-- Front Wheel */ + BLE_SENSOR_LOCATION_LEFT_CRANK = 5 , /**<-- Left Crank */ + BLE_SENSOR_LOCATION_RIGHT_CRANK = 6 , /**<-- Right Crank */ + BLE_SENSOR_LOCATION_LEFT_PEDAL = 7 , /**<-- Left Pedal */ + BLE_SENSOR_LOCATION_RIGHT_PEDAL = 8 , /**<-- Right Pedal */ + BLE_SENSOR_LOCATION_FRONT_HUB = 9 , /**<-- Front Hub */ + BLE_SENSOR_LOCATION_REAR_DROPOUT = 10, /**<-- Rear Dropout */ + BLE_SENSOR_LOCATION_CHAINSTAY = 11, /**<-- Chainstay */ + BLE_SENSOR_LOCATION_REAR_WHEEL = 12, /**<-- Rear Wheel */ + BLE_SENSOR_LOCATION_REAR_HUB = 13, /**<-- Rear Hub */ +}ble_sensor_location_t; + +#define BLE_NB_MAX_SENSOR_LOCATIONS 14 + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_SENSOR_LOCATION_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c new file mode 100644 index 0000000000..db90cc0693 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/* Attention! + * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile + * qualification listings, this section of source code must not be modified. + */ + +#include "ble_srv_common.h" +#include +#include "nordic_common.h" +#include "app_error.h" +#include "nrf_ble.h" + +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); +} + +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data) +{ + uint16_t cccd_value = uint16_decode(p_encoded_data); + return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0); +} + +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref) +{ + uint8_t len = 0; + + p_encoded_buffer[len++] = p_report_ref->report_id; + p_encoded_buffer[len++] = p_report_ref->report_type; + + APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN); + return len; +} + + +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii) +{ + p_utf8->length = (uint16_t)strlen(p_ascii); + p_utf8->p_str = (uint8_t *)p_ascii; +} + + +/**@brief Function for setting security requirements of a characteristic. + * + * @param[in] level required security level. + * @param[out] p_perm Characteristic security requirements. + * + * @return encoded security level and security mode. + */ +static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) +{ + + + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + switch (level) + { + case SEC_NO_ACCESS: + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); + break; + case SEC_OPEN: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); + break; + case SEC_JUST_WORKS: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); + break; + case SEC_MITM: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); + break; + case SEC_SIGNED: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); + break; + case SEC_SIGNED_MITM: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); + break; + } + return; +} + + +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle) +{ + ble_gatts_char_md_t char_md; + ble_gatts_attr_t attr_char_value; + ble_uuid_t char_uuid; + ble_gatts_attr_md_t attr_md; + ble_gatts_attr_md_t user_descr_attr_md; + ble_gatts_attr_md_t cccd_md; + + if (p_char_props->uuid_type == 0) + { + char_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + char_uuid.type = p_char_props->uuid_type; + } + char_uuid.uuid = p_char_props->uuid; + + memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t)); + set_security_req(p_char_props->read_access, &attr_md.read_perm); + set_security_req(p_char_props->write_access, & attr_md.write_perm); + attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_char_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + + + memset(&char_md, 0, sizeof(ble_gatts_char_md_t)); + if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1)) + { + + memset(&cccd_md, 0, sizeof(cccd_md)); + set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); + + cccd_md.vloc = BLE_GATTS_VLOC_STACK; + + char_md.p_cccd_md = &cccd_md; + } + char_md.char_props = p_char_props->char_props; + char_md.char_ext_props = p_char_props->char_ext_props; + + memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t)); + attr_char_value.p_uuid = &char_uuid; + attr_char_value.p_attr_md = &attr_md; + attr_char_value.max_len = p_char_props->max_len; + if (p_char_props->p_init_value != NULL) + { + attr_char_value.init_len = p_char_props->init_len; + attr_char_value.p_value = p_char_props->p_init_value; + } + if (p_char_props->p_user_descr != NULL) + { + memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t)); + char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size; + char_md.char_user_desc_size = p_char_props->p_user_descr->size; + char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc; + + char_md.p_user_desc_md = &user_descr_attr_md; + + set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm); + set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm); + + user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0); + user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0); + user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0); + user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + } + if (p_char_props->p_presentation_format != NULL) + { + char_md.p_char_pf = p_char_props->p_presentation_format; + } + return sd_ble_gatts_characteristic_add(service_handle, + &char_md, + &attr_char_value, + p_char_handle); +} + + +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle) +{ + ble_gatts_attr_t descr_params; + ble_uuid_t desc_uuid; + ble_gatts_attr_md_t attr_md; + + memset(&descr_params, 0, sizeof(descr_params)); + if (p_descr_props->uuid_type == 0) + { + desc_uuid.type = BLE_UUID_TYPE_BLE; + } + else + { + desc_uuid.type = p_descr_props->uuid_type; + } + desc_uuid.uuid = p_descr_props->uuid; + descr_params.p_uuid = &desc_uuid; + + set_security_req(p_descr_props->read_access, &attr_md.read_perm); + set_security_req(p_descr_props->write_access,&attr_md.write_perm); + + attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0); + attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0); + attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0); + attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); + descr_params.p_attr_md = &attr_md; + + descr_params.init_len = p_descr_props->init_len; + descr_params.init_offs = p_descr_props->init_offs; + descr_params.max_len = p_descr_props->max_len; + descr_params.p_value = p_descr_props->p_value; + + return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h new file mode 100644 index 0000000000..a63ed2d41b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h @@ -0,0 +1,409 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_sdk_srv_common Common service definitions + * @{ + * @ingroup ble_sdk_srv + * @brief Constants, type definitions, and functions that are common to all services. + */ + +#ifndef BLE_SRV_COMMON_H__ +#define BLE_SRV_COMMON_H__ + +#include +#include +#include "ble_types.h" +#include "app_util.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "ble_gatt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UUID_SERVICES Service UUID definitions + * @{ */ +#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ +#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ +#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ +#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ +#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */ +#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ +#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ +#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ +#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ +#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ +#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ +#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ +#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ +#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ +#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ +#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ +#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ +#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ +#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */ +#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/ +#define BLE_UUID_CGM_SERVICE 0x181F /**< Continuous Glucose Monitoring service UUID*/ +#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/ +#define BLE_UUID_OTS_SERVICE 0x1825 /**< Object Transfer Service UUID*/ + +/** @} */ + +/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions + * @{ */ +#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */ +#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */ +#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */ +#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */ +#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */ +#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */ +#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */ +#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */ +#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */ +#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */ +#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */ +#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */ +#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */ +#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */ +#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */ +#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */ +#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */ +#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */ +#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */ +#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */ +#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */ +#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */ +#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */ +#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */ +#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */ +#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */ +#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */ +#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */ +#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */ +#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */ +#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */ +#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */ +#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */ +#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */ +#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */ +#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */ +#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */ +#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */ +#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */ +#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */ +#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */ +#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */ +#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */ +#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */ +#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */ +#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */ +#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */ +#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */ +#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */ +#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */ +#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */ +#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */ +#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */ +#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */ +#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */ +#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */ +#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */ +#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */ +#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */ +#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */ +#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */ +#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */ +#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */ +#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */ +#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */ +#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */ +#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */ +#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */ +#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/ +#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/ +#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/ +#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/ +#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/ +#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/ +#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/ +#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_FEATURES 0x2ABD /**< OTS Service, feature characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_NAME 0x2ABE /**< OTS Service, Object Name characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_TYPE 0x2ABF /**< OTS Service, Object Type characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_SIZE 0x2AC0 /**< OTS Service, Object Size characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_FIRST_CREATED 0x2AC1 /**< OTS Service, Object First Created characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_LAST_MODIFIED 0x2AC2 /**< OTS Service, Object Last Modified characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_ID 0x2AC3 /**< OTS Service, Object ID characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_PROPERTIES 0x2AC4 /**< OTS Service, Object Properties characteristic UUID*/ +#define BLE_UUID_OTS_OACP 0x2AC5 /**< OTS Service, Object Action Control Point characteristic UUID*/ +#define BLE_UUID_OTS_OLCP 0x2AC6 /**< OTS Service, Object List Control Point characteristic UUID*/ +#define BLE_UUID_OTS_LF 0x2AC7 /**< OTS Service, Object List Filter characteristic UUID*/ +#define BLE_UUID_OTS_OBJECT_CHANGED 0x2AC8 /**< OTS Service, Object Changed characteristic UUID*/ + + + + +/** @} */ + +/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values + * @{ */ +#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */ +#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */ +#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */ +/** @} */ + +#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */ +#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */ + +/**@brief Type definition for error handler function that will be called in case of an error in + * a service or a service library module. */ +typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error); + + + +/**@brief Value of a Report Reference descriptor. + * + * @details This is mapping information that maps the parent characteristic to the Report ID(s) and + * Report Type(s) defined within a Report Map characteristic. + */ +typedef struct +{ + uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */ + uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */ +} ble_srv_report_ref_t; + +/**@brief UTF-8 string data type. + * + * @note The type can only hold a pointer to the string data (i.e. not the actual data). + */ +typedef struct +{ + uint16_t length; /**< String length. */ + uint8_t * p_str; /**< String data. */ +} ble_srv_utf8_str_t; + + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_security_mode_t; + +/**@brief Security settings structure. + * @details This structure contains the security options needed during initialization of the + * service. It can be used when the characteristics contains a CCCD. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ +} ble_srv_cccd_security_mode_t; + +/**@brief Function for decoding a CCCD value, and then testing if notification is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If notification is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for decoding a CCCD value, and then testing if indication is + * enabled. + * + * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. + * + * @retval TRUE If indication is enabled. + * @retval FALSE Otherwise. + */ +bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data); + + +/**@brief Function for encoding a Report Reference Descriptor. + * + * @param[in] p_encoded_buffer The buffer of the encoded data. + * @param[in] p_report_ref Report Reference value to be encoded. + * + * @return Length of the encoded data. + */ +uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, + const ble_srv_report_ref_t * p_report_ref); + +/**@brief Function for making a UTF-8 structure refer to an ASCII string. + * + * @param[out] p_utf8 UTF-8 structure to be set. + * @param[in] p_ascii ASCII string to be referred to. + */ +void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii); + + +/**@brief Security Access enumeration. + * @details This enumeration gives the possible requirements for accessing a characteristic value. + */ +typedef enum +{ + SEC_NO_ACCESS = 0, /**< Not possible to access. */ + SEC_OPEN = 1, /**< Access open. */ + SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */ + SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */ + SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */ + SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */ +}security_req_t; + + +/**@brief Characteristic User Descriptor parameters. + * @details This structure contains the parameters for User Descriptor. + */ +typedef struct +{ + uint16_t max_size; /**< Maximum size of the user descriptor*/ + uint16_t size; /**< Size of the user descriptor*/ + uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/ + bool is_var_len; /**< Indicates if the user descriptor has variable length.*/ + ble_gatt_char_props_t char_props; /**< user descriptor properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the user descriptor.*/ + security_req_t write_access; /**< Security requirement for writing the user descriptor.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ +}ble_add_char_user_desc_t; + + +/**@brief Add characteristic parameters structure. + * @details This structure contains the parameters needed to use the @ref characteristic_add function. + */ +typedef struct +{ + uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + uint16_t max_len; /**< Maximum length of the characteristic value.*/ + uint16_t init_len; /**< Initial length of the characteristic value.*/ + uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/ + bool is_var_len; /**< Indicates if the characteristic value has variable length.*/ + ble_gatt_char_props_t char_props; /**< Characteristic properties.*/ + ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic extended properties.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + security_req_t read_access; /**< Security requirement for reading the characteristic value.*/ + security_req_t write_access; /**< Security requirement for writing the characteristic value.*/ + security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/ + ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/ +} ble_add_char_params_t; + + +/**@brief Add descriptor parameters structure. + * @details This structure contains the parameters needed to use the @ref descriptor_add function. + */ +typedef struct +{ + uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/ + uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ + bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ + bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ + bool is_var_len; /**< Indicates if the descriptor value has variable length.*/ + security_req_t read_access; /**< Security requirement for reading the descriptor value.*/ + security_req_t write_access; /**< Security requirement for writing the descriptor value.*/ + bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ + uint16_t init_len; /**< Initial descriptor value length in bytes. */ + uint16_t init_offs; /**< Initial descriptor 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 descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ + uint8_t* p_value; /**< Pointer to the value of the descriptor*/ +} ble_add_descr_params_t; + + +/**@brief Function for adding a characteristic to a given service. + * + * If no pointer is given for the initial value, + * the initial length parameter will be ignored and the initial length will be 0. + * + * @param[in] service_handle Handle of the service to which the characteristic is to be added. + * @param[in] p_char_props Information needed to add the characteristic. + * @param[out] p_char_handle Handle of the added characteristic. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t characteristic_add(uint16_t service_handle, + ble_add_char_params_t * p_char_props, + ble_gatts_char_handles_t * p_char_handle); + + +/**@brief Function for adding a characteristic's descriptor to a given characteristic. + * + * @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. + * @param[in] p_descr_props Information needed to add the descriptor. + * @param[out] p_descr_handle Handle of the added descriptor. + * + * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. + */ +uint32_t descriptor_add(uint16_t char_handle, + ble_add_descr_params_t * p_descr_props, + uint16_t * p_descr_handle); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_SRV_COMMON_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c new file mode 100644 index 0000000000..baa42956fa --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c @@ -0,0 +1,552 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_BLE_GATT) + +#include "nrf_ble_gatt.h" + +#define NRF_LOG_MODULE_NAME ble_gatt +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +#define L2CAP_HDR_LEN 4 //!< Length of a L2CAP header, in bytes. + + +STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE <= 251); +STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN <= 255); + + +/**@brief Initialize a link's parameters to defaults. */ +static void link_init(nrf_ble_gatt_link_t * p_link) +{ + p_link->att_mtu_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_link->att_mtu_effective = BLE_GATT_ATT_MTU_DEFAULT; + p_link->att_mtu_exchange_pending = false; + p_link->att_mtu_exchange_requested = false; +#if !defined (S112) + p_link->data_length_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; + p_link->data_length_effective = BLE_GATT_ATT_MTU_DEFAULT + L2CAP_HDR_LEN; +#endif // !defined (S112) +} + +/**@brief Start a data length update request. + * @details This function is called to request a data length update upon connection. + * When the peer requests a data length update, sd_ble_gap_data_length_update() + * is called directly in response to the BLE_GAP_EVT_DATA_LENGTH_UPDATE event in + * on_data_length_update_evt(). + */ +#if !defined (S112) +static void data_length_update(uint16_t conn_handle, nrf_ble_gatt_t const * p_gatt) +{ + NRF_LOG_DEBUG("Requesting to update data length to %u on connection 0x%x.", + p_gatt->links[conn_handle].data_length_desired, conn_handle); + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = p_gatt->links[conn_handle].data_length_desired, + .max_tx_octets = p_gatt->links[conn_handle].data_length_desired, + .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO, + .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO, + }; + + ret_code_t err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gap_data_length_update() (request)" + " on connection 0x%x returned unexpected value 0x%x.", + conn_handle, err_code); + } +} +#endif // !defined (S112) + + +/**@brief Handle a connected event. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_connected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + // Update the link desired settings to reflect the current global settings. +#if !defined (S112) + p_link->data_length_desired = p_gatt->data_length; +#endif // !defined (S112) + switch (p_ble_evt->evt.gap_evt.params.connected.role) + { + case BLE_GAP_ROLE_PERIPH: + p_link->att_mtu_desired = p_gatt->att_mtu_desired_periph; + break; +#if !defined (S112) + case BLE_GAP_ROLE_CENTRAL: + p_link->att_mtu_desired = p_gatt->att_mtu_desired_central; + break; +#endif // !defined (S112) + default: + // Ignore. + break; + } + + // Begin an ATT MTU exchange if necessary. + if (p_link->att_mtu_desired > p_link->att_mtu_effective) + { + NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x.", + p_link->att_mtu_desired, conn_handle); + + err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, p_link->att_mtu_desired); + + if (err_code == NRF_SUCCESS) + { + p_link->att_mtu_exchange_requested = true; + } + else if (err_code == NRF_ERROR_BUSY) + { + p_link->att_mtu_exchange_pending = true; + NRF_LOG_DEBUG("sd_ble_gattc_exchange_mtu_request()" + " on connection 0x%x returned busy, will retry.", conn_handle); + } + else + { + NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request()" + " returned unexpected value 0x%x.", + err_code); + } + } + +#if !defined (S112) + // Send a data length update request if necessary. + if (p_link->data_length_desired > p_link->data_length_effective) + { + data_length_update(conn_handle, p_gatt); + } +#endif // !defined (S112) +} + + +static void on_disconnected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + // Reset connection parameters. + link_init(&p_gatt->links[p_ble_evt->evt.gap_evt.conn_handle]); +} + + +/**@brief Handle a BLE_GATTC_EVT_EXCHANGE_MTU_RSP event. + * + * @details The effective ATT MTU is set to the lowest between what we requested and the peer's + * response. This events concludes the ATT MTU exchange. An event is sent to the user + * and a data length update procedure is started if necessary. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_exchange_mtu_rsp_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; + uint16_t server_rx_mtu = p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu; + + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + // Determine the lowest MTU between our own desired MTU and the peer's. + // The MTU may not be less than BLE_GATT_ATT_MTU_DEFAULT. + p_link->att_mtu_effective = MIN(server_rx_mtu, p_link->att_mtu_desired); + p_link->att_mtu_effective = MAX(p_link->att_mtu_effective, BLE_GATT_ATT_MTU_DEFAULT); + + NRF_LOG_DEBUG("ATT MTU updated to %u bytes on connection 0x%x (response).", + p_link->att_mtu_effective, conn_handle); + + // Trigger an event indicating that the ATT MTU size has changed. + // Send an event to the application only if an ATT MTU exchange was requested. + if ((p_gatt->evt_handler != NULL) && (p_link->att_mtu_exchange_requested)) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, + .conn_handle = conn_handle, + .params.att_mtu_effective = p_link->att_mtu_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } + + p_link->att_mtu_exchange_requested = false; + p_link->att_mtu_exchange_pending = false; +} + + +/**@brief Handle a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +static void on_exchange_mtu_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + uint16_t client_mtu = p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; + + nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; + + NRF_LOG_DEBUG("Peer on connection 0x%x requested an ATT MTU of %u bytes.", + conn_handle, client_mtu); + + client_mtu = MAX(client_mtu, BLE_GATT_ATT_MTU_DEFAULT); + p_link->att_mtu_effective = MIN(client_mtu, p_link->att_mtu_desired); + p_link->att_mtu_exchange_pending = false; + + NRF_LOG_DEBUG("Updating ATT MTU to %u bytes (desired: %u) on connection 0x%x.", + p_link->att_mtu_effective, p_link->att_mtu_desired, conn_handle); + + err_code = sd_ble_gatts_exchange_mtu_reply(conn_handle, p_link->att_mtu_desired); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gatts_exchange_mtu_reply() returned unexpected value 0x%x.", + err_code); + } + + // If an ATT_MTU exchange was requested to the peer, defer sending + // the data length update request and the event to the application until + // the response for that request is received. + if (p_link->att_mtu_exchange_requested) + { + return; + } + + // The ATT MTU exchange has finished. Send an event to the application. + if (p_gatt->evt_handler != NULL) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, + .conn_handle = conn_handle, + .params.att_mtu_effective = p_link->att_mtu_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } +} + + +/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE event. + * + * @details Update the connection data length and send an event to the user. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +#if !defined (S112) +static void on_data_length_update_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ble_gap_evt_t const gap_evt = p_ble_evt->evt.gap_evt; + uint16_t const conn_handle = gap_evt.conn_handle; + + // Update the connection data length. + p_gatt->links[conn_handle].data_length_effective = + gap_evt.params.data_length_update.effective_params.max_tx_octets; + + NRF_LOG_DEBUG("Data length updated to %u on connection 0x%0x.", + p_gatt->links[conn_handle].data_length_effective, + conn_handle); + + NRF_LOG_DEBUG("max_rx_octets: %u", + gap_evt.params.data_length_update.effective_params.max_rx_octets); + NRF_LOG_DEBUG("max_tx_octets: %u", + gap_evt.params.data_length_update.effective_params.max_tx_octets); + NRF_LOG_DEBUG("max_rx_time: %u", + gap_evt.params.data_length_update.effective_params.max_rx_time_us); + NRF_LOG_DEBUG("max_tx_time: %u", + gap_evt.params.data_length_update.effective_params.max_tx_time_us); + + if (p_gatt->evt_handler != NULL) + { + nrf_ble_gatt_evt_t const evt = + { + .evt_id = NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED, + .conn_handle = conn_handle, + .params.data_length = p_gatt->links[conn_handle].data_length_effective, + }; + + p_gatt->evt_handler(p_gatt, &evt); + } +} +#endif // !defined (S112) + + +/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. + * + *@details Reply with a sd_ble_gap_data_length_update() call, using the minimum between the + * link's preferred data length, and what requested by the peer. + * The link preferred data length is set to the global preferred data length + * upon connection and can be overridden by calling nrf_ble_gatt_data_length_set(). + * The default is NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN. + * + *@note The SoftDevice will not send any BLE_GAP_EVT_DATA_LENGTH_UPDATE events on this side. + * Therefore, the connection data length is updated immediately and an event is sent + * to the user. + * + * @param[in] p_gatt GATT structure. + * @param[in] p_ble_evt Event received from the BLE stack. + */ +#if !defined (S112) +static void on_data_length_update_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + + ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; + nrf_ble_gatt_link_t * p_link = &p_gatt->links[p_gap_evt->conn_handle]; + + uint8_t const data_length_peer = + p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; + + NRF_LOG_DEBUG("Peer on connection 0x%x requested a data length of %u bytes.", + p_gap_evt->conn_handle, data_length_peer); + + uint8_t const data_length = MIN(p_link->data_length_desired, data_length_peer); + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = data_length, + .max_tx_octets = data_length, + }; + + NRF_LOG_DEBUG("Updating data length to %u bytes on connection 0x%x.", + data_length, p_gap_evt->conn_handle); + + err_code = sd_ble_gap_data_length_update(p_gap_evt->conn_handle, &dlp, NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_gap_data_length_update() (reply)" + " returned unexpected value 0x%x.", + err_code); + } +} +#endif // !defined (S112) + + +ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + p_gatt->evt_handler = evt_handler; + p_gatt->att_mtu_desired_periph = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + p_gatt->data_length = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; + + for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++) + { + link_init(&p_gatt->links[i]); + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_gatt->att_mtu_desired_periph = desired_mtu; + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) +{ + VERIFY_PARAM_NOT_NULL(p_gatt); + + if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_gatt->att_mtu_desired_central = desired_mtu; + return NRF_SUCCESS; +} + + +uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle) +{ + if ((p_gatt == NULL) || (conn_handle >= NRF_BLE_GATT_LINK_COUNT)) + { + return 0; + } + + return p_gatt->links[conn_handle].att_mtu_effective; +} + +#if !defined (S112) +ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, + uint16_t conn_handle, + uint8_t data_length) +{ + ret_code_t err_code; + + if (p_gatt == NULL) + { + return NRF_ERROR_NULL; + } + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + p_gatt->data_length = MIN(data_length, NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN); + return NRF_SUCCESS; + } + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_gatt->links[conn_handle].data_length_desired = data_length; + + ble_gap_data_length_params_t const dlp = + { + .max_rx_octets = data_length, + .max_tx_octets = data_length, + }; + + err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); + return err_code; +} +#endif // !defined (S112) + + +#if !defined (S112) +ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, + uint16_t conn_handle, + uint8_t * p_data_length) +{ + if ((p_gatt == NULL) || (p_data_length == NULL)) + { + return NRF_ERROR_NULL; + } + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + *p_data_length = p_gatt->data_length; + return NRF_SUCCESS; + } + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return NRF_ERROR_INVALID_PARAM; + } + + *p_data_length = p_gatt->links[conn_handle].data_length_effective; + return NRF_SUCCESS; +} +#endif // !defined (S112) + + +void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + nrf_ble_gatt_t * p_gatt = (nrf_ble_gatt_t *)p_context; + uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; + + if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) + { + return; + } + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connected_evt(p_gatt, p_ble_evt); + break; + + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected_evt(p_gatt, p_ble_evt); + break; + + case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + on_exchange_mtu_rsp_evt(p_gatt, p_ble_evt); + break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + on_exchange_mtu_request_evt(p_gatt, p_ble_evt); + break; +#if !defined (S112) + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: + on_data_length_update_evt(p_gatt, p_ble_evt); + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + on_data_length_update_request_evt(p_gatt, p_ble_evt); + break; +#endif // !defined (S112) + default: + break; + } + + if (p_gatt->links[conn_handle].att_mtu_exchange_pending) + { + ret_code_t err_code; + + err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, + p_gatt->links[conn_handle].att_mtu_desired); + + if (err_code == NRF_SUCCESS) + { + p_gatt->links[conn_handle].att_mtu_exchange_pending = false; + p_gatt->links[conn_handle].att_mtu_exchange_requested = true; + + NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x (retry).", + p_gatt->links[conn_handle].att_mtu_desired, conn_handle); + } + else if (err_code != NRF_ERROR_BUSY) + { + NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned unexpected value 0x%x.", + err_code); + } + } +} + +#endif //NRF_BLE_GATT_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h new file mode 100644 index 0000000000..300efeb9ee --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h @@ -0,0 +1,242 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_ble_gatt GATT module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for negotiating and keeping track of GATT connection parameters and updating the data length. + */ + +#ifndef NRF_BLE_GATT_H__ +#define NRF_BLE_GATT_H__ + +#include +#include +#include +#include "nrf_ble.h" +#include "ble_gatt.h" +#include "sdk_config.h" +#include "sdk_errors.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a nrf_ble_gatt instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define NRF_BLE_GATT_DEF(_name) \ +static nrf_ble_gatt_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + NRF_BLE_GATT_BLE_OBSERVER_PRIO, \ + nrf_ble_gatt_on_ble_evt, &_name) + +/**@brief The maximum number of peripheral and central connections combined. + * This value is based on what is configured in the SoftDevice handler sdk_config. + */ +#define NRF_BLE_GATT_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT) + + +/**@brief GATT module event types. */ +typedef enum +{ + NRF_BLE_GATT_EVT_ATT_MTU_UPDATED = 0xA77, //!< The ATT_MTU size was updated. + NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED = 0xDA7A, //!< The data length was updated. +} nrf_ble_gatt_evt_id_t; + +/**@brief GATT module event. */ +typedef struct +{ + nrf_ble_gatt_evt_id_t evt_id; //!< Event ID. + uint16_t conn_handle; //!< Connection handle on which the event happened. + union + { + uint16_t att_mtu_effective; //!< Effective ATT_MTU. +#if !defined (S112) + uint8_t data_length; //!< Data length value. +#endif // !defined (S112) + } params; +} nrf_ble_gatt_evt_t; + +// Forward declaration of the nrf_ble_gatt_t type. +typedef struct nrf_ble_gatt_s nrf_ble_gatt_t; + +/**@brief GATT module event handler type. + * + * The GATT module calls a function of this type when a parameter value is changed. + */ +typedef void (*nrf_ble_gatt_evt_handler_t) (nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt); + +/**@brief GATT information for each connection. */ +typedef struct +{ + uint16_t att_mtu_desired; //!< Requested ATT_MTU size (in bytes). + uint16_t att_mtu_effective; //!< Effective ATT_MTU size (in bytes). + bool att_mtu_exchange_pending; //!< Indicates that an ATT_MTU exchange request is pending (the call to @ref sd_ble_gattc_exchange_mtu_request returned @ref NRF_ERROR_BUSY). + bool att_mtu_exchange_requested; //!< Indicates that an ATT_MTU exchange request was made. +#if !defined (S112) + uint8_t data_length_desired; //!< Desired data length (in bytes). + uint8_t data_length_effective; //!< Requested data length (in bytes). +#endif // !defined (S112) +} nrf_ble_gatt_link_t; + + +/**@brief GATT structure that contains status information for the GATT module. */ +struct nrf_ble_gatt_s +{ + uint16_t att_mtu_desired_periph; //!< Requested ATT_MTU size for the next peripheral connection that is established. + uint16_t att_mtu_desired_central; //!< Requested ATT_MTU size for the next central connection that is established. + uint8_t data_length; //!< Data length to use for the next connection that is established. + nrf_ble_gatt_link_t links[NRF_BLE_GATT_LINK_COUNT]; //!< GATT related information for all active connections. + nrf_ble_gatt_evt_handler_t evt_handler; //!< GATT event handler. +}; + + +/**@brief Function for initializing the GATT module. + * + * @param[in] evt_handler Event handler. + * @param[out] p_gatt Pointer to the GATT structure. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + */ +ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler); + + +/**@brief Function for setting the ATT_MTU size for the next connection that is established as peripheral. + * + * @param[in] p_gatt Pointer to the GATT structure. + * @param[in] desired_mtu Requested ATT_MTU size. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than + * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller than + * @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); + + +/**@brief Function for setting the ATT_MTU size for the next connection that is established as central. + * + * @param[in,out] p_gatt Pointer to the GATT structure. + * @param[in] desired_mtu Requested ATT_MTU size. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than + * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller + * than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); + + +/**@brief Function for setting the data length for a connection. + * + * @details If @p conn_handle is a handle to an existing connection, a data length update + * request is sent on that connection. + * If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, a data length update request + * is sent on the next connection that is established after the ATT_MTU + * exchange has completed. If no ATT_MTU exchange procedure is carried + * out (for example, if a default ATT_MTU size is used), the data length + * is not changed. + */ +#if !defined (S112) +ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, + uint16_t conn_handle, + uint8_t data_length); +#endif // !defined (S112) + +/**@brief Function for retrieving the data length of a connection. + * + * @details If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, the function retrieves the data + * length that will be requested for the next connection. + * If @p conn_handle is a handle to an existing connection, the function retrieves + * the effective data length that was negotiated for that connection. + * + * @param[in,out] p_gatt Pointer to the GATT structure. + * @param[in] conn_handle The connection for which to retrieve the data length, or + * @ref BLE_CONN_HANDLE_INVALID to retrieve the requested data length + * for the next connection. + * @param[out] p_data_length The connection data length. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_gatt or @p p_data_length is NULL. + * @retval NRF_ERROR_INVALID_PARAM If @p conn_handle is larger than @ref NRF_BLE_GATT_LINK_COUNT. + */ +#if !defined (S112) +ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, + uint16_t conn_handle, + uint8_t * p_data_length); +#endif // !defined (S112) + +/**@brief Function for handling BLE stack events. + * + * @details This function handles events from the BLE stack that are of interest to the module. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Pointer to the GATT structure. + */ +void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +/**@brief Function for getting the current ATT_MTU size for a given connection. + * + * @param[in] p_gatt Pointer to the GATT structure. + * @param[in] conn_handle Connection handle of the connection. + * + * @return ATT_MTU size for the given connection. + * @retval 0 If @p p_gatt is NULL or if @p conn_handle is larger than + * the supported maximum number of connections. + */ +uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_GATT_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c new file mode 100644 index 0000000000..cafd24eca2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c @@ -0,0 +1,447 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_BLE_QWR) +#include +#include "nrf_ble_qwr.h" +#include "nrf_ble.h" +#include "ble_srv_common.h" + + +#define NRF_BLE_QWR_INITIALIZED 0xDE // Non-zero value used to make sure the given structure has been initialized by the module. +#define MODULE_INITIALIZED (p_qwr->initialized == NRF_BLE_QWR_INITIALIZED) +#include "sdk_macros.h" + +ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_init_t const * p_qwr_init) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_PARAM_NOT_NULL(p_qwr_init); + if (MODULE_INITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + memset(p_qwr->attr_handles, 0, sizeof(p_qwr->attr_handles)); + p_qwr->nb_registered_attr = 0; + p_qwr->error_handler = p_qwr_init->error_handler; + p_qwr->is_user_mem_reply_pending = false; + p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; + p_qwr->initialized = NRF_BLE_QWR_INITIALIZED; + p_qwr->mem_buffer = p_qwr_init->mem_buffer; + p_qwr->callback = p_qwr_init->callback; + p_qwr->nb_written_handles = 0; + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_MODULE_INITIALIZED(); + + if (p_qwr->nb_registered_attr == NRF_BLE_QWR_ATTR_LIST_SIZE) + { + return (NRF_ERROR_NO_MEM); + } + + if (attr_handle == BLE_GATT_HANDLE_INVALID) + { + return NRF_ERROR_INVALID_PARAM; + } + + p_qwr->attr_handles[p_qwr->nb_registered_attr] = attr_handle; + p_qwr->nb_registered_attr++; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, + uint16_t attr_handle, + uint8_t * p_mem, + uint16_t * p_len) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_PARAM_NOT_NULL(p_mem); + VERIFY_PARAM_NOT_NULL(p_len); + VERIFY_MODULE_INITIALIZED(); + + uint16_t i = 0; + uint16_t handle = BLE_GATT_HANDLE_INVALID; + uint16_t val_len = 0; + uint16_t val_offset = 0; + uint16_t cur_len = 0; + + do + { + handle = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + + if (handle == BLE_GATT_HANDLE_INVALID) + { + break; + } + + i += sizeof(uint16_t); + val_offset = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + i += sizeof(uint16_t); + val_len = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); + i += sizeof(uint16_t); + + if (handle == attr_handle) + { + cur_len = val_offset + val_len; + if (cur_len <= *p_len) + { + memcpy((p_mem + val_offset), &(p_qwr->mem_buffer.p_mem[i]), val_len); + } + else + { + return NRF_ERROR_NO_MEM; + } + } + + i += val_len; + } + while (i < p_qwr->mem_buffer.len); + + *p_len = cur_len; + return NRF_SUCCESS; +} + + +ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, + uint16_t conn_handle) +{ + VERIFY_PARAM_NOT_NULL(p_qwr); + VERIFY_MODULE_INITIALIZED(); + p_qwr->conn_handle = conn_handle; + return NRF_SUCCESS; +} + + +/**@brief checks if a user_mem_reply is pending, if so attempts to send it. + * + * @param[in] p_qwr QWR structure. + */ +static void user_mem_reply(nrf_ble_qwr_t * p_qwr) +{ + if (p_qwr->is_user_mem_reply_pending) + { + ret_code_t err_code = sd_ble_user_mem_reply(p_qwr->conn_handle, &p_qwr->mem_buffer); + if (err_code == NRF_SUCCESS) + { + p_qwr->is_user_mem_reply_pending = false; + } + else if (err_code == NRF_ERROR_BUSY) + { + p_qwr->is_user_mem_reply_pending = true; + } + else + { + p_qwr->error_handler(err_code); + } + } +} + + +/**@brief Handle a user memory request event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_common_evt User_mem_request event to be handled. + */ +static void on_user_mem_request(nrf_ble_qwr_t * p_qwr, + ble_common_evt_t const * p_common_evt) +{ + if (p_common_evt->conn_handle == p_qwr->conn_handle) + { + if (p_common_evt->params.user_mem_request.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) + { + p_qwr->is_user_mem_reply_pending = true; + user_mem_reply(p_qwr); + } + } +} + + +/**@brief Handle a user memory release event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_common_evt User_mem_release event to be handled. + */ +static void on_user_mem_release(nrf_ble_qwr_t * p_qwr, + ble_common_evt_t const * p_common_evt) +{ + if (p_common_evt->conn_handle == p_qwr->conn_handle) + { + if (p_common_evt->params.user_mem_release.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) + { + // Cancel the current operation. + p_qwr->nb_written_handles = 0; + } + } +} + + +/**@brief Handle a prepare write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write WRITE event to be handled. + */ +static void on_prepare_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + uint32_t i; + + for (i = 0; i < p_qwr->nb_written_handles; i++) + { + if (p_qwr->written_attr_handles[i] == p_evt_write->handle) + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + break; + } + } + + if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) + { + for (i = 0; i < p_qwr->nb_registered_attr; i++) + { + if (p_qwr->attr_handles[i] == p_evt_write->handle) + { + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + p_qwr->written_attr_handles[p_qwr->nb_written_handles++] = p_evt_write->handle; + break; + } + } + } + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Cancel the current operation. + p_qwr->nb_written_handles = 0; + + // Report error to application. + p_qwr->error_handler(err_code); + } + +} + + +/**@brief Handle an execute write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write EXEC WRITE event to be handled. + */ +static void on_execute_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + + if (p_qwr->nb_written_handles == 0) + { + auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + return; + } + + for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) + { + nrf_ble_qwr_evt_t evt; + uint16_t ret_val; + + evt.evt_type = NRF_BLE_QWR_EVT_AUTH_REQUEST; + evt.attr_handle = p_qwr->written_attr_handles[i]; + ret_val = p_qwr->callback(p_qwr, &evt); + if (ret_val != BLE_GATT_STATUS_SUCCESS) + { + auth_reply.params.write.gatt_status = ret_val; + } + } + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + + // If the execute has not been rejected by any of the registered applications, propagate execute write event to all written handles. */ + if (auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) + { + for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) + { + nrf_ble_qwr_evt_t evt; + evt.evt_type = NRF_BLE_QWR_EVT_EXECUTE_WRITE; + evt.attr_handle = p_qwr->written_attr_handles[i]; + /*lint -e534 -save "Ignoring return value of function" */ + p_qwr->callback(p_qwr, &evt); + /*lint -restore*/ + + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + } + } + p_qwr->nb_written_handles = 0; +} + + +/**@brief Handle a cancel write event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_evt_write EXEC WRITE event to be handled. + */ +static void on_cancel_write(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_write_t const * p_evt_write) +{ + uint32_t err_code; + ble_gatts_rw_authorize_reply_params_t auth_reply; + memset(&auth_reply, 0, sizeof(auth_reply)); + + auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); + if (err_code != NRF_SUCCESS) + { + // Report error to application. + p_qwr->error_handler(err_code); + } + p_qwr->nb_written_handles = 0; +} + + +/**@brief Handle a rw_authorize_request event. + * + * @param[in] p_qwr QWR structure. + * @param[in] p_gatts_evt RW_authorize_request event to be handled. + */ +static void on_rw_authorize_request(nrf_ble_qwr_t * p_qwr, + ble_gatts_evt_t const * p_gatts_evt) +{ + if (p_gatts_evt->conn_handle != p_qwr->conn_handle) + { + return; + } + + ble_gatts_evt_rw_authorize_request_t const * p_auth_req = &p_gatts_evt->params.authorize_request; + if (p_auth_req->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) + { + return; + } + + switch (p_auth_req->request.write.op) + { + case BLE_GATTS_OP_PREP_WRITE_REQ: + on_prepare_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_PREP_WRITE_REQ + + case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: + on_execute_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_EXEC_WRITE_REQ_NOW + + case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: + on_cancel_write(p_qwr, &p_auth_req->request.write); + break; // BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL + + default: + // No implementation needed. + break; + } +} + + +void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_context); + VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); + + nrf_ble_qwr_t * p_qwr = (nrf_ble_qwr_t *)p_context; + + VERIFY_MODULE_INITIALIZED_VOID(); + + if (p_ble_evt->evt.common_evt.conn_handle == p_qwr->conn_handle) + { + user_mem_reply(p_qwr); + } + switch (p_ble_evt->header.evt_id) + { + case BLE_EVT_USER_MEM_REQUEST: + on_user_mem_request(p_qwr, &p_ble_evt->evt.common_evt); + break; // BLE_EVT_USER_MEM_REQUEST + + case BLE_EVT_USER_MEM_RELEASE: + on_user_mem_release(p_qwr, &p_ble_evt->evt.common_evt); + break; // BLE_EVT_USER_MEM_REQUEST + + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + on_rw_authorize_request(p_qwr, &p_ble_evt->evt.gatts_evt); + break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST + + case BLE_GAP_EVT_DISCONNECTED: + if (p_ble_evt->evt.gap_evt.conn_handle == p_qwr->conn_handle) + { + p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; + p_qwr->nb_written_handles = 0; + } + break; // BLE_GAP_EVT_DISCONNECTED + + default: + break; + } + +} +#endif // NRF_MODULE_ENABLED(NRF_BLE_QWR) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h new file mode 100644 index 0000000000..7453730e00 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_ble_qwr Queued Writes module + * @{ + * @ingroup ble_sdk_lib + * @brief Module for handling Queued Write operations. + * + * @details This module handles prepare write, execute write, and cancel write + * commands. It also manages memory requests related to these operations. + * + * @note The application must propagate BLE stack events to this module by calling + * @ref nrf_ble_qwr_on_ble_evt(). + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NRF_BLE_QUEUED_WRITES_H__ +#define NRF_BLE_QUEUED_WRITES_H__ + +#include +#include "nordic_common.h" +#include "sdk_common.h" +#include "nrf_ble.h" +#include "ble_srv_common.h" + +/**@brief Macro for defining a nrf_ble_qwr instance. + * + * @param _name Name of the instance. + * @hideinitializer + */ +#define NRF_BLE_QWR_DEF(_name) \ +static nrf_ble_qwr_t _name; \ +NRF_SDH_BLE_OBSERVER(_name ## _obs, \ + NRF_BLE_QWR_BLE_OBSERVER_PRIO, \ + nrf_ble_qwr_on_ble_evt, &_name) + +#ifndef NRF_BLE_QWR_ATTR_LIST_SIZE +#define NRF_BLE_QWR_ATTR_LIST_SIZE 10 //!< Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. +#endif + +#define NRF_BLE_QWR_REJ_REQUEST_ERR_CODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 0 //!< Error code used by the module to reject prepare write requests on non-registered attributes. + + +/**@brief Queued Writes module event types. */ +typedef enum +{ + NRF_BLE_QWR_EVT_EXECUTE_WRITE, //!< Event that indicates that an execute write command was received for a registered handle and that the received data was actually written and is now ready. + NRF_BLE_QWR_EVT_AUTH_REQUEST, //!< Event that indicates that an execute write command was received for a registered handle and that the write request must now be accepted or rejected. +} nrf_ble_qwr_evt_type_t; + +/**@brief Queued Writes module events. */ +typedef struct +{ + nrf_ble_qwr_evt_type_t evt_type; //!< Type of the event. + uint16_t attr_handle; //!< Handle of the attribute to which the event relates. +} nrf_ble_qwr_evt_t; + +// Forward declaration of the nrf_ble_qwr_t type. +struct nrf_ble_qwr_t; + +/**@brief Queued Writes module event handler type. + * + * If the provided event is of type @ref NRF_BLE_QWR_EVT_AUTH_REQUEST, + * this function must accept or reject the execute write request by returning + * one of the @ref BLE_GATT_STATUS_CODES.*/ +typedef uint16_t (* nrf_ble_qwr_evt_handler_t) (struct nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_evt_t * p_evt); + +/**@brief Queued Writes structure. + * @details This structure contains status information for the Queued Writes module. */ +typedef struct nrf_ble_qwr_t +{ + uint8_t initialized; //!< Flag that indicates whether the module has been initialized. + uint16_t attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of handles for registered attributes, for which the module accepts and handles prepare write operations. + uint8_t nb_registered_attr; //!< Number of registered attributes. + uint16_t written_attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of attribute handles that have been written to during the current prepare write or execute write operation. + uint8_t nb_written_handles; //!< Number of attributes that have been written to during the current prepare write or execute write operation. + ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. + ble_srv_error_handler_t error_handler; //!< Error handler. + bool is_user_mem_reply_pending; //!< Flag that indicates whether a mem_reply is pending (because a previous attempt returned busy). + uint16_t conn_handle; //!< Connection handle. + nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. +} nrf_ble_qwr_t; + +/**@brief Queued Writes init structure. + * @details This structure contains all information + * that is needed to initialize the Queued Writes module. */ +typedef struct +{ + ble_srv_error_handler_t error_handler; //!< Error handler. + ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. + nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. +} nrf_ble_qwr_init_t; + + +/**@brief Function for initializing the Queued Writes module. + * + * @details Call this function in the main entry of your application to + * initialize the Queued Writes module. It must be called only once with a + * given Queued Writes structure. + * + * @param[out] p_qwr Queued Writes structure. This structure must be + * supplied by the application. It is initialized by this function + * and is later used to identify the particular Queued Writes instance. + * @param[in] p_qwr_init Initialization structure. + * + * @retval NRF_SUCCESS If the Queued Writes module was initialized successfully. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has already been initialized. + */ +ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, + nrf_ble_qwr_init_t const * p_qwr_init); + + +/**@brief Function for registering an attribute with the Queued Writes module. + * + * @details Call this function for each attribute that you want to enable for + * Queued Writes (thus a series of prepare write and execute write operations). + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] attr_handle Handle of the attribute to register. + * + * @retval NRF_SUCCESS If the registration was successful. + * @retval NRF_ERROR_NO_MEM If no more memory is available to add this registration. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle); + + +/**@brief Function for handling BLE stack events. + * + * @details Handles all events from the BLE stack that are of interest to the Queued Writes module. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Queued Writes structure. + */ +void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + + +/**@brief Function for retrieving the received data for a given attribute. + * + * @details Call this function after receiving an @ref NRF_BLE_QWR_EVT_AUTH_REQUEST + * event to retrieve a linear copy of the data that was received for the given attribute. + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] attr_handle Handle of the attribute. + * @param[out] p_mem Pointer to the application buffer where the received data will be copied. + * @param[in,out] p_len Input: length of the input buffer. Output: length of the received data. + * + * + * @retval NRF_SUCCESS If the data was retrieved and stored successfully. + * @retval NRF_ERROR_NO_MEM If the provided buffer was smaller than the received data. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, + uint16_t attr_handle, + uint8_t * p_mem, + uint16_t * p_len); + + +/**@brief Function for assigning a connection handle to a given instance of the Queued Writes module. + * + * @details Call this function when a link with a peer has been established to + * associate this link to the instance of the module. This makes it + * possible to handle several links and associate each link to a particular + * instance of this module. + * + * @param[in] p_qwr Queued Writes structure. + * @param[in] conn_handle Connection handle to be associated with the given Queued Writes instance. + * + * @retval NRF_SUCCESS If the assignment was successful. + * @retval NRF_ERROR_NULL If any of the given pointers is NULL. + * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. + */ +ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, + uint16_t conn_handle); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BLE_QUEUED_WRITES_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c new file mode 100644 index 0000000000..4d6d43111a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c @@ -0,0 +1,568 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "gatt_cache_manager.h" + +#include "ble_gap.h" +#include "ble_err.h" +#include "ble_conn_state.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "id_manager.h" +#include "gatts_cache_manager.h" +#include "peer_database.h" +#include "pm_mutex.h" + + +// The number of registered event handlers. +#define GCM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + +// GATT Cache Manager event handler in Peer Manager. +extern void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt); + +// GATT Cache Manager events' handlers. +// The number of elements in this array is GCM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t m_evt_handlers[] = +{ + pm_gcm_evt_handler +}; + +static bool m_module_initialized; +static uint8_t m_db_update_in_progress_mutex; /**< Mutex indicating whether a local DB write operation is ongoing. */ +static ble_conn_state_user_flag_id_t m_flag_local_db_update_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB update procedure. */ +static ble_conn_state_user_flag_id_t m_flag_local_db_apply_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB apply procedure. */ +static ble_conn_state_user_flag_id_t m_flag_service_changed_pending; /**< Flag ID for flag collection to keep track of which connections need to be sent a service changed indication. */ +static ble_conn_state_user_flag_id_t m_flag_service_changed_sent; /**< Flag ID for flag collection to keep track of which connections have been sent a service changed indication and are waiting for a handle value confirmation. */ + + +/**@brief Function for resetting the module variable(s) of the GSCM module. + * + * @param[out] The instance to reset. + */ +static void internal_state_reset() +{ + m_module_initialized = false; +} + + +static void evt_send(pm_evt_t * p_gcm_evt) +{ + p_gcm_evt->peer_id = im_peer_id_get_by_conn_handle(p_gcm_evt->conn_handle); + + for (uint32_t i = 0; i < GCM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_gcm_evt); + } +} + + +/**@brief Function for checking a write event for whether a CCCD was written during the write + * operation. + * + * @param[in] p_write_evt The parameters of the write event. + * + * @return Whether the write was on a CCCD. + */ +static bool cccd_written(ble_gatts_evt_write_t const * p_write_evt) +{ + return ( (p_write_evt->op == BLE_GATTS_OP_WRITE_REQ) + && (p_write_evt->uuid.type == BLE_UUID_TYPE_BLE) + && (p_write_evt->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) + ); +} + + +/**@brief Function for sending an PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .conn_handle = conn_handle, + .params = + { + .error_unexpected = + { + .error = err_code, + } + } + }; + evt_send(&error_evt); +} + + +/**@brief Function for performing the local DB update procedure in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static void local_db_apply_in_evt(uint16_t conn_handle) +{ + bool set_procedure_as_pending = false; + ret_code_t err_code; + pm_evt_t event = + { + .conn_handle = conn_handle, + }; + + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + return; + } + + err_code = gscm_local_db_cache_apply(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLIED; + + evt_send(&event); + break; + + case NRF_ERROR_BUSY: + set_procedure_as_pending = true; + break; + + case NRF_ERROR_INVALID_DATA: + event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED; + + evt_send(&event); + break; + + case BLE_ERROR_INVALID_CONN_HANDLE: + /* Do nothing */ + break; + + default: + send_unexpected_error(conn_handle, err_code); + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_apply_pending, set_procedure_as_pending); +} + + +/**@brief Function for asynchronously starting a DB update procedure. + * + * @note This procedure can only be started asynchronously. + * + * @param[in] conn_handle The connection to perform the procedure on. + * @param[in] update Whether to perform the procedure. + */ +static __INLINE void local_db_update(uint16_t conn_handle, bool update) +{ + ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_update_pending, update); +} + + +/**@brief Function for performing the local DB update procedure in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static bool local_db_update_in_evt(uint16_t conn_handle) +{ + bool set_procedure_as_pending = false; + bool success = false; + ret_code_t err_code = gscm_local_db_cache_update(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + success = true; + break; + + case BLE_ERROR_INVALID_CONN_HANDLE: + /* Do nothing */ + break; + + case NRF_ERROR_BUSY: + set_procedure_as_pending = true; + break; + + case NRF_ERROR_STORAGE_FULL: + { + pm_evt_t event = + { + .evt_id = PM_EVT_STORAGE_FULL, + .conn_handle = conn_handle, + }; + + evt_send(&event); + break; + } + + default: + send_unexpected_error(conn_handle, err_code); + break; + } + + local_db_update(conn_handle, set_procedure_as_pending); + + return success; +} + + +/**@brief Function for sending a service changed indication in an event context, where no return + * code can be given. + * + * @details This function will do the procedure, and check the result, set a flag if needed, and + * send an event if needed. + * + * @param[in] conn_handle The connection to perform the procedure on. + */ +static void service_changed_send_in_evt(uint16_t conn_handle) +{ + bool sc_pending_state = true; + bool sc_sent_state = false; + ret_code_t err_code = gscm_service_changed_ind_send(conn_handle); + + switch (err_code) + { + case NRF_SUCCESS: + { + pm_evt_t event = + { + .evt_id = PM_EVT_SERVICE_CHANGED_IND_SENT, + .conn_handle = conn_handle, + }; + + sc_sent_state = true; + + evt_send(&event); + break; + } + + case NRF_ERROR_BUSY: + // Do nothing. + break; + + case NRF_ERROR_INVALID_STATE: + // CCCDs not enabled. Drop indication. + // Fallthrough. + + case NRF_ERROR_NOT_SUPPORTED: + // Service changed not supported. Drop indication. + sc_pending_state = false; + gscm_db_change_notification_done(im_peer_id_get_by_conn_handle(conn_handle)); + break; + + case BLE_ERROR_GATTS_SYS_ATTR_MISSING: + local_db_apply_in_evt(conn_handle); + break; + + case BLE_ERROR_INVALID_CONN_HANDLE: + // Do nothing. + break; + + default: + send_unexpected_error(conn_handle, err_code); + break; + } + + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, sc_pending_state); + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, sc_sent_state); +} + + +/**@brief Function for checking all flags for one id, and handling the ones that are set. + * + * @param[in] flag_id The flag id to check flags for. + */ +static void pending_flags_check(ble_conn_state_user_flag_id_t flag_id) +{ + // Quickly check if any flags are set. + if (sdk_mapped_flags_any_set(ble_conn_state_user_flag_collection(flag_id))) + { + sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); + + // Check each flag. + for (uint32_t i = 0; i < conn_handle_list.len; i++) + { + uint16_t conn_handle = conn_handle_list.flag_keys[i]; + if (ble_conn_state_user_flag_get(conn_handle, flag_id)) + { + // This flag is set. Handle depending on which flags we are checking. + if (flag_id == m_flag_local_db_apply_pending) + { + local_db_apply_in_evt(conn_handle); + } + else if (flag_id == m_flag_local_db_update_pending) + { + if (pm_mutex_lock(&m_db_update_in_progress_mutex, 0)) + { + if (local_db_update_in_evt(conn_handle)) + { + // Successfully started writing to flash. + return; + } + else + { + pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); + } + } + } + else if (flag_id == m_flag_service_changed_pending) + { + if (!ble_conn_state_user_flag_get(conn_handle, m_flag_service_changed_sent)) + { + service_changed_send_in_evt(conn_handle); + } + } + } + } + } +} + + +static __INLINE void apply_pending_flags_check(void) +{ + pending_flags_check(m_flag_local_db_apply_pending); +} + + +static __INLINE void update_pending_flags_check(void) +{ + pending_flags_check(m_flag_local_db_update_pending); +} + + +static __INLINE void service_changed_pending_flags_check(void) +{ + pending_flags_check(m_flag_service_changed_pending); +} + + +/**@brief Callback function for events from the ID Manager module. + * This function is registered in the ID Manager module. + * + * @param[in] p_event The event from the ID Manager module. + */ +void gcm_im_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + local_db_apply_in_evt(p_event->conn_handle); + if (gscm_service_changed_ind_needed(p_event->conn_handle)) + { + ble_conn_state_user_flag_set(p_event->conn_handle, m_flag_service_changed_pending, true); + } + break; + default: + break; + } +} + + +/**@brief Callback function for events from the Peer Database module. + * This handler is extern in Peer Database. + * + * @param[in] p_event The event from the Security Dispatcher module. + */ +void gcm_pdb_evt_handler(pm_evt_t * p_event) +{ + if ( p_event->evt_id == PM_EVT_PEER_DATA_UPDATE_SUCCEEDED + && p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + switch (p_event->params.peer_data_update_succeeded.data_id) + { + case PM_PEER_DATA_ID_BONDING: + { + uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); + + if (conn_handle != BLE_CONN_HANDLE_INVALID) + { + local_db_update(conn_handle, true); + } + break; + } + + case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: + { + ret_code_t err_code; + pm_peer_data_flash_t peer_data; + + err_code = pdb_peer_data_ptr_get(p_event->peer_id, + PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + &peer_data); + + if (err_code == NRF_SUCCESS) + { + if (*peer_data.p_service_changed_pending) + { + uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); + if (conn_handle != BLE_CONN_HANDLE_INVALID) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, true); + service_changed_pending_flags_check(); + } + } + } + break; + } + + case PM_PEER_DATA_ID_GATT_LOCAL: + pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); + // Expecting a call to update_pending_flags_check() immediately. + break; + + default: + /* No action */ + break; + } + } + + update_pending_flags_check(); +} + + +ret_code_t gcm_init() +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + + m_flag_local_db_update_pending = ble_conn_state_user_flag_acquire(); + m_flag_local_db_apply_pending = ble_conn_state_user_flag_acquire(); + m_flag_service_changed_pending = ble_conn_state_user_flag_acquire(); + m_flag_service_changed_sent = ble_conn_state_user_flag_acquire(); + + if ((m_flag_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID) + || (m_flag_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID)) + { + return NRF_ERROR_INTERNAL; + } + + pm_mutex_init(&m_db_update_in_progress_mutex, 1); + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +/**@brief Callback function for BLE events from the SoftDevice. + * + * @param[in] p_ble_evt The BLE event from the SoftDevice. + */ +void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + local_db_apply_in_evt(conn_handle); + break; + + case BLE_GATTS_EVT_SC_CONFIRM: + { + pm_evt_t event = + { + .evt_id = PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, + .peer_id = im_peer_id_get_by_conn_handle(conn_handle), + .conn_handle = conn_handle, + }; + + gscm_db_change_notification_done(event.peer_id); + + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, false); + ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, false); + evt_send(&event); + break; + } + + case BLE_GATTS_EVT_WRITE: + if (cccd_written(&p_ble_evt->evt.gatts_evt.params.write)) + { + local_db_update(conn_handle, true); + update_pending_flags_check(); + } + break; + } + + apply_pending_flags_check(); + service_changed_pending_flags_check(); +} + + +ret_code_t gcm_local_db_cache_update(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + local_db_update(conn_handle, true); + update_pending_flags_check(); + + return NRF_SUCCESS; +} + + +void gcm_local_database_has_changed(void) +{ + gscm_local_database_has_changed(); + + sdk_mapped_flags_key_list_t conn_handles = ble_conn_state_conn_handles(); + + for (uint16_t i = 0; i < conn_handles.len; i++) + { + if (im_peer_id_get_by_conn_handle(conn_handles.flag_keys[i]) == PM_PEER_ID_INVALID) + { + ble_conn_state_user_flag_set(conn_handles.flag_keys[i], m_flag_service_changed_pending, true); + } + } + + service_changed_pending_flags_check(); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h new file mode 100644 index 0000000000..5ea1bcde1c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 GATT_CACHE_MANAGER_H__ +#define GATT_CACHE_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * @cond NO_DOXYGEN + * @defgroup gatt_cache_manager GATT Cache Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT + * attributes. + */ + + +/**@brief Function for initializing the GATT Cache Manager module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t gcm_init(void); + + +/**@brief Function for dispatching SoftDevice events to the GATT Cache Manager module. + * + * @param[in] p_ble_evt The SoftDevice event. + */ +void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt); + + +/**@brief Function for triggering local GATT database data to be stored persistently. + * + * @details Values are retrieved from SoftDevice and written to persistent storage. + * + * @note This operation happens asynchronously, so any errors are reported as events. + * + * @note This function is only needed when you want to override the regular functionality of the + * module, e.g. to immediately store to flash instead of waiting for the native logic to + * perform the update. + * + * @param[in] conn_handle Connection handle to perform update on. + * + * @retval NRF_SUCCESS Store operation started. + */ +ret_code_t gcm_local_db_cache_update(uint16_t conn_handle); + + +/**@brief Function for manually informing that the local database has changed. + * + * @details This causes a service changed notification to be sent to all bonded peers that + * subscribe to it. + */ +void gcm_local_database_has_changed(void); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* GATT_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c new file mode 100644 index 0000000000..b2d2aa6f52 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c @@ -0,0 +1,340 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "gatts_cache_manager.h" + +#include +#include "ble_gap.h" +#include "ble_err.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_database.h" +#include "id_manager.h" + + +// Syntactic sugar, two spoons. +#define SYS_ATTR_SYS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS) +#define SYS_ATTR_USR (BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS) +#define SYS_ATTR_BOTH (SYS_ATTR_SYS | SYS_ATTR_USR) + +static bool m_module_initialized; +static pm_peer_id_t m_current_sc_store_peer_id; + + +/**@brief Function for resetting the module variable(s) of the GSCM module. + */ +static void internal_state_reset() +{ + m_module_initialized = false; + m_current_sc_store_peer_id = PM_PEER_ID_INVALID; +} + + +//lint -save -e550 +/**@brief Function for storing service_changed_pending = true to flash for all peers, in sequence. + * + * This function aborts if it gets @ref NRF_ERROR_BUSY when trying to store. A subsequent call will + * continue where the last call was aborted. + */ +static void service_changed_pending_set(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + ret_code_t err_code; + // Use a uint32_t to enforce 4-byte alignment. + static const uint32_t service_changed_pending = true; + + //lint -save -e65 -e64 + pm_peer_data_const_t peer_data = + { + .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + .length_words = PM_SC_STATE_N_WORDS(), + .p_service_changed_pending = (bool*)&service_changed_pending, + }; + //lint -restore + + err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); + while ((m_current_sc_store_peer_id != PM_PEER_ID_INVALID) && (err_code != NRF_ERROR_BUSY)) + { + m_current_sc_store_peer_id = pdb_next_peer_id_get(m_current_sc_store_peer_id); + err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); + } +} +//lint -restore + + + +/**@brief Event handler for events from the Peer Database module. + * This function is extern in Peer Database. + * + * @param[in] p_event The event that has happend with peer id and flags. + */ +void gscm_pdb_evt_handler(pm_evt_t * p_event) +{ + if (m_current_sc_store_peer_id != PM_PEER_ID_INVALID) + { + service_changed_pending_set(); + } +} + + +ret_code_t gscm_init() +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t gscm_local_db_cache_update(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + ret_code_t err_code; + + if (peer_id == PM_PEER_ID_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + else + { + pm_peer_data_t peer_data; + uint16_t n_bufs = 1; + bool retry_with_bigger_buffer = false; + + do + { + retry_with_bigger_buffer = false; + + err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, n_bufs++, &peer_data); + if (err_code == NRF_SUCCESS) + { + pm_peer_data_local_gatt_db_t * p_local_gatt_db = peer_data.p_local_gatt_db; + + p_local_gatt_db->flags = SYS_ATTR_BOTH; + + err_code = sd_ble_gatts_sys_attr_get(conn_handle, &p_local_gatt_db->data[0], &p_local_gatt_db->len, p_local_gatt_db->flags); + + if (err_code == NRF_SUCCESS) + { + err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, peer_id); + } + else + { + if (err_code == NRF_ERROR_DATA_SIZE) + { + // The sys attributes are bigger than the requested write buffer. + retry_with_bigger_buffer = true; + } + else if (err_code == NRF_ERROR_NOT_FOUND) + { + // There are no sys attributes in the GATT db, so nothing needs to be stored. + err_code = NRF_SUCCESS; + } + + ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL); + if (err_code_release != NRF_SUCCESS) + { + err_code = NRF_ERROR_INTERNAL; + } + } + } + else if (err_code == NRF_ERROR_INVALID_PARAM) + { + // The sys attributes are bigger than the entire write buffer. + err_code = NRF_ERROR_DATA_SIZE; + } + } while (retry_with_bigger_buffer); + } + + return err_code; +} + + +ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + ret_code_t err_code; + pm_peer_data_flash_t peer_data; + uint8_t const * p_sys_attr_data = NULL; + uint16_t sys_attr_len = 0; + uint32_t sys_attr_flags = (SYS_ATTR_BOTH); + bool all_attributes_applied = true; + + if (peer_id != PM_PEER_ID_INVALID) + { + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data); + if (err_code == NRF_SUCCESS) + { + pm_peer_data_local_gatt_db_t const * p_local_gatt_db; + + p_local_gatt_db = peer_data.p_local_gatt_db; + p_sys_attr_data = p_local_gatt_db->data; + sys_attr_len = p_local_gatt_db->len; + sys_attr_flags = p_local_gatt_db->flags; + } + } + + do + { + err_code = sd_ble_gatts_sys_attr_set(conn_handle, p_sys_attr_data, sys_attr_len, sys_attr_flags); + + if (err_code == NRF_ERROR_NO_MEM) + { + err_code = NRF_ERROR_BUSY; + } + else if (err_code == NRF_ERROR_INVALID_STATE) + { + err_code = NRF_SUCCESS; + } + else if (err_code == NRF_ERROR_INVALID_DATA) + { + all_attributes_applied = false; + + if (sys_attr_flags & SYS_ATTR_USR) + { + // Try setting only system attributes. + sys_attr_flags = SYS_ATTR_SYS; + } + else if (p_sys_attr_data || sys_attr_len) + { + // Try reporting that none exist. + p_sys_attr_data = NULL; + sys_attr_len = 0; + sys_attr_flags = SYS_ATTR_BOTH; + } + else + { + err_code = NRF_ERROR_INTERNAL; + } + } + } while (err_code == NRF_ERROR_INVALID_DATA); + + if (!all_attributes_applied) + { + err_code = NRF_ERROR_INVALID_DATA; + } + + return err_code; +} + +void gscm_local_database_has_changed(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + m_current_sc_store_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); + service_changed_pending_set(); +} + + +bool gscm_service_changed_ind_needed(uint16_t conn_handle) +{ + ret_code_t err_code; + bool service_changed_state; + pm_peer_data_flash_t peer_data; + + peer_data.p_service_changed_pending = &service_changed_state; + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data); + + if (err_code != NRF_SUCCESS) + { + return false; + } + + return *peer_data.p_service_changed_pending; +} + + +ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle) +{ + static uint16_t start_handle; + const uint16_t end_handle = 0xFFFF; + ret_code_t err_code; + + err_code = sd_ble_gatts_initial_user_handle_get(&start_handle); + + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + do + { + err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle); + if (err_code == BLE_ERROR_INVALID_ATTR_HANDLE) + { + start_handle += 1; + } + } while (err_code == BLE_ERROR_INVALID_ATTR_HANDLE); + + return err_code; +} + + +void gscm_db_change_notification_done(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + // Use a uint32_t to enforce 4-byte alignment. + static const uint32_t service_changed_pending = false; + + //lint -save -e65 -e64 + pm_peer_data_const_t peer_data = + { + .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, + .length_words = PM_SC_STATE_N_WORDS(), + .p_service_changed_pending = (bool*)&service_changed_pending, + }; + //lint -restore + + // Don't need to check return code, because all error conditions can be ignored. + //lint -save -e550 + (void) pdb_raw_store(peer_id, &peer_data, NULL); + //lint -restore +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h new file mode 100644 index 0000000000..a463344d28 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 GATTS_CACHE_MANAGER_H__ +#define GATTS_CACHE_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * @cond NO_DOXYGEN + * @defgroup gatts_cache_manager GATT Server Cache Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT + * attributes pertaining to the GATT server role of the local device. + */ + + +/**@brief Function for initializing the GATT Server Cache Manager module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t gscm_init(void); + + +/**@brief Function for triggering local GATT database data to be stored persistently. Values are + * retrieved from the SoftDevice and written to persistent storage. + * + * @param[in] conn_handle Connection handle to perform update on. + * + * @retval NRF_SUCCESS Store operation started. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a + * bonded peer. + * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. + * @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with + * this GATT database. + * @retval NRF_ERROR_STORAGE_FULL No room in persistent_storage. Free up space; the + * operation will be automatically reattempted after the + * next FDS garbage collection procedure. + */ +ret_code_t gscm_local_db_cache_update(uint16_t conn_handle); + + +/**@brief Function for applying stored local GATT database data to the SoftDevice. Values are + * retrieved from persistent storage and given to the SoftDevice. + * + * @param[in] conn_handle Connection handle to apply values to. + * + * @retval NRF_SUCCESS Store operation started. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a + * bonded peer. + * @retval NRF_ERROR_INVALID_DATA The stored data was rejected by the SoftDevice, which + * probably means that the local database has changed. The + * system part of the sys_attributes was attempted applied, + * so service changed indications can be sent to subscribers. + * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. + * @return An unexpected return value from an internal function call. + */ +ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle); + + +/**@brief Function for storing the fact that the local database has changed, for all currently + * bonded peers. + * + * @note This will cause a later call to @ref gscm_service_changed_ind_needed to return true for + * a connection with a currently bonded peer. + */ +void gscm_local_database_has_changed(void); + + +/**@brief Function for checking if a service changed indication should be sent. + * + * @param[in] conn_handle The connection to check. + * + * @return true if a service changed indication should be sent, false if not. + */ +bool gscm_service_changed_ind_needed(uint16_t conn_handle); + + +/**@brief Function for sending a service changed indication to a connected peer. + * + * @param[in] conn_handle The connection to send the indication on. + * + * @retval NRF_SUCCESS Indication sent or not needed. + * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection. + * @retval NRF_ERROR_BUSY Unable to send indication at this time. Reattempt later. + * @retval BLE_ERROR_GATTS_SYS_ATTR_MISSING Information missing. Apply local cache, then reattempt. + * @retval NRF_ERROR_INVALID_PARAM From @ref sd_ble_gatts_service_changed. Unexpected. + * @retval NRF_ERROR_NOT_SUPPORTED Service changed characteristic is not present. + * @retval NRF_ERROR_INVALID_STATE Service changed cannot be indicated to this peer + * because the peer has not subscribed to it. + * @retval NRF_ERROR_INTERNAL An unexpected error happened. + */ +ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle); + + +/**@brief Function for specifying that a peer has been made aware of the latest local database + * change. + * + * @note After calling this, a later call to @ref gscm_service_changed_ind_needed will to return + * false for this peer unless @ref gscm_local_database_has_changed is called again. + * + * @param[in] peer_id The connection to send the indication on. + */ +void gscm_db_change_notification_done(pm_peer_id_t peer_id); + +/** @} + * @endcond +*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* GATTS_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c new file mode 100644 index 0000000000..dd1b5c0bd9 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c @@ -0,0 +1,1065 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "id_manager.h" + +#include +#include "nrf_ble.h" +#include "ble_gap.h" +#include "ble_err.h" +#include "ble_conn_state.h" +#include "peer_manager_types.h" +#include "peer_database.h" +#include "peer_data_storage.h" +#include "nrf_soc.h" + + +#define IM_MAX_CONN_HANDLES (20) +#define IM_NO_INVALID_CONN_HANDLES (0xFF) +#define IM_ADDR_CLEARTEXT_LENGTH (3) +#define IM_ADDR_CIPHERTEXT_LENGTH (3) + +// The number of registered event handlers. +#define IM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Identity Manager event handlers in Peer Manager and GATT Cache Manager. +extern void pm_im_evt_handler(pm_evt_t * p_event); +extern void gcm_im_evt_handler(pm_evt_t * p_event); + +// Identity Manager events' handlers. +// The number of elements in this array is IM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_im_evt_handler, + gcm_im_evt_handler +}; + + +typedef struct +{ + pm_peer_id_t peer_id; + uint16_t conn_handle; + ble_gap_addr_t peer_address; +} im_connection_t; + +static bool m_module_initialized; +static im_connection_t m_connections[IM_MAX_CONN_HANDLES]; +static ble_conn_state_user_flag_id_t m_conn_state_user_flag_id; + +static uint8_t m_wlisted_peer_cnt; +static pm_peer_id_t m_wlisted_peers[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + +#if (NRF_SD_BLE_API_VERSION <= 2) + static ble_gap_addr_t m_current_id_addr; +#endif + + +static void internal_state_reset() +{ + m_conn_state_user_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; + + for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) + { + m_connections[i].conn_handle = BLE_CONN_HANDLE_INVALID; + } +} + + +/**@brief Function for sending an event to all registered event handlers. + * + * @param[in] p_event The event to distribute. + */ +static void evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < IM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + +/**@brief Function finding a free position in m_connections. + * + * @detail All connection handles in the m_connections array are checked against the connection + * state module. The index of the first one that is not a connection handle for a current + * connection is returned. This position in the array can safely be used for a new connection. + * + * @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free + position exists. + */ +uint8_t get_free_connection() +{ + for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) + { + // Query the connection state module to check if the + // connection handle does not belong to a valid connection. + if (!ble_conn_state_user_flag_get(m_connections[i].conn_handle, m_conn_state_user_flag_id)) + { + return i; + } + } + // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. + return IM_NO_INVALID_CONN_HANDLES; +} + + +/**@brief Function finding a particular connection handle m_connections. + * + * @param[in] conn_handle The handle to find. + * + * @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the + * handle was not found. + */ +uint8_t get_connection_by_conn_handle(uint16_t conn_handle) +{ + if (ble_conn_state_user_flag_get(conn_handle, m_conn_state_user_flag_id)) + { + for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) + { + if (m_connections[i].conn_handle == conn_handle) + { + return i; + } + } + } + // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. + return IM_NO_INVALID_CONN_HANDLES; +} + + +/**@brief Function for registering a new connection instance. + * + * @param[in] conn_handle The handle of the new connection. + * @param[in] p_ble_addr The address used to connect. + * + * @return Either the index of the new connection in the array or IM_NO_INVALID_CONN_HANDLES if no + * free position exists. + */ +uint8_t new_connection(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) +{ + uint8_t conn_index = IM_NO_INVALID_CONN_HANDLES; + + if ((p_ble_addr != NULL) && (conn_handle != BLE_CONN_HANDLE_INVALID)) + { + ble_conn_state_user_flag_set(conn_handle, m_conn_state_user_flag_id, true); + + conn_index = get_connection_by_conn_handle(conn_handle); + if (conn_index == IM_NO_INVALID_CONN_HANDLES) + { + conn_index = get_free_connection(); + } + + if (conn_index != IM_NO_INVALID_CONN_HANDLES) + { + m_connections[conn_index].conn_handle = conn_handle; + m_connections[conn_index].peer_id = PM_PEER_ID_INVALID; + m_connections[conn_index].peer_address = *p_ble_addr; + } + } + return conn_index; +} + + +/**@brief Function checking the validity of an IRK + * + * @detail An all-zero IRK is not valid. This function will check if a given IRK is valid. + * + * @param[in] p_irk The IRK for which the validity is going to be checked. + * + * @retval true The IRK is valid. + * @retval false The IRK is invalid. + */ +bool is_valid_irk(ble_gap_irk_t const * p_irk) +{ + NRF_PM_DEBUG_CHECK(p_irk != NULL); + + for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++) + { + if (p_irk->irk[i] != 0) + { + return true; + } + } + return false; +} + + +/**@brief Function for comparing two addresses to determine if they are identical + * + * @note The address type need to be identical, as well as every bit in the address itself. + * + * @param[in] p_addr1 The first address to be compared. + * @param[in] p_addr2 The second address to be compared. + * + * @retval true The addresses are identical. + * @retval false The addresses are not identical. + */ +bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2) +{ + // @note emdi: use NRF_PM_DEBUG_CHECK ? + if ((p_addr1 == NULL) || (p_addr2 == NULL)) + { + return false; + } + + // Check that the addr type is identical, return false if it is not + if (p_addr1->addr_type != p_addr2->addr_type) + { + return false; + } + + // Check if the addr bytes are is identical + return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0); +} + + +void im_ble_evt_handler(ble_evt_t const * ble_evt) +{ + ble_gap_evt_t gap_evt; + pm_peer_id_t bonded_matching_peer_id; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + if (ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) + { + // Nothing to do. + return; + } + + gap_evt = ble_evt->evt.gap_evt; + bonded_matching_peer_id = PM_PEER_ID_INVALID; + + if ( gap_evt.params.connected.peer_addr.addr_type + != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + { + /* Search the database for bonding data matching the one that triggered the event. + * Public and static addresses can be matched on address alone, while resolvable + * random addresses can be resolved agains known IRKs. Non-resolvable random addresses + * are never matching because they are not longterm form of identification. + */ + + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + pds_peer_data_iterate_prepare(); + + switch (gap_evt.params.connected.peer_addr.addr_type) + { + case BLE_GAP_ADDR_TYPE_PUBLIC: + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + { + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (addr_compare(&gap_evt.params.connected.peer_addr, + &peer_data.p_bonding_data->peer_ble_id.id_addr_info)) + { + bonded_matching_peer_id = peer_id; + break; + } + } + } + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: + { + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_address_resolve(&gap_evt.params.connected.peer_addr, + &peer_data.p_bonding_data->peer_ble_id.id_info)) + { + bonded_matching_peer_id = peer_id; + break; + } + } + } + break; + + default: + NRF_PM_DEBUG_CHECK(false); + break; + } + } + + uint8_t new_index = new_connection(gap_evt.conn_handle, + &gap_evt.params.connected.peer_addr); + UNUSED_VARIABLE(new_index); + + if (bonded_matching_peer_id != PM_PEER_ID_INVALID) + { + im_new_peer_id(gap_evt.conn_handle, bonded_matching_peer_id); + + // Send a bonded peer event + pm_evt_t im_evt; + im_evt.conn_handle = gap_evt.conn_handle; + im_evt.peer_id = bonded_matching_peer_id; + im_evt.evt_id = PM_EVT_BONDED_PEER_CONNECTED; + evt_send(&im_evt); + } +} + + +/**@brief Function to compare two sets of bonding data to check if they belong to the same device. + * @note Invalid irks will never match even though they are identical. + * + * @param[in] p_bonding_data1 First bonding data for comparison + * @param[in] p_bonding_data2 Second bonding data for comparison + * + * @return True if the input matches, false if it does not. + */ +bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, + pm_peer_data_bonding_t const * p_bonding_data2) +{ + NRF_PM_DEBUG_CHECK(p_bonding_data1 != NULL); + NRF_PM_DEBUG_CHECK(p_bonding_data2 != NULL); + + ble_gap_addr_t const * p_addr1 = &p_bonding_data1->peer_ble_id.id_addr_info; + ble_gap_addr_t const * p_addr2 = &p_bonding_data2->peer_ble_id.id_addr_info; + + bool duplicate_irk = ((memcmp(p_bonding_data1->peer_ble_id.id_info.irk, + p_bonding_data2->peer_ble_id.id_info.irk, + BLE_GAP_SEC_KEY_LEN) == 0) + && is_valid_irk(&p_bonding_data1->peer_ble_id.id_info) + && is_valid_irk(&p_bonding_data2->peer_ble_id.id_info)); + + bool duplicate_addr = addr_compare(p_addr1, p_addr2); + + bool id_addrs = ((p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + && (p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)); + + return (duplicate_addr && id_addrs) || (duplicate_irk && !id_addrs); +} + + +pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, + pm_peer_id_t peer_id_skip) +{ + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data_duplicate; + + NRF_PM_DEBUG_CHECK(p_bonding_data != NULL); + + pds_peer_data_iterate_prepare(); + + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data_duplicate)) + { + if ( (peer_id != peer_id_skip) + && im_is_duplicate_bonding_data(p_bonding_data, + peer_data_duplicate.p_bonding_data)) + { + return peer_id; + } + } + return PM_PEER_ID_INVALID; +} + + +ret_code_t im_init(void) +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + + m_conn_state_user_flag_id = ble_conn_state_user_flag_acquire(); + if (m_conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + return NRF_ERROR_INTERNAL; + } + + #if (NRF_SD_BLE_API_VERSION <= 2) + ret_code_t ret_code = sd_ble_gap_address_get(&m_current_id_addr); + if (ret_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + #endif + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle) +{ + uint8_t conn_index; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + conn_index = get_connection_by_conn_handle(conn_handle); + + if (conn_index != IM_NO_INVALID_CONN_HANDLES) + { + return m_connections[conn_index].peer_id; + } + + return PM_PEER_ID_INVALID; +} + + +ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) +{ + uint8_t conn_index; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_ble_addr != NULL); + + conn_index = get_connection_by_conn_handle(conn_handle); + + if (conn_index != IM_NO_INVALID_CONN_HANDLES) + { + *p_ble_addr = m_connections[conn_index].peer_address; + return NRF_SUCCESS; + } + + return NRF_ERROR_NOT_FOUND; +} + + +bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, + ble_gap_master_id_t const * p_master_id2) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_master_id1 != NULL); + NRF_PM_DEBUG_CHECK(p_master_id2 != NULL); + + if (!im_master_id_is_valid(p_master_id1)) + { + return false; + } + + if (p_master_id1->ediv != p_master_id2->ediv) + { + return false; + } + + return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0); +} + + +pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id) +{ + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_master_id != NULL); + + pds_peer_data_iterate_prepare(); + + // For each stored peer, check if the master_id matches p_master_id + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->own_ltk.master_id) || + im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->peer_ltk.master_id)) + { + // If a matching master ID is found then return the peer ID. + return peer_id; + } + } + + // If no matching master ID is found return PM_PEER_ID_INVALID. + return PM_PEER_ID_INVALID; +} + + +uint16_t im_conn_handle_get(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) + { + if (peer_id == m_connections[i].peer_id) + { + return m_connections[i].conn_handle; + } + } + return BLE_CONN_HANDLE_INVALID; +} + + +bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + if (p_master_id->ediv != 0) + { + return true; + } + + for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++) + { + if (p_master_id->rand[i] != 0) + { + return true; + } + } + return false; +} + + +/**@brief Function to set the peer ID associated with a connection handle. + * + * @param[in] conn_handle The connection handle. + * @param[in] peer_id The peer ID to associate with @c conn_handle. + */ +static void peer_id_set(uint16_t conn_handle, pm_peer_id_t peer_id) +{ + uint8_t conn_index = get_connection_by_conn_handle(conn_handle); + if (conn_index != IM_NO_INVALID_CONN_HANDLES) + { + m_connections[conn_index].peer_id = peer_id; + } +} + + +void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + peer_id_set(conn_handle, peer_id); +} + + +ret_code_t im_peer_free(pm_peer_id_t peer_id) +{ + uint16_t conn_handle; + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + conn_handle = im_conn_handle_get(peer_id); + ret = pdb_peer_free(peer_id); + + if ((conn_handle != BLE_CONN_HANDLE_INVALID) && (ret == NRF_SUCCESS)) + { + peer_id_set(conn_handle, PM_PEER_ID_INVALID); + } + return ret; +} + + +/**@brief Given a list of peers, loads their GAP address and IRK into the provided buffers. + */ +static ret_code_t peers_id_keys_get(pm_peer_id_t const * p_peers, + uint32_t peer_cnt, + ble_gap_addr_t * p_gap_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_gap_irks, + uint32_t * p_irk_cnt) +{ + ret_code_t ret; + + pm_peer_data_bonding_t bond_data; + pm_peer_data_t peer_data; + + uint32_t const buf_size = sizeof(bond_data); + + bool copy_addrs = false; + bool copy_irks = false; + + NRF_PM_DEBUG_CHECK(p_peers != NULL); + + // One of these two has to be provided. + NRF_PM_DEBUG_CHECK((p_gap_addrs != NULL) || (p_gap_irks != NULL)); + + if ((p_gap_addrs != NULL) && (p_addr_cnt != NULL)) + { + NRF_PM_DEBUG_CHECK((*p_addr_cnt) >= peer_cnt); + + copy_addrs = true; + *p_addr_cnt = 0; + } + + if ((p_gap_irks != NULL) && (p_irk_cnt != NULL)) + { + NRF_PM_DEBUG_CHECK((*p_irk_cnt) >= peer_cnt); + + copy_irks = true; + *p_irk_cnt = 0; + } + + memset(&peer_data, 0x00, sizeof(peer_data)); + peer_data.p_bonding_data = &bond_data; + + // Read through flash memory and look for peers ID keys. + + for (uint32_t i = 0; i < peer_cnt; i++) + { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, + &peer_data, &buf_size); + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) + { + // Peer data coulnd't be found in flash or peer ID is not valid. + return NRF_ERROR_NOT_FOUND; + } + + uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; + + if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && + (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) + { + // The address shared by the peer during bonding can't be used for whitelisting. + return BLE_ERROR_GAP_INVALID_BLE_ADDR; + } + + // Copy the GAP address. + if (copy_addrs) + { + memcpy(&p_gap_addrs[i], &bond_data.peer_ble_id.id_addr_info, sizeof(ble_gap_addr_t)); + (*p_addr_cnt)++; + } + + // Copy the IRK. + if (copy_irks) + { + memcpy(&p_gap_irks[i], bond_data.peer_ble_id.id_info.irk, BLE_GAP_SEC_KEY_LEN); + (*p_irk_cnt)++; + } + } + + return NRF_SUCCESS; +} + + +ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + #if (NRF_SD_BLE_API_VERSION >= 3) + + ret_code_t ret; + pm_peer_data_t peer_data; + pm_peer_data_bonding_t bond_data; + + ble_gap_id_key_t keys[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + ble_gap_id_key_t const * key_ptrs[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + + if ((p_peers == NULL) || (peer_cnt == 0)) + { + // Clear the device identities list. + return sd_ble_gap_device_identities_set(NULL, NULL, 0); + } + + peer_data.p_bonding_data = &bond_data; + uint32_t const buf_size = sizeof(bond_data); + + memset(keys, 0x00, sizeof(keys)); + for (uint32_t i = 0; i < BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; i++) + { + key_ptrs[i] = &keys[i]; + } + + for (uint32_t i = 0; i < peer_cnt; i++) + { + memset(&bond_data, 0x00, sizeof(bond_data)); + + // Read peer data from flash. + ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, + &peer_data, &buf_size); + + if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) + { + // Peer data coulnd't be found in flash or peer ID is not valid. + return NRF_ERROR_NOT_FOUND; + } + + uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; + + if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && + (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) + { + // The address shared by the peer during bonding can't be whitelisted. + return BLE_ERROR_GAP_INVALID_BLE_ADDR; + } + + // Copy data to the buffer. + memcpy(&keys[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); + } + + return sd_ble_gap_device_identities_set(key_ptrs, NULL, peer_cnt); + + #else + + return NRF_ERROR_NOT_SUPPORTED; + + #endif +} + + +#if (NRF_SD_BLE_API_VERSION <= 2) + +static ret_code_t address_set_v2(uint8_t cycle_mode, ble_gap_addr_t * p_addr) +{ + NRF_PM_DEBUG_CHECK(p_addr != NULL); + + ret_code_t ret = sd_ble_gap_address_set(cycle_mode, p_addr); + + switch (ret) + { + case NRF_SUCCESS: + case NRF_ERROR_BUSY: + case NRF_ERROR_INVALID_STATE: + case NRF_ERROR_INVALID_PARAM: // If cycle_mode is not AUTO or NONE. + case BLE_ERROR_GAP_INVALID_BLE_ADDR: // If the GAP address is not valid. + return ret; + + default: + return NRF_ERROR_INTERNAL; + } +} + +#endif + + +ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr) +{ + #if (NRF_SD_BLE_API_VERSION <= 2) + + ret_code_t ret; + ble_gap_addr_t current_addr; + + NRF_PM_DEBUG_CHECK(p_addr != NULL); + + (void) sd_ble_gap_address_get(¤t_addr); + + ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, (ble_gap_addr_t *)p_addr); + if (ret != NRF_SUCCESS) + { + return ret; + } + + if ( current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + || current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + { + // If currently using privacy, it must be re-enabled. + // We force AUTO when privacy is enabled. + ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, ¤t_addr); + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + memcpy(&m_current_id_addr, p_addr, sizeof(ble_gap_addr_t)); + + return NRF_SUCCESS; + + #else + + return sd_ble_gap_addr_set(p_addr); + + #endif +} + + +ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr) +{ + NRF_PM_DEBUG_CHECK(p_addr != NULL); + + #if (NRF_SD_BLE_API_VERSION <= 2) + memcpy(p_addr, &m_current_id_addr, sizeof(ble_gap_addr_t)); + return NRF_SUCCESS; + #else + return sd_ble_gap_addr_get(p_addr); + #endif +} + + +ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params) +{ + #if (NRF_SD_BLE_API_VERSION <= 2) + + ret_code_t ret; + ble_gap_addr_t privacy_addr; + ble_gap_irk_t current_irk; + ble_opt_t privacy_options; + ble_opt_t current_privacy_options; + + NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); + + privacy_addr.addr_type = p_privacy_params->private_addr_type; + privacy_options.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; + privacy_options.gap_opt.privacy.interval_s = p_privacy_params->private_addr_cycle_s; + current_privacy_options.gap_opt.privacy.p_irk = ¤t_irk; + + // Can not fail. + (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); + (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_options); + + if (p_privacy_params->privacy_mode == BLE_GAP_PRIVACY_MODE_OFF) + { + ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, &m_current_id_addr); + } + else + { + ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &privacy_addr); + } + + if (ret != NRF_SUCCESS) + { + // Restore previous settings. + (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); + } + + // NRF_ERROR_BUSY, + // NRF_ERROR_INVALID_STATE, + // NRF_ERROR_INVALID_PARAM, if address type is not valid. + return ret; + + #else + + return sd_ble_gap_privacy_set(p_privacy_params); + + #endif +} + + +ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params) +{ + #if (NRF_SD_BLE_API_VERSION <= 2) + + ble_gap_addr_t cur_addr; + ble_opt_t cur_privacy_opt; + + NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); + NRF_PM_DEBUG_CHECK(p_privacy_params->p_device_irk != NULL); + + cur_privacy_opt.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; + + // Can not fail. + (void) sd_ble_gap_address_get(&cur_addr); + + if ( cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + || cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) + { + p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; + p_privacy_params->private_addr_type = cur_addr.addr_type; + } + else + { + p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; + } + + // Can not fail. + (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &cur_privacy_opt); + + p_privacy_params->private_addr_cycle_s = cur_privacy_opt.gap_opt.privacy.interval_s; + + return NRF_SUCCESS; + + #else + + return sd_ble_gap_privacy_get(p_privacy_params); + + #endif +} + + +/* Create a whitelist for the user using the cached list of peers. + * This whitelist is meant to be provided by the application to the Advertising module. + */ +ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt) +{ + // One of the two buffers has to be provided. + NRF_PM_DEBUG_CHECK((p_addrs != NULL) || (p_irks != NULL)); + NRF_PM_DEBUG_CHECK((p_addr_cnt != NULL) || (p_irk_cnt != NULL)); + + if (((p_addr_cnt != NULL) && (m_wlisted_peer_cnt > *p_addr_cnt)) || + ((p_irk_cnt != NULL) && (m_wlisted_peer_cnt > *p_irk_cnt))) + { + // The size of the cached list of peers is larger than the provided buffers. + return NRF_ERROR_NO_MEM; + } + + // NRF_SUCCESS or + // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. + // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. + return peers_id_keys_get(m_wlisted_peers, m_wlisted_peer_cnt, + p_addrs, p_addr_cnt, + p_irks, p_irk_cnt); +} + + +/* Copies the peers to whitelist into a local cache. + * The cached list will be used by im_whitelist_get() to retrieve the active whitelist. + * For SoftDevices 3x, also loads the peers' GAP addresses and whitelists them using + * sd_ble_gap_whitelist_set(). + */ +ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + // Clear the cache of whitelisted peers. + memset(m_wlisted_peers, 0x00, sizeof(m_wlisted_peers)); + + if ((p_peers == NULL) || (peer_cnt == 0)) + { + // Clear the current whitelist. + m_wlisted_peer_cnt = 0; + #if (NRF_SD_BLE_API_VERSION >= 3) + // NRF_SUCCESS, or + // BLE_GAP_ERROR_WHITELIST_IN_USE + return sd_ble_gap_whitelist_set(NULL, 0); + #else + // The cached list of whitelisted peers is already cleared; nothing to do. + return NRF_SUCCESS; + #endif + } + + // @todo emdi: should not ever cache more than BLE_GAP_WHITELIST_ADDR_MAX_COUNT... + + // Copy the new whitelisted peers. + m_wlisted_peer_cnt = peer_cnt; + memcpy(m_wlisted_peers, p_peers, sizeof(pm_peer_id_t) * peer_cnt); + + #if (NRF_SD_BLE_API_VERSION >= 3) + + ret_code_t ret; + uint32_t wlist_addr_cnt = 0; + + ble_gap_addr_t const * addr_ptrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_addr_t addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + + memset(addrs, 0x00, sizeof(addrs)); + + // Fetch GAP addresses for these peers, but don't fetch IRKs. + ret = peers_id_keys_get(p_peers, peer_cnt, addrs, &wlist_addr_cnt, NULL, NULL); + + if (ret != NRF_SUCCESS) + { + // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. + // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. + return ret; + } + + for (uint32_t i = 0; i < BLE_GAP_WHITELIST_ADDR_MAX_COUNT; i++) + { + addr_ptrs[i] = &addrs[i]; + } + + // NRF_ERROR_DATA_SIZE, if peer_cnt > BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + // BLE_ERROR_GAP_WHITELIST_IN_USE, if a whitelist is in use. + return sd_ble_gap_whitelist_set(addr_ptrs, peer_cnt); + + #else + + return NRF_SUCCESS; + + #endif +} + + +/**@brief Function for calculating the ah() hash function described in Bluetooth core specification + * 4.2 section 3.H.2.2.2. + * + * @detail BLE uses a hash function to calculate the first half of a resolvable address + * from the second half of the address and an irk. This function will use the ECB + * periferal to hash these data acording to the Bluetooth core specification. + * + * @note The ECB expect little endian input and output. + * This function expect big endian and will reverse the data as necessary. + * + * @param[in] p_k The key used in the hash function. + * For address resolution this is should be the irk. + * The array must have a length of 16. + * @param[in] p_r The rand used in the hash function. For generating a new address + * this would be a random number. For resolving a resolvable address + * this would be the last half of the address being resolved. + * The array must have a length of 3. + * @param[out] p_local_hash The result of the hash operation. For address resolution this + * will match the first half of the address being resolved if and only + * if the irk used in the hash function is the same one used to generate + * the address. + * The array must have a length of 16. + */ +void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash) +{ + nrf_ecb_hal_data_t ecb_hal_data; + + for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++) + { + ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i]; + } + + memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH); + + for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++) + { + ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i]; + } + + // Can only return NRF_SUCCESS. + (void) sd_ecb_block_encrypt(&ecb_hal_data); + + for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++) + { + p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i]; + } +} + + +bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH]; + uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH]; + uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH]; + + if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) + { + return false; + } + + memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH); + memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH); + ah(p_irk->irk, prand, local_hash); + + return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h new file mode 100644 index 0000000000..1350a4a853 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h @@ -0,0 +1,327 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PEER_ID_MANAGER_H__ +#define PEER_ID_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup id_manager ID Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for keeping track of peer identities + * (IRK and peer address). + */ + + +/**@brief Function for initializing the Identity manager. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL If an error occurred. + */ +ret_code_t im_init(void); + + +/**@brief Function for dispatching SoftDevice events to the ID Manager module. + * + * @param[in] p_ble_evt The SoftDevice event. + */ +void im_ble_evt_handler(ble_evt_t const * p_ble_evt); + + +/**@brief Function for getting the corresponding peer ID from a connection handle. + * + * @param[in] conn_handle The connection handle. + * + * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. + */ +pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle); + + +/**@brief Function for getting the corresponding peer ID from a master ID (EDIV and rand). + * + * @param[in] p_master_id The master ID. + * + * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. + */ +pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id); + + +/**@brief Function for getting the corresponding connection handle from a peer ID. + * + * @param[in] peer_id The peer ID. + * + * @return The corresponding connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be + * resolved. + */ +uint16_t im_conn_handle_get(pm_peer_id_t peer_id); + + +/**@brief Function for comparing two master ids + * @note Two invalid master IDs will not match. + * + * @param[in] p_master_id1 First master id for comparison + * @param[in] p_master_id2 Second master id for comparison + * + * @return True if the input matches, false if it does not. + */ +bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, + ble_gap_master_id_t const * p_master_id2); + + +/**@brief Function for getting the BLE address used by the peer when connecting. + * + * @param[in] conn_handle The connection handle. + * @param[out] p_ble_addr The BLE address used by the peer when the connection specified by + * conn_handle was established. + * + * @retval NRF_SUCCESS The address was found and copied. + * @retval BLE_ERROR_CONN_HANDLE_INVALID conn_handle does not refer to an active connection. + * @retval NRF_ERROR_NULL p_ble_addr was NULL. + */ +ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr); + + +/**@brief Function for checking if a master ID is valid or invalid + * + * @param[in] p_master_id The master ID. + * + * @retval true The master id is valid. + * @retval false The master id is invalid (i.e. all zeros). + */ +bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id); + + +/**@brief Function for checking if two pieces of bonding data correspond to the same peer. + * + * @param[in] p_bonding_data1 The first piece of bonding data to check. + * @param[in] p_bonding_data2 The second piece of bonding data to check. + * + * @retval true The bonding data correspond to the same peer. + * @retval false The bonding data do not correspond to the same peer. + */ +bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, + pm_peer_data_bonding_t const * p_bonding_data2); + + +/**@brief Function for finding if we are already bonded to a peer. + * + * @param[in] p_bonding_data The bonding data to check. + * @param[in] peer_id_skip Optional peer to ignore when searching for duplicates. + * + * @return An existing peer ID for the peer, or PM_PEER_ID_INVALID if none was found. + */ +pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, + pm_peer_id_t peer_id_skip); + + +/**@brief Function for reporting that a new peer ID has been allocated for a specified connection. + * + * @param[in] conn_handle The connection. + * @param[in] peer_id The new peer ID. + */ +void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id); + + +/**@brief Function for deleting all of a peer's data from flash and disassociating it from any + * connection handles it is associated with. + * + * @param[in] peer_id The peer to free. + * + * @return Any error code returned by @ref pdb_peer_free. + */ +ret_code_t im_peer_free(pm_peer_id_t peer_id); + + +/**@brief Function to set the local Bluetooth identity address. + * + * @details The local Bluetooth identity address is the address that identifies this device to other + * peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are + * running. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the + * ability to reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC + * upon being enabled. The address is a random number populated during the IC manufacturing + * process and remains unchanged for the lifetime of each IC. + * + * @param[in] p_addr Pointer to address structure. + * + * @retval NRF_SUCCESS Address successfully set. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the GAP address is invalid. + * @retval NRF_ERROR_BUSY Could not process at this time. Process SoftDevice events + * and retry. + * @retval NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, + * scanning, or while in a connection. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr); + + +/**@brief Function to get the local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval NRF_SUCCESS If the address was successfully retrieved. + */ +ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr); + + +/**@brief Function to set privacy settings. + * + * @details Privacy settings cannot be set while advertising, scanning, or while in a connection. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If privacy options were set successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. + * @retval NRF_ERROR_INVALID_PARAM If the address type is not valid. + * @retval NRF_ERROR_BUSY If the request could not be processed at this time. + * Process SoftDevice events and retry. + * @retval NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while BLE roles using + * privacy are enabled. + */ +ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params); + + +/**@brief Function to retrieve the current privacy settings. + * + * @details The privacy settings returned include the current device irk as well. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS Successfully retrieved privacy settings. + * @retval NRF_ERROR_NULL @c p_privacy_params is NULL. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params); + + +/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). + * + * @details This function will use the ECB peripheral to resolve a resolvable address. + * This can be used to resolve the identity of a device distributing a random + * resolvable address based on any IRKs you have received earlier. If an address is + * resolved by an IRK, the device distributing the address must also know the IRK. + * + * @param[in] p_addr A random resolvable address. + * @param[in] p_irk An identity resolution key (IRK). + * + * @retval true The irk used matched the one used to create the address. + * @retval false The irk used did not match the one used to create the address, or an argument was + * NULL. + */ +bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); + + +/**@brief Function for setting / clearing the whitelist. + * + * @param p_peers The peers to whitelist. Pass NULL to clear the whitelist. + * @param peer_cnt The number of peers to whitelist. Pass zero to clear the whitelist. + * + * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. + * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is in use. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used + * for whitelisting. + * @retval NRF_ERROR_NOT_FOUND If any peer or its data could not be found. + * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + */ +ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t const peer_cnt); + + +/**@brief Retrieves the current whitelist, set by a previous call to @ref im_whitelist_set. + * + * @param[out] A buffer where to copy the GAP addresses. + * @param[inout] In: the size of the @p p_addrs buffer. + * Out: the number of address copied into the buffer. + * @param[out] A buffer where to copy the IRKs. + * @param[inout] In: the size of the @p p_irks buffer. + * Out: the number of IRKs copied into the buffer. + * + * @retval NRF_SUCCESS If the whitelist was successfully retreived. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used for + * whitelisting. + * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers + * can not be found anymore. It might have been deleted in + * the meanwhile. + * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. + */ +ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt); + + +/**@brief Set the device identities list. + */ +ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_ID_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c new file mode 100644 index 0000000000..aa25bf29fa --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c @@ -0,0 +1,685 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "peer_data_storage.h" + +#include +#include +#include "sdk_errors.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_id.h" +#include "fds.h" + + +// Macro for verifying that the peer id is within a valid range. +#define VERIFY_PEER_ID_IN_RANGE(id) VERIFY_FALSE((id >= PM_PEER_ID_N_AVAILABLE_IDS), \ + NRF_ERROR_INVALID_PARAM) + +// Macro for verifying that the peer data id is withing a valid range. +#define VERIFY_PEER_DATA_ID_IN_RANGE(id) VERIFY_TRUE(peer_data_id_is_valid(id), \ + NRF_ERROR_INVALID_PARAM) + +// The number of registered event handlers. +#define PDS_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Peer Data Storage event handler in Peer Database. +extern void pdb_pds_evt_handler(pm_evt_t *); + +// Peer Data Storage events' handlers. +// The number of elements in this array is PDS_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pdb_pds_evt_handler, +}; + +static bool m_module_initialized = false; +static bool m_peer_delete_queued = false; +static bool m_peer_delete_ongoing = false; + +// A token used for Flash Data Storage searches. +static fds_find_token_t m_fds_ftok; + + +// Function for dispatching events to all registered event handlers. +static void pds_evt_send(pm_evt_t * p_event) +{ + p_event->conn_handle = BLE_CONN_HANDLE_INVALID; + + for (uint32_t i = 0; i < PDS_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +// Function to convert peer IDs to file IDs. +static uint16_t peer_id_to_file_id(pm_peer_id_t peer_id) +{ + return (uint16_t)(peer_id + PEER_ID_TO_FILE_ID); +} + + +// Function to convert peer data id to type id. +static pm_peer_id_t file_id_to_peer_id(uint16_t file_id) +{ + return (pm_peer_id_t)(file_id + FILE_ID_TO_PEER_ID); +} + + +// Function to convert peer data IDs to record keys. +static uint16_t peer_data_id_to_record_key(pm_peer_data_id_t peer_data_id) +{ + return (uint16_t)(peer_data_id + DATA_ID_TO_RECORD_KEY); +} + + +// Function to convert record keys to peer data IDs. +static pm_peer_data_id_t record_key_to_peer_data_id(uint16_t record_key) +{ + return (pm_peer_data_id_t)(record_key + RECORD_KEY_TO_DATA_ID); +} + + +// Function for checking whether a file ID is relevant for the Peer Manager. +static bool file_id_within_pm_range(uint16_t file_id) +{ + return ((PDS_FIRST_RESERVED_FILE_ID <= file_id) + && (file_id <= PDS_LAST_RESERVED_FILE_ID)); +} + + +// Function for checking whether a record key is relevant for the Peer Manager. +static bool record_key_within_pm_range(uint16_t record_key) +{ + return ((PDS_FIRST_RESERVED_RECORD_KEY <= record_key) + && (record_key <= PDS_LAST_RESERVED_RECORD_KEY)); +} + + +static bool peer_data_id_is_valid(pm_peer_data_id_t data_id) +{ + return ((data_id == PM_PEER_DATA_ID_BONDING) || + (data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING) || + (data_id == PM_PEER_DATA_ID_GATT_LOCAL) || + (data_id == PM_PEER_DATA_ID_GATT_REMOTE) || + (data_id == PM_PEER_DATA_ID_PEER_RANK) || + (data_id == PM_PEER_DATA_ID_APPLICATION)); +} + + +/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] peer_id The peer the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(pm_peer_id_t peer_id, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .peer_id = peer_id, + .params = + { + .error_unexpected = + { + .error = err_code, + } + } + }; + pds_evt_send(&error_evt); +} + + +// Function for deleting all data beloning to a peer. +// These operations will be sent to FDS one at a time. +static void peer_data_delete() +{ + ret_code_t ret; + pm_peer_id_t peer_id; + uint16_t file_id; + fds_record_desc_t desc; + fds_find_token_t ftok; + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + peer_id = peer_id_get_next_deleted(PM_PEER_ID_INVALID); + + while ( (peer_id != PM_PEER_ID_INVALID) + && (fds_record_find_in_file(peer_id_to_file_id(peer_id), &desc, &ftok) + == FDS_ERR_NOT_FOUND)) + { + peer_id_free(peer_id); + peer_id = peer_id_get_next_deleted(peer_id); + } + + if (!m_peer_delete_ongoing && (peer_id != PM_PEER_ID_INVALID)) + { + m_peer_delete_ongoing = true; + + file_id = peer_id_to_file_id(peer_id); + ret = fds_file_delete(file_id); + + if (ret == FDS_ERR_NO_SPACE_IN_QUEUES) + { + m_peer_delete_queued = true; + } + else if (ret != NRF_SUCCESS) + { + m_peer_delete_ongoing = false; + + send_unexpected_error(peer_id, ret); + } + } +} + + +static ret_code_t peer_data_find(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + fds_record_desc_t * const p_desc) +{ + ret_code_t ret; + fds_find_token_t ftok; + + NRF_PM_DEBUG_CHECK(peer_id < PM_PEER_ID_N_AVAILABLE_IDS); + NRF_PM_DEBUG_CHECK(peer_data_id_is_valid(data_id)); + NRF_PM_DEBUG_CHECK(p_desc != NULL); + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + + uint16_t file_id = peer_id_to_file_id(peer_id); + uint16_t record_key = peer_data_id_to_record_key(data_id); + + ret = fds_record_find(file_id, record_key, p_desc, &ftok); + + if (ret != FDS_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + return NRF_SUCCESS; +} + + +static void peer_ids_load() +{ + fds_record_desc_t record_desc; + fds_flash_record_t record; + fds_find_token_t ftok; + + memset(&ftok, 0x00, sizeof(fds_find_token_t)); + + uint16_t const record_key = peer_data_id_to_record_key(PM_PEER_DATA_ID_BONDING); + + while (fds_record_find_by_key(record_key, &record_desc, &ftok) == FDS_SUCCESS) + { + pm_peer_id_t peer_id; + + // It is safe to ignore the return value since the descriptor was + // just obtained and also 'record' is different from NULL. + (void)fds_record_open(&record_desc, &record); + peer_id = file_id_to_peer_id(record.p_header->file_id); + (void)fds_record_close(&record_desc); + + (void)peer_id_allocate(peer_id); + } +} + + +static void fds_evt_handler(fds_evt_t const * const p_fds_evt) +{ + pm_evt_t pds_evt = + { + .peer_id = file_id_to_peer_id(p_fds_evt->write.file_id) + }; + + switch (p_fds_evt->id) + { + case FDS_EVT_WRITE: + case FDS_EVT_UPDATE: + case FDS_EVT_DEL_RECORD: + if ( file_id_within_pm_range(p_fds_evt->write.file_id) + || record_key_within_pm_range(p_fds_evt->write.record_key)) + { + pds_evt.params.peer_data_update_succeeded.data_id + = record_key_to_peer_data_id(p_fds_evt->write.record_key); + pds_evt.params.peer_data_update_succeeded.action + = (p_fds_evt->id == FDS_EVT_DEL_RECORD) ? PM_PEER_DATA_OP_DELETE + : PM_PEER_DATA_OP_UPDATE; + pds_evt.params.peer_data_update_succeeded.token = p_fds_evt->write.record_id; + + if (p_fds_evt->result == FDS_SUCCESS) + { + pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; + pds_evt.params.peer_data_update_succeeded.flash_changed = true; + } + else + { + pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED; + pds_evt.params.peer_data_update_failed.error = p_fds_evt->result; + } + + pds_evt_send(&pds_evt); + } + break; + + case FDS_EVT_DEL_FILE: + if ( file_id_within_pm_range(p_fds_evt->del.file_id) + && (p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY)) + { + if (p_fds_evt->result == FDS_SUCCESS) + { + pds_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED; + peer_id_free(pds_evt.peer_id); + } + else + { + pds_evt.evt_id = PM_EVT_PEER_DELETE_FAILED; + } + + m_peer_delete_queued = false; + m_peer_delete_ongoing = false; + + peer_data_delete(); + + pds_evt_send(&pds_evt); + } + break; + + case FDS_EVT_GC: + pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTED; + pds_evt.peer_id = PM_PEER_ID_INVALID; + + pds_evt_send(&pds_evt); + break; + + default: + // No action. + break; + } + + if (m_peer_delete_queued) + { + m_peer_delete_queued = false; + peer_data_delete(); + } +} + + +ret_code_t pds_init() +{ + ret_code_t ret; + + // Check for re-initialization if debugging. + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + ret = fds_register(fds_evt_handler); + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + ret = fds_init(); + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_STORAGE_FULL; + } + + peer_id_init(); + peer_ids_load(); + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_data, + uint32_t const * const p_buf_len) +{ + ret_code_t ret; + fds_record_desc_t rec_desc; + fds_flash_record_t rec_flash; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_data != NULL); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + ret = peer_data_find(peer_id, data_id, &rec_desc); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + // Shouldn't fail, unless the record was deleted in the meanwhile or the CRC check has failed. + ret = fds_record_open(&rec_desc, &rec_flash); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + p_data->data_id = data_id; + p_data->length_words = rec_flash.p_header->length_words; + + // If p_buf_len is NULL, provide a pointer to data in flash, otherwise, + // check that the buffer is large enough and copy the data in flash into the buffer. + if (p_buf_len == NULL) + { + // The cast is necessary because if no buffer is provided, we just copy the pointer, + // but in that case it should be considered a pointer to const data by the caller, + // since it is a pointer to data in flash. + p_data->p_all_data = (void*)rec_flash.p_data; + } + else + { + uint32_t const data_len_bytes = (p_data->length_words * sizeof(uint32_t)); + + if ((*p_buf_len) >= data_len_bytes) + { + memcpy(p_data->p_all_data, rec_flash.p_data, data_len_bytes); + } + else + { + return NRF_ERROR_NO_MEM; + } + } + + // Shouldn't fail unless the record was already closed, in which case it can be ignored. + (void)fds_record_close(&rec_desc); + + return NRF_SUCCESS; +} + + +void pds_peer_data_iterate_prepare(void) +{ + memset(&m_fds_ftok, 0x00, sizeof(fds_find_token_t)); +} + + +bool pds_peer_data_iterate(pm_peer_data_id_t data_id, + pm_peer_id_t * const p_peer_id, + pm_peer_data_flash_t * const p_data) +{ + ret_code_t ret; + uint16_t rec_key; + fds_record_desc_t rec_desc; + fds_flash_record_t rec_flash; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_id != NULL); + NRF_PM_DEBUG_CHECK(p_data != NULL); + + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + rec_key = peer_data_id_to_record_key(data_id); + + if (fds_record_find_by_key(rec_key, &rec_desc, &m_fds_ftok) != NRF_SUCCESS) + { + return false; + } + + ret = fds_record_open(&rec_desc, &rec_flash); + + if (ret != NRF_SUCCESS) + { + // It can only happen if the record was deleted after the call to fds_record_find_by_key(), + // before we could open it, or if CRC support was enabled in Flash Data Storage at compile + // time and the CRC check failed. + return false; + } + + p_data->data_id = data_id; + p_data->length_words = rec_flash.p_header->length_words; + p_data->p_all_data = rec_flash.p_data; + + *p_peer_id = file_id_to_peer_id(rec_flash.p_header->file_id); + + (void)fds_record_close(&rec_desc); + + return true; +} + + +ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, + pm_prepare_token_t * p_prepare_token) +{ + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + NRF_PM_DEBUG_CHECK(p_prepare_token != NULL); + + VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); + + ret = fds_reserve((fds_reserve_token_t*)p_prepare_token, p_peer_data->length_words); + + switch (ret) + { + case FDS_SUCCESS: + return NRF_SUCCESS; + + case FDS_ERR_RECORD_TOO_LARGE: + return NRF_ERROR_INVALID_LENGTH; + + case FDS_ERR_NO_SPACE_IN_FLASH: + return NRF_ERROR_STORAGE_FULL; + + default: + return NRF_ERROR_INTERNAL; + } +} + + +ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token) +{ + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(prepare_token != PDS_PREPARE_TOKEN_INVALID); + + ret = fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); + + if (ret != FDS_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_const_t const * p_peer_data, + pm_prepare_token_t prepare_token, + pm_store_token_t * p_store_token) +{ + ret_code_t ret; + fds_record_t rec; + fds_record_desc_t rec_desc; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); + + // Prepare the record to be stored in flash. + rec.file_id = peer_id_to_file_id(peer_id); + rec.key = peer_data_id_to_record_key(p_peer_data->data_id); + rec.data.p_data = (void*)p_peer_data->p_all_data; + rec.data.length_words = p_peer_data->length_words; + + ret = peer_data_find(peer_id, p_peer_data->data_id, &rec_desc); + + if (ret == NRF_ERROR_NOT_FOUND) + { + // No previous data exists in flash. + if (prepare_token == PDS_PREPARE_TOKEN_INVALID) + { + // No space was previously reserved. + ret = fds_record_write(&rec_desc, &rec); + } + else + { + // Space for this record was previously reserved. + ret = fds_record_write_reserved(&rec_desc, &rec, (fds_reserve_token_t*)&prepare_token); + } + } + else // NRF_SUCCESS + { + if (prepare_token != PDS_PREPARE_TOKEN_INVALID) + { + (void)fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); + } + + // Update existing record. + ret = fds_record_update(&rec_desc, &rec); + } + + switch (ret) + { + case FDS_SUCCESS: + if (p_store_token != NULL) + { + // Update the store token. + (void)fds_record_id_from_desc(&rec_desc, (uint32_t*)p_store_token); + } + return NRF_SUCCESS; + + case FDS_ERR_BUSY: + case FDS_ERR_NO_SPACE_IN_QUEUES: + return NRF_ERROR_BUSY; + + case FDS_ERR_NO_SPACE_IN_FLASH: + return NRF_ERROR_STORAGE_FULL; + + default: + return NRF_ERROR_INTERNAL; + } +} + + +ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + ret_code_t ret; + fds_record_desc_t record_desc; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_PEER_ID_IN_RANGE(peer_id); + VERIFY_PEER_DATA_ID_IN_RANGE(data_id); + + ret = peer_data_find(peer_id, data_id, &record_desc); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_NOT_FOUND; + } + + ret = fds_record_delete(&record_desc); + + switch (ret) + { + case FDS_SUCCESS: + return NRF_SUCCESS; + + case FDS_ERR_NO_SPACE_IN_QUEUES: + return NRF_ERROR_BUSY; + + default: + return NRF_ERROR_INTERNAL; + } +} + + +pm_peer_id_t pds_peer_id_allocate(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_allocate(PM_PEER_ID_INVALID); +} + + +ret_code_t pds_peer_id_free(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + VERIFY_PEER_ID_IN_RANGE(peer_id); + + (void)peer_id_delete(peer_id); + peer_data_delete(); + + return NRF_SUCCESS; +} + + +bool pds_peer_id_is_allocated(pm_peer_id_t peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_is_allocated(peer_id); +} + + +pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_get_next_used(prev_peer_id); +} + + +pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_get_next_deleted(prev_peer_id); +} + + +uint32_t pds_peer_count_get(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return peer_id_n_ids(); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h new file mode 100644 index 0000000000..2138a3b61d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PEER_DATA_STORAGE_H__ +#define PEER_DATA_STORAGE_H__ + + +#include +#include "sdk_errors.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_manager_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup peer_data_storage Peer Data Storage + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module provides a Peer Manager-specific API + * to the persistent storage. + * + * @details This module uses Flash Data Storage (FDS) to interface with persistent storage. + */ + +#define PDS_PREPARE_TOKEN_INVALID (0) /**< Invalid value for prepare token. */ +#define PDS_FIRST_RESERVED_FILE_ID (0xC000) /**< The beginning of the range of file IDs reserved for Peer Manager. */ +#define PDS_LAST_RESERVED_FILE_ID (0xFFFE) /**< The end of the range of file IDs reserved for Peer Manager. */ +#define PDS_FIRST_RESERVED_RECORD_KEY (0xC000) /**< The beginning of the range of record keys reserved for Peer Manager. */ +#define PDS_LAST_RESERVED_RECORD_KEY (0xFFFE) /**< The end of the range of record keys reserved for Peer Manager. */ + +#define PEER_ID_TO_FILE_ID ( PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting a @ref pm_peer_id_t to an FDS file ID. +#define FILE_ID_TO_PEER_ID (-PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting an FDS file ID to a @ref pm_peer_id_t. +#define DATA_ID_TO_RECORD_KEY ( PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting a @ref pm_peer_data_id_t to an FDS record ID. +#define RECORD_KEY_TO_DATA_ID (-PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting an FDS record ID to a @ref pm_peer_data_id_t. + + +/**@brief Function for initializing the module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_STORAGE_FULL If no flash pages were available for use. + * @retval NRF_ERROR_INTERNAL If the module couldn't register with the flash filesystem. + */ +ret_code_t pds_init(void); + + +/**@brief Function for reading peer data in flash. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] data_id The data to retrieve. + * @param[out] p_data The peer data. May not be @c NULL. + * @param[in] p_buf_len Length of the provided buffer, in bytes. Pass @c NULL to only copy + * a pointer to the data in flash. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. + * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. + */ +ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_data, + uint32_t const * const p_buf_len); + + +/**@brief Function to prepare iterating over peer data in flash using @ref pds_peer_data_iterate. + * Call this function once each time before iterating using @ref pds_peer_data_iterate. + */ +void pds_peer_data_iterate_prepare(void); + + +/**@brief Function for iterating peers' data in flash. + * Always call @ref pds_peer_data_iterate_prepare before starting iterating. + * + * @param[in] data_id The peer data to iterate over. + * @param[out] p_peer_id The peer the data belongs to. + * @param[out] p_data The peer data in flash. + * + * @retval true If the operation was successful. + * @retval false If the data was not found in flash, or another error occurred. + */ +bool pds_peer_data_iterate(pm_peer_data_id_t data_id, + pm_peer_id_t * const p_peer_id, + pm_peer_data_flash_t * const p_data); + + +/**@brief Function for reserving space in flash to store data. + * + * @param[in] p_peer_data The data to be stored in flash. Only data length and type (ID) are + * relevant for this operation. May not be @c NULL. + * @param[out] p_prepare_token A token identifying the reserved space. May not be @c NULL. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If the data ID in @p p_peer_data is invalid. + * @retval NRF_ERROR_INVALID_LENGTH If data length exceeds the maximum allowed length. + * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, + pm_prepare_token_t * p_prepare_token); + + +/**@brief Function for undoing a previous call to @ref pds_space_reserve. + * + * @param[in] prepare_token A token identifying the reservation to cancel. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token); + + +/**@brief Function for storing peer data in flash. If the same piece of data already exists for the + * given peer, it will be updated. This operation is asynchronous. + * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED + * event. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] p_peer_data The peer data. May not be @c NULL. + * @param[in] prepare_token A token identifying the reservation made in flash to store the data. + * Pass @ref PDS_PREPARE_TOKEN_INVALID if no space was reserved. + * @param[out] p_store_token A token identifying this particular store operation. The token can be + * used to identify events pertaining to this operation. Pass @p NULL + * if not used. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or the data ID in @p_peer_data are invalid. + * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. This can only happen if + * @p p_prepare_token is @ref PDS_PREPARE_TOKEN_INVALID. + * @retval NRF_ERROR_BUSY If the flash filesystem was busy. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_const_t const * p_peer_data, + pm_prepare_token_t prepare_token, + pm_store_token_t * p_store_token); + + +/**@brief Function for deleting peer data in flash. This operation is asynchronous. + * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED + * event. + * + * @param[in] peer_id The peer the data belongs to + * @param[in] data_id The data to delete. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. + * @retval NRF_ERROR_BUSY If the flash filesystem was busy. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for claiming an unused peer ID. + * + * @retval PM_PEER_ID_INVALID If no peer ID was available. + */ +pm_peer_id_t pds_peer_id_allocate(void); + + +/**@brief Function for freeing a peer ID and deleting all data associated with it in flash. + * + * @param[in] peer_id The ID of the peer to free. + * + * @retval NRF_SUCCESS The operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id is invalid. + */ +ret_code_t pds_peer_id_free(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is in use. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true @p peer_id is in use. + * @retval false @p peer_id is free. + */ +bool pds_peer_id_is_allocated(pm_peer_id_t peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be + * used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The first ordinary peer ID If @p prev_peer_id is @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID If @p prev_peer_id is the last ordinary peer ID or the module + * is not initialized. + */ +pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. + * Can be used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID pending deletion. + * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module + * is not initialized. + */ +pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers + * in persistent storage. + * + * @return The number of valid peer IDs. + */ +uint32_t pds_peer_count_get(void); + + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_DATA_STORAGE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c new file mode 100644 index 0000000000..9216136959 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c @@ -0,0 +1,831 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "peer_database.h" + +#include +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "peer_data_storage.h" +#include "pm_buffer.h" + + +/**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer. + * + * @param[in] data_id The data ID to verify. + */ +// @note emdi: could this maybe be a function? +#define VERIFY_DATA_ID_WRITE_BUF(data_id) \ +do \ +{ \ + if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \ + { \ + return NRF_ERROR_INVALID_PARAM; \ + } \ +} while (0) + + +// The number of registered event handlers. +#define PDB_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Peer Database event handlers in other Peer Manager submodules. +extern void pm_pdb_evt_handler(pm_evt_t * p_event); +extern void sm_pdb_evt_handler(pm_evt_t * p_event); +extern void gscm_pdb_evt_handler(pm_evt_t * p_event); +extern void gcm_pdb_evt_handler(pm_evt_t * p_event); + +// Peer Database events' handlers. +// The number of elements in this array is PDB_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_pdb_evt_handler, + sm_pdb_evt_handler, + gscm_pdb_evt_handler, + gcm_pdb_evt_handler, +}; + + +/**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written + * or cancelled. + */ +typedef struct +{ + pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */ + pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */ + pm_prepare_token_t prepare_token; /**< Token given by Peer Data Storage if room in flash has been reserved. */ + pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. This is used as the check for whether such an operation has been successfully requested. */ + uint8_t n_bufs; /**< The number of buffer blocks containing peer data. */ + uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */ + uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */ + uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */ +} pdb_buffer_record_t; + + +static bool m_module_initialized; +static pm_buffer_t m_write_buffer; /**< The state of the write buffer. */ +static pdb_buffer_record_t m_write_buffer_records[PM_FLASH_BUFFERS]; /**< The available write buffer records. */ +static uint32_t m_n_pending_writes; /**< The number of pending (Not yet successfully requested in Peer Data Storage) store operations. */ + + + +/**@brief Function for invalidating a record of a write buffer allocation. + * + * @param[in] p_record The record to invalidate. + */ +static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record) +{ + p_record->peer_id = PM_PEER_ID_INVALID; + p_record->data_id = PM_PEER_DATA_ID_INVALID; + p_record->buffer_block_id = PM_BUFFER_INVALID_ID; + p_record->store_busy = false; + p_record->store_flash_full = false; + p_record->n_bufs = 0; + p_record->prepare_token = PDS_PREPARE_TOKEN_INVALID; + p_record->store_token = PM_STORE_TOKEN_INVALID; +} + + +/**@brief Function for finding a record of a write buffer allocation. + * + * @param[in] peer_id The peer ID in the record. + * @param[inout] p_index In: The starting index, out: The index of the record + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, uint32_t * p_index) +{ + for (uint32_t i = *p_index; i < PM_FLASH_BUFFERS; i++) + { + if ((m_write_buffer_records[i].peer_id == peer_id)) + { + *p_index = i; + return &m_write_buffer_records[i]; + } + } + return NULL; +} + + +/**@brief Function for finding a record of a write buffer allocation. + * + * @param[in] peer_id The peer ID in the record. + * @param[in] data_id The data ID in the record. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id) +{ + uint32_t index = 0; + pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); + + while ((p_record != NULL) && ( (p_record->data_id != data_id) + || (p_record->store_busy) + || (p_record->store_flash_full) + || (p_record->store_token != PM_STORE_TOKEN_INVALID))) + { + index++; + p_record = write_buffer_record_find_next(peer_id, &index); + } + + return p_record; +} + + +/**@brief Function for finding a record of a write buffer allocation that has been sent to be stored. + * + * @param[in] store_token The store token received when store was called for the record. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_stored(pm_store_token_t store_token) +{ + for (int i = 0; i < PM_FLASH_BUFFERS; i++) + { + if (m_write_buffer_records[i].store_token == store_token) + { + return &m_write_buffer_records[i]; + } + } + return NULL; +} + + +/**@brief Function for finding an available record for write buffer allocation. + * + * @return A pointer to the available record, or NULL if none was found. + */ +static pdb_buffer_record_t * write_buffer_record_find_unused(void) +{ + return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID); +} + + +/**@brief Function for gracefully deactivating a write buffer record. + * + * @details This function will first release any buffers, then invalidate the record. + * + * @param[inout] p_write_buffer_record The record to release. + * + * @return A pointer to the matching record, or NULL if none was found. + */ +static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record) +{ + for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++) + { + pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); + } + + write_buffer_record_invalidate(p_write_buffer_record); +} + + +/**@brief Function for claiming and activating a write buffer record. + * + * @param[out] pp_write_buffer_record The claimed record. + * @param[in] peer_id The peer ID this record should have. + * @param[in] data_id The data ID this record should have. + */ +static void write_buffer_record_acquire(pdb_buffer_record_t ** pp_write_buffer_record, + pm_peer_id_t peer_id, + pm_peer_data_id_t data_id) +{ + if (pp_write_buffer_record == NULL) + { + return; + } + *pp_write_buffer_record = write_buffer_record_find_unused(); + if (*pp_write_buffer_record == NULL) + { + // This also means the buffer is full. + return; + } + (*pp_write_buffer_record)->peer_id = peer_id; + (*pp_write_buffer_record)->data_id = data_id; +} + + +/**@brief Function for dispatching outbound events to all registered event handlers. + * + * @param[in] p_event The event to dispatch. + */ +static void pdb_evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < PDB_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for resetting the internal state of the Peer Database module. + * + * @param[out] p_event The event to dispatch. + */ +static void internal_state_reset() +{ + for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) + { + write_buffer_record_invalidate(&m_write_buffer_records[i]); + } +} + + +static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs) +{ + uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE; + p_peer_data->data_id = data_id; + + p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory; + p_peer_data->length_words = BYTES_TO_WORDS(n_bytes); +} + + +static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs) +{ + peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs); +} + + +static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data) +{ + switch (p_peer_data->data_id) + { + case PM_PEER_DATA_ID_BONDING: + p_peer_data->length_words = PM_BONDING_DATA_N_WORDS(); + break; + case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: + p_peer_data->length_words = PM_SC_STATE_N_WORDS(); + break; + case PM_PEER_DATA_ID_PEER_RANK: + p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS(); + break; + case PM_PEER_DATA_ID_GATT_LOCAL: + p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len); + break; + default: + // No action needed. + break; + } +} + + +/**@brief Function for writing data into persistent storage. Writing happens asynchronously. + * + * @note This will unlock the data after it has been written. + * + * @param[in] p_write_buffer_record The write buffer record to write into persistent storage. + * + * @retval NRF_SUCCESS Data storing was successfully started. + * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some + * space, the operation will be reattempted after the next compress + * procedure. This error will not happen if + * @ref pdb_write_buf_store_prepare is called beforehand. + * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. + * @retval NRF_ERROR_INVALID_STATE Module is not initialized. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t write_buf_store(pdb_buffer_record_t * p_write_buffer_record) +{ + ret_code_t err_code = NRF_SUCCESS; + pm_peer_data_const_t peer_data = {.data_id = p_write_buffer_record->data_id}; + uint8_t * p_buffer_memory; + + p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); + if (p_buffer_memory == NULL) + { + return NRF_ERROR_INTERNAL; + } + + peer_data_const_point_to_buffer(&peer_data, + p_write_buffer_record->data_id, + p_buffer_memory, + p_write_buffer_record->n_bufs); + write_buf_length_words_set(&peer_data); + + err_code = pds_peer_data_store(p_write_buffer_record->peer_id, + &peer_data, + p_write_buffer_record->prepare_token, + &p_write_buffer_record->store_token); + + if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full) + { + m_n_pending_writes--; + } + + switch (err_code) + { + case NRF_SUCCESS: + p_write_buffer_record->store_busy = false; + p_write_buffer_record->store_flash_full = false; + break; + + case NRF_ERROR_BUSY: + m_n_pending_writes++; + + p_write_buffer_record->store_busy = true; + p_write_buffer_record->store_flash_full = false; + + err_code = NRF_SUCCESS; + break; + + case NRF_ERROR_STORAGE_FULL: + m_n_pending_writes++; + + p_write_buffer_record->store_busy = false; + p_write_buffer_record->store_flash_full = true; + break; + + case NRF_ERROR_INVALID_PARAM: + // No action. + break; + + default: + err_code = NRF_ERROR_INTERNAL; + break; + } + + return err_code; +} + + +/**@brief This calls @ref write_buf_store and sends events based on the return value. + * + * See @ref write_buf_store for more info. + * + * @return Whether or not the store operation succeeded. + */ +static bool write_buf_store_in_event(pdb_buffer_record_t * p_write_buffer_record) +{ + ret_code_t err_code; + pm_evt_t event; + + err_code = write_buf_store(p_write_buffer_record); + if (err_code != NRF_SUCCESS) + { + event.conn_handle = BLE_CONN_HANDLE_INVALID; + event.peer_id = p_write_buffer_record->peer_id; + + if (err_code == NRF_ERROR_STORAGE_FULL) + { + event.evt_id = PM_EVT_STORAGE_FULL; + } + else + { + event.evt_id = PM_EVT_ERROR_UNEXPECTED; + event.params.error_unexpected.error = err_code; + } + + pdb_evt_send(&event); + + return false; + } + + return true; +} + + +/**@brief This reattempts store operations on write buffers, that previously failed because of @ref + * NRF_ERROR_BUSY or @ref NRF_ERROR_STORAGE_FULL errors. + * + * param[in] retry_flash_full Whether to retry operations that failed because of an + * @ref NRF_ERROR_STORAGE_FULL error. + */ +static void reattempt_previous_operations(bool retry_flash_full) +{ + // Reattempt previously rejected store operations. + + if (m_n_pending_writes == 0) + { + return; + } + + for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) + { + if ((m_write_buffer_records[i].store_busy) + || (m_write_buffer_records[i].store_flash_full && retry_flash_full)) + { + bool success = write_buf_store_in_event(&m_write_buffer_records[i]); + + if (!success) + { + break; + } + } + } +} + + +/**@brief Function for handling events from the Peer Data Storage module. + * This function is extern in Peer Data Storage. + * + * @param[in] p_event The event to handle. + */ +void pdb_pds_evt_handler(pm_evt_t * p_event) +{ + pdb_buffer_record_t * p_write_buffer_record; + bool evt_send = true; + bool retry_flash_full = false; + + p_write_buffer_record = write_buffer_record_find_stored(p_event->params.peer_data_update_succeeded.token); + + switch (p_event->evt_id) + { + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + && (p_write_buffer_record != NULL)) + { + // The write came from PDB. + write_buffer_record_release(p_write_buffer_record); + } + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + && (p_write_buffer_record != NULL)) + { + // The write came from PDB, retry. + m_n_pending_writes++; + p_write_buffer_record->store_token = PM_STORE_TOKEN_INVALID; + p_write_buffer_record->store_busy = true; + evt_send = false; + } + break; + + case PM_EVT_FLASH_GARBAGE_COLLECTED: + retry_flash_full = true; + break; + + default: + break; + } + + if (evt_send) + { + // Forward the event to all registered Peer Database event handlers. + pdb_evt_send(p_event); + } + + reattempt_previous_operations(retry_flash_full); +} + + +ret_code_t pdb_init() +{ + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + internal_state_reset(); + + PM_BUFFER_INIT(&m_write_buffer, PM_FLASH_BUFFERS, PDB_WRITE_BUF_SIZE, ret); + + if (ret != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +pm_peer_id_t pdb_peer_allocate(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_peer_id_allocate(); +} + + +ret_code_t pdb_peer_free(pm_peer_id_t peer_id) +{ + ret_code_t err_code_in = NRF_SUCCESS; + ret_code_t err_code_out = NRF_SUCCESS; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint32_t index = 0; + pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); + + while (p_record != NULL) + { + err_code_in = pdb_write_buf_release(peer_id, p_record->data_id); + + if ( (err_code_in != NRF_SUCCESS) + && (err_code_in != NRF_ERROR_NOT_FOUND)) + { + err_code_out = NRF_ERROR_INTERNAL; + } + + index++; + p_record = write_buffer_record_find_next(peer_id, &index); + } + + if (err_code_out == NRF_SUCCESS) + { + err_code_in = pds_peer_id_free(peer_id); + + if (err_code_in == NRF_SUCCESS) + { + // No action needed. + } + else if (err_code_in == NRF_ERROR_INVALID_PARAM) + { + err_code_out = NRF_ERROR_INVALID_PARAM; + } + else + { + err_code_out = NRF_ERROR_INTERNAL; + } + } + + return err_code_out; +} + + +ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_flash_t * const p_peer_data) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + + // Pass NULL to only retrieve a pointer. + return pds_peer_data_read(peer_id, data_id, (pm_peer_data_t*)p_peer_data, NULL); +} + + + +ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + uint32_t n_bufs, + pm_peer_data_t * p_peer_data) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_PARAM_NOT_NULL(p_peer_data); + VERIFY_DATA_ID_WRITE_BUF(data_id); + + if ( (n_bufs == 0) + || (n_bufs > PM_FLASH_BUFFERS) + || !pds_peer_id_is_allocated(peer_id)) + { + return NRF_ERROR_INVALID_PARAM; + } + + pdb_buffer_record_t * p_write_buffer_record; + uint8_t * p_buffer_memory; + bool new_record = false; + bool find_new_buffer = false; + + p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + find_new_buffer = true; + } + else if (p_write_buffer_record->n_bufs < n_bufs) + { + // @TODO: Copy? + // Existing buffer is too small. + for (uint8_t i = 0; i < p_write_buffer_record->n_bufs; i++) + { + pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); + } + write_buffer_record_invalidate(p_write_buffer_record); + find_new_buffer = true; + } + else if (p_write_buffer_record->n_bufs > n_bufs) + { + // Release excess blocks. + for (uint8_t i = n_bufs; i < p_write_buffer_record->n_bufs; i++) + { + pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); + } + } + else + { + // Do nothing. + } + + if (find_new_buffer) + { + // No buffer exists. + write_buffer_record_acquire(&p_write_buffer_record, peer_id, data_id); + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_BUSY; + } + } + + if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) + { + p_write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_write_buffer, n_bufs); + + if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) + { + write_buffer_record_invalidate(p_write_buffer_record); + return NRF_ERROR_BUSY; + } + + new_record = true; + } + + p_write_buffer_record->n_bufs = n_bufs; + + p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); + + if (p_buffer_memory == NULL) + { + return NRF_ERROR_INTERNAL; + } + + peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs); + if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL)) + { + p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words); + } + + return NRF_SUCCESS; +} + + +ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + ret_code_t err_code = NRF_SUCCESS; + pdb_buffer_record_t * p_write_buffer_record; + p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_NOT_FOUND; + } + + if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID) + { + err_code = pds_space_reserve_cancel(p_write_buffer_record->prepare_token); + if (err_code != NRF_SUCCESS) + { + err_code = NRF_ERROR_INTERNAL; + } + } + + write_buffer_record_release(p_write_buffer_record); + + return err_code; +} + + +ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_DATA_ID_WRITE_BUF(data_id); + + ret_code_t err_code = NRF_SUCCESS; + pdb_buffer_record_t * p_write_buffer_record; + p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_NOT_FOUND; + } + + if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID) + { + uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, + p_write_buffer_record->buffer_block_id); + pm_peer_data_const_t peer_data = {.data_id = data_id}; + + if (p_buffer_memory == NULL) + { + return NRF_ERROR_INTERNAL; + } + + peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs); + + write_buf_length_words_set(&peer_data); + + err_code = pds_space_reserve(&peer_data, &p_write_buffer_record->prepare_token); + if (err_code == NRF_ERROR_INVALID_LENGTH) + { + return NRF_ERROR_INTERNAL; + } + } + + return err_code; +} + + +ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_id_t new_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + VERIFY_DATA_ID_WRITE_BUF(data_id); + + pdb_buffer_record_t * p_write_buffer_record = write_buffer_record_find(peer_id, data_id); + + if (p_write_buffer_record == NULL) + { + return NRF_ERROR_NOT_FOUND; + } + + p_write_buffer_record->peer_id = new_peer_id; + p_write_buffer_record->data_id = data_id; + return write_buf_store(p_write_buffer_record); +} + + +ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_peer_data_delete(peer_id, data_id); +} + + +uint32_t pdb_n_peers(void) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_peer_count_get(); +} + + +pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_next_peer_id_get(prev_peer_id); +} + + +pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_next_deleted_peer_id_get(prev_peer_id); +} + + +ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_peer_data) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_peer_data != NULL); + + // Provide the buffer length in bytes. + uint32_t const data_len_bytes = (p_peer_data->length_words * sizeof(uint32_t)); + return pds_peer_data_read(peer_id, data_id, p_peer_data, &data_len_bytes); +} + + +ret_code_t pdb_raw_store(pm_peer_id_t peer_id, + pm_peer_data_const_t * p_peer_data, + pm_store_token_t * p_store_token) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + return pds_peer_data_store(peer_id, p_peer_data, PDS_PREPARE_TOKEN_INVALID, p_store_token); +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h new file mode 100644 index 0000000000..5e1e0fb6b8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h @@ -0,0 +1,306 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PEER_DATABASE_H__ +#define PEER_DATABASE_H__ + +#include +#include "peer_manager_types.h" +#include "peer_manager_internal.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @cond NO_DOXYGEN + * @defgroup peer_database Peer Database + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for simple management of reading and + * writing of peer data into persistent storage. + * + */ + +#define PDB_WRITE_BUF_SIZE (sizeof(pm_peer_data_bonding_t)) //!< The size (in bytes) of each block in the internal buffer accessible via @ref pdb_write_buf_get. + + +/**@brief Function for initializing the module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL An unexpected error happened. + */ +ret_code_t pdb_init(void); + + +/**@brief Function for allocating persistent bond storage for a peer. + * + * @return The ID of the newly allocated storage. + * @retval PM_PEER_ID_INVALID If no peer ID is available. + */ +pm_peer_id_t pdb_peer_allocate(void); + + +/**@brief Function for freeing a peer's persistent bond storage. + * + * @note This function will call @ref pdb_write_buf_release on the data for this peer. + * + * @param[in] peer_id ID to be freed. + * + * @retval NRF_SUCCESS Peer ID was released and clear operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM Peer ID was invalid. + */ +ret_code_t pdb_peer_free(pm_peer_id_t peer_id); + + +/**@brief Function for retrieving a pointer to peer data in flash (read-only). + * + * @note Dereferencing this pointer is not the safest thing to do if interrupts are enabled, + * because Flash Data Storage garbage collection might move the data around. Either disable + * interrupts while using the data, or use @ref pdb_peer_data_load. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] data_id The data to read. + * @param[out] p_peer_data The peer data, read-only. + * + * @retval NRF_SUCCESS If the pointer to the data was retrieved successfully. + * @retval NRF_ERROR_INVALID_PARAM If either @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. + */ +ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_flash_t * const p_peer_data); + + +/**@brief Function for retrieving pointers to a write buffer for peer data. + * + * @details This function will provide pointers to a buffer of the data. The data buffer will not be + * written to persistent storage until @ref pdb_write_buf_store is called. The buffer is + * released by calling either @ref pdb_write_buf_release, @ref pdb_write_buf_store, or + * @ref pdb_peer_free. + * + * When the data_id refers to a variable length data type, the available size is written + * to the data, both the top-level, and any internal length fields. + * + * @note Calling this function on a peer_id/data_id pair that already has a buffer created will + * give the same buffer, not create a new one. If n_bufs was increased since last time, the + * buffer might be relocated to be able to provide additional room. In this case, the data + * will be copied. If n_bufs was increased since last time, this function might return @ref + * NRF_ERROR_BUSY. In that case, the buffer is automatically released. + * + * @param[in] peer_id ID of peer to get a write buffer for. + * @param[in] data_id Which piece of data to get. + * @param[in] n_bufs The number of contiguous buffers needed. + * @param[out] p_peer_data Pointers to mutable peer data. + * + * @retval NRF_SUCCESS Data retrieved successfully. + * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated, or n_bufs was 0 + * or more than the total available buffers. + * @retval NRF_ERROR_NULL p_peer_data was NULL. + * @retval NRF_ERROR_BUSY Not enough buffer(s) available. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + uint32_t n_bufs, + pm_peer_data_t * p_peer_data); + + +/**@brief Function for freeing a write buffer allocated with @ref pdb_write_buf_get. + * + * @note This function will not write peer data to persistent memory. Data in released buffer will + * be lost. + * + * @note This function will undo any previous call to @ref pdb_write_buf_store_prepare for this + * piece of data. + * + * @param[in] peer_id ID of peer to release buffer for. + * @param[in] data_id Which piece of data to release buffer for. + * + * @retval NRF_SUCCESS Successfully released buffer. + * @retval NRF_ERROR_NOT_FOUND No buffer was allocated for this peer ID/data ID pair. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for reserving space in persistent storage for data in a buffer. + * + * @note This function only works for data which has a write buffer allocated. If the write buffer + * is released, this prepare is undone. + * + * @note If space has already been reserved for this data, nothing is done. + * + * @param[in] peer_id The peer whose data to reserve space for. + * @param[in] data_id The type of data to reserve space for. + * + * @retval NRF_SUCCESS Successfully reserved space in persistent storage. + * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. + * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. + * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. + */ +ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for writing data into persistent storage. Writing happens asynchronously. + * + * @note This will unlock the data after it has been written. + * + * @param[in] peer_id The ID used to address the write buffer. + * @param[in] data_id Which piece of data to store. + * @param[in] new_peer_id The ID to put in flash. This will usually be the same as peer_id. + * + * @retval NRF_SUCCESS Data storing was successfully started. + * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some + * space, the operation will be reattempted after the next compress + * procedure. This error will not happen if + * @ref pdb_write_buf_store_prepare is called beforehand. + * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. + * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. + * @retval NRF_ERROR_INTERNAL Unexpected internal error. + */ +ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_id_t new_peer_id); + + +/**@brief Function for clearing data from persistent storage. + * + * @param[in] peer_id ID of peer to clear data for. + * @param[in] data_id Which piece of data to clear. + * + * @retval NRF_SUCCESS The clear was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM Data ID or peer ID was invalid. + * @retval NRF_ERROR_NOT_FOUND Nothing to clear for this peer ID/data ID combination. + * @retval NRF_ERROR_BUSY Underlying modules are busy and can't take any more requests at + * this moment. + * @retval NRF_ERROR_INTERNAL Internal error. + */ +ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers + * in persistent storage. + * + * @return The number of valid peer IDs. + */ +uint32_t pdb_n_peers(void); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be + * used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. + * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. + */ +pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. + * Can be used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID pending deletion. + * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. + */ +pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for copy peer data from flash into a provided buffer. + * + * @param[in] peer_id The peer the data belongs to. + * @param[in] data_id The data to read. + * @param[inout] p_peer_data The buffer where to copy data into. The field @c length_words in this + * parameter must represent the buffer length in words. + * + * @note Actually, it represents the buffer length in bytes upon entering the function, + * and upon exit it represents the length of the data in words.. not good. Fix this. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. + * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. + * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. + */ +ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + pm_peer_data_t * const p_peer_data); + + +/**@brief Function for writing data directly to persistent storage from external memory. + * + * @param[in] peer_id ID of peer to write data for. + * @param[in] p_peer_data Data to store. + * @param[out] p_store_token A token identifying this particular store operation. The token can be + * used to identify events pertaining to this operation. + * + * @retval NRF_SUCCESS Data successfully written. + * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. + * @retval NRF_ERROR_NULL p_peer_data contained a NULL pointer. + * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. + * @retval NRF_ERROR_INVALID_LENGTH Data length above the maximum allowed. + * @retval NRF_ERROR_BUSY Unable to perform operation at this time. + */ +ret_code_t pdb_raw_store(pm_peer_id_t peer_id, + pm_peer_data_const_t * p_peer_data, + pm_store_token_t * p_store_token); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_DATABASE_H__ */ + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c new file mode 100644 index 0000000000..06b0594c71 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "peer_id.h" + +#include +#include +#include "sdk_errors.h" +#include "peer_manager_types.h" +#include "pm_mutex.h" + + +typedef struct +{ + uint8_t used_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are in use. */ + uint8_t deleted_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are marked for deletion. */ +} pi_t; + + +static pi_t m_pi = {{0}, {0}}; + + +static void internal_state_reset(pi_t * p_pi) +{ + memset(p_pi, 0, sizeof(pi_t)); +} + + +void peer_id_init(void) +{ + internal_state_reset(&m_pi); + pm_mutex_init(m_pi.used_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); + pm_mutex_init(m_pi.deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); +} + + +static pm_peer_id_t claim(pm_peer_id_t peer_id, uint8_t * mutex_group) +{ + pm_peer_id_t allocated_peer_id = PM_PEER_ID_INVALID; + if (peer_id == PM_PEER_ID_INVALID) + { + allocated_peer_id = pm_mutex_lock_first_available(mutex_group, PM_PEER_ID_N_AVAILABLE_IDS); + if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS) + { + allocated_peer_id = PM_PEER_ID_INVALID; + } + } + else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + bool lock_success = pm_mutex_lock(mutex_group, peer_id); + allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID; + } + return allocated_peer_id; +} + + +static void release(pm_peer_id_t peer_id, uint8_t * mutex_group) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + pm_mutex_unlock(mutex_group, peer_id); + } +} + + +pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id) +{ + return claim(peer_id, m_pi.used_peer_ids); +} + + +bool peer_id_delete(pm_peer_id_t peer_id) +{ + pm_peer_id_t deleted_peer_id; + + if (peer_id == PM_PEER_ID_INVALID) + { + return false; + } + + deleted_peer_id = claim(peer_id, m_pi.deleted_peer_ids); + + return (deleted_peer_id == peer_id); +} + + +void peer_id_free(pm_peer_id_t peer_id) +{ + release(peer_id, m_pi.used_peer_ids); + release(peer_id, m_pi.deleted_peer_ids); +} + + +bool peer_id_is_allocated(pm_peer_id_t peer_id) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + return pm_mutex_lock_status_get(m_pi.used_peer_ids, peer_id); + } + return false; +} + + +bool peer_id_is_deleted(pm_peer_id_t peer_id) +{ + if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) + { + return pm_mutex_lock_status_get(m_pi.deleted_peer_ids, peer_id); + } + return false; +} + + +pm_peer_id_t next_id_get(pm_peer_id_t prev_peer_id, uint8_t * mutex_group) +{ + pm_peer_id_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1); + for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) + { + if (pm_mutex_lock_status_get(mutex_group, i)) + { + return i; + } + } + + return PM_PEER_ID_INVALID; +} + + +pm_peer_id_t peer_id_get_next_used(pm_peer_id_t peer_id) +{ + peer_id = next_id_get(peer_id, m_pi.used_peer_ids); + + while (peer_id != PM_PEER_ID_INVALID) + { + if (!peer_id_is_deleted(peer_id)) + { + return peer_id; + } + + peer_id = next_id_get(peer_id, m_pi.used_peer_ids); + } + + return peer_id; +} + + +pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id) +{ + return next_id_get(prev_peer_id, m_pi.deleted_peer_ids); +} + + +uint32_t peer_id_n_ids(void) +{ + uint32_t n_ids = 0; + + for (pm_peer_id_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) + { + n_ids += pm_mutex_lock_status_get(m_pi.used_peer_ids, i); + } + + return n_ids; +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h new file mode 100644 index 0000000000..5664ccc574 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PEER_ID_H__ +#define PEER_ID_H__ + + +#include +#include "sdk_errors.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup peer_id Peer IDs + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module keeps track of which peer IDs are in + * use and which are free. + */ + + +/**@brief Function for initializing the module. + */ +void peer_id_init(void); + + +/**@brief Function for claiming an unused peer ID. + * + * @param peer_id The peer ID to allocate. If this is @ref PM_PEER_ID_INVALID, the first available + * will be allocated. + * + * @return The allocated peer ID. + * @retval PM_PEER_ID_INVALID If no peer ID could be allocated or module is not initialized. + */ +pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id); + + +/**@brief Function for marking a peer ID for deletion. + * + * @param peer_id The peer ID to delete. + * + * @retval true Deletion was successful. + * @retval false Peer ID already marked for deletion, peer_id was PM_PEER_ID_INVALID, or module is + * not initialized. + */ +bool peer_id_delete(pm_peer_id_t peer_id); + + +/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent + * storage. + * + * @param[in] peer_id Peer ID to free. + */ +void peer_id_free(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is marked for deletion. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true peer_id is in marked for deletion. + * @retval false peer_id is not marked for deletion, or the module is not initialized. + */ +bool peer_id_is_deleted(pm_peer_id_t peer_id); + + +/**@brief Function for finding out whether a peer ID is in use. + * + * @param[in] peer_id The peer ID to inquire about. + * + * @retval true peer_id is in use. + * @retval false peer_id is free, or the module is not initialized. + */ +bool peer_id_is_allocated(pm_peer_id_t peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be + * used to loop through all used peer IDs. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. + * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is + * not initialized. + */ +pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all peer IDs marked for deletion. + * Can be used to loop through all peer IDs marked for deletion. + * + * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary + * peer ID. + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. + * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. + * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is + * not initialized. + */ +pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers + * in persistent storage. + * + * @return The number of valid peer IDs, or 0 if module is not initialized. + */ +uint32_t peer_id_n_ids(void); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_ID_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c new file mode 100644 index 0000000000..9d31a463ca --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c @@ -0,0 +1,965 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "ble_err.h" +#include "peer_manager.h" +#include +#include "security_manager.h" +#include "security_dispatcher.h" +#include "gatt_cache_manager.h" +#include "gatts_cache_manager.h" +#include "peer_database.h" +#include "peer_data_storage.h" +#include "id_manager.h" +#include "ble_conn_state.h" +#include "peer_manager_internal.h" +#include "nrf_sdh_ble.h" + + +#define MODULE_INITIALIZED (m_module_initialized) /**< Macro indicating whether the module has been initialized properly. */ + + +static bool m_module_initialized; /**< Whether or not @ref pm_init has been called successfully. */ +static bool m_peer_rank_initialized; /**< Whether or not @ref rank_init has been called successfully. */ +static bool m_deleting_all; /**< True from when @ref pm_peers_delete is called until all peers have been deleted. */ +static pm_store_token_t m_peer_rank_token; /**< The store token of an ongoing peer rank update via a call to @ref pm_peer_rank_highest. If @ref PM_STORE_TOKEN_INVALID, there is no ongoing update. */ +static uint32_t m_current_highest_peer_rank; /**< The current highest peer rank. Used by @ref pm_peer_rank_highest. */ +static pm_peer_id_t m_highest_ranked_peer; /**< The peer with the highest peer rank. Used by @ref pm_peer_rank_highest. */ +static pm_evt_handler_t m_evt_handlers[PM_MAX_REGISTRANTS];/**< The subscribers to Peer Manager events, as registered through @ref pm_register. */ +static uint8_t m_n_registrants; /**< The number of event handlers registered through @ref pm_register. */ +static ble_conn_state_user_flag_id_t m_bonded_flag_id; /**< The flag ID for which connections are with a peer with which we are bonded. */ + + +/**@brief Function for sending a Peer Manager event to all subscribers. + * + * @param[in] p_pm_evt The event to send. + */ +static void evt_send(pm_evt_t const * p_pm_evt) +{ + for (int i = 0; i < m_n_registrants; i++) + { + m_evt_handlers[i](p_pm_evt); + } +} + + +/**@brief Function for initializing peer rank static variables. + */ +static void rank_vars_update(void) +{ + ret_code_t err_code = pm_peer_ranks_get(&m_highest_ranked_peer, + &m_current_highest_peer_rank, + NULL, + NULL); + + m_peer_rank_initialized = ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); +} + + +/**@brief Event handler for events from the Peer Database module. + * This handler is extern in the Peer Database module. + * + * @param[in] p_pdb_evt The incoming Peer Database event. + */ +void pm_pdb_evt_handler(pm_evt_t * p_pdb_evt) +{ + bool send_evt = true; + + p_pdb_evt->conn_handle = im_conn_handle_get(p_pdb_evt->peer_id); + + switch (p_pdb_evt->evt_id) + { + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) + && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_succeeded.token)) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_highest_ranked_peer = p_pdb_evt->peer_id; + + p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + } + else if ( m_peer_rank_initialized + && (p_pdb_evt->peer_id == m_highest_ranked_peer) + && (p_pdb_evt->params.peer_data_update_succeeded.data_id + == PM_PEER_DATA_ID_PEER_RANK)) + { + // Update peer rank variable if highest ranked peer has changed its rank. + rank_vars_update(); + } + } + else if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_DELETE) + { + if ( m_peer_rank_initialized + && (p_pdb_evt->peer_id == m_highest_ranked_peer) + && (p_pdb_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_PEER_RANK)) + { + // Update peer rank variable if highest ranked peer has deleted its rank. + rank_vars_update(); + } + } + break; + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) + { + if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) + && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_failed.token)) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_current_highest_peer_rank -= 1; + + p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + } + } + break; + + case PM_EVT_PEER_DELETE_SUCCEEDED: + // Check that no peers marked for deletion are left. + if (m_deleting_all + && (pdb_next_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID) + && (pdb_next_deleted_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID)) + { + // pm_peers_delete() has been called and this is the last peer to be deleted. + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + + send_evt = false; + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); // Ensure that PEER_DELETE_SUCCEEDED arrives before PEERS_DELETE_SUCCEEDED. + evt_send(&pm_delete_all_evt); + } + + if (m_peer_rank_initialized && (p_pdb_evt->peer_id == m_highest_ranked_peer)) + { + // Update peer rank variable if highest ranked peer has been deleted. + rank_vars_update(); + } + break; + + case PM_EVT_PEER_DELETE_FAILED: + if (m_deleting_all) + { + // pm_peers_delete() was called and has thus failed. + + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_FAILED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + pm_delete_all_evt.params.peers_delete_failed_evt.error + = p_pdb_evt->params.peer_delete_failed.error; + + send_evt = false; + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); // Ensure that PEER_DELETE_FAILED arrives before PEERS_DELETE_FAILED. + evt_send(&pm_delete_all_evt); + } + break; + + default: + // Do nothing. + break; + } + + if (send_evt) + { + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_pdb_evt); + } +} + + +/**@brief Event handler for events from the Security Manager module. + * This handler is extern in the Security Manager module. + * + * @param[in] p_sm_evt The incoming Security Manager event. + */ +void pm_sm_evt_handler(pm_evt_t * p_sm_evt) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_sm_evt); + + switch (p_sm_evt->evt_id) + { + case PM_EVT_CONN_SEC_SUCCEEDED: + { + bool bonded = p_sm_evt->params.conn_sec_succeeded.procedure + == PM_LINK_SECURED_PROCEDURE_BONDING; + ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_bonded_flag_id, bonded); + break; + } + + default: + /* No action */ + break; + } + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_sm_evt); +} + + +/**@brief Event handler for events from the GATT Cache Manager module. + * This handler is extern in GATT Cache Manager. + * + * @param[in] p_gcm_evt The incoming GATT Cache Manager event. + */ +void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt) +{ + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_gcm_evt); +} + + +/**@brief Event handler for events from the ID Manager module. + * This function is registered in the ID Manager. + * + * @param[in] p_im_evt The incoming ID Manager event. + */ +void pm_im_evt_handler(pm_evt_t * p_im_evt) +{ + switch (p_im_evt->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + ble_conn_state_user_flag_set(p_im_evt->conn_handle, m_bonded_flag_id, true); + break; + default: + /* No action. */ + break; + } + + // Forward the event to all registered Peer Manager event handlers. + evt_send(p_im_evt); +} + +/** + * @brief Function for handling BLE events. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context Context. + */ +static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) +{ + VERIFY_MODULE_INITIALIZED_VOID(); + + im_ble_evt_handler(p_ble_evt); + sm_ble_evt_handler(p_ble_evt); + gcm_ble_evt_handler(p_ble_evt); +} + +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, PM_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); + + +/**@brief Function for resetting the internal state of this module. + */ +static void internal_state_reset() +{ + m_highest_ranked_peer = PM_PEER_ID_INVALID; + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_bonded_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; +} + + +ret_code_t pm_init(void) +{ + ret_code_t err_code; + + err_code = pds_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = pdb_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = sm_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = smd_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = gcm_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = gscm_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + err_code = im_init(); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + internal_state_reset(); + + m_bonded_flag_id = ble_conn_state_user_flag_acquire(); + if (m_bonded_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + return NRF_ERROR_INTERNAL; + } + + m_peer_rank_initialized = false; + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +ret_code_t pm_register(pm_evt_handler_t event_handler) +{ + VERIFY_MODULE_INITIALIZED(); + + if (m_n_registrants >= PM_MAX_REGISTRANTS) + { + return NRF_ERROR_NO_MEM; + } + + m_evt_handlers[m_n_registrants] = event_handler; + m_n_registrants += 1; + + return NRF_SUCCESS; +} + + +ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params) +{ + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + + err_code = sm_sec_params_set(p_sec_params); + + // NRF_ERROR_INVALID_PARAM if parameters are invalid, + // NRF_SUCCESS otherwise. + return err_code; +} + + +ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing) +{ + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + + err_code = sm_link_secure(conn_handle, force_repairing); + + return err_code; +} + + +void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + if (p_conn_sec_config != NULL) + { + sm_conn_sec_config_reply(conn_handle, p_conn_sec_config); + } +} + + +ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context) +{ + VERIFY_MODULE_INITIALIZED(); + + return sm_sec_params_reply(conn_handle, p_sec_params, p_context); +} + + +void pm_local_database_has_changed(void) +{ + VERIFY_MODULE_INITIALIZED_VOID(); + gcm_local_database_has_changed(); +} + + +ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr) +{ + VERIFY_MODULE_INITIALIZED(); + return im_id_addr_set(p_addr); +} + + +ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_addr); + return im_id_addr_get(p_addr); +} + + +ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_privacy_params); + return im_privacy_set(p_privacy_params); +} + + +ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_privacy_params); + VERIFY_PARAM_NOT_NULL(p_privacy_params->p_device_irk); + return im_privacy_get(p_privacy_params); +} + + +bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) +{ + VERIFY_MODULE_INITIALIZED(); + + if ((p_addr == NULL) || (p_irk == NULL)) + { + return false; + } + else + { + return im_address_resolve(p_addr, p_irk); + } +} + + +ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + return im_whitelist_set(p_peers, peer_cnt); +} + + +ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + + if (((p_addrs == NULL) && (p_irks == NULL)) || + ((p_addrs != NULL) && (p_addr_cnt == NULL)) || + ((p_irks != NULL) && (p_irk_cnt == NULL))) + { + // The buffers can't be both NULL, and if a buffer is provided its size must be specified. + return NRF_ERROR_NULL; + } + + return im_whitelist_get(p_addrs, p_addr_cnt, p_irks, p_irk_cnt); +} + + +ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt) +{ + VERIFY_MODULE_INITIALIZED(); + return im_device_identities_list_set(p_peers, peer_cnt); +} + + +ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_conn_sec_status); + + ble_conn_state_status_t status = ble_conn_state_status(conn_handle); + + if (status == BLE_CONN_STATUS_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + + p_conn_sec_status->connected = (status == BLE_CONN_STATUS_CONNECTED); + p_conn_sec_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_bonded_flag_id); + p_conn_sec_status->encrypted = ble_conn_state_encrypted(conn_handle); + p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); + return NRF_SUCCESS; +} + + +ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) +{ + VERIFY_MODULE_INITIALIZED(); + return sm_lesc_public_key_set(p_public_key); +} + + +ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_conn_handle); + *p_conn_handle = im_conn_handle_get(peer_id); + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_peer_id); + *p_peer_id = im_peer_id_get_by_conn_handle(conn_handle); + return NRF_SUCCESS; +} + + +uint32_t pm_peer_count(void) +{ + if (!MODULE_INITIALIZED) + { + return 0; + } + return pdb_n_peers(); +} + + +pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id) +{ + if (!MODULE_INITIALIZED) + { + return PM_PEER_ID_INVALID; + } + return pdb_next_peer_id_get(prev_peer_id); +} + + +ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void * p_data, + uint16_t * p_length) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_data); + VERIFY_PARAM_NOT_NULL(p_length); + if (ALIGN_NUM(4, *p_length) != *p_length) + { + return NRF_ERROR_INVALID_PARAM; + } + + pm_peer_data_t peer_data; + memset(&peer_data, 0, sizeof(peer_data)); + peer_data.length_words = BYTES_TO_WORDS(*p_length); + peer_data.data_id = data_id; + peer_data.p_all_data = p_data; + + ret_code_t err_code = pdb_peer_data_load(peer_id, data_id, &peer_data); + + *p_length = peer_data.length_words * BYTES_PER_WORD; + + return err_code; +} + + +ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, + pm_peer_data_bonding_t * p_data) +{ + uint16_t length = sizeof(pm_peer_data_bonding_t); + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_BONDING, + p_data, + &length); +} + + +ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, + ble_gatt_db_srv_t * p_data, + uint16_t * p_length) +{ + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_GATT_REMOTE, + p_data, + p_length); +} + + +ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, + void * p_data, + uint16_t * p_length) +{ + return pm_peer_data_load(peer_id, + PM_PEER_DATA_ID_APPLICATION, + p_data, + p_length); +} + + +ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void const * p_data, + uint16_t length, + pm_store_token_t * p_token) +{ + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_data); + if (ALIGN_NUM(4, length) != length) + { + return NRF_ERROR_INVALID_PARAM; + } + + pm_peer_data_flash_t peer_data; + memset(&peer_data, 0, sizeof(peer_data)); + peer_data.length_words = BYTES_TO_WORDS(length); + peer_data.data_id = data_id; + peer_data.p_all_data = p_data; + + return pdb_raw_store(peer_id, &peer_data, p_token); +} + + +ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, + pm_peer_data_bonding_t const * p_data, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_BONDING, + p_data, + ALIGN_NUM(4, sizeof(pm_peer_data_bonding_t)), + p_token); +} + + +ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, + ble_gatt_db_srv_t const * p_data, + uint16_t length, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_GATT_REMOTE, + p_data, + length, + p_token); +} + + +ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, + void const * p_data, + uint16_t length, + pm_store_token_t * p_token) +{ + return pm_peer_data_store(peer_id, + PM_PEER_DATA_ID_APPLICATION, + p_data, + length, + p_token); +} + + +ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) +{ + VERIFY_MODULE_INITIALIZED(); + + if (data_id == PM_PEER_DATA_ID_BONDING) + { + return NRF_ERROR_INVALID_PARAM; + } + + return pdb_clear(peer_id, data_id); +} + + +ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, + pm_peer_data_bonding_t * p_bonding_data, + pm_store_token_t * p_token) +{ + ret_code_t err_code; + pm_peer_id_t peer_id; + pm_peer_data_flash_t peer_data; + + VERIFY_MODULE_INITIALIZED(); + VERIFY_PARAM_NOT_NULL(p_bonding_data); + VERIFY_PARAM_NOT_NULL(p_new_peer_id); + + memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); + + // Search through existing bonds to look for a duplicate. + pds_peer_data_iterate_prepare(); + + // @note emdi: should maybe use a critical section, since data is not copied while iterating. + while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) + { + if (im_is_duplicate_bonding_data(p_bonding_data, peer_data.p_bonding_data)) + { + *p_new_peer_id = peer_id; + return NRF_SUCCESS; + } + } + + // If no duplicate data is found, prepare to write a new bond to flash. + + *p_new_peer_id = pdb_peer_allocate(); + + if (*p_new_peer_id == PM_PEER_ID_INVALID) + { + return NRF_ERROR_NO_MEM; + } + + memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); + + peer_data.data_id = PM_PEER_DATA_ID_BONDING; + peer_data.p_bonding_data = p_bonding_data; + peer_data.length_words = BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)); + + err_code = pdb_raw_store(*p_new_peer_id, &peer_data, p_token); + + if (err_code != NRF_SUCCESS) + { + if (im_peer_free(*p_new_peer_id) != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + // NRF_ERROR_STORAGE_FULL, if no space in flash. + // NRF_ERROR_BUSY, if flash filesystem was busy. + // NRF_ERROR_INTENRAL, on internal error. + return err_code; + } + + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_delete(pm_peer_id_t peer_id) +{ + VERIFY_MODULE_INITIALIZED(); + + return im_peer_free(peer_id); +} + + +ret_code_t pm_peers_delete(void) +{ + VERIFY_MODULE_INITIALIZED(); + + m_deleting_all = true; + + pm_peer_id_t current_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); + + if (current_peer_id == PM_PEER_ID_INVALID) + { + // No peers bonded. + m_deleting_all = false; + + pm_evt_t pm_delete_all_evt; + memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); + pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; + pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; + pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; + + evt_send(&pm_delete_all_evt); + } + + while (current_peer_id != PM_PEER_ID_INVALID) + { + ret_code_t err_code = pm_peer_delete(current_peer_id); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + current_peer_id = pdb_next_peer_id_get(current_peer_id); + } + + return NRF_SUCCESS; +} + + +ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, + uint32_t * p_highest_rank, + pm_peer_id_t * p_lowest_ranked_peer, + uint32_t * p_lowest_rank) +{ + VERIFY_MODULE_INITIALIZED(); + + pm_peer_id_t peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); + uint32_t peer_rank = 0; + //lint -save -e65 -e64 + pm_peer_data_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(peer_rank)), + .p_peer_rank = &peer_rank}; + //lint -restore + ret_code_t err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); + uint32_t highest_rank = 0; + uint32_t lowest_rank = 0xFFFFFFFF; + pm_peer_id_t highest_ranked_peer = PM_PEER_ID_INVALID; + pm_peer_id_t lowest_ranked_peer = PM_PEER_ID_INVALID; + + if (err_code == NRF_ERROR_INVALID_PARAM) + { + // No peer IDs exist. + return NRF_ERROR_NOT_FOUND; + } + + while ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)) + { + if (err_code == NRF_ERROR_NOT_FOUND) + { + peer_rank = 0; + } + if (peer_rank >= highest_rank) + { + highest_rank = peer_rank; + highest_ranked_peer = peer_id; + } + if (peer_rank < lowest_rank) + { + lowest_rank = peer_rank; + lowest_ranked_peer = peer_id; + } + peer_id = pdb_next_peer_id_get(peer_id); + err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); + } + if (peer_id == PM_PEER_ID_INVALID) + { + err_code = NRF_SUCCESS; + if (p_highest_ranked_peer != NULL) + { + *p_highest_ranked_peer = highest_ranked_peer; + } + if (p_highest_rank != NULL) + { + *p_highest_rank = highest_rank; + } + if (p_lowest_ranked_peer != NULL) + { + *p_lowest_ranked_peer = lowest_ranked_peer; + } + if (p_lowest_rank != NULL) + { + *p_lowest_rank = lowest_rank; + } + } + else + { + err_code = NRF_ERROR_INTERNAL; + } + return err_code; +} + + +/**@brief Function for initializing peer rank functionality. + */ +static void rank_init(void) +{ + rank_vars_update(); +} + + +ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id) +{ + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + //lint -save -e65 -e64 + pm_peer_data_flash_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(m_current_highest_peer_rank)), + .data_id = PM_PEER_DATA_ID_PEER_RANK, + .p_peer_rank = &m_current_highest_peer_rank}; + //lint -restore + + + if (!m_peer_rank_initialized) + { + rank_init(); + } + + if (!m_peer_rank_initialized || (m_peer_rank_token != PM_STORE_TOKEN_INVALID)) + { + err_code = NRF_ERROR_BUSY; + } + else + { + if ((peer_id == m_highest_ranked_peer) && (m_current_highest_peer_rank > 0)) + { + pm_evt_t pm_evt; + + // The reported peer is already regarded as highest (provided it has an index at all) + err_code = NRF_SUCCESS; + + memset(&pm_evt, 0, sizeof(pm_evt)); + pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; + pm_evt.conn_handle = im_conn_handle_get(peer_id); + pm_evt.peer_id = peer_id; + pm_evt.params.peer_data_update_succeeded.data_id = PM_PEER_DATA_ID_PEER_RANK; + pm_evt.params.peer_data_update_succeeded.action = PM_PEER_DATA_OP_UPDATE; + pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; + pm_evt.params.peer_data_update_succeeded.flash_changed = false; + + evt_send(&pm_evt); + } + else + { + m_current_highest_peer_rank += 1; + err_code = pdb_raw_store(peer_id, &peer_data, &m_peer_rank_token); + if (err_code != NRF_SUCCESS) + { + m_peer_rank_token = PM_STORE_TOKEN_INVALID; + m_current_highest_peer_rank -= 1; + { + if ((err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_STORAGE_FULL)) + err_code = NRF_ERROR_INTERNAL; + } + } + } + } + return err_code; +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h new file mode 100644 index 0000000000..b8a65f098f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h @@ -0,0 +1,765 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 peer_manager.h + * + * @defgroup peer_manager Peer Manager + * @ingroup ble_sdk_lib + * @{ + * @brief Module for managing BLE bonding, which includes controlling encryption and pairing + * procedures as well as persistently storing different pieces of data that must be stored + * when bonded. + * + * @details The API consists of functions for configuring the pairing and encryption behavior of the + * device and functions for manipulating the stored data. + * + * This module uses Flash Data Storage (FDS) to interface with persistent storage. The + * Peer Manager needs exclusive use of certain FDS file IDs and record keys. See + * @ref lib_fds_functionality_keys for more information. + */ + + +#ifndef PEER_MANAGER_H__ +#define PEER_MANAGER_H__ + +#include +#include +#include "sdk_common.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "peer_database.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/**@brief Security status of a connection. + */ +typedef struct +{ + uint8_t connected : 1; /**< @brief The connection is active (not disconnected). */ + uint8_t encrypted : 1; /**< @brief Communication on this link is encrypted. */ + uint8_t mitm_protected : 1; /**< @brief The encrypted communication is also protected against man-in-the-middle attacks. */ + uint8_t bonded : 1; /**< @brief The peer is bonded with us. */ +} pm_conn_sec_status_t; + + +/**@brief Function for initializing the Peer Manager. + * + * @details You must initialize the Peer Manager before you can call any other Peer Manager + * functions. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_init(void); + + +/**@brief Function for registering an event handler with the Peer Manager. + * + * @param[in] event_handler Callback for events from the @ref peer_manager module. @p event_handler + * is called for every event that the Peer Manager sends after this + * function is called. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If @p event_handler was NULL. + * @retval NRF_ERROR_NO_MEM If no more registrations can happen. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_register(pm_evt_handler_t event_handler); + + +/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. + * + * @details Until this function is called, all bonding procedures that are initiated by the + * peer are rejected. + * + * This function can be called multiple times with different parameters, even with NULL as + * @p p_sec_params, in which case the Peer Manager starts rejecting all procedures again. + * + * @param[in] p_sec_params Security parameters to be used for subsequent security procedures. + * + * @retval NRF_SUCCESS If the parameters were set successfully. + * @retval NRF_ERROR_INVALID_PARAM If the combination of parameters is invalid. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params); + + +/**@brief Function for establishing encryption on a connection, and optionally establishing a bond. + * + * @details This function attempts to secure the link that is specified by @p conn_handle. It uses + * the parameters that were previously provided in a call to @ref pm_sec_params_set. + * + * If the connection is a master connection, calling this function starts a security + * procedure on the link. If we have keys from a previous bonding procedure with this peer + * and the keys meet the security requirements in the currently active security parameters, + * the function attempts to establish encryption with the existing keys. If no key exists, + * the function attempts to perform pairing and bonding according to the currently active + * security parameters. + * + * If the function completes successfully, a @ref PM_EVT_CONN_SEC_START event is sent. + * The procedure might be queued, in which case the @ref PM_EVT_CONN_SEC_START event is + * delayed until the procedure is initiated in the SoftDevice. + * + * If the connection is a slave connection, the function sends a security request to + * the peer (master). It is up to the peer then to initiate pairing or encryption. + * If the peer ignores the request, a @ref BLE_GAP_EVT_TIMEOUT event occurs + * with the source @ref BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST. Otherwise, the peer initiates + * security, in which case things happen as if the peer had initiated security itself. + * See @ref PM_EVT_CONN_SEC_START for information about peer-initiated security. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[in] force_repairing Whether to force a pairing procedure even if there is an existing + * encryption key. This argument is relevant only for + * the central role. Recommended value: false. + * + * @retval NRF_SUCCESS If the operation completed successfully. + * @retval NRF_ERROR_TIMEOUT If there was an SMP time-out, so that no more security + * operations can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. + * @retval NRF_ERROR_NOT_FOUND If the security parameters have not been set, either by + * @ref pm_sec_params_set or by @ref pm_conn_sec_params_reply. + * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. + * @retval NRF_ERROR_NO_MEM If no more authentication procedures can run in parallel + * for the given role. See @ref sd_ble_gap_authenticate. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized, or the peer is + * disconnected or in the process of disconnecting. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing security parameters for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, the parameters given in @ref pm_sec_params_set are used. See @ref + * pm_conn_sec_config_t for the value of the default. + * + * @param[in] conn_handle The connection to set the parameters for. + * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. + * @param[in] p_context The context found in the request event that this function replies to. + * + * @retval NRF_SUCCESS Successful reply. + * @retval NRF_ERROR_NULL p_sec_params or p_context was null. + * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context); + + +/**@brief Function for manually informing that the local database has changed. + * + * @details This function sends a service changed indication to all bonded and/or connected peers + * that subscribe to this indication. If a bonded peer is not connected, the indication is + * sent when it reconnects. Every time an indication is sent, a @ref + * PM_EVT_SERVICE_CHANGED_IND_SENT event occurs, followed by a @ref + * PM_EVT_SERVICE_CHANGED_IND_CONFIRMED when the peer sends its confirmation. Peers that + * are not subscribed to the service changed indication when this function is called do not + * receive an indication, and no events are sent to the user. Likewise, if the service + * changed characteristic is not present in the local database, this no indications are + * sent peers, and no events are sent to the user. + */ +void pm_local_database_has_changed(void); + + +/**@brief Function for getting the security status of a connection. + * + * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. + * @param[out] p_conn_sec_status Security status of the link. + * + * @retval NRF_SUCCESS If pairing was initiated successfully. + * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. + * @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status); + + +/**@brief Experimental function for specifying the public key to use for LESC operations. + * + * @details This function can be called multiple times. The specified public key will be used for + * all subsequent LESC (LE Secure Connections) operations until the next time this function + * is called. + * + * @note The key must continue to reside in application memory as it is not copied by Peer Manager. + * + * @param[in] p_public_key The public key to use for all subsequent LESC operations. + * + * @retval NRF_SUCCESS If pairing was initiated successfully. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); + + +/**@brief Function for setting or clearing the whitelist. + * + * When using the S13x SoftDevice v3.x, this function sets or clears the whitelist. + * When using the S13x SoftDevice v2.x, this function caches a list of + * peers that can be retrieved later by @ref pm_whitelist_get to pass to the @ref lib_ble_advertising. + * + * To clear the current whitelist, pass either NULL as @p p_peers or zero as @p peer_cnt. + * + * @param[in] p_peers The peers to add to the whitelist. Pass NULL to clear the current whitelist. + * @param[in] peer_cnt The number of peers to add to the whitelist. The number must not be greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. Pass zero to clear the current + * whitelist. + * + * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. + * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is already in use and cannot be set. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer in @p p_peers has an address that cannot + * be used for whitelisting. + * @retval NRF_ERROR_NOT_FOUND If any of the peers in @p p_peers cannot be found. + * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than + * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/**@brief Function for retrieving the previously set whitelist. + * + * The function retrieves the whitelist of GAP addresses and IRKs that was + * previously set by @ref pm_whitelist_set. + * + * To retrieve only GAP addresses or only IRKs, provide only one of the + * buffers. If a buffer is provided, its size must be specified. + * + * @param[out] p_addrs The buffer where to store GAP addresses. Pass NULL to retrieve + * only IRKs (in that case, @p p_irks must not be NULL). + * @param[in,out] p_addr_cnt In: The size of the @p p_addrs buffer. + * May be NULL if and only if @p p_addrs is NULL. + * Out: The number of GAP addresses copied into the buffer. + * If @p p_addrs is NULL, this parameter remains unchanged. + * @param[out] p_irks The buffer where to store IRKs. Pass NULL to retrieve + * only GAP addresses (in that case, @p p_addrs must not NULL). + * @param[in,out] p_irk_cnt In: The size of the @p p_irks buffer. + * May be NULL if and only if @p p_irks is NULL. + * Out: The number of IRKs copied into the buffer. + * If @p p_irks is NULL, this paramater remains unchanged. + * + * @retval NRF_SUCCESS If the whitelist was successfully retrieved. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be used for + * whitelisting (this error can occur only + * when using the S13x SoftDevice v2.x). + * @retval NRF_ERROR_NULL If a required parameter is NULL. + * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. + * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers + * cannot be found. It might have been deleted. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, + uint32_t * p_addr_cnt, + ble_gap_irk_t * p_irks, + uint32_t * p_irk_cnt); + + +/**@brief Function for setting and clearing the device identities list. + * + * @param[in] p_peers The peers to add to the device identities list. Pass NULL to clear + * the device identities list. + * @param[in] peer_cnt The number of peers. Pass zero to clear the device identities list. + * + * @retval NRF_SUCCESS If the device identities list was successfully + * set or cleared. + * @retval NRF_ERROR_NOT_FOUND If a peer is invalid or its data could not + * be found in flash. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be + * used for whitelisting. + * @retval BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE If the device identities list is in use and + * cannot be set. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_NOT_SUPPORTED If using a SoftDevice that does not support + * device identities, e.g. S130 v2.0. + */ +ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, + uint32_t peer_cnt); + + +/**@brief Function for setting the local Bluetooth identity address. + * + * @details The local Bluetooth identity address is the address that identifies the device + * to other peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are running. + * + * The SoftDevice sets a default address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC when it is + * enabled. This default address is a random number that is populated during the IC manufacturing + * process. It remains unchanged for the lifetime of each IC, but the application can use this + * function to assign a different identity address. + * + * The identity address is distributed to the peer during bonding. Changing the identity address + * means bonded devices might not recognize us. + * + * + * @param[in] p_addr The GAP address to be set. + * + * @retval NRF_SUCCESS If the identity address was set successfully. + * @retval NRF_ERROR_NULL If @p p_addr is NULL. + * @retval NRF_ERROR_INVALID_ADDR If the @p p_addr pointer is invalid. + * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address is invalid. + * @retval NRF_ERROR_BUSY If the SoftDevice was busy. Process SoftDevice events + * and retry. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized or if this function + * was called while advertising, scanning, or while connected. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr); + + +/**@brief Function for retrieving the local Bluetooth identity address. + * + * This function always returns the identity address, irrespective of the privacy settings. + * This means that the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref + * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to the address structure to be filled in. + * + * @retval NRF_SUCCESS If the address was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_addr is NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr); + + +/**@brief Function for configuring privacy settings. + * + * The privacy settings cannot be configured while advertising, scanning, or while in a connection. + * + * @note The SoftDevice functions @ref sd_ble_gap_addr_set + * and @ref sd_ble_gap_privacy_set must not be called when using the Peer Manager. + * Use this function instead. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If the privacy settings were configured successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. + * @retval NRF_ERROR_BUSY If the operation could not be performed at this time. + * Process SoftDevice events and retry. + * @retval NRF_ERROR_INVALID_PARAM If the address type is invalid. + * @retval NRF_ERROR_INVALID_STATE If this function is called while BLE roles using + * privacy are enabled. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params); + + +/**@brief Function for retrieving privacy settings. + * + * The privacy settings that are returned include the current IRK as well. + * + * @param[out] p_privacy_params Privacy settings. + * + * @retval NRF_SUCCESS If the privacy settings were retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_privacy_params or @p p_privacy_params->p_device_irk is + * NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params); + + +/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). + * + * @param[in] p_addr A private random resolvable address. + * @param[in] p_irk An identity resolution key (IRK). + * + * @retval true The IRK used matched the one used to create the address. + * @retval false The IRK used did not match the one used to create the address, or an argument was + * NULL or invalid. + */ +bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); + + +/**@brief Function for getting the connection handle of the connection with a bonded peer. + * + * @param[in] peer_id The peer ID of the bonded peer. + * @param[out] p_conn_handle Connection handle, or @ref BLE_ERROR_INVALID_CONN_HANDLE if the peer + * is not connected. + * + * @retval NRF_SUCCESS If the connection handle was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_conn_handle was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle); + + +/**@brief Function for retrieving the ID of a peer, given its connection handle. + * + * @param[in] conn_handle The connection handle of the peer. + * @param[out] p_peer_id The peer ID, or @ref PM_PEER_ID_INVALID if the peer is not bonded or + * @p conn_handle does not refer to a valid connection. + * + * @retval NRF_SUCCESS If the peer ID was retrieved successfully. + * @retval NRF_ERROR_NULL If @p p_peer_id was NULL. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id); + + +/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. + * + * @details This function can be used to loop through all used peer IDs. The order in which + * peer IDs are returned should be considered unpredictable. @ref PM_PEER_ID_INVALID + * is considered to be before the first and after the last used peer ID. + * + * @details To loop through all peer IDs exactly once, use the following constuct: + * @code{c} + * pm_peer_id_t current_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); + * while (current_peer_id != PM_PEER_ID_INVALID) + * { + * // Do something with current_peer_id. + * current_peer_id = pm_next_peer_id_get(current_peer_id) + * } + * @endcode + * + * @param[in] prev_peer_id The previous peer ID. + * + * @return The next peer ID. If @p prev_peer_id was @ref PM_PEER_ID_INVALID, the + * next peer ID is the first used peer ID. If @p prev_peer_id was the last + * used peer ID, the function returns @ref PM_PEER_ID_INVALID. + */ +pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id); + + +/**@brief Function for querying the number of valid peer IDs that are available. + * + * @details This function returns the number of peers for which there is data in persistent storage. + * + * @return The number of valid peer IDs. + */ +uint32_t pm_peer_count(void); + + + + +/**@anchor PM_PEER_DATA_FUNCTIONS + * @name Functions (Peer Data) + * Functions for manipulating peer data. + * @{ + */ + +/** + * @{ + */ + +/**@brief Function for retrieving stored data of a peer. + * + * @note The length of the provided buffer must be a multiple of 4. + * + * @param[in] peer_id Peer ID to get data for. + * @param[in] data_id Which type of data to read. + * @param[out] p_data Where to put the retrieved data. The documentation for + * @ref pm_peer_data_id_t specifies what data type each data ID is stored as. + * @param[inout] p_len In: The length in bytes of @p p_data. + * Out: The length in bytes of the read data, if the read was successful. + * + * @retval NRF_SUCCESS If the data was read successfully. + * @retval NRF_ERROR_INVALID_PARAM If the the data type or the peer ID was invalid or unallocated, + * or if the length in @p p_length was not a multiple of 4. + * @retval NRF_ERROR_NULL If a pointer parameter was NULL. + * @retval NRF_ERROR_NOT_FOUND If no stored data was found for this peer ID/data ID combination. + * @retval NRF_ERROR_DATA_SIZE If the provided buffer was not large enough. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void * p_data, + uint16_t * p_len); + +/**@brief Function for reading a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, + pm_peer_data_bonding_t * p_data); + +/**@brief Function for reading a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, + ble_gatt_db_srv_t * p_data, + uint16_t * p_len); + +/**@brief Function for reading a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). + * @details See @ref pm_peer_data_load for parameters and return values. */ +ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, + void * p_data, + uint16_t * p_len); +/** @}*/ + + +/** + * @{ + */ + +/**@brief Function for setting or updating stored data of a peer. + * + * @note Writing the data to persistent storage happens asynchronously. Therefore, the buffer + * that contains the data must be kept alive until the operation has completed. + * + * @note The data written using this function might later be overwritten as a result of internal + * operations in the Peer Manager. A Peer Manager event is sent each time data is updated, + * regardless of whether the operation originated internally or from action by the user. + * + * @param[in] peer_id Peer ID to set data for. + * @param[in] data_id Which type of data to set. + * @param[in] p_data New value to set. The documentation for @ref pm_peer_data_id_t specifies + * what data type each data ID should be stored as. + * @param[in] len The length in bytes of @p p_data. + * @param[out] p_token A token that identifies this particular store operation. The token can be + * used to identify events that pertain to this operation. This parameter can + * be NULL. + * + * @retval NRF_SUCCESS If the data is scheduled to be written to persistent storage. + * @retval NRF_ERROR_NULL If @p p_data is NULL. + * @retval NRF_ERROR_NOT_FOUND If no peer was found for the peer ID. + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, + pm_peer_data_id_t data_id, + void const * p_data, + uint16_t len, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, + pm_peer_data_bonding_t const * p_data, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, + ble_gatt_db_srv_t const * p_data, + uint16_t len, + pm_store_token_t * p_token); + +/**@brief Function for setting or updating a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). + * @details See @ref pm_peer_data_store for parameters and return values. */ +ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, + void const * p_data, + uint16_t len, + pm_store_token_t * p_token); +/** @}*/ + + +/** + * @{ + */ + +/**@brief Function for deleting a peer's stored pieces of data. + * + * @details This function deletes specific data that is stored for a peer. Note that bonding data + * cannot be cleared separately. + * + * To delete all data for a peer (including bonding data), use @ref pm_peer_delete. + * + * @note Clearing data in persistent storage happens asynchronously. + * + * @param[in] peer_id Peer ID to clear data for. + * @param[in] data_id Which data to clear. + * + * @retval NRF_SUCCESS If the clear procedure was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If @p data_id was PM_PEER_DATA_ID_BONDING or invalid, or + * @p peer_id was invalid. + * @retval NRF_ERROR_NOT_FOUND If there was no data to clear for this peer ID/data ID combination. + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); + + +/**@brief Function for manually adding a peer to the persistent storage. + * + * @details This function allocates a new peer ID and stores bonding data for the new peer. The + * bonding data is necessary to prevent ambiguity/inconsistency in peer data. + * + * @param[in] p_bonding_data The bonding data of the new peer (must contain a public/static + * address or a non-zero IRK). + * @param[out] p_new_peer_id Peer ID for the new peer, or an existing peer if a match was found. + * @param[out] p_token A token that identifies this particular store operation (storing the + * bonding data). The token can be used to identify events that pertain + * to this operation. This parameter can be NULL. + * + * @retval NRF_SUCCESS If the store operation for bonding data was initiated successfully. + * @retval NRF_ERROR_NULL If @p p_bonding_data or @p p_new_peer_id is NULL. + * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. + * @retval NRF_ERROR_NO_MEM If there are no more available peer IDs. + * @retval NRF_ERROR_BUSY If the underlying flash filesystem is busy with other flash + * operations. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, + pm_peer_data_bonding_t * p_bonding_data, + pm_store_token_t * p_token); + + +/**@brief Function for freeing persistent storage for a peer. + * + * @details This function deletes every piece of data that is associated with the specified peer and + * frees the peer ID to be used for another peer. The deletion happens asynchronously, and + * the peer ID is not freed until the data is deleted. When the operation finishes, a @ref + * PM_EVT_PEER_DELETE_SUCCEEDED or @ref PM_EVT_PEER_DELETE_FAILED event is sent. + * + * @warning Use this function only when not connected to or connectable for the peer that is being + * deleted. If the peer is or becomes connected or data is manually written in flash during + * this procedure (until the success or failure event happens), the behavior is undefined. + * + * @param[in] peer_id Peer ID to be freed and have all associated data deleted. + * + * @retval NRF_SUCCESS If the operation was initiated successfully. + * @retval NRF_ERROR_INVALID_PARAM If the peer ID was not valid. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + */ +ret_code_t pm_peer_delete(pm_peer_id_t peer_id); + + +/**@brief Function for deleting all data stored for all peers. + * + * @details This function sends either a @ref PM_EVT_PEERS_DELETE_SUCCEEDED or a @ref + * PM_EVT_PEERS_DELETE_FAILED event. In addition, a @ref PM_EVT_PEER_DELETE_SUCCEEDED or + * @ref PM_EVT_PEER_DELETE_FAILED event is sent for each deleted peer. + * + * @note When there is no peer data in flash the @ref PM_EVT_PEER_DELETE_SUCCEEDED event is sent synchronously. + * + * @warning Use this function only when not connected or connectable. If a peer is or becomes + * connected or a @ref PM_PEER_DATA_FUNCTIONS function is used during this procedure (until + * the success or failure event happens), the behavior is undefined. + * + * @retval NRF_SUCCESS If the deletion process was initiated successfully. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peers_delete(void); +/** @}*/ + + +/** + * @{ + */ + + +/**@brief Function for finding the highest and lowest ranked peers. + * + * @details The rank is saved in persistent storage under the data ID @ref PM_PEER_DATA_ID_PEER_RANK. + * + * @details The interpretation of rank is up to the user, because the rank is only updated by + * calling @ref pm_peer_rank_highest or by manipulating the value using a @ref + * PM_PEER_DATA_FUNCTIONS function. + * + * @note Any argument that is NULL is ignored. + * + * @param[out] p_highest_ranked_peer The peer ID with the highest rank of all peers, for example, + * the most recently used peer. + * @param[out] p_highest_rank The highest rank. + * @param[out] p_lowest_ranked_peer The peer ID with the lowest rank of all peers, for example, + * the least recently used peer. + * @param[out] p_lowest_rank The lowest rank. + * + * @retval NRF_SUCCESS If the operation completed successfully. + * @retval NRF_ERROR_NOT_FOUND If no peers were found. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, + uint32_t * p_highest_rank, + pm_peer_id_t * p_lowest_ranked_peer, + uint32_t * p_lowest_rank); + + +/**@brief Function for updating the rank of a peer to be highest among all stored peers. + * + * @details If this function returns @ref NRF_SUCCESS, either a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or a + * @ref PM_EVT_PEER_DATA_UPDATE_FAILED event is sent with a @ref + * PM_STORE_TOKEN_INVALID store token when the operation is complete. Until the operation + * is complete, this function returns @ref NRF_ERROR_BUSY. + * + * When the operation is complete, the peer is the highest ranked peer as reported by + * @ref pm_peer_ranks_get. + * + * @note The @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event can arrive before the function returns if the peer + * is already ranked highest. In this case, the @ref pm_peer_data_update_succeeded_evt_t::flash_changed flag + * in the event will be false. + * + * @param[in] peer_id The peer to rank highest. + * + * @retval NRF_SUCCESS If the peer's rank is, or will be updated to be highest. + * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash + * operations, or if a previous call to this function has not + * completed. Try again after receiving a Peer Manager event. + * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. + * @retval NRF_ERROR_INTERNAL If an internal error occurred. + */ +ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id); + +/** @}*/ + +/** @} */ + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // PEER_MANAGER_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h new file mode 100644 index 0000000000..f3299d0a1e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PEER_MANAGER_INTERNAL_H__ +#define PEER_MANAGER_INTERNAL_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @file peer_manager_types.h + * + * @addtogroup peer_manager + * @brief File containing definitions used solely inside the Peer Manager's modules. + * @{ + */ + +ANON_UNIONS_ENABLE + +/**@brief One piece of data associated with a peer, together with its type. + * + * @note This type is deprecated. + */ +typedef struct +{ + uint16_t length_words; /**< @brief The length of the data in words. */ + pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ + union + { + pm_peer_data_bonding_t * p_bonding_data; /**< @brief The exchanged bond information in addition to metadata of the bonding. */ + uint32_t * p_peer_rank; /**< @brief A value locally assigned to this peer. Its interpretation is up to the user. The rank is not set automatically by the Peer Manager, but it is assigned by the user using either @ref pm_peer_rank_highest or a @ref PM_PEER_DATA_FUNCTIONS function. */ + bool * p_service_changed_pending; /**< @brief Whether a service changed indication should be sent to the peer. */ + pm_peer_data_local_gatt_db_t * p_local_gatt_db; /**< @brief Persistent information pertaining to a peer GATT client. */ + ble_gatt_db_srv_t * p_remote_gatt_db; /**< @brief Persistent information pertaining to a peer GATT server. */ + uint8_t * p_application_data; /**< @brief Arbitrary data to associate with the peer. This data can be freely used by the application. */ + void * p_all_data; /**< @brief Generic access pointer to the data. It is used only to handle the data without regard to type. */ + }; /**< @brief The data. */ +} pm_peer_data_t; + + +/**@brief Immutable version of @ref pm_peer_data_t. + * + * @note This type is deprecated. + */ +typedef struct +{ + uint16_t length_words; /**< @brief The length of the data in words. */ + pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ + union + { + pm_peer_data_bonding_t const * p_bonding_data; /**< @brief Immutable @ref pm_peer_data_t::p_bonding_data. */ + uint32_t const * p_peer_rank; /**< @brief Immutable @ref pm_peer_data_t::p_peer_rank. */ + bool const * p_service_changed_pending; /**< @brief Immutable @ref pm_peer_data_t::p_service_changed_pending. */ + pm_peer_data_local_gatt_db_t const * p_local_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_local_gatt_db. */ + ble_gatt_db_srv_t const * p_remote_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_remote_gatt_db. */ + uint8_t const * p_application_data; /**< @brief Immutable @ref pm_peer_data_t::p_application_data. */ + void const * p_all_data; /**< @brief Immutable @ref pm_peer_data_t::p_all_data. */ + }; /**< @brief The data. */ +} pm_peer_data_const_t; + +ANON_UNIONS_DISABLE + + +/**@brief Version of @ref pm_peer_data_t that reflects the structure of peer data in flash. + * + * @note This type is deprecated. + */ +typedef pm_peer_data_const_t pm_peer_data_flash_t; + + +/**@brief Event handler for events from the @ref peer_manager module. + * + * @sa pm_register + * + * @param[in] p_event The event that has occurred. + */ +typedef void (*pm_evt_handler_internal_t)(pm_evt_t * p_event); + + +/**@brief Macro for calculating the flash size of bonding data. + * + * @return The number of words that the data takes in flash. + */ +#define PM_BONDING_DATA_N_WORDS() BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)) + + +/**@brief Macro for calculating the flash size of service changed pending state. + * + * @return The number of words that the data takes in flash. + */ +#define PM_SC_STATE_N_WORDS() BYTES_TO_WORDS(sizeof(bool)) + + +/**@brief Macro for calculating the flash size of local GATT database data. + * + * @param[in] local_db_len The length, in bytes, of the database as reported by the SoftDevice. + * + * @return The number of words that the data takes in flash. + */ +#define PM_LOCAL_DB_N_WORDS(local_db_len) \ + BYTES_TO_WORDS((local_db_len) + PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + + +/**@brief Macro for calculating the length of a local GATT database attribute array. + * + * @param[in] n_words The number of words that the data takes in flash. + * + * @return The length of the database attribute array. + */ +#define PM_LOCAL_DB_LEN(n_words) (((n_words) * BYTES_PER_WORD) - PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + + +/**@brief Macro for calculating the flash size of remote GATT database data. + * + * @param[in] service_count The number of services in the service array. + * + * @return The number of words that the data takes in flash. + */ +#define PM_REMOTE_DB_N_WORDS(service_count) BYTES_TO_WORDS(sizeof(ble_gatt_db_srv_t) * (service_count)) + + +/**@brief Macro for calculating the flash size of remote GATT database data. + * + * @param[in] n_words The length in number of words. + * + * @return The number of words that the data takes in flash. + */ +#define PM_REMOTE_DB_N_SERVICES(n_words) (((n_words) * BYTES_PER_WORD) / sizeof(ble_gatt_db_srv_t)) + + +/**@brief Function for calculating the flash size of the usage index. + * + * @return The number of words that the data takes in flash. + */ +#define PM_USAGE_INDEX_N_WORDS() BYTES_TO_WORDS(sizeof(uint32_t)) + +/** @} + * @endcond + */ + + +#ifdef NRF_PM_DEBUG + + #define NRF_PM_DEBUG_CHECK(condition) \ + if (!(condition)) \ + { \ + __asm("bkpt #0"); \ + } + +#else + + // Prevent "variable set but never used" compiler warnings. + #define NRF_PM_DEBUG_CHECK(condition) (void)(condition) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_MANAGER_INTERNAL_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h new file mode 100644 index 0000000000..8c699839fb --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h @@ -0,0 +1,377 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 peer_manager_types.h + * + * @addtogroup peer_manager + * @{ + */ + +#ifndef PEER_MANAGER_TYPES_H__ +#define PEER_MANAGER_TYPES_H__ + +#include +#include +#include +#include "nrf.h" +#include "ble_gap.h" +#include "ble_hci.h" +#include "ble_gatt_db.h" +#include "app_util.h" +#include "app_util_platform.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Handle to uniquely identify a peer for which we have persistently stored data. + */ +typedef uint16_t pm_peer_id_t; + +/**@brief Type that is used for write prepares (used to reserve space in flash). + */ +typedef uint32_t pm_prepare_token_t; + +/**@brief Type that is used to hold a reference to a stored item in flash. + */ +typedef uint32_t pm_store_token_t; + +/**@brief Errors from security procedures in Peer Manager. + * + * @details Possible values are defined in @ref PM_SEC_ERRORS and @ref BLE_GAP_SEC_STATUS. + */ +typedef uint16_t pm_sec_error_code_t; + + +//lint -emacro(516,PM_LOCAL_DB_LEN_OVERHEAD_BYTES) + +#define PM_PEER_ID_INVALID 0xFFFF /**< @brief Invalid value for @ref pm_peer_id_t. */ +#define PM_STORE_TOKEN_INVALID 0 /**< @brief Invalid value for store token. */ +#define PM_PEER_ID_N_AVAILABLE_IDS 256 /**< @brief The number of available peer IDs. */ +#define PM_LOCAL_DB_LEN_OVERHEAD_BYTES offsetof(pm_peer_data_local_gatt_db_t, data) /**< @brief The static-length part of the local GATT data struct. */ + + +#define PM_CONN_SEC_ERROR_BASE 0x1000 /**< @brief The base for Peer Manager defined errors. See @ref PM_SEC_ERRORS and @ref pm_sec_error_code_t. */ + + +/**@defgroup PM_SEC_ERRORS Peer Manager defined security errors + * + * @details The first 256 numbers in this range correspond to the status codes in + * @ref BLE_HCI_STATUS_CODES. + * @{ */ +#define PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING (PM_CONN_SEC_ERROR_BASE + 0x06) /**< @brief Encryption failed because the peripheral has lost the LTK for this bond. See also @ref BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING and Table 3.7 ("Pairing Failed Reason Codes") in the Bluetooth Core Specification 4.2, section 3.H.3.5.5 (@linkBLEcore). */ +#define PM_CONN_SEC_ERROR_MIC_FAILURE (PM_CONN_SEC_ERROR_BASE + 0x3D) /**< @brief Encryption ended with disconnection because of mismatching keys or a stray packet during a procedure. See the SoftDevice GAP Message Sequence Charts on encryption (@linkBLEMSCgap), the Bluetooth Core Specification 4.2, sections 6.B.5.1.3.1 and 3.H.3.5.5 (@linkBLEcore), and @ref BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE. */ +#define PM_CONN_SEC_ERROR_DISCONNECT (PM_CONN_SEC_ERROR_BASE + 0x100) /**< @brief Pairing or encryption did not finish before the link disconnected for an unrelated reason. */ +#define PM_CONN_SEC_ERROR_SMP_TIMEOUT (PM_CONN_SEC_ERROR_BASE + 0x101) /**< @brief Pairing/bonding could not start because an SMP time-out has already happened on this link. This means that no more pairing or bonding can happen on this link. To be able to pair or bond, the link must be disconnected and then reconnected. See Bluetooth Core Specification 4.2 section 3.H.3.4 (@linkBLEcore). */ + /** @} */ + + + +/**@defgroup PM_PEER_ID_VERSIONS All versions of Peer IDs. + * @brief The data ID for each iteration of the data formats in flash. + * @details Each time the format (in flash) of a piece of peer data changes, the data ID will also + * be updated. This list of defines is a record of each data ID that has ever existed, and + * code that caters to legacy formats can find the relevant IDs here. + * @{ */ +#define PM_PEER_DATA_ID_FIRST_VX 0 /**< @brief The smallest data ID. */ +#define PM_PEER_DATA_ID_BONDING_V1 0 /**< @brief The data ID of the first version of bonding data. */ +#define PM_PEER_DATA_ID_BONDING_V2 7 /**< @brief The data ID of the second version of bonding data. */ +#define PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1 1 /**< @brief The data ID of the first version of the service changed pending flag. */ +#define PM_PEER_DATA_ID_GATT_LOCAL_V1 2 /**< @brief The data ID of the first version of local GATT data. */ +#define PM_PEER_DATA_ID_GATT_LOCAL_V2 8 /**< @brief The data ID of the second version of local GATT data. */ +#define PM_PEER_DATA_ID_GATT_REMOTE_V1 3 /**< @brief The data ID of the first version of remote GATT data. */ +#define PM_PEER_DATA_ID_APPLICATION_V1 4 /**< @brief The data ID of the first version of application data. */ +#define PM_PEER_DATA_ID_GATT_REMOTE_V2 5 /**< @brief The data ID of the second version of remote GATT data. */ +#define PM_PEER_DATA_ID_PEER_RANK_V1 6 /**< @brief The data ID of the first version of the rank. */ +#define PM_PEER_DATA_ID_LAST_VX 9 /**< @brief The data ID after the last valid one. */ +#define PM_PEER_DATA_ID_INVALID_VX 0xFF /**< @brief A data ID guaranteed to be invalid. */ +/**@}*/ + + +/**@brief The different types of data associated with a peer. + */ +typedef enum +{ + PM_PEER_DATA_ID_FIRST = PM_PEER_DATA_ID_FIRST_VX, /**< @brief The smallest data ID. */ + PM_PEER_DATA_ID_BONDING = PM_PEER_DATA_ID_BONDING_V2, /**< @brief The data ID for bonding data. Type: @ref pm_peer_data_bonding_t. */ + PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1, /**< @brief The data ID for service changed state. Type: bool. */ + PM_PEER_DATA_ID_GATT_LOCAL = PM_PEER_DATA_ID_GATT_LOCAL_V2, /**< @brief The data ID for local GATT data (sys attributes). Type: @ref pm_peer_data_local_gatt_db_t. */ + PM_PEER_DATA_ID_GATT_REMOTE = PM_PEER_DATA_ID_GATT_REMOTE_V2, /**< @brief The data ID for remote GATT data. Type: uint8_t array. */ + PM_PEER_DATA_ID_PEER_RANK = PM_PEER_DATA_ID_PEER_RANK_V1, /**< @brief The data ID for peer rank. See @ref pm_peer_rank_highest. Type: uint32_t. */ + PM_PEER_DATA_ID_APPLICATION = PM_PEER_DATA_ID_APPLICATION_V1, /**< @brief The data ID for application data. Type: uint8_t array. */ + PM_PEER_DATA_ID_LAST = PM_PEER_DATA_ID_LAST_VX, /**< @brief One more than the highest data ID. */ + PM_PEER_DATA_ID_INVALID = PM_PEER_DATA_ID_INVALID_VX, /**< @brief A data ID guaranteed to be invalid. */ +} pm_peer_data_id_t; + + +/**@brief Different procedures that can lead to an encrypted link. + */ +typedef enum +{ + PM_LINK_SECURED_PROCEDURE_ENCRYPTION, /**< @brief Using an LTK that was shared during a previous bonding procedure to encrypt the link. */ + PM_LINK_SECURED_PROCEDURE_BONDING, /**< @brief A pairing procedure, followed by a bonding procedure. */ + PM_LINK_SECURED_PROCEDURE_PAIRING, /**< @brief A pairing procedure with no bonding. */ +} pm_conn_sec_procedure_t; + + +/**@brief Configuration of a security procedure. + */ +typedef struct +{ + bool allow_repairing; /** @brief Whether to allow the peer to pair if it wants to, but is already bonded. If this is false, the procedure is rejected, and no more events are sent. Default: false. */ +} pm_conn_sec_config_t; + + +/**@brief Data associated with a bond to a peer. + */ +typedef struct +{ + uint8_t own_role; /**< @brief The BLE role of the local device during bonding. See @ref BLE_GAP_ROLES. */ + ble_gap_id_key_t peer_ble_id; /**< @brief The peer's Bluetooth address and identity resolution key (IRK). */ + ble_gap_enc_key_t peer_ltk; /**< @brief The peer's long-term encryption key (LTK) and master ID. */ + ble_gap_enc_key_t own_ltk; /**< @brief Locally generated long-term encryption key (LTK) and master ID, distributed to the peer. */ +} pm_peer_data_bonding_t; + + +/**@brief Data on a local GATT database. + */ +typedef struct +{ + uint32_t flags; /**< @brief Flags that describe the database attributes. */ + uint16_t len; /**< @brief Size of the attribute array. */ + uint8_t data[1]; /**< @brief Array to hold the database attributes. */ +} pm_peer_data_local_gatt_db_t; + + +/**@brief Device Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of + * time. The privacy feature, when enabled, hides the local device identity and replaces it + * with a private address that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity + * Resolving Key (IRK). With this key, a device can generate a random private address that + * can only be recognized by peers in possession of that key, and devices can establish + * connections without revealing their real identities. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref + * sd_ble_gap_sec_params_reply is called. + */ +#if (NRF_SD_BLE_API_VERSION < 3) + +typedef struct +{ + uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ + uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ + uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ + ble_gap_irk_t * p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. + When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. + By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ +} pm_privacy_params_t; + + +/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes + * @{ */ +#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ +#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ +/**@} */ + +#else + +typedef ble_gap_privacy_params_t pm_privacy_params_t; + +#endif + + +/**@brief Types of events that can come from the @ref peer_manager module. + */ +typedef enum +{ + PM_EVT_BONDED_PEER_CONNECTED, /**< @brief A connected peer has been identified as one with which we have a bond. When performing bonding with a peer for the first time, this event will not be sent until a new connection is established with the peer. When we are central, this event is always sent when the Peer Manager receives the @ref BLE_GAP_EVT_CONNECTED event. When we are peripheral, this event might in rare cases arrive later. */ + PM_EVT_CONN_SEC_START, /**< @brief A security procedure has started on a link, initiated either locally or remotely. The security procedure is using the last parameters provided via @ref pm_sec_params_set. This event is always followed by either a @ref PM_EVT_CONN_SEC_SUCCEEDED or a @ref PM_EVT_CONN_SEC_FAILED event. This is an informational event; no action is needed for the procedure to proceed. */ + PM_EVT_CONN_SEC_SUCCEEDED, /**< @brief A link has been encrypted, either as a result of a call to @ref pm_conn_secure or a result of an action by the peer. The event structure contains more information about the circumstances. This event might contain a peer ID with the value @ref PM_PEER_ID_INVALID, which means that the peer (central) used an address that could not be identified, but it used an encryption key (LTK) that is present in the database. */ + PM_EVT_CONN_SEC_FAILED, /**< @brief A pairing or encryption procedure has failed. In some cases, this means that security is not possible on this link (temporarily or permanently). How to handle this error depends on the application. */ + PM_EVT_CONN_SEC_CONFIG_REQ, /**< @brief The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref pm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */ + PM_EVT_CONN_SEC_PARAMS_REQ, /**< @brief Security parameters (@ref ble_gap_sec_params_t) are needed for an ongoing security procedure. Reply with @ref pm_conn_sec_params_reply before the event handler returns. If no reply is sent, the parameters given in @ref pm_sec_params_set are used. If a peripheral connection, the central's sec_params will be available in the event. */ + PM_EVT_STORAGE_FULL, /**< @brief There is no more room for peer data in flash storage. To solve this problem, delete data that is not needed anymore and run a garbage collection procedure in FDS. */ + PM_EVT_ERROR_UNEXPECTED, /**< @brief An unrecoverable error happened inside Peer Manager. An operation failed with the provided error. */ + PM_EVT_PEER_DATA_UPDATE_SUCCEEDED, /**< @brief A piece of peer data was stored, updated, or cleared in flash storage. This event is sent for all successful changes to peer data, also those initiated internally in Peer Manager. To identify an operation, compare the store token in the event with the store token received during the initiating function call. Events from internally initiated changes might have invalid store tokens. */ + PM_EVT_PEER_DATA_UPDATE_FAILED, /**< @brief A piece of peer data could not be stored, updated, or cleared in flash storage. This event is sent instead of @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED for the failed operation. */ + PM_EVT_PEER_DELETE_SUCCEEDED, /**< @brief A peer was cleared from flash storage, for example because a call to @ref pm_peer_delete succeeded. This event can also be sent as part of a call to @ref pm_peers_delete or internal cleanup. */ + PM_EVT_PEER_DELETE_FAILED, /**< @brief A peer could not be cleared from flash storage. This event is sent instead of @ref PM_EVT_PEER_DELETE_SUCCEEDED for the failed operation. */ + PM_EVT_PEERS_DELETE_SUCCEEDED, /**< @brief A call to @ref pm_peers_delete has completed successfully. Flash storage now contains no peer data. */ + PM_EVT_PEERS_DELETE_FAILED, /**< @brief A call to @ref pm_peers_delete has failed, which means that at least one of the peers could not be deleted. Other peers might have been deleted, or might still be queued to be deleted. No more @ref PM_EVT_PEERS_DELETE_SUCCEEDED or @ref PM_EVT_PEERS_DELETE_FAILED events are sent until the next time @ref pm_peers_delete is called. */ + PM_EVT_LOCAL_DB_CACHE_APPLIED, /**< @brief Local database values for a peer (taken from flash storage) have been provided to the SoftDevice. */ + PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED, /**< @brief Local database values for a peer (taken from flash storage) were rejected by the SoftDevice, which means that either the database has changed or the user has manually set the local database to an invalid value (using @ref pm_peer_data_store). */ + PM_EVT_SERVICE_CHANGED_IND_SENT, /**< @brief A service changed indication has been sent to a peer, as a result of a call to @ref pm_local_database_has_changed. This event will be followed by a @ref PM_EVT_SERVICE_CHANGED_IND_CONFIRMED event if the peer acknowledges the indication. */ + PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< @brief A service changed indication that was sent has been confirmed by a peer. The peer can now be considered aware that the local database has changed. */ + PM_EVT_SLAVE_SECURITY_REQ, /**< @brief The peer (peripheral) has requested link encryption, which has been enabled. */ + PM_EVT_FLASH_GARBAGE_COLLECTED, /**< @brief The flash has been garbage collected (By FDS), possibly freeing up space. */ +} pm_evt_id_t; + + +/**@brief Events parameters specific to the @ref PM_EVT_CONN_SEC_START event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that has started. */ +} pm_conn_sec_start_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that led to securing the link. */ + bool data_stored; /**< @brief Whether bonding data was successfully requested to be stored. This is false if: No bonding happened, or an internal error occurred when trying to store the data, or if the data was rejected via @ref pm_conn_sec_config_reply. */ +} pm_conn_secured_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. + */ +typedef struct +{ + pm_conn_sec_procedure_t procedure; /**< @brief The procedure that failed. */ + pm_sec_error_code_t error; /**< @brief An error code that describes the failure. */ + uint8_t error_src; /**< @brief The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ +} pm_conn_secure_failed_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. + */ +typedef struct +{ + ble_gap_sec_params_t const * p_peer_params; /**< @brief Peer security parameters, if role is peripheral. Otherwise, this is NULL. */ + void const * p_context; /**< @brief This pointer must be provided in the reply if the reply function takes a p_context argument. */ +} pm_conn_sec_params_req_evt_t; + + +/**@brief Actions that can be performed to peer data in persistent storage. + */ +typedef enum +{ + PM_PEER_DATA_OP_UPDATE, /**< @brief Writing or overwriting the data. */ + PM_PEER_DATA_OP_DELETE, /**< @brief Removing the data. */ +} pm_peer_data_op_t; + + +/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. + */ +typedef struct +{ + pm_peer_data_id_t data_id; /**< @brief The type of the data that was changed. */ + pm_peer_data_op_t action; /**< @brief What happened to the data. */ + pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ + uint8_t flash_changed : 1; /**< @brief If this is false, no operation was done in flash, because the value was already what it should be. Please note that in certain scenarios, this flag will be true even if the new value is the same as the old. */ +} pm_peer_data_update_succeeded_evt_t; + + +/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. + */ +typedef struct +{ + pm_peer_data_id_t data_id; /**< @brief The type of the data that was supposed to be changed. */ + pm_peer_data_op_t action; /**< @brief The action that failed. */ + pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ + ret_code_t error; /**< @brief An error code that describes the failure. */ +} pm_peer_data_update_failed_t; + + +/**@brief Standard parameters for failure events. + */ +typedef struct +{ + ret_code_t error; /**< @brief The error that occurred. */ +} pm_failure_evt_t; + + +/**@brief Events parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. + */ +typedef struct +{ + bool bond; /**< @brief Whether the peripheral requested bonding. */ + bool mitm; /**< @brief Whether the peripheral requested man-in-the-middle protection. */ +} pm_evt_slave_security_req_t; + + +/**@brief An event from the @ref peer_manager module. + * + * @details The structure contains both standard parameters and parameters that are specific to some events. + */ +typedef struct +{ + pm_evt_id_t evt_id; /**< @brief The type of the event. */ + uint16_t conn_handle; /**< @brief The connection that this event pertains to, or @ref BLE_CONN_HANDLE_INVALID. */ + pm_peer_id_t peer_id; /**< @brief The bonded peer that this event pertains to, or @ref PM_PEER_ID_INVALID. */ + union + { + pm_conn_sec_start_evt_t conn_sec_start; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_START event. */ + pm_conn_secured_evt_t conn_sec_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. */ + pm_conn_secure_failed_evt_t conn_sec_failed; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. */ + pm_conn_sec_params_req_evt_t conn_sec_params_req; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. */ + pm_peer_data_update_succeeded_evt_t peer_data_update_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. */ + pm_peer_data_update_failed_t peer_data_update_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. */ + pm_failure_evt_t peer_delete_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */ + pm_failure_evt_t peers_delete_failed_evt; /**< @brief Parameters specific to the @ref PM_EVT_PEERS_DELETE_FAILED event. */ + pm_failure_evt_t error_unexpected; /**< @brief Parameters specific to the @ref PM_EVT_ERROR_UNEXPECTED event. */ + pm_evt_slave_security_req_t slave_security_req; /**< @brief Parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. */ + } params; +} pm_evt_t; + + +/**@brief Event handler for events from the @ref peer_manager module. + * + * @sa pm_register + * + * @param[in] p_event The event that has occurred. + */ +typedef void (*pm_evt_handler_t)(pm_evt_t const * p_event); + +#ifdef __cplusplus +} +#endif + +#endif /* PEER_MANAGER_TYPES_H__ */ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c new file mode 100644 index 0000000000..83fdf77f11 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "pm_buffer.h" + +#include +#include +#include "nrf_error.h" +#include "pm_mutex.h" + + +#define BUFFER_IS_VALID(p_buffer) ((p_buffer != NULL) \ + && (p_buffer->p_memory != NULL) \ + && (p_buffer->p_mutex != NULL)) + + + +ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, + uint8_t * p_buffer_memory, + uint32_t buffer_memory_size, + uint8_t * p_mutex_memory, + uint32_t mutex_memory_size, + uint32_t n_blocks, + uint32_t block_size) +{ + if ( (p_buffer != NULL) + && (p_buffer_memory != NULL) + && (p_mutex_memory != NULL) + && (buffer_memory_size >= (n_blocks * block_size)) + && (mutex_memory_size >= MUTEX_STORAGE_SIZE(n_blocks)) + && (n_blocks != 0) + && (block_size != 0)) + { + p_buffer->p_memory = p_buffer_memory; + p_buffer->p_mutex = p_mutex_memory; + p_buffer->n_blocks = n_blocks; + p_buffer->block_size = block_size; + pm_mutex_init(p_buffer->p_mutex, n_blocks); + + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } +} + + +uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks) +{ + if (!BUFFER_IS_VALID(p_buffer)) + { + return ( PM_BUFFER_INVALID_ID ); + } + + uint8_t first_locked_mutex = PM_BUFFER_INVALID_ID; + + for (uint8_t i = 0; i < p_buffer->n_blocks; i++) + { + if (pm_mutex_lock(p_buffer->p_mutex, i)) + { + if (first_locked_mutex == PM_BUFFER_INVALID_ID) + { + first_locked_mutex = i; + } + if ((i - first_locked_mutex + 1) == n_blocks) + { + return first_locked_mutex; + } + } + else if (first_locked_mutex != PM_BUFFER_INVALID_ID) + { + for (uint8_t j = first_locked_mutex; j < i; j++) + { + pm_buffer_release(p_buffer, j); + } + first_locked_mutex = PM_BUFFER_INVALID_ID; + } + } + + return ( PM_BUFFER_INVALID_ID ); +} + + +uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id) +{ + if (!BUFFER_IS_VALID(p_buffer)) + { + return ( NULL ); + } + + if ( (id != PM_BUFFER_INVALID_ID) + && pm_mutex_lock_status_get(p_buffer->p_mutex, id) ) + { + return ( &p_buffer->p_memory[id * p_buffer->block_size] ); + } + else + { + return ( NULL ); + } +} + + +void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id) +{ + if ( BUFFER_IS_VALID(p_buffer) + && (id != PM_BUFFER_INVALID_ID) + && pm_mutex_lock_status_get(p_buffer->p_mutex, id)) + { + pm_mutex_unlock(p_buffer->p_mutex, id); + } +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h new file mode 100644 index 0000000000..3697441fbf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 BUFFER_H__ +#define BUFFER_H__ + +#include +#include "compiler_abstraction.h" +#include "sdk_errors.h" +#include "pm_mutex.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup pm_buffer Buffer + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module provides a simple buffer. + */ + + +#define PM_BUFFER_INVALID_ID 0xFF //!< Invalid buffer block ID. + + +/**@brief Convenience macro for declaring memory and initializing a buffer instance. + * + * @param[out] p_buffer The buffer instance to initialize. + * @param[in] n_blocks The desired number of blocks in the buffer. + * @param[in] block_size The desired block size of the buffer. + * @param[out] err_code The return code from @ref pm_buffer_init. + */ +#define PM_BUFFER_INIT(p_buffer, n_blocks, block_size, err_code) \ +do \ +{ \ + __ALIGN(4) static uint8_t buffer_memory[(n_blocks) * (block_size)]; \ + static uint8_t mutex_memory[MUTEX_STORAGE_SIZE(n_blocks)]; \ + err_code = pm_buffer_init((p_buffer), \ + buffer_memory, \ + (n_blocks) * (block_size), \ + mutex_memory, \ + MUTEX_STORAGE_SIZE(n_blocks), \ + (n_blocks), \ + (block_size)); \ +} while (0) + + +typedef struct +{ + uint8_t * p_memory; /**< The storage for all buffer entries. The size of the buffer must be n_blocks*block_size. */ + uint8_t * p_mutex; /**< A mutex group with one mutex for each buffer entry. */ + uint32_t n_blocks; /**< The number of allocatable blocks in the buffer. */ + uint32_t block_size; /**< The size of each block in the buffer. */ +} pm_buffer_t; + +/**@brief Function for initializing a buffer instance. + * + * @param[out] p_buffer The buffer instance to initialize. + * @param[in] p_buffer_memory The memory this buffer will use. + * @param[in] buffer_memory_size The size of p_buffer_memory. This must be at least + * n_blocks*block_size. + * @param[in] p_mutex_memory The memory for the mutexes. This must be at least + * @ref MUTEX_STORAGE_SIZE(n_blocks). + * @param[in] mutex_memory_size The size of p_mutex_memory. + * @param[in] n_blocks The number of blocks in the buffer. + * @param[in] block_size The size of each block. + * + * @retval NRF_SUCCESS Successfully initialized buffer instance. + * @retval NRF_ERROR_INVALID_PARAM A parameter was 0 or NULL or a size was too small. + */ +ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, + uint8_t * p_buffer_memory, + uint32_t buffer_memory_size, + uint8_t * p_mutex_memory, + uint32_t mutex_memory_size, + uint32_t n_blocks, + uint32_t block_size); + + +/**@brief Function for acquiring a buffer block in a buffer. + * + * @param[in] p_buffer The buffer instance acquire from. + * @param[in] n_blocks The number of contiguous blocks to acquire. + * + * @return The id of the acquired block, if successful. + * @retval PM_BUFFER_INVALID_ID If unsuccessful. + */ +uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks); + + +/**@brief Function for getting a pointer to a specific buffer block. + * + * @param[in] p_buffer The buffer instance get from. + * @param[in] id The id of the buffer to get the pointer for. + * + * @return A pointer to the buffer for the specified id, if the id is valid. + * @retval NULL If the id is invalid. + */ +uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id); + + +/**@brief Function for releasing a buffer block. + * + * @param[in] p_buffer The buffer instance containing the block to release. + * @param[in] id The id of the block to release. + */ +void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id); + + + +#ifdef __cplusplus +} +#endif + +#endif // BUFFER_H__ + +/** + * @} + * @endcond + */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c new file mode 100644 index 0000000000..10c26078b0 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "pm_mutex.h" + +#include +#include +#include "nrf_error.h" +#include "app_util_platform.h" + + + +/**@brief Locks the mutex defined by the mask. + * + * @param p_mutex pointer to the mutex storage. + * @param mutex_mask the mask identifying the mutex position. + * + * @retval true if the mutex could be locked. + * @retval false if the mutex was already locked. + */ +static bool lock_by_mask(uint8_t * p_mutex, uint8_t mutex_mask) +{ + bool success = false; + + if ( (*p_mutex & mutex_mask) == 0 ) + { + CRITICAL_REGION_ENTER(); + if ( (*p_mutex & mutex_mask) == 0 ) + { + *p_mutex |= mutex_mask; + + success = true; + } + CRITICAL_REGION_EXIT(); + } + + return ( success ); +} + + +void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size) +{ + if (p_mutex != NULL) + { + memset(&p_mutex[0], 0, MUTEX_STORAGE_SIZE(mutex_size)); + } +} + + +bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_id) +{ + if (p_mutex != NULL) + { + return ( lock_by_mask(&(p_mutex[mutex_id >> 3]), (1 << (mutex_id & 0x07))) ); + } + else + { + return false; + } +} + + +void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_id) +{ + uint8_t mutex_base = mutex_id >> 3; + uint8_t mutex_mask = (1 << (mutex_id & 0x07)); + + if ((p_mutex != NULL) + && (p_mutex[mutex_base] & mutex_mask)) + { + CRITICAL_REGION_ENTER(); + p_mutex[mutex_base] &= ~mutex_mask; + CRITICAL_REGION_EXIT(); + } +} + + +uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size) +{ + if (p_mutex != NULL) + { + for ( uint16_t i = 0; i < mutex_size; i++ ) + { + if ( lock_by_mask(&(p_mutex[i >> 3]), 1 << (i & 0x07)) ) + { + return ( i ); + } + } + } + + return ( mutex_size ); +} + + +bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_id) +{ + if (p_mutex != NULL) + { + return ( (p_mutex[mutex_id >> 3] & (1 << (mutex_id & 0x07))) ); + } + else + { + return true; + } +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h new file mode 100644 index 0000000000..7031d73fcb --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 MUTEX_H__ +#define MUTEX_H__ + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @cond NO_DOXYGEN + * @defgroup pm_mutex Mutex + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. This module provides thread-safe mutexes. + */ + + +/**@brief Defines the storage size of a specified mutex group. + * + * @param number_of_mutexes the number of mutexes in the group. + */ +#define MUTEX_STORAGE_SIZE(number_of_mutexes) ((7 + (number_of_mutexes)) >> 3) + + +/**@brief Initializes a mutex group. + * + * @param[in] p_mutex Pointer to the mutex group. See @ref MUTEX_STORAGE_SIZE(). + * @param[in] mutex_size The size of the mutex group in number of mutexes. + */ +void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size); + + +/**@brief Locks the mutex specified by the bit id. + * + * @param[inout] p_mutex Pointer to the mutex group. + * @param[in] mutex_bit_id The bit id of the mutex. + * + * @retval true if it was possible to lock the mutex. + * @retval false otherwise. + */ +bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_bit_id); + + +/**@brief Locks the first unlocked mutex within the mutex group. + * + * @param[in, out] p_mutex Pointer to the mutex group. + * @param[in] mutex_size The size of the mutex group. + * + * @return The first unlocked mutex id in the group. + * @retval group-size if there was no unlocked mutex available. + */ +uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size); + + +/**@brief Unlocks the mutex specified by the bit id. + * + * @param[in, out] p_mutex Pointer to the mutex group. + * @param[in] mutex_bit_id The bit id of the mutex. + */ +void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_bit_id); + + +/**@brief Gets the locking status of the specified mutex. + * + * @param[in, out] p_mutex Pointer to the mutex group. + * @param[in] mutex_bit_id The bit id of the mutex. + * + * @retval true if the mutex was locked. + * @retval false otherwise. + */ +bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_bit_id); + + + +#ifdef __cplusplus +} +#endif + +#endif // MUTEX_H__ + +/** @} + * @endcond + */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c new file mode 100644 index 0000000000..b36fea2aae --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c @@ -0,0 +1,1119 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "security_dispatcher.h" + +#include +#include "nrf_ble.h" +#include "ble_gap.h" +#include "ble_err.h" +#include "ble_conn_state.h" +#include "peer_manager_types.h" +#include "peer_database.h" +#include "id_manager.h" + +#ifndef PM_CENTRAL_ENABLED + #define PM_CENTRAL_ENABLED 1 +#endif + +// The number of registered event handlers. +#define SMD_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + +STATIC_ASSERT((NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0) || PM_CENTRAL_ENABLED, + "Peer Manager Central operation must be enabled when using central links."); + +// Security Dispacher event handlers in Security Manager and GATT Cache Manager. +extern void sm_smd_evt_handler(pm_evt_t * p_event); + +// Security Dispatcher events' handlers. +// The number of elements in this array is SMD_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + sm_smd_evt_handler +}; + +static bool m_module_initialized; + +static ble_conn_state_user_flag_id_t m_flag_sec_proc = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_sec_proc_pairing = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_sec_proc_bonding = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_sec_proc_new_peer = BLE_CONN_STATE_USER_FLAG_INVALID; +static ble_conn_state_user_flag_id_t m_flag_allow_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; + +static ble_gap_lesc_p256_pk_t m_peer_pk; + + +static __INLINE bool sec_procedure(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc); +} + +static __INLINE bool pairing(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_pairing); +} + +static __INLINE bool bonding(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_bonding); +} + +static __INLINE bool peer_created(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_new_peer); +} + +static __INLINE bool allow_repairing(uint16_t conn_handle) +{ + return ble_conn_state_user_flag_get(conn_handle, m_flag_allow_repairing); +} + + +/**@brief Function for sending an SMD event to all event handlers. + * + * @param[in] p_event The event to pass to all event handlers. + */ +static void evt_send(pm_evt_t * p_event) +{ + p_event->peer_id = im_peer_id_get_by_conn_handle(p_event->conn_handle); + + for (uint32_t i = 0; i < SMD_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for sending a PM_EVT_CONN_SEC_START event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] procedure The procedure that has started on the connection. + */ +static void sec_start_send(uint16_t conn_handle, + pm_conn_sec_procedure_t procedure) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_START, + .conn_handle = conn_handle, + .params = {.conn_sec_start = {.procedure = procedure}} + }; + evt_send(&evt); +} + + +/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. + * + * @param[in] conn_handle The connection handle the event pertains to. + * @param[in] err_code The unexpected error that occurred. + */ +static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) +{ + pm_evt_t error_evt = + { + .evt_id = PM_EVT_ERROR_UNEXPECTED, + .conn_handle = conn_handle, + .params = + { + .error_unexpected = + { + .error = err_code, + } + } + }; + evt_send(&error_evt); +} + + +/**@brief Function for cleaning up after a failed security procedure. + * + * @param[in] conn_handle The handle of the connection the security procedure happens on. + * @param[in] procedure The procedure that failed. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static void conn_sec_failure(uint16_t conn_handle, + pm_conn_sec_procedure_t procedure, + pm_sec_error_code_t error, + uint8_t error_src) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_FAILED, + .conn_handle = conn_handle, + .params = + { + .conn_sec_failed = + { + .procedure = procedure, + .error = error, + .error_src = error_src, + } + } + }; + + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); + + evt_send(&evt); + return; +} + + +/**@brief Function for cleaning up after a failed pairing procedure. + * + * @param[in] conn_handle The handle of the connection the pairing procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The source of the error (local or remote). See @ref + * BLE_GAP_SEC_STATUS_SOURCES. + */ +static void pairing_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + ret_code_t err_code = NRF_SUCCESS; + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + pm_conn_sec_procedure_t procedure = bonding(conn_handle) ? PM_LINK_SECURED_PROCEDURE_BONDING + : PM_LINK_SECURED_PROCEDURE_PAIRING; + + if (peer_created(conn_handle)) + { + // The peer_id was created during the procedure, and should be freed, because no data is + // stored under it. + err_code = im_peer_free(peer_id); // Attempt to free allocated peer. + UNUSED_VARIABLE(err_code); + } + else if(peer_id != PM_PEER_ID_INVALID) + { + err_code = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND /* No buffer was allocated */)) + { + send_unexpected_error(conn_handle, err_code); + } + } + + conn_sec_failure(conn_handle, procedure, error, error_src); + + return; +} + + +/**@brief Function for cleaning up after a failed encryption procedure. + * + * @param[in] conn_handle The handle of the connection the encryption procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static __INLINE void encryption_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + conn_sec_failure(conn_handle, PM_LINK_SECURED_PROCEDURE_ENCRYPTION, error, error_src); + + return; +} + + +/**@brief Function for possibly cleaning up after a failed pairing or encryption procedure. + * + * @param[in] conn_handle The handle of the connection the pairing procedure happens on. + * @param[in] error The error the procedure failed with. + * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. + */ +static void link_secure_failure(uint16_t conn_handle, + pm_sec_error_code_t error, + uint8_t error_src) +{ + if (sec_procedure(conn_handle)) + { + if (pairing(conn_handle)) + { + pairing_failure(conn_handle, error, error_src); + } + else + { + encryption_failure(conn_handle, error, error_src); + } + } +} + + +/**@brief Function for administrative actions to be taken when a security process has started. + * + * @param[in] conn_handle The connection the security process was attempted on. + * @param[in] success Whether the procedure was started successfully. + * @param[in] procedure The procedure that was started. + */ +static void sec_proc_start(uint16_t conn_handle, + bool success, + pm_conn_sec_procedure_t procedure) +{ + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, success); + if (success) + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_sec_proc_pairing, + (procedure != PM_LINK_SECURED_PROCEDURE_ENCRYPTION)); + ble_conn_state_user_flag_set(conn_handle, + m_flag_sec_proc_bonding, + (procedure == PM_LINK_SECURED_PROCEDURE_BONDING)); + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, false); + sec_start_send(conn_handle, procedure); + } +} + + + +/**@brief Function for administrative actions to be taken during the course of a security process. + * + * @param[in] conn_handle The connection the security process was attempted on. + * @param[in] peer_id The peer ID given to the connected peer. + * @param[in] success Whether the process was started successfully. + * @param[in] new_peer_created Whether a new peer was created during the process attempt. + */ +static void sec_proc_housekeeping(uint16_t conn_handle, + pm_peer_id_t peer_id, + bool success, + bool new_peer_created) +{ + if (success) + { + if (new_peer_created) + { + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, true); + im_new_peer_id(conn_handle, peer_id); + } + } + else + { + if (new_peer_created) + { + ret_code_t err_code = im_peer_free(peer_id); // Attempt to free allocated peer. + UNUSED_VARIABLE(err_code); + } + } +} + + + +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_INFO_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_info_request_process(ble_gap_evt_t const * p_gap_evt) +{ + ret_code_t err_code; + ble_gap_enc_info_t const * p_enc_info = NULL; + pm_peer_data_flash_t peer_data; + pm_peer_id_t peer_id = im_peer_id_get_by_master_id( + &p_gap_evt->params.sec_info_request.master_id); + + if (peer_id == PM_PEER_ID_INVALID) + { + peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle); + } + else + { + // The peer might have been unrecognized until now (since connecting). E.g. if using a + // random non-resolvable advertising address. Report the discovered peer ID just in case. + im_new_peer_id(p_gap_evt->conn_handle, peer_id); + } + + sec_proc_start(p_gap_evt->conn_handle, true, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); + + if (peer_id != PM_PEER_ID_INVALID) + { + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); + + if (err_code == NRF_SUCCESS) + { + // There is stored bonding data for this peer. + ble_gap_enc_key_t const * p_existing_key = &peer_data.p_bonding_data->own_ltk; + + if ( p_existing_key->enc_info.lesc + || (im_master_ids_compare(&p_existing_key->master_id, + &p_gap_evt->params.sec_info_request.master_id))) + { + p_enc_info = &p_existing_key->enc_info; + } + } + } + + err_code = sd_ble_gap_sec_info_reply(p_gap_evt->conn_handle, p_enc_info, NULL, NULL); + + if (err_code != NRF_SUCCESS) + { + sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); + send_unexpected_error(p_gap_evt->conn_handle, err_code); + } + else if (p_enc_info == NULL) + { + sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); + encryption_failure(p_gap_evt->conn_handle, + PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, + BLE_GAP_SEC_STATUS_SOURCE_LOCAL); + } + + return; +} + + + +/**@brief Function for sending a CONFIG_REQ event. + * + * @param[in] conn_handle The connection the sec parameters are needed for. + */ +static void send_config_req(uint16_t conn_handle) +{ + pm_evt_t evt; + memset(&evt, 0, sizeof(evt)); + + evt.evt_id = PM_EVT_CONN_SEC_CONFIG_REQ; + evt.conn_handle = conn_handle; + + evt_send(&evt); +} + + +void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); + + ble_conn_state_user_flag_set(conn_handle, + m_flag_allow_repairing, + p_conn_sec_config->allow_repairing); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_DISCONNECT event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void disconnect_process(ble_gap_evt_t const * p_gap_evt) +{ + pm_sec_error_code_t error = (p_gap_evt->params.disconnected.reason + == BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE) + ? PM_CONN_SEC_ERROR_MIC_FAILURE : PM_CONN_SEC_ERROR_DISCONNECT; + + link_secure_failure(p_gap_evt->conn_handle, error, BLE_GAP_SEC_STATUS_SOURCE_LOCAL); +} + + +/**@brief Function for sending a PARAMS_REQ event. + * + * @param[in] conn_handle The connection the security parameters are needed for. + * @param[in] p_peer_params The security parameters from the peer. Can be NULL if the peer's parameters + * are not yet available. + */ +static void send_params_req(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_CONN_SEC_PARAMS_REQ, + .conn_handle = conn_handle, + .params = + { + .conn_sec_params_req = + { + .p_peer_params = p_peer_params + }, + }, + }; + + evt_send(&evt); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_params_request_process(ble_gap_evt_t const * p_gap_evt) +{ + if (ble_conn_state_role(p_gap_evt->conn_handle) == BLE_GAP_ROLE_PERIPH) + { + sec_proc_start(p_gap_evt->conn_handle, + true, + p_gap_evt->params.sec_params_request.peer_params.bond + ? PM_LINK_SECURED_PROCEDURE_BONDING + : PM_LINK_SECURED_PROCEDURE_PAIRING); + } + + send_params_req(p_gap_evt->conn_handle, &p_gap_evt->params.sec_params_request.peer_params); + return; +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when + * the auth_status is success. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_success_process(ble_gap_evt_t const * p_gap_evt) +{ + ret_code_t err_code = NRF_SUCCESS; + uint16_t conn_handle = p_gap_evt->conn_handle; + uint8_t role = ble_conn_state_role(conn_handle); + pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); + pm_peer_id_t new_peer_id = peer_id; + pm_peer_data_t peer_data; + bool data_stored = false; + + ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); + + if (role == BLE_GAP_ROLE_INVALID) + { + /* Unlikely, but maybe possible? */ + return; + } + + if (p_gap_evt->params.auth_status.bonded) + { + pm_peer_id_t duplicate_peer_id = PM_PEER_ID_INVALID; + data_stored = true; + + err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); + if (err_code != NRF_SUCCESS) + { + send_unexpected_error(conn_handle, err_code); + data_stored = false; + } + else + { + duplicate_peer_id = im_find_duplicate_bonding_data(peer_data.p_bonding_data, + PM_PEER_ID_INVALID); + } + + if (duplicate_peer_id != PM_PEER_ID_INVALID) + { + // The peer has been identified as someone we have already bonded with. + new_peer_id = duplicate_peer_id; + im_new_peer_id(conn_handle, new_peer_id); + + // If the flag is true, the configuration has been requested before. + if (!allow_repairing(conn_handle)) + { + send_config_req(conn_handle); + if (!allow_repairing(conn_handle)) + { + data_stored = false; + } + } + } + + if (data_stored) + { + err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_BONDING, new_peer_id); + if (err_code != NRF_SUCCESS) + { + /* Unexpected */ + send_unexpected_error(conn_handle, err_code); + data_stored = false; + } + } + + if ((duplicate_peer_id != PM_PEER_ID_INVALID) && peer_created(conn_handle)) + { + // We already have a bond with the peer. Now that the data has been stored for the + // existing peer, the peer created for this bonding procedure can be freed. + ret_code_t err_code_free = im_peer_free(peer_id); + UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. + } + } + else if (peer_created(conn_handle)) + { + ret_code_t err_code_free = im_peer_free(peer_id); + UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. + } + else + { + // No action. + } + + pm_evt_t pairing_success_evt; + + pairing_success_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; + pairing_success_evt.conn_handle = conn_handle; + pairing_success_evt.params.conn_sec_succeeded.procedure = p_gap_evt->params.auth_status.bonded + ? PM_LINK_SECURED_PROCEDURE_BONDING + : PM_LINK_SECURED_PROCEDURE_PAIRING; + pairing_success_evt.params.conn_sec_succeeded.data_stored = data_stored; + + evt_send(&pairing_success_evt); + + return; +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when + * the auth_status is failure. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_failure_process(ble_gap_evt_t const * p_gap_evt) +{ + link_secure_failure(p_gap_evt->conn_handle, + p_gap_evt->params.auth_status.auth_status, + p_gap_evt->params.auth_status.error_src); +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void auth_status_process(ble_gap_evt_t const * p_gap_evt) +{ + switch (p_gap_evt->params.auth_status.auth_status) + { + case BLE_GAP_SEC_STATUS_SUCCESS: + auth_status_success_process(p_gap_evt); + break; + + default: + auth_status_failure_process(p_gap_evt); + break; + } +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_CONN_SEC_UPDATE event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void conn_sec_update_process(ble_gap_evt_t const * p_gap_evt) +{ + if (!pairing(p_gap_evt->conn_handle)) + { + // This is an encryption procedure (not pairing), so this event marks the end of the procedure. + + if (!ble_conn_state_encrypted(p_gap_evt->conn_handle)) + { + encryption_failure(p_gap_evt->conn_handle, + PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, + BLE_GAP_SEC_STATUS_SOURCE_REMOTE); + } + else + { + ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_flag_sec_proc, false); + + pm_evt_t evt; + + evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; + evt.conn_handle = p_gap_evt->conn_handle; + evt.params.conn_sec_succeeded.procedure = PM_LINK_SECURED_PROCEDURE_ENCRYPTION; + evt.params.conn_sec_succeeded.data_stored = false; + + evt_send(&evt); + } + } +} + + +/**@brief Funtion for initializing a BLE Connection State user flag. + * + * @param[out] flag_id The flag to initialize. + */ +static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) +{ + if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + *p_flag_id = ble_conn_state_user_flag_acquire(); + } +} + + +ret_code_t smd_init(void) +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + flag_id_init(&m_flag_sec_proc); + flag_id_init(&m_flag_sec_proc_pairing); + flag_id_init(&m_flag_sec_proc_bonding); + flag_id_init(&m_flag_sec_proc_new_peer); + flag_id_init(&m_flag_allow_repairing); + + if ((m_flag_sec_proc == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_sec_proc_pairing == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_sec_proc_bonding == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_sec_proc_new_peer == BLE_CONN_STATE_USER_FLAG_INVALID) || + (m_flag_allow_repairing == BLE_CONN_STATE_USER_FLAG_INVALID)) + { + return NRF_ERROR_INTERNAL; + } + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +/**@brief Function for putting retrieving a buffer and putting pointers into a @ref ble_gap_sec_keyset_t. + * + * @param[in] conn_handle The connection the security procedure is happening on. + * @param[in] peer_id The peer the security procedure is happening with. + * @param[in] role Our role in the connection. + * @param[in] p_public_key Pointer to a buffer holding the public key, or NULL. + * @param[out] p_sec_keyset Pointer to the keyset to be filled. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. + * @retval NRF_ERROR_BUSY Could not process request at this time. Reattempt later. + * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. + * @retval NRF_ERROR_INTERNAL Fatal error. + */ +static ret_code_t sec_keyset_fill(uint16_t conn_handle, + pm_peer_id_t peer_id, + uint8_t role, + ble_gap_lesc_p256_pk_t * p_public_key, + ble_gap_sec_keyset_t * p_sec_keyset) +{ + ret_code_t err_code; + pm_peer_data_t peer_data; + + if (p_sec_keyset == NULL) + { + return NRF_ERROR_INTERNAL; + } + + // Acquire a memory buffer to receive bonding data into. + err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); + + if (err_code == NRF_ERROR_BUSY) + { + // No action. + } + else if (err_code != NRF_SUCCESS) + { + err_code = NRF_ERROR_INTERNAL; + } + else /* if (err_code == NRF_SUCCESS) */ + { + memset(peer_data.p_bonding_data, 0, sizeof(pm_peer_data_bonding_t)); + + peer_data.p_bonding_data->own_role = role; + + p_sec_keyset->keys_own.p_enc_key = &peer_data.p_bonding_data->own_ltk; + p_sec_keyset->keys_own.p_pk = p_public_key; + p_sec_keyset->keys_peer.p_enc_key = &peer_data.p_bonding_data->peer_ltk; + p_sec_keyset->keys_peer.p_id_key = &peer_data.p_bonding_data->peer_ble_id; + p_sec_keyset->keys_peer.p_pk = &m_peer_pk; + + // Retrieve the address the peer used during connection establishment. + // This address will be overwritten if ID is shared. Should not fail. + err_code = im_ble_addr_get(conn_handle, &peer_data.p_bonding_data->peer_ble_id.id_addr_info); + if (err_code != NRF_SUCCESS) + { + return NRF_ERROR_INTERNAL; + } + + // Buffer is OK, reserve room in flash for the data. + err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); + if (err_code == NRF_ERROR_NOT_FOUND) + { + return NRF_ERROR_INTERNAL; + } + } + + return err_code; +} + + +ret_code_t smd_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + ble_gap_lesc_p256_pk_t * p_public_key) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint8_t role = ble_conn_state_role(conn_handle); + pm_peer_id_t peer_id = PM_PEER_ID_INVALID; + ret_code_t err_code = NRF_SUCCESS; + uint8_t sec_status = BLE_GAP_SEC_STATUS_SUCCESS; + bool new_peer_created = peer_created(conn_handle); + ble_gap_sec_keyset_t sec_keyset; + + memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t)); + if (role == BLE_GAP_ROLE_PERIPH) + { + // Set the default value for allowing repairing at the start of the sec proc. (for peripheral) + ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, false); + } + + if (role == BLE_GAP_ROLE_INVALID) + { + return BLE_ERROR_INVALID_CONN_HANDLE; + } + + if (p_sec_params == NULL) + { + // NULL params means reject pairing. + sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; + } + else if (!p_sec_params->bond) + { + // Pairing, no bonding. + + sec_keyset.keys_own.p_pk = p_public_key; + sec_keyset.keys_peer.p_pk = &m_peer_pk; + } + else + { + // Bonding is to be performed, prepare to receive bonding data. + + peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + if (peer_id == PM_PEER_ID_INVALID) + { + // Peer is unknown to us, allocate a new peer ID for it. + peer_id = pdb_peer_allocate(); + if (peer_id != PM_PEER_ID_INVALID) + { + new_peer_created = true; + } + else + { + err_code = NRF_ERROR_INTERNAL; + } + } + else if (role == BLE_GAP_ROLE_PERIPH && !allow_repairing(conn_handle)) + { + // Bond already exists. Reject the pairing request if the user doesn't intervene. + // send_config_req(conn_handle, peer_id); + send_config_req(conn_handle); + if (!allow_repairing(conn_handle)) + { + // Reject pairing. + sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; + } + } + + if ((sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP) && (err_code == NRF_SUCCESS)) + { + err_code = sec_keyset_fill(conn_handle, peer_id, role, p_public_key, &sec_keyset); + } + } + + if (err_code == NRF_SUCCESS) + { + // Everything OK, reply to SoftDevice. If an error happened, the user is given an + // opportunity to change the parameters and retry the call. + if (role == BLE_GAP_ROLE_PERIPH) + { + err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_sec_params, &sec_keyset); + } + else + { + err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, NULL, &sec_keyset); + } + } + + sec_proc_housekeeping(conn_handle, + peer_id, + (err_code == NRF_SUCCESS) && (sec_status == BLE_GAP_SEC_STATUS_SUCCESS), + new_peer_created); + + return err_code; +} + + +#if PM_CENTRAL_ENABLED +/**@brief Function for initiating encryption as a central. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_central_encryption(uint16_t conn_handle, + pm_peer_id_t peer_id) +{ + pm_peer_data_flash_t peer_data; + ret_code_t err_code; + ble_gap_enc_key_t const * p_existing_key = NULL; + bool lesc = false; + + err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); + + if (err_code == NRF_SUCCESS) + { + // Use peer's key since they are peripheral. + p_existing_key = &(peer_data.p_bonding_data->peer_ltk); + + lesc = peer_data.p_bonding_data->own_ltk.enc_info.lesc; + if (lesc) // LESC was used during bonding. + { + // For LESC, always use own key. + p_existing_key = &(peer_data.p_bonding_data->own_ltk); + } + } + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) + { + if (err_code != NRF_ERROR_BUSY) + { + // Unexpected error code. + err_code = NRF_ERROR_INTERNAL; + } + } + else if (p_existing_key == NULL) /* There is no bonding data stored. This means that a bonding + procedure is in ongoing, or that the records in flash are + in a bad state. */ + { + err_code = NRF_ERROR_BUSY; + } + else if (!lesc && !im_master_id_is_valid(&(p_existing_key->master_id))) /* There is no valid LTK stored. */ + { + // No LTK to encrypt with. + err_code = NRF_ERROR_INVALID_DATA; + } + else + { + // Encrypt with existing LTK. + err_code = sd_ble_gap_encrypt(conn_handle, + &(p_existing_key->master_id), + &(p_existing_key->enc_info)); + } + + sec_proc_start(conn_handle, err_code == NRF_SUCCESS, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); + sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), false); + + return err_code; +} + + +/**@brief Function for intiating pairing as a central. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_central_pairing(uint16_t conn_handle, + pm_peer_id_t peer_id, + ble_gap_sec_params_t * p_sec_params) +{ + pm_conn_sec_procedure_t procedure = PM_LINK_SECURED_PROCEDURE_PAIRING; + bool new_peer_created = false; + ret_code_t err_code = NRF_SUCCESS; + pm_peer_data_t dummy_peer_data; + + if (p_sec_params == NULL) + { + err_code = sd_ble_gap_authenticate(conn_handle, NULL); + } + else + { + if (p_sec_params->bond) + { + procedure = PM_LINK_SECURED_PROCEDURE_BONDING; + + if (peer_id == PM_PEER_ID_INVALID) + { + // New peer is required. + peer_id = pdb_peer_allocate(); + new_peer_created = true; + } + + if (peer_id == PM_PEER_ID_INVALID) + { + err_code = NRF_ERROR_INTERNAL; + } + else + { + err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &dummy_peer_data); + if (err_code == NRF_SUCCESS) + { + err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); + } + } + } + + if (err_code == NRF_SUCCESS) + { + err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); + } + + if (err_code != NRF_SUCCESS) + { + ret_code_t err_code_free = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); + if ((err_code_free != NRF_SUCCESS) && (err_code_free != NRF_ERROR_NOT_FOUND)) + { + err_code = NRF_ERROR_INTERNAL; + } + } + } + + if (err_code == NRF_ERROR_NO_MEM) + { + // sd_ble_gap_authenticate() returned NRF_ERROR_NO_MEM. Too many other sec procedures running. + err_code = NRF_ERROR_BUSY; + } + + sec_proc_start(conn_handle, err_code == NRF_SUCCESS, procedure); + sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), new_peer_created); + + return err_code; +} + + + +/**@brief Function for intiating security as a central. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_central(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing) +{ + ret_code_t err_code; + pm_peer_id_t peer_id; + + if (p_sec_params == NULL) + { + return sd_ble_gap_authenticate(conn_handle, NULL); + } + + // Set the default value for allowing repairing at the start of the sec proc. (for central) + ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, force_repairing); + + peer_id = im_peer_id_get_by_conn_handle(conn_handle); + + if ((peer_id != PM_PEER_ID_INVALID) && !force_repairing) + { + // There is already data in flash for this peer, and repairing has not been requested, so + // link will be encrypted with the existing keys. + err_code = link_secure_central_encryption(conn_handle, peer_id); + } + else + { + // There are no existing keys, or repairing has been explicitly requested, so pairing + // (possibly including bonding) will be performed to encrypt the link. + err_code = link_secure_central_pairing(conn_handle, peer_id, p_sec_params); + } + + return err_code; +} + + +/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_REQUEST event from the SoftDevice. + * + * @param[in] p_gap_evt The event from the SoftDevice. + */ +static void sec_request_process(ble_gap_evt_t const * p_gap_evt) +{ + pm_evt_t evt = + { + .evt_id = PM_EVT_SLAVE_SECURITY_REQ, + .conn_handle = p_gap_evt->conn_handle, + .params = + { + .slave_security_req = + { + .bond = p_gap_evt->params.sec_request.bond, + .mitm = p_gap_evt->params.sec_request.mitm, + } + } + }; + evt_send(&evt); + return; +} +#endif // PM_CENTRAL_ENABLED + + +/**@brief Function for asking the central to secure the link. See @ref smd_link_secure for more info. + */ +static ret_code_t link_secure_peripheral(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (p_sec_params != NULL) + { + err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); + } + + return err_code; +} + + +ret_code_t smd_link_secure(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + uint8_t role = ble_conn_state_role(conn_handle); + + switch (role) + { +#if PM_CENTRAL_ENABLED + case BLE_GAP_ROLE_CENTRAL: + return link_secure_central(conn_handle, p_sec_params, force_repairing); +#endif + + case BLE_GAP_ROLE_PERIPH: + return link_secure_peripheral(conn_handle, p_sec_params); + + default: + return BLE_ERROR_INVALID_CONN_HANDLE; + } +} + + +void smd_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_DISCONNECTED: + disconnect_process(&(p_ble_evt->evt.gap_evt)); + break; + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + sec_params_request_process(&(p_ble_evt->evt.gap_evt)); + break; + + case BLE_GAP_EVT_SEC_INFO_REQUEST: + sec_info_request_process(&(p_ble_evt->evt.gap_evt)); + break; + +#if PM_CENTRAL_ENABLED + case BLE_GAP_EVT_SEC_REQUEST: + sec_request_process(&(p_ble_evt->evt.gap_evt)); + break; +#endif + + case BLE_GAP_EVT_AUTH_STATUS: + auth_status_process(&(p_ble_evt->evt.gap_evt)); + break; + + case BLE_GAP_EVT_CONN_SEC_UPDATE: + conn_sec_update_process(&(p_ble_evt->evt.gap_evt)); + break; + }; +} +#endif //NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h new file mode 100644 index 0000000000..b985fe25d3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SECURITY_DISPATCHER_H__ +#define SECURITY_DISPATCHER_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup security_dispatcher Security Dispatcher + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and + * encryption, including flash storage of shared data. + * + */ + + +/**@brief Function for initializing the Security Dispatcher module. + * + * @retval NRF_SUCCESS Initialization was successful. + * @retval NRF_ERROR_INTERNAL An unexpected fatal error occurred. + */ +ret_code_t smd_init(void); + + +/**@brief Function for dispatching SoftDevice events to the Security Dispatcher module. + * + * @param[in] ble_evt The SoftDevice event. + */ +void smd_ble_evt_handler(ble_evt_t const * ble_evt); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing pairing and bonding parameters to use for the current pairing + * procedure on a connection. + * + * @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref + * BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_STORAGE_FULL, this function can be called + * again after corrective action. + * + * @note To reject a request, call this function with NULL p_sec_params. + * + * @param[in] conn_handle The connection handle of the connection the pairing is happening on. + * @param[in] p_sec_params The security parameters to use for this link. + * @param[in] p_public_key A pointer to the public key to use if using LESC, or NULL. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_INVALID_STATE No parameters have been requested on that conn_handle, or + * the link is disconnecting. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next + * FDS garbage collection procedure. + * @retval NRF_ERROR_BUSY No write buffer. Reattempt later. + * @retval NRF_ERROR_INTERNAL A fatal error occurred. + */ +ret_code_t smd_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + ble_gap_lesc_p256_pk_t * p_public_key); + + +/**@brief Function for initiating security on the link, with the specified parameters. + * + * @note If the connection is a peripheral connection, this will send a security request to the + * master, but the master is not obligated to initiate pairing or encryption in response. + * @note If the connection is a central connection and a key is available, the parameters will be + * used to determine whether to re-pair or to encrypt using the existing key. If no key is + * available, pairing will be started. + * + * @param[in] conn_handle Handle of the connection to initiate pairing on. + * @param[in] p_sec_params The security parameters to use for this link. As a central, this can + * be NULL to reject a slave security request. + * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether + * an encryption key already exists. This argument is only relevant for + * the central role. Recommended value: false + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_NULL p_sec_params was NULL (peripheral only). + * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, + * or the link is disconnecting. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). + * @retval NRF_ERROR_BUSY Unable to initiate procedure at this time. + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next + * FDS garbage collection procedure. + * @retval NRF_ERROR_INTERNAL No more available peer IDs. + */ +ret_code_t smd_link_secure(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + bool force_repairing); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SECURITY_DISPATCHER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c new file mode 100644 index 0000000000..c2c8ad7d1d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c @@ -0,0 +1,695 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PEER_MANAGER) +#include "security_manager.h" + +#include +#include "ble_err.h" +#include "security_dispatcher.h" +#include "peer_database.h" +#include "ble_conn_state.h" +#include "id_manager.h" + + +// The number of registered event handlers. +#define SM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) + + +// Security Manager event handler in Peer Manager. +extern void pm_sm_evt_handler(pm_evt_t * p_sm_evt); + +// Security Manager events' handlers. +// The number of elements in this array is SM_EVENT_HANDLERS_CNT. +static pm_evt_handler_internal_t const m_evt_handlers[] = +{ + pm_sm_evt_handler +}; + + +// The context type that is used in PM_EVT_CONN_SEC_PARAMS_REQ events and in calls to sm_sec_params_reply(). +typedef struct +{ + ble_gap_sec_params_t * p_sec_params; //!< The security parameters to use in the call to the security_dispatcher + ble_gap_sec_params_t sec_params_mem; //!< The buffer for holding the security parameters. + bool params_reply_called; //!< Whether @ref sm_sec_params_reply has been called for this context instance. +} sec_params_reply_context_t; + +static bool m_module_initialized; //!< Whether the Security Manager module has been initialized. + +static ble_gap_sec_params_t m_sec_params; //!< The buffer for the default security parameters set by @ref sm_sec_params_set. +static ble_gap_sec_params_t * mp_sec_params = NULL; //!< The default security parameters set by @ref sm_sec_params_set. +static bool m_sec_params_set = false; //!< Whether @ref sm_sec_params_set has been called. + +static ble_gap_lesc_p256_pk_t * m_p_public_key; //!< Pointer, provided by the user, to the public key to use for LESC procedures. + +static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_BUSY. +static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_STORAGE_FULL. +static ble_conn_state_user_flag_id_t m_flag_link_secure_force_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with true for the force_repairing parameter. +static ble_conn_state_user_flag_id_t m_flag_link_secure_null_params = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with NULL security parameters. +static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_BUSY. +static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_STORAGE_FULL. + + +/**@brief Function for sending an SM event to all registered event handlers. + * + * @param[in] p_event The event to send. + */ +static void evt_send(pm_evt_t * p_event) +{ + for (uint32_t i = 0; i < SM_EVENT_HANDLERS_CNT; i++) + { + m_evt_handlers[i](p_event); + } +} + + +/**@brief Function for setting or clearing user flags based on error codes returned from @ref + * smd_link_secure or @ref smd_params_reply. + * + * @param[in] conn_handle The connection the call pertained to. + * @param[in] err_code The error code returned from @ref smd_link_secure or + * @ref smd_params_reply. + * @param[in] params_reply Whether the call was to @ref smd_params_reply. + */ +static void flags_set_from_err_code(uint16_t conn_handle, ret_code_t err_code, bool params_reply) +{ + bool flag_value_flash_full = false; + bool flag_value_busy = false; + + if ((err_code == NRF_ERROR_STORAGE_FULL)) + { + flag_value_busy = false; + flag_value_flash_full = true; + } + else if (err_code == NRF_ERROR_BUSY) + { + flag_value_busy = true; + flag_value_flash_full = false; + } + else + { + flag_value_busy = false; + flag_value_flash_full = false; + } + + if (params_reply) + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_params_reply_pending_flash_full, + flag_value_flash_full); + ble_conn_state_user_flag_set(conn_handle, + m_flag_params_reply_pending_busy, + flag_value_busy); + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_flash_full, + false); + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_busy, + false); + } + else + { + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_flash_full, + flag_value_flash_full); + ble_conn_state_user_flag_set(conn_handle, + m_flag_link_secure_pending_busy, + flag_value_busy); + } +} + + +/**@brief Function for sending an event based on error codes returned from @ref smd_link_secure or + * @ref smd_params_reply. + * + * @param[in] conn_handle The connection the event pertains to. + * @param[in] err_code The error code returned from @ref smd_link_secure or + * @ref smd_params_reply. + * @param[in] p_sec_params The security parameters attempted to pass in the call to + * @ref smd_link_secure or @ref smd_params_reply. + */ +static void events_send_from_err_code(uint16_t conn_handle, + ret_code_t err_code, + ble_gap_sec_params_t * p_sec_params) +{ + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_INVALID_STATE)) + { + pm_evt_t evt = + { + .conn_handle = conn_handle, + .peer_id = im_peer_id_get_by_conn_handle(conn_handle), + }; + if (err_code == NRF_ERROR_TIMEOUT) + { + evt.evt_id = PM_EVT_CONN_SEC_FAILED; + evt.params.conn_sec_failed.procedure = ((p_sec_params != NULL) && p_sec_params->bond) + ? PM_LINK_SECURED_PROCEDURE_BONDING + : PM_LINK_SECURED_PROCEDURE_PAIRING; + evt.params.conn_sec_failed.error_src = BLE_GAP_SEC_STATUS_SOURCE_LOCAL; + evt.params.conn_sec_failed.error = PM_CONN_SEC_ERROR_SMP_TIMEOUT; + } + else if (err_code == NRF_ERROR_STORAGE_FULL) + { + evt.evt_id = PM_EVT_STORAGE_FULL; + } + else + { + evt.evt_id = PM_EVT_ERROR_UNEXPECTED; + evt.params.error_unexpected.error = err_code; + } + evt_send(&evt); + } +} + + +/**@brief Function for sending an PM_EVT_CONN_SEC_PARAMS_REQ event. + * + * @param[in] conn_handle The connection the event pertains to. + * @param[in] p_peer_params The peer's security parameters to include in the event. Can be NULL. + * @param[in] p_context Pointer to a context that the user must include in the call to @ref + * sm_sec_params_reply(). + */ +static void params_req_send(uint16_t conn_handle, + ble_gap_sec_params_t const * p_peer_params, + sec_params_reply_context_t * p_context) +{ + pm_evt_t evt; + evt.evt_id = PM_EVT_CONN_SEC_PARAMS_REQ; + evt.conn_handle = conn_handle; + evt.peer_id = im_peer_id_get_by_conn_handle(conn_handle); + evt.params.conn_sec_params_req.p_peer_params = p_peer_params; + evt.params.conn_sec_params_req.p_context = p_context; + + evt_send(&evt); +} + + +/**@brief Function for creating a new @ref sec_params_reply_context_t with the correct initial values. + * + * @return The new context. + */ +static sec_params_reply_context_t new_context_get(void) +{ + sec_params_reply_context_t new_context = + { + .p_sec_params = mp_sec_params, + .params_reply_called = false + }; + return new_context; +} + + +/**@brief Internal function corresponding to @ref sm_link_secure. + * + * @param[in] conn_handle The connection to secure. + * @param[in] null_params Whether to pass NULL security parameters to the security_dispatcher. + * @param[in] force_repairing Whether to force rebonding if peer exists. + * @param[in] send_events Whether to send events based on the result of @ref smd_link_secure. + * + * @return Same return codes as @ref sm_link_secure. + */ +static ret_code_t link_secure(uint16_t conn_handle, + bool null_params, + bool force_repairing, + bool send_events) +{ + ret_code_t err_code; + ret_code_t return_err_code; + ble_gap_sec_params_t * p_sec_params; + + if (null_params) + { + p_sec_params = NULL; + } + else + { + sec_params_reply_context_t context = new_context_get(); + params_req_send(conn_handle, NULL, &context); + p_sec_params = context.p_sec_params; + + if (!m_sec_params_set && !context.params_reply_called) + { + // Security parameters have not been set. + return NRF_ERROR_NOT_FOUND; + } + } + + + err_code = smd_link_secure(conn_handle, p_sec_params, force_repairing); + + flags_set_from_err_code(conn_handle, err_code, false); + + switch (err_code) + { + case NRF_ERROR_BUSY: + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); + return_err_code = NRF_SUCCESS; + break; + case NRF_ERROR_STORAGE_FULL: + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); + ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); + /* fallthrough */ + case NRF_SUCCESS: + case NRF_ERROR_TIMEOUT: + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_STATE: + return_err_code = err_code; + break; + default: + return_err_code = NRF_ERROR_INTERNAL; + break; + } + + if (send_events) + { + events_send_from_err_code(conn_handle, err_code, p_sec_params); + } + + return return_err_code; +} + + +/**@brief Function for requesting security parameters from the user and passing them to the security_dispatcher. + * + * @param[in] conn_handle The connection that needs security parameters. + * @param[in] p_peer_params The peer's security parameters if present. Otherwise NULL. + */ +static void smd_params_reply_perform(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) +{ + ret_code_t err_code; + sec_params_reply_context_t context = new_context_get(); + + params_req_send(conn_handle, p_peer_params, &context); + + err_code = smd_params_reply(conn_handle, context.p_sec_params, m_p_public_key); + + flags_set_from_err_code(conn_handle, err_code, true); + events_send_from_err_code(conn_handle, err_code, context.p_sec_params); +} + + +/**@brief Function for handling @ref PM_EVT_CONN_SEC_PARAMS_REQ events. + * + * @param[in] p_event The @ref PM_EVT_CONN_SEC_PARAMS_REQ event. + */ +static __INLINE void params_req_process(pm_evt_t const * p_event) +{ + smd_params_reply_perform(p_event->conn_handle, p_event->params.conn_sec_params_req.p_peer_params); +} + + +/**@brief Function for handling @ref PM_EVT_SLAVE_SECURITY_REQ events. + * + * @param[in] p_event The @ref PM_EVT_SLAVE_SECURITY_REQ event. + */ +static void sec_req_process(pm_evt_t const * p_event) +{ + bool null_params = false; + if (mp_sec_params == NULL) + { + null_params = true; + } + else if ((bool)m_sec_params.bond < (bool)p_event->params.slave_security_req.bond) + { + null_params = true; + } + else if ((bool)m_sec_params.mitm < (bool)p_event->params.slave_security_req.mitm) + { + null_params = true; + } + else + { + // No action. + } + ret_code_t err_code = link_secure(p_event->conn_handle, null_params, false, true); + UNUSED_VARIABLE(err_code); // It is acceptable to ignore the return code because it is + // acceptable to ignore a security request. +} + + +/**@brief Function for translating an SMD event to an SM event and passing it on to SM event handlers. + * + * @param[in] p_event The event to forward. + */ +static void evt_forward(pm_evt_t * p_event) +{ + evt_send(p_event); +} + + +/**@brief Event handler for events from the Security Dispatcher module. + * This handler is extern in Security Dispatcher. + * + * @param[in] p_event The event that has happened. + */ +void sm_smd_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_CONN_SEC_PARAMS_REQ: + params_req_process(p_event); + break; + case PM_EVT_SLAVE_SECURITY_REQ: + sec_req_process(p_event); + /* fallthrough */ + default: + // Forward the event to all registered Security Manager event handlers. + evt_forward(p_event); + break; + } +} + + +/**@brief Function for checking our user flags for pending calls to @ref smd_link_secure. + * + * @details This function will attempt to perform any pending calls. + * + * @param[in] flag_id The user flag to check. Must be either @ref m_flag_link_secure_pending_busy + * or @ref m_flag_link_secure_pending_flash_full. + */ +static void link_secure_pending_process(ble_conn_state_user_flag_id_t flag_id) +{ + sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); + if (sdk_mapped_flags_any_set(flag_collection)) + { + sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); + + for (uint32_t i = 0; i < conn_handle_list.len; i++) + { + bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); + if (pending) + { + bool force_repairing = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_force_repairing); + bool null_params = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_null_params); + + ret_code_t err_code = link_secure(conn_handle_list.flag_keys[i], null_params, force_repairing, true); // If this fails, it will be automatically retried. + UNUSED_VARIABLE(err_code); + } + } + } +} + + +/**@brief Function for checking our user flags for pending calls to @ref smd_params_reply. + * + * @details This function will attempt to perform any pending calls. + * + * @param[in] flag_id The user flag to check. Must be either @ref m_flag_params_reply_pending_busy + * or @ref m_flag_params_reply_pending_flash_full. + */ +static void params_reply_pending_process(ble_conn_state_user_flag_id_t flag_id) +{ + sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); + if (sdk_mapped_flags_any_set(flag_collection)) + { + sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); + + for (uint32_t i = 0; i < conn_handle_list.len; i++) + { + bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); + if (pending) + { + smd_params_reply_perform(conn_handle_list.flag_keys[i], NULL); + } + } + } +} + + +/**@brief Event handler for events from the Peer Database module. + * This handler is extern in Peer Database. + * + * @param[in] p_event The event that has happened. + */ +void sm_pdb_evt_handler(pm_evt_t * p_event) +{ + switch (p_event->evt_id) + { + case PM_EVT_FLASH_GARBAGE_COLLECTED: + params_reply_pending_process(m_flag_params_reply_pending_flash_full); + link_secure_pending_process(m_flag_link_secure_pending_flash_full); + /* fallthrough */ + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + case PM_EVT_PEER_DATA_UPDATE_FAILED: + case PM_EVT_PEER_DELETE_SUCCEEDED: + case PM_EVT_PEER_DELETE_FAILED: + params_reply_pending_process(m_flag_params_reply_pending_busy); + link_secure_pending_process(m_flag_link_secure_pending_busy); + break; + default: + // Do nothing. + break; + } +} + + +/**@brief Funtion for initializing a BLE Connection State user flag. + * + * @param[out] flag_id The flag to initialize. + */ +static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) +{ + if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) + { + *p_flag_id = ble_conn_state_user_flag_acquire(); + } +} + + +ret_code_t sm_init(void) +{ + NRF_PM_DEBUG_CHECK(!m_module_initialized); + + flag_id_init(&m_flag_link_secure_pending_busy); + flag_id_init(&m_flag_link_secure_pending_flash_full); + flag_id_init(&m_flag_link_secure_force_repairing); + flag_id_init(&m_flag_link_secure_null_params); + flag_id_init(&m_flag_params_reply_pending_busy); + flag_id_init(&m_flag_params_reply_pending_flash_full); + + if (m_flag_params_reply_pending_flash_full == BLE_CONN_STATE_USER_FLAG_INVALID) + { + return NRF_ERROR_INTERNAL; + } + + m_module_initialized = true; + + return NRF_SUCCESS; +} + + +void sm_ble_evt_handler(ble_evt_t const * p_ble_evt) +{ + NRF_PM_DEBUG_CHECK(p_ble_evt != NULL); + + smd_ble_evt_handler(p_ble_evt); + link_secure_pending_process(m_flag_link_secure_pending_busy); +} + + +/**@brief Funtion for checking whether security parameters are valid. + * + * @param[out] p_sec_params The security parameters to verify. + * + * @return Whether the security parameters are valid. + */ +static bool sec_params_verify(ble_gap_sec_params_t * p_sec_params) +{ + // NULL check. + if (p_sec_params == NULL) + { + return false; + } + + // OOB not allowed unless MITM. + if (!p_sec_params->mitm && p_sec_params->oob) + { + return false; + } + + // IO Capabilities must be one of the valid values from @ref BLE_GAP_IO_CAPS. + if (p_sec_params->io_caps > BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY) + { + return false; + } + + // Must have either IO capabilities or OOB if MITM. + if (p_sec_params->mitm && (p_sec_params->io_caps == BLE_GAP_IO_CAPS_NONE) && !p_sec_params->oob) + { + return false; + } + + // Minimum key size cannot be larger than maximum key size. + if (p_sec_params->min_key_size > p_sec_params->max_key_size) + { + return false; + } + + // Key size cannot be below 7 bytes. + if (p_sec_params->min_key_size < 7) + { + return false; + } + + // Key size cannot be above 16 bytes. + if (p_sec_params->max_key_size > 16) + { + return false; + } + + // Signing is not supported. + if (p_sec_params->kdist_own.sign || p_sec_params->kdist_peer.sign) + { + return false; + } + + // link bit must be 0. + if (p_sec_params->kdist_own.link || p_sec_params->kdist_peer.link) + { + return false; + } + + // If bonding is not enabled, no keys can be distributed. + if (!p_sec_params->bond && ( p_sec_params->kdist_own.enc + || p_sec_params->kdist_own.id + || p_sec_params->kdist_peer.enc + || p_sec_params->kdist_peer.id)) + { + return false; + } + + // If bonding is enabled, one or more keys must be distributed. + if ( p_sec_params->bond + && !p_sec_params->kdist_own.enc + && !p_sec_params->kdist_own.id + && !p_sec_params->kdist_peer.enc + && !p_sec_params->kdist_peer.id) + { + return false; + } + + return true; +} + + +ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + if (p_sec_params == NULL) + { + mp_sec_params = NULL; + m_sec_params_set = true; + return NRF_SUCCESS; + } + else if (sec_params_verify(p_sec_params)) + { + m_sec_params = *p_sec_params; + mp_sec_params = &m_sec_params; + m_sec_params_set = true; + return NRF_SUCCESS; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } +} + + +void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); + + smd_conn_sec_config_reply(conn_handle, p_conn_sec_config); +} + + +ret_code_t sm_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + VERIFY_PARAM_NOT_NULL(p_context); + + sec_params_reply_context_t * p_sec_params_reply_context = (sec_params_reply_context_t *)p_context; + if (p_sec_params == NULL) + { + // Set the store pointer to NULL, so that NULL is passed to the SoftDevice. + p_sec_params_reply_context->p_sec_params = NULL; + } + else if (sec_params_verify(p_sec_params)) + { + // Copy the provided sec_params into the store. + p_sec_params_reply_context->sec_params_mem = *p_sec_params; + p_sec_params_reply_context->p_sec_params = &p_sec_params_reply_context->sec_params_mem; + } + else + { + return NRF_ERROR_INVALID_PARAM; + } + p_sec_params_reply_context->params_reply_called = true; + + return NRF_SUCCESS; +} + + +ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) +{ + NRF_PM_DEBUG_CHECK(m_module_initialized); + + m_p_public_key = p_public_key; + + return NRF_SUCCESS; +} + + +ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing) +{ + ret_code_t ret; + + NRF_PM_DEBUG_CHECK(m_module_initialized); + + ret = link_secure(conn_handle, false, force_repairing, false); + return ret; +} +#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h new file mode 100644 index 0000000000..dda231cb72 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SECURITY_MANAGER_H__ +#define SECURITY_MANAGER_H__ + +#include +#include "sdk_errors.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "peer_manager_types.h" +#include "security_dispatcher.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @cond NO_DOXYGEN + * @defgroup security_manager Security Manager + * @ingroup peer_manager + * @{ + * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and + * encryption, including flash storage of shared data. + */ + + +/**@brief Function for initializing the Security Manager module. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. + */ +ret_code_t sm_init(void); + + +/**@brief Function for dispatching SoftDevice events to the Security Manager module. + * + * @param[in] ble_evt The SoftDevice event. + */ +void sm_ble_evt_handler(ble_evt_t const * ble_evt); + + +/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. + * + * @details Until this is called, all bonding procedures initiated by the peer will be rejected. + * This function can be called multiple times, even with NULL p_sec_params, in which case + * it will go back to rejecting all procedures. + * + * @param[in] p_sec_params The security parameters to use for this link. Can be NULL to reject + * all pairing procedures. + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters. + */ +ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params); + + +/**@brief Function for providing security configuration for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it + * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t + * for the value of the default. + * + * @param[in] conn_handle The connection to set the configuration for. + * @param[in] p_conn_sec_config The configuration. + */ +void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); + + +/**@brief Function for providing security parameters for a link. + * + * @details This function is optional, and must be called in reply to a @ref + * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Security Manager event handler returns. If + * it is not called in time, the parameters given in @ref sm_sec_params_set are used. See + * @ref pm_conn_sec_config_t for the value of the default. + * + * @param[in] conn_handle The connection to set the parameters for. + * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. + * @param[in] p_context The context found in the request event that this function replies to. + * + * @retval NRF_SUCCESS Successful reply. + * @retval NRF_ERROR_NULL p_context was null. + * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t sm_sec_params_reply(uint16_t conn_handle, + ble_gap_sec_params_t * p_sec_params, + void const * p_context); + + +/**@brief Experimental function for specifying the public key to use for LESC operations. + * + * @details This function can be called multiple times. The specified public key will be used for + * all subsequent LESC (LE Secure Connections) operations until the next time this function + * is called. + * + * @note The key must continue to reside in application memory as it is not copied by Peer Manager. + * + * @param[in] p_public_key The public key to use for all subsequent LESC operations. + * + * @retval NRF_SUCCESS Pairing initiated successfully. + * @retval NRF_ERROR_INVALID_STATE This module is not initialized. + */ +ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); + + + +/**@brief Function for initiating security on the link, with the specified parameters. + * + * @note If the connection is a peripheral connection, this will send a security request to the + * master, but the master is not obligated to initiate pairing or encryption in response. + * @note If the connection is a central connection and a key is available, the parameters will be + * used to determine whether to re-pair or to encrypt using the existing key. If no key is + * available, pairing will be started. + * + * @param[in] conn_handle Handle of the connection to initiate pairing on. + * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether + * an encryption key already exists. This argument is only relevant for + * the central role. Recommended value: false + * + * @retval NRF_SUCCESS Success. + * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations + * can be performed on this link. + * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. + * @retval NRF_ERROR_NOT_FOUND Security parameters have not been set. + * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, + * or the link is disconnecting. + * @retval NRF_ERROR_INTERNAL An unexpected error occurred. + */ +ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing); + +/** @} + * @endcond + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SECURITY_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.c new file mode 100644 index 0000000000..6b75b364a6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.c @@ -0,0 +1,616 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_FSTORAGE) + +#include "nrf_fstorage_sd.h" +#include +#include +#include +#include "nordic_common.h" +#include "nrf_soc.h" +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#include "nrf_atomic.h" +#include "nrf_atfifo.h" +#include "app_util_platform.h" + + +#if (NRF_FSTORAGE_SD_MAX_WRITE_SIZE % 4) +#error NRF_FSTORAGE_SD_MAX_WRITE_SIZE must be a multiple of the word size. +#endif + + +/**@brief fstorage operation codes. */ +typedef enum +{ + NRF_FSTORAGE_OP_WRITE, //!< Write bytes to flash. + NRF_FSTORAGE_OP_ERASE //!< Erase flash pages. +} nrf_fstorage_sd_opcode_t; + +ANON_UNIONS_ENABLE +/**@brief fstorage operation queue element. */ +typedef struct +{ + nrf_fstorage_t const * p_fs; //!< The fstorage instance that requested the operation. + nrf_fstorage_sd_opcode_t op_code; //!< Requested operation. + void * p_param; //!< User-defined parameter passed to the event handler. + union + { + struct + { + void const * p_src; //!< Data to be written to flash. + uint32_t dest; //!< Destination of the data in flash. + uint32_t len; //!< Length of the data to be written (in bytes). + uint32_t offset; //!< Write offset. + } write; + struct + { + uint32_t page; //!< Physical page number. + uint32_t progress; //!< Number of pages erased. + uint32_t pages_to_erase; //!< Total number of pages to erase. + } erase; + }; +} nrf_fstorage_sd_op_t; +ANON_UNIONS_DISABLE + +typedef enum +{ + NRF_FSTORAGE_STATE_IDLE, //!< No operations requested to the SoftDevice. + NRF_FSTORAGE_STATE_OP_PENDING, //!< A non-fstorage operation is pending. + NRF_FSTORAGE_STATE_OP_EXECUTING, //!< An fstorage operation is executing. +} nrf_fstorage_sd_state_t; + +/**@brief Internal state. */ +typedef struct +{ + nrf_atomic_flag_t initialized; //!< fstorage is initalized. + nrf_atomic_flag_t queue_running; //!< The queue is running. + /** Prevent API calls from entering queue_process(). */ + nrf_fstorage_sd_state_t state; //!< Internal fstorage state. + uint32_t retries; //!< Number of times an operation has been retried on timeout. + bool sd_enabled; //!< The SoftDevice is enabled. + bool paused; //!< A SoftDevice state change is impending. + /** Do not load a new operation when the last one completes. */ +} nrf_fstorage_sd_work_t; + + +void nrf_fstorage_sys_evt_handler(uint32_t, void *); +bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t, void *); +void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t, void *); + + +/* Flash device information. */ +static nrf_fstorage_info_t m_flash_info = +{ +#if defined(NRF51) + .erase_unit = 1024, +#elif defined(NRF52_SERIES) + .erase_unit = 4096, +#endif + .program_unit = 4, + .rmap = true, + .wmap = false, +}; + +/* Queue of fstorage operations. */ +NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE); + +/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */ +NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL); + +/* nrf_sdh request observer. */ +NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) = +{ + .handler = nrf_fstorage_sdh_req_handler, +}; + +/* nrf_sdh state observer. */ +NRF_SDH_STATE_OBSERVER(m_state_obs, 0) = +{ + .handler = nrf_fstorage_sdh_state_handler, +}; + +static nrf_fstorage_sd_work_t m_flags; /* Internal status. */ +static nrf_fstorage_sd_op_t * m_p_cur_op; /* The current operation being executed. */ +static nrf_atfifo_item_get_t m_iget_ctx; /* Context for nrf_atfifo_item_get() and nrf_atfifo_item_free(). */ + + +/* Send events to the application. */ +static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result) +{ + if (p_op->p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + return; + } + + nrf_fstorage_evt_t evt = + { + .result = result, + .p_param = p_op->p_param, + }; + + switch (p_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + evt.id = NRF_FSTORAGE_EVT_WRITE_RESULT; + evt.addr = p_op->write.dest; + evt.len = p_op->write.len; + break; + + case NRF_FSTORAGE_OP_ERASE: + evt.id = NRF_FSTORAGE_EVT_ERASE_RESULT; + evt.addr = (p_op->erase.page * m_flash_info.erase_unit); + evt.len = p_op->erase.pages_to_erase; + break; + + default: + /* Should not happen. */ + break; + } + + p_op->p_fs->evt_handler(&evt); +} + + +/* Write to flash. */ +static uint32_t write_execute(nrf_fstorage_sd_op_t const * p_op) +{ + uint32_t chunk_len; + + chunk_len = MIN(p_op->write.len - p_op->write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE); + chunk_len = MAX(1, chunk_len / m_flash_info.program_unit); + + /* Cast to p_src to uint32_t to perform arithmetic. */ + uint32_t * p_dest = (uint32_t*)(p_op->write.dest + p_op->write.offset); + uint32_t const * p_src = (uint32_t*)((uint32_t)p_op->write.p_src + p_op->write.offset); + + return sd_flash_write(p_dest, p_src, chunk_len); +} + + +/* Erase flash page(s). */ +static uint32_t erase_execute(nrf_fstorage_sd_op_t const * p_op) +{ + return sd_flash_page_erase(p_op->erase.page + p_op->erase.progress); +} + + +/* Free the current queue element. */ +static void queue_free(void) +{ + (void) nrf_atfifo_item_free(m_fifo, &m_iget_ctx); +} + + +/* Load a new operation from the queue. */ +static bool queue_load_next(void) +{ + m_p_cur_op = nrf_atfifo_item_get(m_fifo, &m_iget_ctx); + + return (m_p_cur_op != NULL); +} + + +/* Execute an operation in the queue. */ +static void queue_process(void) +{ + if (m_flags.state == NRF_FSTORAGE_STATE_IDLE) + { + if (!queue_load_next()) + { + /* No more operations, nothing to do. */ + m_flags.queue_running = false; + return; + } + } + + m_flags.state = NRF_FSTORAGE_STATE_OP_EXECUTING; + + uint32_t rc; + switch (m_p_cur_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + rc = write_execute(m_p_cur_op); + break; + + case NRF_FSTORAGE_OP_ERASE: + rc = erase_execute(m_p_cur_op); + break; + + default: + rc = NRF_ERROR_INTERNAL; + break; + } + + switch (rc) + { + case NRF_SUCCESS: + { + /* The operation was accepted by the SoftDevice. + * If the SoftDevice is enabled, wait for a system event. Otherwise, + * the SoftDevice call is synchronous and will not send an event so we simulate it. */ + if (!m_flags.sd_enabled) + { + nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL); + } + } break; + + case NRF_ERROR_BUSY: + { + /* The SoftDevice is executing a flash operation that was not requested by fstorage. + * Stop processing the queue until a system event is received. */ + m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING; + } break; + + default: + { + /* An error has occurred. We cannot proceed further with this operation. + * Reset the internal state so we can accept other operations. */ + event_send(m_p_cur_op, NRF_ERROR_INTERNAL); + m_flags.state = NRF_FSTORAGE_STATE_IDLE; + m_flags.queue_running = false; + } break; + } +} + + +/* Start processing the queue if it is not running and fstorage is not paused. */ +static void queue_start(void) +{ + nrf_atomic_flag_t queue_running = nrf_atomic_u32_fetch_store(&m_flags.queue_running, true); + + if ( (!queue_running) + && (!m_flags.paused)) + { + queue_process(); + } +} + + +/* Flash operation success callback. Keeps track of the progress of an operation. */ +static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op) +{ + /* Reset the retry counter on success. */ + m_flags.retries = 0; + + switch (p_op->op_code) + { + case NRF_FSTORAGE_OP_WRITE: + { + /* Update the offset only if the operation is successful + * so that it can be retried in case it times out. */ + uint32_t const chunk_len = MIN(p_op->write.len - p_op->write.offset, + NRF_FSTORAGE_SD_MAX_WRITE_SIZE); + + p_op->write.offset += chunk_len; + + if (p_op->write.offset == p_op->write.len) + { + return true; + } + } break; + + case NRF_FSTORAGE_OP_ERASE: + { + p_op->erase.progress++; + + if (p_op->erase.progress == p_op->erase.pages_to_erase) + { + return true; + } + } break; + + default: + /* Should not happen. */ + break; + } + + return false; +} + + +/* Flash operation failure callback. */ +static bool on_operation_failure(nrf_fstorage_sd_op_t const * p_op) +{ + UNUSED_PARAMETER(p_op); + + m_flags.retries++; + + if (m_flags.retries > NRF_FSTORAGE_SD_MAX_RETRIES) + { + /* Maximum amount of retries reached. Give up. */ + m_flags.retries = 0; + return true; + } + + return false; +} + + +static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_param); + + if (!nrf_atomic_flag_set_fetch(&m_flags.initialized)) + { + p_fs->p_flash_info = &m_flash_info; + +#if NRF_SDH_ENABLED + m_flags.sd_enabled = nrf_sdh_is_enabled(); +#endif + + (void) NRF_ATFIFO_INIT(m_fifo); + } + + return NRF_SUCCESS; +} + + +static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(p_param); + + /* The state is re-initialized upon init(). + * The common uninitialization code is run by the caller. */ + + memset(&m_flags, 0x00, sizeof(m_flags)); + + (void) nrf_atfifo_clear(m_fifo); + + return NRF_SUCCESS; +} + + +static ret_code_t write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param) +{ + nrf_fstorage_sd_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t)); + + p_op->op_code = NRF_FSTORAGE_OP_WRITE; + p_op->p_fs = p_fs; + p_op->p_param = p_param; + p_op->write.dest = dest; + p_op->write.p_src = p_src; + p_op->write.len = len; + + /* Put the operation on the queue. */ + (void) nrf_atfifo_item_put(m_fifo, &iput_ctx); + + queue_start(); + + return NRF_SUCCESS; +} + + +static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len) +{ + memcpy(p_dest, (uint32_t*)src, len); + + return NRF_SUCCESS; +} + + +static ret_code_t erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param) +{ + nrf_fstorage_sd_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + /* Get a free queue element. */ + p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx); + + if (p_op == NULL) + { + return NRF_ERROR_NO_MEM; + } + + /* Initialize the operation. */ + memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t)); + + p_op->op_code = NRF_FSTORAGE_OP_ERASE; + p_op->p_fs = p_fs; + p_op->p_param = p_param; + p_op->erase.page = (page_addr / m_flash_info.erase_unit); + p_op->erase.pages_to_erase = len; + + /* Put the operation on the queue. */ + (void) nrf_atfifo_item_put(m_fifo, &iput_ctx); + + queue_start(); + + return NRF_SUCCESS; +} + + +static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + + return (uint8_t*)addr; +} + + +static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(addr); + + /* Not supported. */ + return NULL; +} + + +static bool is_busy(nrf_fstorage_t const * p_fs) +{ + UNUSED_PARAMETER(p_fs); + + return (m_flags.state != NRF_FSTORAGE_STATE_IDLE); +} + + +void nrf_fstorage_sys_evt_handler(uint32_t sys_evt, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + switch (m_flags.state) + { + case NRF_FSTORAGE_STATE_OP_EXECUTING: + { + /* Handle the result of a flash operation initiated by this module. */ + bool operation_finished = false; + + switch (sys_evt) + { + case NRF_EVT_FLASH_OPERATION_SUCCESS: + operation_finished = on_operation_success(m_p_cur_op); + break; + + case NRF_EVT_FLASH_OPERATION_ERROR: + operation_finished = on_operation_failure(m_p_cur_op); + break; + + default: + break; + } + + if (operation_finished) + { + /* The operation has finished. Change state to NRF_FSTORAGE_STATE_IDLE + * so that queue_process() will fetch a new operation from the queue. */ + m_flags.state = NRF_FSTORAGE_STATE_IDLE; + + event_send(m_p_cur_op, (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) ? + NRF_SUCCESS : NRF_ERROR_TIMEOUT); + + /* Free the queue element after sending out the event to prevent API calls made + * in the event context to queue elements indefinitely, without this function + * ever returning in case the SoftDevice calls are synchronous. */ + queue_free(); + } + } break; + + case NRF_FSTORAGE_STATE_OP_PENDING: + /* The SoftDevice has completed a flash operation that was not requested by fstorage. + * It should be possible to request an operation now. + * Process the queue at the end of this function. */ + break; + + default: + /* If idle, return. */ + return; + } + + if (!m_flags.paused) + { + queue_process(); + } + else + { + /* A flash operation has completed. Let the SoftDevice to change state. */ + (void) nrf_sdh_request_continue(); + } +} + + +bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t req, void * p_context) +{ + UNUSED_PARAMETER(req); + UNUSED_PARAMETER(p_context); + + m_flags.paused = true; + + /* If there are any operations ongoing, pause the SoftDevice state change. */ + return (m_flags.state == NRF_FSTORAGE_STATE_IDLE); +} + + +void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + UNUSED_PARAMETER(p_context); + + if ( (state == NRF_SDH_EVT_STATE_ENABLED) + || (state == NRF_SDH_EVT_STATE_DISABLED)) + { + m_flags.paused = false; + m_flags.sd_enabled = (state == NRF_SDH_EVT_STATE_ENABLED); + + /* Execute any operations still in the queue. */ + queue_process(); + } +} + + +/* Exported API implementation. */ +nrf_fstorage_api_t nrf_fstorage_sd = +{ + .init = init, + .uninit = uninit, + .read = read, + .write = write, + .erase = erase, + .rmap = rmap, + .wmap = wmap, + .is_busy = is_busy +}; + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.h new file mode 100644 index 0000000000..27f2789909 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/libraries/fstorage/nrf_fstorage_sd.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_fstorage_sd SoftDevice implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the SoftDevice. +*/ + +#ifndef NRF_FSTORAGE_SD_H__ +#define NRF_FSTORAGE_SD_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the SoftDevice. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_sd.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_sd; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_SD_H__ +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.c new file mode 100644 index 0000000000..ae7ebb3e39 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.c @@ -0,0 +1,422 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_SDH) + +#include "nrf_sdh.h" + +#include + +#include "nrf_sdm.h" +#include "nrf_nvic.h" +#include "sdk_config.h" +#include "app_error.h" +#include "app_util_platform.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh +#if NRF_SDH_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH) + #if !APP_SCHEDULER_ENABLED + #error "APP_SCHEDULER is required." + #endif + #include "app_scheduler.h" +#endif // (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH) + + +// Create section "sdh_req_observers". +NRF_SECTION_SET_DEF(sdh_req_observers, nrf_sdh_req_observer_t, NRF_SDH_REQ_OBSERVER_PRIO_LEVELS); + +// Create section "sdh_state_observers". +NRF_SECTION_SET_DEF(sdh_state_observers, nrf_sdh_state_observer_t, NRF_SDH_STATE_OBSERVER_PRIO_LEVELS); + +// Create section "sdh_stack_observers". +NRF_SECTION_SET_DEF(sdh_stack_observers, nrf_sdh_stack_observer_t, NRF_SDH_STACK_OBSERVER_PRIO_LEVELS); + + +static bool m_nrf_sdh_enabled; /**< Variable to indicate whether the SoftDevice is enabled. */ +static bool m_nrf_sdh_suspended; /**< Variable to indicate whether this module is suspended. */ +static bool m_nrf_sdh_continue; /**< Variable to indicate whether enable/disable process was started. */ + + +/**@brief Function for notifying request observers. + * + * @param[in] evt Type of request event. + */ +static ret_code_t sdh_request_observer_notify(nrf_sdh_req_evt_t req) +{ + nrf_section_iter_t iter; + + NRF_LOG_DEBUG("State request: 0x%08X", req); + + for (nrf_section_iter_init(&iter, &sdh_req_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_req_observer_t * p_observer; + nrf_sdh_req_evt_handler_t handler; + + p_observer = (nrf_sdh_req_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + if (handler(req, p_observer->p_context)) + { + NRF_LOG_DEBUG("Notify observer 0x%08X => ready", p_observer); + } + else + { + // Process is stopped. + NRF_LOG_DEBUG("Notify observer 0x%08X => blocking", p_observer); + return NRF_ERROR_BUSY; + } + } + return NRF_SUCCESS; +} + + +/**@brief Function for stage request observers. + * + * @param[in] evt Type of stage event. + */ +static void sdh_state_observer_notify(nrf_sdh_state_evt_t evt) +{ + nrf_section_iter_t iter; + + NRF_LOG_DEBUG("State change: 0x%08X", evt); + + for (nrf_section_iter_init(&iter, &sdh_state_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_state_observer_t * p_observer; + nrf_sdh_state_evt_handler_t handler; + + p_observer = (nrf_sdh_state_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(evt, p_observer->p_context); + } +} + + +static void softdevices_evt_irq_enable(void) +{ +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_EnableIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + // In case of serialization, NVIC must be accessed directly. + NVIC_EnableIRQ(SD_EVT_IRQn); +#endif +} + + +static void softdevice_evt_irq_disable(void) +{ +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_DisableIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + // In case of serialization, NVIC must be accessed directly. + NVIC_DisableIRQ(SD_EVT_IRQn); +#endif +} + + +#ifndef S140 +static void swi_interrupt_priority_workaround(void) +{ + // The priorities of SoftDevice SWI SD_EVT_IRQn and RADIO_NOTIFICATION_IRQn + // in version S132 v5.0.0, S112 v5.0.0, S212 v5.0.0 and S332 v5.0.0 are set to 6. + // Set their priority to APP_IRQ_PRIORITY_LOWEST (7) so that they don't preempt + // peripheral interrupts and vice-versa. + +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code; + ret_code = sd_nvic_SetPriority(SD_EVT_IRQn, APP_IRQ_PRIORITY_LOWEST); + APP_ERROR_CHECK(ret_code); + ret_code = sd_nvic_SetPriority(RADIO_NOTIFICATION_IRQn, APP_IRQ_PRIORITY_LOWEST); + APP_ERROR_CHECK(ret_code); +#else + // In case of serialization, NVIC must be accessed directly. + NVIC_SetPriority(SD_EVT_IRQn, APP_IRQ_PRIORITY_LOWEST); + NVIC_SetPriority(RADIO_NOTIFICATION_IRQn, APP_IRQ_PRIORITY_LOWEST); +#endif +} +#endif + + +ret_code_t nrf_sdh_enable_request(void) +{ + ret_code_t ret_code; + + if (m_nrf_sdh_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + m_nrf_sdh_continue = true; + + // Notify observers about SoftDevice enable request. + if (sdh_request_observer_notify(NRF_SDH_EVT_ENABLE_REQUEST) == NRF_ERROR_BUSY) + { + // Enable process was stopped. + return NRF_SUCCESS; + } + + // Notify observers about starting SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLE_PREPARE); + + nrf_clock_lf_cfg_t const clock_lf_cfg = + { + .source = NRF_SDH_CLOCK_LF_SRC, + .rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV, + .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV, + #ifdef S140 + .xtal_accuracy = NRF_SDH_CLOCK_LF_XTAL_ACCURACY + #else + .accuracy = NRF_SDH_CLOCK_LF_XTAL_ACCURACY + #endif + }; + + #ifdef ANT_LICENSE_KEY + ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler, ANT_LICENSE_KEY); + #else + ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler); + #endif + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + m_nrf_sdh_enabled = true; + m_nrf_sdh_continue = false; + m_nrf_sdh_suspended = false; + +#ifndef S140 + // Set the interrupt priority after enabling the SoftDevice, since + // sd_softdevice_enable() sets the SoftDevice interrupt priority. + swi_interrupt_priority_workaround(); +#endif + + // Enable event interrupt. + // Interrupt priority has already been set by the stack. + softdevices_evt_irq_enable(); + + // Notify observers about a finished SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_disable_request(void) +{ + ret_code_t ret_code; + + if (!m_nrf_sdh_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + m_nrf_sdh_continue = true; + + // Notify observers about SoftDevice disable request. + if (sdh_request_observer_notify(NRF_SDH_EVT_DISABLE_REQUEST) == NRF_ERROR_BUSY) + { + // Disable process was stopped. + return NRF_SUCCESS; + } + + // Notify observers about starting SoftDevice disable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLE_PREPARE); + + ret_code = sd_softdevice_disable(); + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + m_nrf_sdh_enabled = false; + m_nrf_sdh_continue = false; + + softdevice_evt_irq_disable(); + + // Notify observers about a finished SoftDevice enable process. + sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLED); + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_request_continue(void) +{ + if (!m_nrf_sdh_continue) + { + return NRF_ERROR_INVALID_STATE; + } + + if (m_nrf_sdh_enabled) + { + return nrf_sdh_disable_request(); + } + else + { + return nrf_sdh_enable_request(); + } +} + + +bool nrf_sdh_is_enabled(void) +{ + return m_nrf_sdh_enabled; +} + + +void nrf_sdh_suspend(void) +{ + if (!m_nrf_sdh_enabled) + { + return; + } + + softdevice_evt_irq_disable(); + m_nrf_sdh_suspended = true; +} + + +void nrf_sdh_resume(void) +{ + if ((!m_nrf_sdh_suspended) || (!m_nrf_sdh_enabled)) + { + return; + } + + // Force calling ISR again to make sure that events not previously pulled have been processed. +#ifdef SOFTDEVICE_PRESENT + ret_code_t ret_code = sd_nvic_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn); + APP_ERROR_CHECK(ret_code); +#else + NVIC_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn); +#endif + + softdevices_evt_irq_enable(); + + m_nrf_sdh_suspended = false; +} + + +bool nrf_sdh_is_suspended(void) +{ + return (!m_nrf_sdh_enabled) || (m_nrf_sdh_suspended); +} + + +void nrf_sdh_evts_poll(void) +{ + nrf_section_iter_t iter; + + // Notify observers about pending SoftDevice event. + for (nrf_section_iter_init(&iter, &sdh_stack_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_stack_observer_t * p_observer; + nrf_sdh_stack_evt_handler_t handler; + + p_observer = (nrf_sdh_stack_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(p_observer->p_context); + } +} + + +#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_INTERRUPT) + +void SD_EVT_IRQHandler(void) +{ + nrf_sdh_evts_poll(); +} + +#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH) + +/**@brief Function for polling SoftDevice events. + * + * @note This function is compatible with @ref app_sched_event_handler_t. + * + * @param[in] p_event_data Pointer to the event data. + * @param[in] event_size Size of the event data. + */ +static void appsh_events_poll(void * p_event_data, uint16_t event_size) +{ + UNUSED_PARAMETER(p_event_data); + UNUSED_PARAMETER(event_size); + + nrf_sdh_evts_poll(); +} + + +void SD_EVT_IRQHandler(void) +{ + ret_code_t ret_code = app_sched_event_put(NULL, 0, appsh_events_poll); + APP_ERROR_CHECK(ret_code); +} + +#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_POLLING) + +#else + +#error "Unknown SoftDevice handler dispatch model." + +#endif // NRF_SDH_DISPATCH_MODEL + +#endif // NRF_MODULE_ENABLED(NRF_SDH) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.h new file mode 100644 index 0000000000..2fbd0dd638 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh.h @@ -0,0 +1,304 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_sdh SoftDevice Handler + * @{ + * @ingroup app_common + * @brief API for initializing and disabling the SoftDevice. + */ + +#ifndef NRF_SDH_H__ +#define NRF_SDH_H__ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include "nrf_section_iter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Softdevice Handler dispatch models + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice events are passed to the application from the interrupt context. */ +#define NRF_SDH_DISPATCH_MODEL_INTERRUPT 0 + +/**@brief SoftDevice events are passed to the application using @ref app_scheduler. + * + * @note @ref app_scheduler must be initialized before enabling the SoftDevice handler. + */ +#define NRF_SDH_DISPATCH_MODEL_APPSH 1 + +/**@brief SoftDevice events are polled manually using @ref nrf_sdh_evts_poll(). + * + * @note In this mode, a user application can also implement SD_EVT_IRQHandler() to receive a + * notification about incoming events. + */ +#define NRF_SDH_DISPATCH_MODEL_POLLING 2 + +/** @} */ + +/** + * @name SoftDevice Handler state change requests + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice Handler state requests. */ +typedef enum +{ + NRF_SDH_EVT_ENABLE_REQUEST, //!< Request to enable the SoftDevice. + NRF_SDH_EVT_DISABLE_REQUEST, //!< Request to disable the SoftDevice. +} nrf_sdh_req_evt_t; + +/**@brief SoftDevice Handler state request handler. + * + * @retval true If ready for the SoftDevice to change state. + * @retval false If not ready for the SoftDevice to change state. + * If false is returned, the state change is aborted. + */ +typedef bool (*nrf_sdh_req_evt_handler_t)(nrf_sdh_req_evt_t request, void * p_context); + +/**@brief SoftDevice Handler state request observer. */ +typedef struct +{ + nrf_sdh_req_evt_handler_t handler; //!< Request handler. + void * p_context; //!< A parameter to the handler function. +} const nrf_sdh_req_observer_t; + +/**@brief Macro for registering a SoftDevice state change request observer. + * + * An observer of SoftDevice state change requests receives requests to change the state of the + * SoftDevice from enabled to disabled and vice versa. These requests may or may not be acknowledged + * by the observer, depending on the value returned by its request handler function. Thus, a + * request observer has the capability to defer the change of state of the SoftDevice. If it does + * so, it has the responsibility to call @ref nrf_sdh_request_continue when it is ready to let the + * SoftDevice change its state. If such capability is not necessary and you only need to be informed + * about changes of the SoftDevice state, use the @ref NRF_SDH_STATE_OBSERVER macro instead. + * + * @note This macro places the observer in a section named "sdh_req_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + * @hideinitializer + */ +#define NRF_SDH_REQUEST_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_REQ_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_req_observers, _prio, nrf_sdh_req_observer_t const _observer) + +/** @} */ + +/** + * @name SoftDevice Handler state events + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice Handler state events. */ +typedef enum +{ + NRF_SDH_EVT_STATE_ENABLE_PREPARE, //!< SoftDevice is going to be enabled. + NRF_SDH_EVT_STATE_ENABLED, //!< SoftDevice is enabled. + NRF_SDH_EVT_STATE_DISABLE_PREPARE, //!< SoftDevice is going to be disabled. + NRF_SDH_EVT_STATE_DISABLED, //!< SoftDevice is disabled. +} nrf_sdh_state_evt_t; + +/**@brief SoftDevice Handler state event handler. */ +typedef void (*nrf_sdh_state_evt_handler_t)(nrf_sdh_state_evt_t state, void * p_context); + +/**@brief SoftDevice Handler state observer. */ +typedef struct +{ + nrf_sdh_state_evt_handler_t handler; //!< State event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_state_observer_t; + +/**@brief Macro for registering a SoftDevice state observer. + * + * A SoftDevice state observer receives events when the SoftDevice state has changed or is + * about to change. These events are only meant to inform the state observer, which, contrary + * to a state change request observer, does not have the capability to defer the change of state. + * If such capability is required, use the @ref NRF_SDH_REQUEST_OBSERVER macro instead. + * + * This macro places the observer in a section named "sdh_state_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + * @hideinitializer + */ +#define NRF_SDH_STATE_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_STATE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_state_observers, _prio, static nrf_sdh_state_observer_t const _observer) + +/** @} */ + +/** + * @name SoftDevice stack events + * @{ + * @ingroup nrf_sdh */ + +/**@brief SoftDevice stack event handler. */ +typedef void (*nrf_sdh_stack_evt_handler_t)(void * p_evt); + +/**@brief SoftDevice stack event observer. */ +typedef struct +{ + nrf_sdh_stack_evt_handler_t handler; //!< SoftDevice event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_stack_observer_t; + +/**@brief Macro for registering a SoftDevice stack events observer. + * + * A SoftDevice stack event observer receives all events from the SoftDevice. These events can be + * either BLE, ANT, or SoC events. If you need to receive BLE, ANT, or SoC events separately, use the + * @ref NRF_SDH_BLE_OBSERVER, @ref NRF_SDH_ANT_OBSERVER, or @ref NRF_SDH_SOC_OBSERVER macros + * respectively. + * + * @note This macro places the observer in a section named "sdh_stack_observers". + * + * @param[in] _observer Name of the observer. + * @param[in] _prio Priority of the observer's event handler. + * The smaller the number, the higher the priority. + ** @hideinitializer + */ +#define NRF_SDH_STACK_OBSERVER(_observer, _prio) \ +STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_STACK_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_stack_observers, _prio, static nrf_sdh_stack_observer_t const _observer) + +/** @} */ + +/**@brief Function for requesting to enable the SoftDevice. + * + * This function issues a @ref NRF_SDH_EVT_ENABLE_REQUEST request to all observers that + * were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or + * may not acknowledge the request. If all observers acknowledge the request, the + * SoftDevice will be enabled. Otherwise, the process will be stopped and the observers + * that did not acknowledge have the responsibility to restart it by calling + * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * + * @retval NRF_SUCCESS The process is started. + * @retval NRF_ERROR_INVALID_STATE The SoftDevice is already enabled. + */ +ret_code_t nrf_sdh_enable_request(void); + + +/**@brief Function for requesting to disable the SoftDevice. + * + * This function issues a @ref NRF_SDH_EVT_DISABLE_REQUEST request to all observers that + * were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or + * may not acknowledge the request. If all observers acknowledge the request, the + * SoftDevice will be disabled. Otherwise, the process will be stopped and the observers + * that did not acknowledge have the responsibility to restart it by calling + * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * + * @retval NRF_SUCCESS The process is started. + * @retval NRF_ERROR_INVALID_STATE The SoftDevice is already disabled. + */ +ret_code_t nrf_sdh_disable_request(void); + + +/**@brief Function for restarting the SoftDevice Enable/Disable process. + * + * Modules which did not acknowledge a @ref NRF_SDH_EVT_ENABLE_REQUEST or + * @ref NRF_SDH_EVT_DISABLE_REQUEST request must call this function to restart the + * SoftDevice state change process. + * + * @retval NRF_SUCCESS The process is restarted. + * @retval NRF_ERROR_INVALID_STATE No state change request was pending. + */ +ret_code_t nrf_sdh_request_continue(void); + + +/**@brief Function for retrieving the SoftDevice state. + * + * @retval true If the SoftDevice is enabled. + * @retval false If the SoftDevice is disabled. + */ +bool nrf_sdh_is_enabled(void); + + +/**@brief Function for stopping the incoming stack events. + * + * This function disables the SoftDevice interrupt. To resume polling for events, + * call @ref nrf_sdh_resume. + */ +void nrf_sdh_suspend(void); + + +/**@brief Function for resuming polling incoming events from the SoftDevice. */ +void nrf_sdh_resume(void); + + +/**@brief Function for retrieving the information about the module state. + * + * @retval true The SoftDevice handler is paused, and it will not fetch events from the stack. + * @retval false The SoftDevice handler is running, and it will fetch and dispatch events from + * the stack to the registered stack observers. + */ +bool nrf_sdh_is_suspended(void); + + +/**@brief Function for polling stack events from the SoftDevice. + * + * The events are passed to the application using the registered event handlers. + * + * @note @ref NRF_SDH_DISPATCH_MODEL_POLLING must be selected to use this function. + */ +void nrf_sdh_evts_poll(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.c new file mode 100644 index 0000000000..1aa6a19609 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.c @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_SDH_ANT) + +#include "nrf_sdh_ant.h" + +#include "nrf_sdh.h" +#include "app_error.h" +#include "ant_interface.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_ant +#if NRF_SDH_ANT_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_ANT_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_ANT_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_ANT_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_ANT_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +STATIC_ASSERT(NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED <= MAX_ANT_CHANNELS); +STATIC_ASSERT(NRF_SDH_ANT_ENCRYPTED_CHANNELS <= NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED); + +// Create section set "sdh_ant_observers". +NRF_SECTION_SET_DEF(sdh_ant_observers, nrf_sdh_ant_evt_observer_t, NRF_SDH_ANT_OBSERVER_PRIO_LEVELS); + +// Memory buffer provided in order to support channel configuration. +__ALIGN(4) static uint8_t m_ant_stack_buffer[NRF_SDH_ANT_BUF_SIZE]; + + +ret_code_t nrf_sdh_ant_enable(void) +{ + ANT_ENABLE ant_enable_cfg = + { + .ucTotalNumberOfChannels = NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED, + .ucNumberOfEncryptedChannels = NRF_SDH_ANT_ENCRYPTED_CHANNELS, + .usNumberOfEvents = NRF_SDH_ANT_EVENT_QUEUE_SIZE, + .pucMemoryBlockStartLocation = m_ant_stack_buffer, + .usMemoryBlockByteSize = sizeof(m_ant_stack_buffer), + }; + + ret_code_t ret_code = sd_ant_enable(&ant_enable_cfg); + return ret_code; +} + + +/**@brief Function for polling ANT events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_ant_evts_poll(void * p_context) +{ + ret_code_t ret_code; + + UNUSED_VARIABLE(p_context); + + while (true) + { + ant_evt_t ant_evt; + + ret_code = sd_ant_event_get(&ant_evt.channel, &ant_evt.event, ant_evt.message.aucMessage); + if (ret_code != NRF_SUCCESS) + { + break; + } + + NRF_LOG_DEBUG("ANT Event 0x%02X Channel 0x%02X", ant_evt.event, ant_evt.channel); + + // Forward the event to ANT observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_ant_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_ant_evt_observer_t * p_observer; + nrf_sdh_ant_evt_handler_t handler; + + p_observer = (nrf_sdh_ant_evt_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(&ant_evt, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ant_evts_poll, NRF_SDH_ANT_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_ant_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_ANT) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.h new file mode 100644 index 0000000000..da3bd7d6b6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ant.h @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_sdh_ant ANT support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for ANT stack support. + */ + +#ifndef NRF_SDH_ANT_H__ +#define NRF_SDH_ANT_H__ + +#include "ant_parameters.h" +#include "app_util.h" +#include "nrf_section_iter.h" +#include "sdk_errors.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE 1 //!< Size of the channel field in ANT stack event +#define NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE 1 //!< Size of the event field in ANT stack event + +/**@brief Size of the buffer provided to the ANT SoftDevice. + * @hideinitializer + */ +#define NRF_SDH_ANT_BUF_SIZE ANT_ENABLE_GET_REQUIRED_SPACE( \ + NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED, \ + NRF_SDH_ANT_ENCRYPTED_CHANNELS, \ + NRF_SDH_ANT_BURST_QUEUE_SIZE, \ + NRF_SDH_ANT_EVENT_QUEUE_SIZE) + +/**@brief Size of the buffer provided to the ANT SoftDevice to receive ANT events. */ +#define NRF_SDH_ANT_MESSAGE_SIZE ((CEIL_DIV(MESG_BUFFER_SIZE, sizeof(uint32_t))) * sizeof(uint32_t)) + +/**@brief Size of the buffer provided to the Events Scheduler to hold ANT events. */ +#define NRF_SDH_ANT_EVT_BUF_SIZE ((CEIL_DIV(NRF_SDH_ANT_MESSAGE_SIZE + \ + NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE + \ + NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE, \ + sizeof(uint32_t))) * sizeof(uint32_t)) + + +#if !(defined(__LINT__)) +/**@brief Macro for registering an ANT observer. Modules that want to be + * notified about ANT events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_ant_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler ANT event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_ANT_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_ant_evt_observer_t. + * Modules that want to be notified about ANT events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_ant_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler ANT event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_ANT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_ANT_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_ANT_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief ANT stack event. */ +typedef struct +{ + ANT_MESSAGE message; //!< ANT Message. + uint8_t channel; //!< Channel number. + uint8_t event; //!< Event code. +} ant_evt_t; + +/**@brief ANT stack event handler. */ +typedef void (*nrf_sdh_ant_evt_handler_t)(ant_evt_t * p_ant_evt, void * p_context); + +/**@brief ANT event observer. */ +typedef struct +{ + nrf_sdh_ant_evt_handler_t handler; //!< ANT event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_ant_evt_observer_t; + + +/**@brief Function for configuring and enabling the ANT stack. + * + * @details The function sets the channel configuration for the stack using the parameters + * provided in the @c sdk_config file. It also assigns a correspondingly large + * buffer as a static resource. + */ +ret_code_t nrf_sdh_ant_enable(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_ANT_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.c new file mode 100644 index 0000000000..990ba0af0b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.c @@ -0,0 +1,300 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_SDH_BLE) + +#include "nrf_sdh_ble.h" + +#include "nrf_sdh.h" +#include "app_error.h" +#include "nrf_strerror.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_ble +#if NRF_SDH_BLE_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_BLE_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_BLE_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_BLE_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_BLE_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +// Create section set "sdh_ble_observers". +NRF_SECTION_SET_DEF(sdh_ble_observers, nrf_sdh_ble_evt_observer_t, NRF_SDH_BLE_OBSERVER_PRIO_LEVELS); + + +//lint -save -e10 -e19 -e40 -e27 Illegal character (0x24) +#if defined(__CC_ARM) + extern uint32_t Image$$RW_IRAM1$$Base; + uint32_t const * const m_ram_start = &Image$$RW_IRAM1$$Base; +#elif defined(__ICCARM__) + extern uint32_t __ICFEDIT_region_RAM_start__; + uint32_t const * const m_ram_start = &__ICFEDIT_region_RAM_start__; +#elif defined(__SES_ARM) + extern uint32_t __app_ram_start__; + uint32_t const * const m_ram_start = &__app_ram_start__; +#elif defined(__GNUC__) + extern uint32_t __data_start__; + uint32_t const * const m_ram_start = &__data_start__; +#endif +//lint -restore + +#define RAM_START 0x20000000 +#define APP_RAM_START (uint32_t)m_ram_start + + +ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start) +{ + if (p_app_ram_start == NULL) + { + return NRF_ERROR_NULL; + } + + *p_app_ram_start = APP_RAM_START; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start) +{ + uint32_t ret_code; + + ret_code = nrf_sdh_ble_app_ram_start_get(p_ram_start); + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + +#ifdef S112 + STATIC_ASSERT(NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0, "When using s112, NRF_SDH_BLE_CENTRAL_LINK_COUNT must be 0."); +#endif + + // Overwrite some of the default settings of the BLE stack. + // If any of the calls to sd_ble_cfg_set() fail, log the error but carry on so that + // wrong RAM settings can be caught by nrf_sdh_ble_enable() and a meaningful error + // message will be printed to the user suggesting the correct value. + ble_cfg_t ble_cfg; + +#if (NRF_SDH_BLE_TOTAL_LINK_COUNT != 0) + // Configure the connection count. + memset(&ble_cfg, 0, sizeof(ble_cfg)); + ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag; + ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = NRF_SDH_BLE_TOTAL_LINK_COUNT; + ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = NRF_SDH_BLE_GAP_EVENT_LENGTH; + + ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GAP.", + nrf_strerror_get(ret_code)); + } + + // Configure the connection roles. + memset(&ble_cfg, 0, sizeof(ble_cfg)); + ble_cfg.gap_cfg.role_count_cfg.periph_role_count = NRF_SDH_BLE_PERIPHERAL_LINK_COUNT; +#ifndef S112 + ble_cfg.gap_cfg.role_count_cfg.central_role_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT; + ble_cfg.gap_cfg.role_count_cfg.central_sec_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT ? + BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT : 0; +#endif + + ret_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GAP_CFG_ROLE_COUNT.", + nrf_strerror_get(ret_code)); + } + + // Configure the maximum ATT MTU. +#if (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 23) + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag; + ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; + + ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GATT, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GATT.", + nrf_strerror_get(ret_code)); + } +#endif +#endif // NRF_SDH_BLE_TOTAL_LINK_COUNT != 0 + + // Configure number of custom UUIDS. + memset(&ble_cfg, 0, sizeof(ble_cfg)); + ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = NRF_SDH_BLE_VS_UUID_COUNT; + + ret_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_COMMON_CFG_VS_UUID.", + nrf_strerror_get(ret_code)); + } + + // Configure the GATTS attribute table. + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE; + + ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_ATTR_TAB_SIZE.", + nrf_strerror_get(ret_code)); + } + + // Configure Service Changed characteristic. + memset(&ble_cfg, 0x00, sizeof(ble_cfg)); + ble_cfg.gatts_cfg.service_changed.service_changed = NRF_SDH_BLE_SERVICE_CHANGED; + + ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &ble_cfg, *p_ram_start); + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_SERVICE_CHANGED.", + nrf_strerror_get(ret_code)); + } + + return NRF_SUCCESS; +} + + +/**@brief Function for finding the end address of the RAM. */ +static uint32_t ram_end_address_get(void) +{ + uint32_t ram_total_size; + +#ifdef NRF51 + uint32_t block_size = NRF_FICR->SIZERAMBLOCKS; + ram_total_size = block_size * NRF_FICR->NUMRAMBLOCK; +#else + ram_total_size = NRF_FICR->INFO.RAM * 1024; +#endif + + return RAM_START + ram_total_size; +} + + +ret_code_t nrf_sdh_ble_enable(uint32_t * const p_app_ram_start) +{ + // Start of RAM, obtained from linker symbol. + uint32_t const app_ram_start_link = *p_app_ram_start; + + NRF_LOG_DEBUG("RAM starts at 0x%x", app_ram_start_link); + + ret_code_t ret_code = sd_ble_enable(p_app_ram_start); + if (*p_app_ram_start != app_ram_start_link) + { + NRF_LOG_WARNING("RAM starts at 0x%x, can be adjusted to 0x%x.", + app_ram_start_link, *p_app_ram_start); + + NRF_LOG_WARNING("RAM size can be adjusted to 0x%x.", + ram_end_address_get() - (*p_app_ram_start)); + } + + if (ret_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("sd_ble_enable() returned %s.", nrf_strerror_get(ret_code)); + } + + return ret_code; +} + + +/**@brief Function for polling BLE events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_ble_evts_poll(void * p_context) +{ + ret_code_t ret_code; + + UNUSED_VARIABLE(p_context); + + while (true) + { + __ALIGN(4) uint8_t evt_buffer[NRF_SDH_BLE_EVT_BUF_SIZE]; + + ble_evt_t * p_ble_evt; + uint16_t evt_len = (uint16_t)sizeof(evt_buffer); + + ret_code = sd_ble_evt_get(evt_buffer, &evt_len); + if (ret_code != NRF_SUCCESS) + { + break; + } + + p_ble_evt = (ble_evt_t *)evt_buffer; + + NRF_LOG_DEBUG("BLE event: 0x%x.", p_ble_evt->header.evt_id); + + // Forward the event to BLE observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_ble_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_ble_evt_observer_t * p_observer; + nrf_sdh_ble_evt_handler_t handler; + + p_observer = (nrf_sdh_ble_evt_observer_t *)nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(p_ble_evt, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ble_evts_poll, NRF_SDH_BLE_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_ble_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_BLE) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.h new file mode 100644 index 0000000000..844fd960c7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_ble.h @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_sdh_ble BLE support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for BLE stack + * support. + */ + +#ifndef NRF_SDH_BLE_H__ +#define NRF_SDH_BLE_H__ + +#include "app_util.h" +#include "nrf_ble.h" +#include "nrf_section_iter.h" +#include "sdk_config.h" +#include "sdk_errors.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Size of the buffer for a BLE event. */ +#if (defined(NRF_SD_BLE_API_VERSION) && (NRF_SD_BLE_API_VERSION < 3)) +#define NRF_SDH_BLE_EVT_BUF_SIZE (sizeof(ble_evt_t) + (NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) +#else +#define NRF_SDH_BLE_EVT_BUF_SIZE BLE_EVT_LEN_MAX(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) +#endif + +#if !(defined(__LINT__)) +/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be + * notified about SoC events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler BLE event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_BLE_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_ble_evt_observer_t. + * Modules that want to be notified about SoC events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_ble_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler BLE event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_BLE_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_BLE_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_BLE_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief BLE stack event handler. */ +typedef void (*nrf_sdh_ble_evt_handler_t)(ble_evt_t const * p_ble_evt, void * p_context); + +/**@brief BLE event observer. */ +typedef struct +{ + nrf_sdh_ble_evt_handler_t handler; //!< BLE event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_ble_evt_observer_t; + + +/**@brief Function for retrieving the address of the start of application's RAM. + * + * @param[out] p_app_ram_start Address of the start of application's RAM. + * + * @retval NRF_SUCCESS If the address was successfully retrieved. + * @retval NRF_ERROR_NULL If @p p_app_ram_start was @c NULL. + */ +ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start); + + +/**@brief Set the default BLE stack configuration. + * + * This function configures the BLE stack with the settings specified in the + * SoftDevice handler BLE configuration. The following configurations will be set: + * - Number of peripheral links + * - Number of central links + * - ATT MTU size (for the given connection) + * - Vendor specific UUID count + * - GATTS Attribute table size + * - Service changed + * + * @param[in] conn_cfg_tag The connection to configure. + * @param[out] p_ram_start Application RAM start address. + */ +ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start); + + +/**@brief Function for configuring and enabling the BLE stack. + * + * @param[in] p_app_ram_start Address of the start of application's RAM. + */ +ret_code_t nrf_sdh_ble_enable(uint32_t * p_app_ram_start); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_BLE_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.c new file mode 100644 index 0000000000..cf037022ca --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.c @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_SDH_SOC) + +#include "nrf_sdh_soc.h" + +#include "nrf_sdh.h" +#include "nrf_soc.h" +#include "app_error.h" + + +#define NRF_LOG_MODULE_NAME nrf_sdh_soc +#if NRF_SDH_SOC_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_SDH_SOC_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_SDH_SOC_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_SDH_SOC_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_SDH_SOC_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +// Create section set "sdh_soc_observers". +NRF_SECTION_SET_DEF(sdh_soc_observers, nrf_sdh_soc_evt_observer_t, NRF_SDH_SOC_OBSERVER_PRIO_LEVELS); + + +/**@brief Function for polling SoC events. + * + * @param[in] p_context Context of the observer. + */ +static void nrf_sdh_soc_evts_poll(void * p_context) +{ + ret_code_t ret_code; + + UNUSED_VARIABLE(p_context); + + while (true) + { + uint32_t evt_id; + + ret_code = sd_evt_get(&evt_id); + if (ret_code != NRF_SUCCESS) + { + break; + } + + NRF_LOG_DEBUG("SoC event: 0x%x.", evt_id); + + // Forward the event to SoC observers. + nrf_section_iter_t iter; + for (nrf_section_iter_init(&iter, &sdh_soc_observers); + nrf_section_iter_get(&iter) != NULL; + nrf_section_iter_next(&iter)) + { + nrf_sdh_soc_evt_observer_t * p_observer; + nrf_sdh_soc_evt_handler_t handler; + + p_observer = (nrf_sdh_soc_evt_observer_t *) nrf_section_iter_get(&iter); + handler = p_observer->handler; + + handler(evt_id, p_observer->p_context); + } + } + + if (ret_code != NRF_ERROR_NOT_FOUND) + { + APP_ERROR_HANDLER(ret_code); + } +} + + +NRF_SDH_STACK_OBSERVER(m_nrf_sdh_soc_evts_poll, NRF_SDH_SOC_STACK_OBSERVER_PRIO) = +{ + .handler = nrf_sdh_soc_evts_poll, + .p_context = NULL, +}; + +#endif // NRF_MODULE_ENABLED(NRF_SDH_SOC) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.h new file mode 100644 index 0000000000..42eb541ac0 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/softdevice/common/nrf_sdh_soc.h @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_sdh_soc SoC support in SoftDevice Handler + * @{ + * @ingroup nrf_sdh + * @brief This file contains the declarations of types and functions required for SoftDevice Handler + * SoC support. + */ + +#ifndef NRF_SDH_SOC_H__ +#define NRF_SDH_SOC_H__ + +#include "app_util.h" +#include "nrf_section_iter.h" +#include "nrf_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !(defined(__LINT__)) +/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be + * notified about SoC events must register the handler using this macro. + * + * @details This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler SoC event handler. + * @param[in] _context Parameter to the event handler. + * @hideinitializer + */ +#define NRF_SDH_SOC_OBSERVER(_name, _prio, _handler, _context) \ +STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name) = \ +{ \ + .handler = _handler, \ + .p_context = _context \ +} + +/**@brief Macro for registering an array of @ref nrf_sdh_soc_evt_observer_t. + * Modules that want to be notified about SoC events must register the handler using + * this macro. + * + * Each observer's handler will be dispatched an event with its relative context from @p _context. + * This macro places the observer in a section named "sdh_soc_observers". + * + * @param[in] _name Observer name. + * @param[in] _prio Priority of the observer event handler. + * The smaller the number, the higher the priority. + * @param[in] _handler SoC event handler. + * @param[in] _context An array of parameters to the event handler. + * @param[in] _cnt Number of observers to register. + * @hideinitializer + */ +#define NRF_SDH_SOC_EVENT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \ +STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \ +STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \ +NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name[_cnt]) = \ +{ \ + MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \ +} + +#if !(defined(DOXYGEN)) +#define HANDLER_SET(_idx, _handler, _context) \ +{ \ + .handler = _handler, \ + .p_context = _context[_idx], \ +}, +#endif + +#else // __LINT__ + +/* Swallow semicolons */ +/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */ +#define NRF_SDH_SOC_OBSERVER(A, B, C, D) static int semicolon_swallow_##A +#define NRF_SDH_SOC_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A +/*lint -restore */ + +#endif + + +/**@brief SoC event handler. */ +typedef void (*nrf_sdh_soc_evt_handler_t) (uint32_t evt_id, void * p_context); + +/**@brief SoC event observer. */ +typedef struct +{ + nrf_sdh_soc_evt_handler_t handler; //!< SoC event handler. + void * p_context; //!< A parameter to the event handler. +} const nrf_sdh_soc_evt_observer_t; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SDH_SOC_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.c new file mode 100644 index 0000000000..b7c1ac01f6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.c @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_FSTORAGE) + +#include "nrf_fstorage_nvmc.h" +#include +#include +#include +#include "nrf_nvmc.h" +#include "nrf_atomic.h" + + +static nrf_fstorage_info_t m_flash_info = +{ +#if defined(NRF51) + .erase_unit = 1024, +#elif defined(NRF52_SERIES) + .erase_unit = 4096, +#endif + .program_unit = 4, + .rmap = true, + .wmap = false, +}; + + + /* An operation initiated by fstorage is ongoing. */ +static nrf_atomic_flag_t m_flash_operation_ongoing; + + +/* Send event to the event handler. */ +static void event_send(nrf_fstorage_t const * p_fs, + nrf_fstorage_evt_id_t evt_id, + uint32_t addr, + uint32_t len, + void * p_param) +{ + if (p_fs->evt_handler == NULL) + { + /* Nothing to do. */ + return; + } + + nrf_fstorage_evt_t evt = + { + .result = NRF_SUCCESS, + .id = evt_id, + .addr = addr, + .len = len, + .p_param = p_param, + }; + + p_fs->evt_handler(&evt); +} + + +static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_param); + + p_fs->p_flash_info = &m_flash_info; + + return NRF_SUCCESS; +} + + +static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(p_param); + + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + return NRF_SUCCESS; +} + + +static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len) +{ + UNUSED_PARAMETER(p_fs); + + memcpy(p_dest, (uint32_t*)src, len); + + return NRF_SUCCESS; +} + + +static ret_code_t write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param) +{ + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + nrf_nvmc_write_words(dest, (uint32_t*)p_src, (len / m_flash_info.program_unit)); + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_WRITE_RESULT, dest, len, p_param); + + return NRF_SUCCESS; +} + + +static ret_code_t erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param) +{ + uint32_t progress = 0; + + if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing)) + { + return NRF_ERROR_BUSY; + } + + while (progress != len) + { + nrf_nvmc_page_erase(page_addr + (progress * m_flash_info.erase_unit)); + progress++; + } + + /* Clear the flag before sending the event, to allow API calls in the event context. */ + (void) nrf_atomic_flag_clear(&m_flash_operation_ongoing); + + event_send(p_fs, NRF_FSTORAGE_EVT_ERASE_RESULT, page_addr, len, p_param); + + return NRF_SUCCESS; +} + + +static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + + return (uint8_t*)addr; +} + + +static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + UNUSED_PARAMETER(p_fs); + UNUSED_PARAMETER(addr); + + /* Not supported. */ + return NULL; +} + + +static bool is_busy(nrf_fstorage_t const * p_fs) +{ + UNUSED_PARAMETER(p_fs); + + return m_flash_operation_ongoing; +} + + +/* The exported API. */ +nrf_fstorage_api_t nrf_fstorage_nvmc = +{ + .init = init, + .uninit = uninit, + .read = read, + .write = write, + .erase = erase, + .rmap = rmap, + .wmap = wmap, + .is_busy = is_busy +}; + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.h new file mode 100644 index 0000000000..be3477556c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/libraries/fstorage/nrf_fstorage_nvmc.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_fstorage_nvmc NVMC implementation + * @ingroup nrf_fstorage + * @{ + * + * @brief API implementation of fstorage that uses the non-volatile memory controller (NVMC). +*/ + +#ifndef NRF_FSTORAGE_NVMC_H__ +#define NRF_FSTORAGE_NVMC_H__ + +#include "nrf_fstorage.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief API implementation that uses the non-volatile memory controller. + * + * @details An fstorage instance with this API implementation can be initialized by providing + * this structure as a parameter to @ref nrf_fstorage_init. + * The structure is defined in @c nrf_fstorage_nvmc.c. + */ +extern nrf_fstorage_api_t nrf_fstorage_nvmc; + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_NVMC_H__ +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_error.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_error.h new file mode 100644 index 0000000000..6ae2c9b52a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_error.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/* Header guard */ +#ifndef NRF_ERROR_H__ +#define NRF_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/// @cond Make doxygen skip this file + +/** @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) ///< Data size exceeds limit +#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 + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_ERROR_H__ + +/// @endcond +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.c new file mode 100644 index 0000000000..45803bf61a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.c @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf_soc.h" +#include "nrf_error.h" + +static uint8_t m_in_critical_region = 0; + +uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn) +{ + NVIC_EnableIRQ(IRQn); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn) +{ + NVIC_DisableIRQ(IRQn); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq) +{ + if (p_pending_irq != NULL) + { + *p_pending_irq = NVIC_GetPendingIRQ(IRQn); + return NRF_SUCCESS; + } + return NRF_ERROR_NULL; +} + +uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC_SetPendingIRQ(IRQn); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC_ClearPendingIRQ(IRQn); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + NVIC_SetPriority(IRQn, priority); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority) +{ + if (p_priority != NULL) + { + *p_priority = NVIC_GetPriority(IRQn); + return NRF_SUCCESS; + } + + return NRF_ERROR_NULL; +} + +uint32_t sd_nvic_SystemReset(void) +{ + NVIC_SystemReset(); + return NRF_SUCCESS; +} + +uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region) +{ + __disable_irq(); + + *p_is_nested_critical_region = (m_in_critical_region != 0); + m_in_critical_region++; + + return NRF_SUCCESS; +} + +uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region) +{ + m_in_critical_region--; + + if (is_nested_critical_region == 0) + { + m_in_critical_region = 0; + __enable_irq(); + } + return NRF_SUCCESS; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.h new file mode 100644 index 0000000000..3ab15d66d1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_nvic.h @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_NVIC_H__ +#define NRF_NVIC_H__ + +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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 + */ +uint32_t sd_nvic_SystemReset(void); + +/**@brief Enters critical region. + * + * @post Application interrupts will be disabled. + * @sa sd_nvic_critical_region_exit + * + * @param[out] p_is_nested_critical_region 1: If in a nested critical region. + * 0: Otherwise. + * + * @retval ::NRF_SUCCESS + */ +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 + */ +uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_NVIC_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.c new file mode 100644 index 0000000000..8b273d74bf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.c @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf_soc.h" +#include "nrf_error.h" + +uint32_t sd_app_evt_wait(void) +{ + __WFE(); + return NRF_SUCCESS; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.h new file mode 100644 index 0000000000..3119ada366 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_NONE/nrf_soc_nosd/nrf_soc.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SOC_H__ +#define NRF_SOC_H__ + +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@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 + */ +uint32_t sd_app_evt_wait(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_SOC_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf51822_5.1.0_release-notes.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf51822_5.1.0_release-notes.pdf new file mode 100644 index 0000000000..08f82cbe53 Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf51822_5.1.0_release-notes.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf52810_5.1.0_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf52810_5.1.0_licence-agreement.txt new file mode 100644 index 0000000000..00c2e54c47 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/doc/s112_nrf52810_5.1.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 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 form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_err.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_err.h new file mode 100644 index 0000000000..1b0b9d4435 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_err.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x004) /**< Invalid role. */ +/** @} */ + + +/** @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_.h or ble_error_.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 + + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gap.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gap.h new file mode 100644 index 0000000000..f25cb40638 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gap.h @@ -0,0 +1,1847 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_GAP Generic Access Profile (GAP) + @{ + @brief Definitions and prototypes for the GAP interface. + */ + +#ifndef BLE_GAP_H__ +#define BLE_GAP_H__ + +#include +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup BLE_GAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GAP API SVC numbers. + */ +enum BLE_GAP_SVCS +{ + SD_BLE_GAP_ADDR_SET = BLE_GAP_SVC_BASE, /**< Set own Bluetooth Address. */ + SD_BLE_GAP_ADDR_GET = BLE_GAP_SVC_BASE + 1, /**< Get own Bluetooth Address. */ + SD_BLE_GAP_WHITELIST_SET = BLE_GAP_SVC_BASE + 2, /**< Set active whitelist. */ + SD_BLE_GAP_DEVICE_IDENTITIES_SET = BLE_GAP_SVC_BASE + 3, /**< Set device identity list. */ + SD_BLE_GAP_PRIVACY_SET = BLE_GAP_SVC_BASE + 4, /**< Set Privacy settings*/ + SD_BLE_GAP_PRIVACY_GET = BLE_GAP_SVC_BASE + 5, /**< Get Privacy settings*/ + SD_BLE_GAP_ADV_DATA_SET = BLE_GAP_SVC_BASE + 6, /**< Set Advertising Data. */ + SD_BLE_GAP_ADV_START = BLE_GAP_SVC_BASE + 7, /**< Start Advertising. */ + SD_BLE_GAP_ADV_STOP = BLE_GAP_SVC_BASE + 8, /**< Stop Advertising. */ + SD_BLE_GAP_CONN_PARAM_UPDATE = BLE_GAP_SVC_BASE + 9, /**< Connection Parameter Update. */ + SD_BLE_GAP_DISCONNECT = BLE_GAP_SVC_BASE + 10, /**< Disconnect. */ + SD_BLE_GAP_TX_POWER_SET = BLE_GAP_SVC_BASE + 11, /**< Set TX Power. */ + SD_BLE_GAP_APPEARANCE_SET = BLE_GAP_SVC_BASE + 12, /**< Set Appearance. */ + SD_BLE_GAP_APPEARANCE_GET = BLE_GAP_SVC_BASE + 13, /**< Get Appearance. */ + SD_BLE_GAP_PPCP_SET = BLE_GAP_SVC_BASE + 14, /**< Set PPCP. */ + SD_BLE_GAP_PPCP_GET = BLE_GAP_SVC_BASE + 15, /**< Get PPCP. */ + SD_BLE_GAP_DEVICE_NAME_SET = BLE_GAP_SVC_BASE + 16, /**< Set Device Name. */ + SD_BLE_GAP_DEVICE_NAME_GET = BLE_GAP_SVC_BASE + 17, /**< Get Device Name. */ + SD_BLE_GAP_AUTHENTICATE = BLE_GAP_SVC_BASE + 18, /**< Initiate Pairing/Bonding. */ + SD_BLE_GAP_SEC_PARAMS_REPLY = BLE_GAP_SVC_BASE + 19, /**< Reply with Security Parameters. */ + SD_BLE_GAP_AUTH_KEY_REPLY = BLE_GAP_SVC_BASE + 20, /**< Reply with an authentication key. */ + SD_BLE_GAP_LESC_DHKEY_REPLY = BLE_GAP_SVC_BASE + 21, /**< Reply with an LE Secure Connections DHKey. */ + SD_BLE_GAP_KEYPRESS_NOTIFY = BLE_GAP_SVC_BASE + 22, /**< Notify of a keypress during an authentication procedure. */ + SD_BLE_GAP_LESC_OOB_DATA_GET = BLE_GAP_SVC_BASE + 23, /**< Get the local LE Secure Connections OOB data. */ + SD_BLE_GAP_LESC_OOB_DATA_SET = BLE_GAP_SVC_BASE + 24, /**< Set the remote LE Secure Connections OOB data. */ + SD_BLE_GAP_SEC_INFO_REPLY = BLE_GAP_SVC_BASE + 26, /**< Reply with Security Information. */ + SD_BLE_GAP_CONN_SEC_GET = BLE_GAP_SVC_BASE + 27, /**< Obtain connection security level. */ + SD_BLE_GAP_RSSI_START = BLE_GAP_SVC_BASE + 28, /**< Start reporting of changes in RSSI. */ + SD_BLE_GAP_RSSI_STOP = BLE_GAP_SVC_BASE + 29, /**< Stop reporting of changes in RSSI. */ + SD_BLE_GAP_RSSI_GET = BLE_GAP_SVC_BASE + 34, /**< Get the last RSSI sample. */ + SD_BLE_GAP_PHY_UPDATE = BLE_GAP_SVC_BASE + 35, /**< Initiate or respond to a PHY Update Procedure. */ +}; + +/**@brief GAP Event IDs. + * IDs that uniquely identify an event coming from the stack to the application. + */ +enum BLE_GAP_EVTS +{ + BLE_GAP_EVT_CONNECTED = BLE_GAP_EVT_BASE, + BLE_GAP_EVT_DISCONNECTED = BLE_GAP_EVT_BASE + 1, /**< Disconnected from peer. \n See @ref ble_gap_evt_disconnected_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE = BLE_GAP_EVT_BASE + 2, /**< Connection Parameters updated. \n See @ref ble_gap_evt_conn_param_update_t. */ + BLE_GAP_EVT_SEC_PARAMS_REQUEST = BLE_GAP_EVT_BASE + 3, /**< Request to provide security parameters. \n Reply with @ref sd_ble_gap_sec_params_reply. \n See @ref ble_gap_evt_sec_params_request_t. */ + BLE_GAP_EVT_SEC_INFO_REQUEST = BLE_GAP_EVT_BASE + 4, /**< Request to provide security information. \n Reply with @ref sd_ble_gap_sec_info_reply. \n See @ref ble_gap_evt_sec_info_request_t. */ + BLE_GAP_EVT_PASSKEY_DISPLAY = BLE_GAP_EVT_BASE + 5, /**< Request to display a passkey to the user. \n In LESC Numeric Comparison, reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_passkey_display_t. */ + BLE_GAP_EVT_KEY_PRESSED = BLE_GAP_EVT_BASE + 6, /**< Notification of a keypress on the remote device.\n See @ref ble_gap_evt_key_pressed_t */ + BLE_GAP_EVT_AUTH_KEY_REQUEST = BLE_GAP_EVT_BASE + 7, /**< Request to provide an authentication key. \n Reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_auth_key_request_t. */ + BLE_GAP_EVT_LESC_DHKEY_REQUEST = BLE_GAP_EVT_BASE + 8, /**< Request to calculate an LE Secure Connections DHKey. \n Reply with @ref sd_ble_gap_lesc_dhkey_reply. \n See @ref ble_gap_evt_lesc_dhkey_request_t */ + BLE_GAP_EVT_AUTH_STATUS = BLE_GAP_EVT_BASE + 9, /**< Authentication procedure completed with status. \n See @ref ble_gap_evt_auth_status_t. */ + BLE_GAP_EVT_CONN_SEC_UPDATE = BLE_GAP_EVT_BASE + 10, /**< Connection security updated. \n See @ref ble_gap_evt_conn_sec_update_t. */ + BLE_GAP_EVT_TIMEOUT = BLE_GAP_EVT_BASE + 11, /**< Timeout expired. \n See @ref ble_gap_evt_timeout_t. */ + BLE_GAP_EVT_RSSI_CHANGED = BLE_GAP_EVT_BASE + 12, /**< RSSI report. \n See @ref ble_gap_evt_rssi_changed_t. */ + BLE_GAP_EVT_SEC_REQUEST = BLE_GAP_EVT_BASE + 14, /**< Security Request. \n See @ref ble_gap_evt_sec_request_t. */ + BLE_GAP_EVT_SCAN_REQ_REPORT = BLE_GAP_EVT_BASE + 16, /**< Scan request report. \n See @ref ble_gap_evt_scan_req_report_t. */ + BLE_GAP_EVT_PHY_UPDATE_REQUEST = BLE_GAP_EVT_BASE + 17, /**< PHY Update Request. \n Reply with @ref sd_ble_gap_phy_update. \n See @ref ble_gap_evt_phy_update_request_t. */ + BLE_GAP_EVT_PHY_UPDATE = BLE_GAP_EVT_BASE + 18, /**< PHY Update Procedure is complete. \n See @ref ble_gap_evt_phy_update_t. */ +}; + +/**@brief GAP Option IDs. + * IDs that uniquely identify a GAP option. + */ +enum BLE_GAP_OPTS +{ + BLE_GAP_OPT_CH_MAP = BLE_GAP_OPT_BASE, /**< Channel Map. @ref ble_gap_opt_ch_map_t */ + BLE_GAP_OPT_LOCAL_CONN_LATENCY = BLE_GAP_OPT_BASE + 1, /**< Local connection latency. @ref ble_gap_opt_local_conn_latency_t */ + BLE_GAP_OPT_PASSKEY = BLE_GAP_OPT_BASE + 2, /**< Set passkey. @ref ble_gap_opt_passkey_t */ + BLE_GAP_OPT_SCAN_REQ_REPORT = BLE_GAP_OPT_BASE + 3, /**< Scan request report. @ref ble_gap_opt_scan_req_report_t */ + BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT = BLE_GAP_OPT_BASE + 5, /**< Set Authenticated payload timeout. @ref ble_gap_opt_auth_payload_timeout_t */ + BLE_GAP_OPT_SLAVE_LATENCY_DISABLE = BLE_GAP_OPT_BASE + 6, /**< Disable slave latency. @ref ble_gap_opt_slave_latency_disable_t */ +}; + +/**@brief GAP Configuration IDs. + * + * IDs that uniquely identify a GAP configuration. + */ +enum BLE_GAP_CFGS +{ + BLE_GAP_CFG_ROLE_COUNT = BLE_GAP_CFG_BASE, /**< Role count configuration. */ + BLE_GAP_CFG_DEVICE_NAME = BLE_GAP_CFG_BASE + 1, /**< Device name configuration. */ +}; + +/** @} */ + +/**@addtogroup BLE_GAP_DEFINES Defines + * @{ */ + +/**@defgroup BLE_ERRORS_GAP SVC return values specific to GAP + * @{ */ +#define BLE_ERROR_GAP_UUID_LIST_MISMATCH (NRF_GAP_ERR_BASE + 0x000) /**< UUID list does not contain an integral number of UUIDs. */ +#define BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST (NRF_GAP_ERR_BASE + 0x001) /**< Use of Whitelist not permitted with discoverable advertising. */ +#define BLE_ERROR_GAP_INVALID_BLE_ADDR (NRF_GAP_ERR_BASE + 0x002) /**< The upper two bits of the address do not correspond to the specified address type. */ +#define BLE_ERROR_GAP_WHITELIST_IN_USE (NRF_GAP_ERR_BASE + 0x003) /**< Attempt to modify the whitelist while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE (NRF_GAP_ERR_BASE + 0x004) /**< Attempt to modify the device identity list while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE (NRF_GAP_ERR_BASE + 0x005) /**< The device identity list contains entries with duplicate identity addresses. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLES GAP Roles + * @{ */ +#define BLE_GAP_ROLE_INVALID 0x0 /**< Invalid Role. */ +#define BLE_GAP_ROLE_PERIPH 0x1 /**< Peripheral Role. */ +/**@} */ + + +/**@defgroup BLE_GAP_TIMEOUT_SOURCES GAP Timeout sources + * @{ */ +#define BLE_GAP_TIMEOUT_SRC_ADVERTISING 0x00 /**< Advertising timeout. */ +#define BLE_GAP_TIMEOUT_SRC_CONN 0x02 /**< Connection timeout. */ +#define BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD 0x03 /**< Authenticated payload timeout. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADDR_TYPES GAP Address types + * @{ */ +#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00 /**< Public address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01 /**< Random static address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02 /**< Random private resolvable address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03 /**< Random private non-resolvable address. */ +/**@} */ + + +/**@brief The default interval in seconds at which a private address is refreshed. */ +#define BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S (900) /* 15 minutes. */ +/**@brief The maximum interval in seconds at which a private address can be refreshed. */ +#define BLE_GAP_MAX_PRIVATE_ADDR_CYCLE_INTERVAL_S (41400) /* 11 hours 30 minutes. */ + + +/** @brief BLE address length. */ +#define BLE_GAP_ADDR_LEN (6) + + +/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes + * @{ */ +#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ +#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ +#define BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY 0x02 /**< Device will send and accept only private addresses for its own address, + and will not accept a peer using identity address as sender address when + the peer IRK is exchanged, non-zero and added to the identity list. */ +/**@} */ + + +/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format + * @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm + * @{ */ +#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */ +#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */ +#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */ +#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */ +#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */ +#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */ +#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */ +#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */ +#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */ +#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */ +#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */ +#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */ +#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ +#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ +#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FLAGS GAP Advertisement Flags + * @{ */ +#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_INTERVALS GAP Advertising interval max and min + * @{ */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 /**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 /**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ + /**@} */ + + +/**@brief Maximum size of advertising data in octets. */ +#define BLE_GAP_ADV_MAX_SIZE (31) + + +/**@defgroup BLE_GAP_ADV_TYPES GAP Advertising types + * @{ */ +#define BLE_GAP_ADV_TYPE_ADV_IND 0x00 /**< Connectable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01 /**< Connectable directed. */ +#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02 /**< Scannable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03 /**< Non connectable undirected. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FILTER_POLICIES GAP Advertising filter policies + * @{ */ +#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ +#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01 /**< Filter scan requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02 /**< Filter connect requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03 /**< Filter both scan and connect requests with whitelist. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_TIMEOUT_VALUES GAP Advertising timeout values + * @{ */ +#define BLE_GAP_ADV_TIMEOUT_LIMITED_MAX (180) /**< Maximum advertising time in limited discoverable mode (TGAP(lim_adv_timeout) = 180 s). */ +#define BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED (0) /**< Unlimited advertising in general discoverable mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_DISC_MODES GAP Discovery modes + * @{ */ +#define BLE_GAP_DISC_MODE_NOT_DISCOVERABLE 0x00 /**< Not discoverable discovery Mode. */ +#define BLE_GAP_DISC_MODE_LIMITED 0x01 /**< Limited Discovery Mode. */ +#define BLE_GAP_DISC_MODE_GENERAL 0x02 /**< General Discovery Mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_IO_CAPS GAP IO Capabilities + * @{ */ +#define BLE_GAP_IO_CAPS_DISPLAY_ONLY 0x00 /**< Display Only. */ +#define BLE_GAP_IO_CAPS_DISPLAY_YESNO 0x01 /**< Display and Yes/No entry. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_ONLY 0x02 /**< Keyboard Only. */ +#define BLE_GAP_IO_CAPS_NONE 0x03 /**< No I/O capabilities. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY 0x04 /**< Keyboard and Display. */ +/**@} */ + + +/**@defgroup BLE_GAP_AUTH_KEY_TYPES GAP Authentication Key Types + * @{ */ +#define BLE_GAP_AUTH_KEY_TYPE_NONE 0x00 /**< No key (may be used to reject). */ +#define BLE_GAP_AUTH_KEY_TYPE_PASSKEY 0x01 /**< 6-digit Passkey. */ +#define BLE_GAP_AUTH_KEY_TYPE_OOB 0x02 /**< Out Of Band data. */ +/**@} */ + + +/**@defgroup BLE_GAP_KP_NOT_TYPES GAP Keypress Notification Types + * @{ */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_START 0x00 /**< Passkey entry started. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_IN 0x01 /**< Passkey digit entered. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_OUT 0x02 /**< Passkey digit erased. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_CLEAR 0x03 /**< Passkey cleared. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_END 0x04 /**< Passkey entry completed. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS GAP Security status + * @{ */ +#define BLE_GAP_SEC_STATUS_SUCCESS 0x00 /**< Procedure completed with success. */ +#define BLE_GAP_SEC_STATUS_TIMEOUT 0x01 /**< Procedure timed out. */ +#define BLE_GAP_SEC_STATUS_PDU_INVALID 0x02 /**< Invalid PDU received. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_BEGIN 0x03 /**< Reserved for Future Use range #1 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_END 0x80 /**< Reserved for Future Use range #1 end. */ +#define BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user canceled or other). */ +#define BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE 0x82 /**< Out of Band Key not available. */ +#define BLE_GAP_SEC_STATUS_AUTH_REQ 0x83 /**< Authentication requirements not met. */ +#define BLE_GAP_SEC_STATUS_CONFIRM_VALUE 0x84 /**< Confirm value failed. */ +#define BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 0x85 /**< Pairing not supported. */ +#define BLE_GAP_SEC_STATUS_ENC_KEY_SIZE 0x86 /**< Encryption key size. */ +#define BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED 0x87 /**< Unsupported SMP command. */ +#define BLE_GAP_SEC_STATUS_UNSPECIFIED 0x88 /**< Unspecified reason. */ +#define BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS 0x89 /**< Too little time elapsed since last attempt. */ +#define BLE_GAP_SEC_STATUS_INVALID_PARAMS 0x8A /**< Invalid parameters. */ +#define BLE_GAP_SEC_STATUS_DHKEY_FAILURE 0x8B /**< DHKey check failure. */ +#define BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE 0x8C /**< Numeric Comparison failure. */ +#define BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG 0x8D /**< BR/EDR pairing in progress. */ +#define BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED 0x8E /**< BR/EDR Link Key cannot be used for LE keys. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_BEGIN 0x8F /**< Reserved for Future Use range #2 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_END 0xFF /**< Reserved for Future Use range #2 end. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS_SOURCES GAP Security status sources + * @{ */ +#define BLE_GAP_SEC_STATUS_SOURCE_LOCAL 0x00 /**< Local failure. */ +#define BLE_GAP_SEC_STATUS_SOURCE_REMOTE 0x01 /**< Remote failure. */ +/**@} */ + + +/**@defgroup BLE_GAP_CP_LIMITS GAP Connection Parameters Limits + * @{ */ +#define BLE_GAP_CP_MIN_CONN_INTVL_NONE 0xFFFF /**< No new minimum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 /**< Lowest minimum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MAX 0x0C80 /**< Highest minimum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_NONE 0xFFFF /**< No new maximum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MIN 0x0006 /**< Lowest maximum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MAX 0x0C80 /**< Highest maximum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_SLAVE_LATENCY_MAX 0x01F3 /**< Highest slave latency permitted, in connection events. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE 0xFFFF /**< No new supervision timeout specified in connect parameters. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN 0x000A /**< Lowest supervision timeout permitted, in units of 10 ms, i.e. 100 ms. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 0x0C80 /**< Highest supervision timeout permitted, in units of 10 ms, i.e. 32 s. */ +/**@} */ + + +/**@defgroup BLE_GAP_DEVNAME GAP device name defines. + * @{ */ +#define BLE_GAP_DEVNAME_DEFAULT "nRF5x" /**< Default device name value. */ +#define BLE_GAP_DEVNAME_DEFAULT_LEN 31 /**< Default number of octets in device name. */ +#define BLE_GAP_DEVNAME_MAX_LEN 248 /**< Maximum number of octets in device name. */ +/**@} */ + + +/**@brief Disable RSSI events for connections */ +#define BLE_GAP_RSSI_THRESHOLD_INVALID 0xFF + +/**@defgroup BLE_GAP_PHYS GAP PHYs + * @{ */ +#define BLE_GAP_PHY_AUTO 0x00 /**< Automatic PHY selection. Refer @ref sd_ble_gap_phy_update for more information.*/ +#define BLE_GAP_PHY_1MBPS 0x01 /**< 1 Mbps PHY. */ +#define BLE_GAP_PHY_2MBPS 0x02 /**< 2 Mbps PHY. */ +#define BLE_GAP_PHY_CODED 0x04 /**< Coded PHY. */ + +/**@} */ + +/**@defgroup BLE_GAP_CONN_SEC_MODE_SET_MACROS GAP attribute security requirement setters + * + * See @ref ble_gap_conn_sec_mode_t. + * @{ */ +/**@brief Set sec_mode pointed to by ptr to have no access rights.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(ptr) do {(ptr)->sm = 0; (ptr)->lv = 0;} while(0) +/**@brief Set sec_mode pointed to by ptr to require no protection, open link.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_OPEN(ptr) do {(ptr)->sm = 1; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption, but no MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 2;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 3;} while(0) +/**@brief Set sec_mode pointed to by ptr to require LESC encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 4;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption, no MITM protection needed.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption with MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 2;} while(0) +/**@} */ + + +/**@brief GAP Security Random Number Length. */ +#define BLE_GAP_SEC_RAND_LEN 8 + + +/**@brief GAP Security Key Length. */ +#define BLE_GAP_SEC_KEY_LEN 16 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key Length. */ +#define BLE_GAP_LESC_P256_PK_LEN 64 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman DHKey Length. */ +#define BLE_GAP_LESC_DHKEY_LEN 32 + + +/**@brief GAP Passkey Length. */ +#define BLE_GAP_PASSKEY_LEN 6 + + +/**@brief Maximum amount of addresses in the whitelist. */ +#define BLE_GAP_WHITELIST_ADDR_MAX_COUNT (8) + + +/**@brief Maximum amount of identities in the device identities list. */ +#define BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT (8) + + +/**@brief Default connection count for a configuration. */ +#define BLE_GAP_CONN_COUNT_DEFAULT (1) + + +/**@defgroup BLE_GAP_EVENT_LENGTH GAP event length defines. + * @{ */ +#define BLE_GAP_EVENT_LENGTH_MIN (2) /**< Minimum event length, in 1.25 ms units. */ +#define BLE_GAP_EVENT_LENGTH_DEFAULT (3) /**< Default event length, in 1.25 ms units. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLE_COUNT GAP concurrent connection count defines. + * @{ */ +#define BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT (1) /**< Default maximum number of connections concurrently acting as peripherals. */ +#define BLE_GAP_ROLE_COUNT_COMBINED_MAX (20) /**< Maximum supported number of concurrent connections in the peripheral roles. */ + +/**@} */ + + +/**@defgroup BLE_GAP_AUTH_PAYLOAD_TIMEOUT Authenticated payload timeout defines. + * @{ */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX (48000) /**< Maximum authenticated payload timeout in 10 ms units, i.e. 8 minutes. */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MIN (1) /**< Minimum authenticated payload timeout in 10 ms units, i.e. 10 ms. */ +/**@} */ + +/**@defgroup GAP_SEC_MODES GAP Security Modes + * @{ */ +#define BLE_GAP_SEC_MODE 0x00 /**< No key (may be used to reject). */ +/**@} */ +/** @} */ + + +/**@addtogroup BLE_GAP_STRUCTURES Structures + * @{ */ + +/**@brief Bluetooth Low Energy address. */ +typedef struct +{ + uint8_t addr_id_peer : 1; /**< Only valid for peer addresses. + Reference to peer in device identities list (as set with @ref sd_ble_gap_device_identities_set) when peer is using privacy. */ + uint8_t addr_type : 7; /**< See @ref BLE_GAP_ADDR_TYPES. */ + uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format. */ +} ble_gap_addr_t; + + +/**@brief GAP connection parameters. + * + * @note When ble_conn_params_t is received in an event, both min_conn_interval and + * max_conn_interval will be equal to the connection interval set by the central. + * + * @note If both conn_sup_timeout and max_conn_interval are specified, then the following constraint applies: + * conn_sup_timeout * 4 > (1 + slave_latency) * max_conn_interval + * that corresponds to the following Bluetooth Spec requirement: + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, where Conn_Interval_Max is given in milliseconds. + */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/ +} ble_gap_conn_params_t; + + +/**@brief GAP connection security modes. + * + * Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\n + * Security Mode 1 Level 1: No security is needed (aka open link).\n + * Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\n + * Security Mode 1 Level 3: MITM protected encrypted link required.\n + * Security Mode 1 Level 4: LESC MITM protected encrypted link using a 128-bit strength encryption key required.\n + * Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\n + * Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\n + */ +typedef struct +{ + uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */ + uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */ + +} ble_gap_conn_sec_mode_t; + + +/**@brief GAP connection security status.*/ +typedef struct +{ + ble_gap_conn_sec_mode_t sec_mode; /**< Currently active security mode for this connection.*/ + uint8_t encr_key_size; /**< Length of currently active encryption key, 7 to 16 octets (only applicable for bonding procedures). */ +} ble_gap_conn_sec_t; + +/**@brief Identity Resolving Key. */ +typedef struct +{ + uint8_t irk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing IRK. */ +} ble_gap_irk_t; + + +/**@brief Channel mask for RF channels used in advertising. */ +typedef struct +{ + uint8_t ch_37_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 37 */ + uint8_t ch_38_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 38 */ + uint8_t ch_39_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 39 */ +} ble_gap_adv_ch_mask_t; + + +/**@brief GAP advertising parameters. */ +typedef struct +{ + uint8_t type; /**< See @ref BLE_GAP_ADV_TYPES. */ + ble_gap_addr_t const *p_peer_addr; /**< Address of a known peer. + - When privacy is enabled and the local device use @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE addresses, the device identity list is searched for a matching + entry. If the local IRK for that device identity is set, the local IRK for that device will be used to generate the advertiser address field in the advertise packet. + - If type is @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this must be set to the targeted initiator. If the initiator is in the device identity list, + the peer IRK for that device will be used to generate the initiator address field in the ADV_DIRECT_IND packet. */ + uint8_t fp; /**< Filter Policy, see @ref BLE_GAP_ADV_FILTER_POLICIES. */ + uint16_t interval; /**< Advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20 ms to 10.24 s), see @ref BLE_GAP_ADV_INTERVALS. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for high duty cycle directed advertising. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, set @ref BLE_GAP_ADV_INTERVAL_MIN <= interval <= @ref BLE_GAP_ADV_INTERVAL_MAX for low duty cycle advertising.*/ + uint16_t timeout; /**< Advertising timeout between 0x0001 and 0x3FFF in seconds, 0x0000 disables timeout. See also @ref BLE_GAP_ADV_TIMEOUT_VALUES. If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for High duty cycle directed advertising. */ + ble_gap_adv_ch_mask_t channel_mask; /**< Advertising channel mask. See @ref ble_gap_adv_ch_mask_t. */ +} ble_gap_adv_params_t; + + +/**@brief Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of time. + * The privacy feature, when enabled, hides the local device identity and replaces it with a private address + * that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity Resolving Key (IRK). + * With this key, a device can generate a random private address that can only be recognized by peers in possession of that key, + * and devices can establish connections without revealing their real identities. + * + * Both network privacy (@ref BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY) and device privacy (@ref BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY) + * are supported. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref sd_ble_gap_sec_params_reply is called. + */ +typedef struct +{ + uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ + uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ + uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ + ble_gap_irk_t *p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. + When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. + By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ +} ble_gap_privacy_params_t; + + +/**@brief PHY preferences for TX and RX + * @note tx_phys and rx_phys are bit fields. Multiple bits can be set in them to indicate multiple preferred PHYs for each direction. + * @code + * p_gap_phys->tx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * p_gap_phys->rx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * @endcode + * + */ +typedef struct +{ + uint8_t tx_phys; /**< Preferred transmit PHYs, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phys; /**< Preferred receive PHYs, see @ref BLE_GAP_PHYS. */ +} ble_gap_phys_t; + +/** @brief Keys that can be exchanged during a bonding procedure. */ +typedef struct +{ + uint8_t enc : 1; /**< Long Term Key and Master Identification. */ + uint8_t id : 1; /**< Identity Resolving Key and Identity Address Information. */ + uint8_t sign : 1; /**< Connection Signature Resolving Key. */ + uint8_t link : 1; /**< Derive the Link Key from the LTK. */ +} ble_gap_sec_kdist_t; + + +/**@brief GAP security parameters. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Enable Man In The Middle protection. */ + uint8_t lesc : 1; /**< Enable LE Secure Connection pairing. */ + uint8_t keypress : 1; /**< Enable generation of keypress notifications. */ + uint8_t io_caps : 3; /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ + uint8_t oob : 1; /**< The OOB data flag. + - In LE legacy pairing, this flag is set if a device has out of band authentication data. + The OOB method is used if both of the devices have out of band authentication data. + - In LE Secure Connections pairing, this flag is set if a device has the peer device's out of band authentication data. + The OOB method is used if at least one device has the peer device's OOB data available. */ + uint8_t min_key_size; /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ + uint8_t max_key_size; /**< Maximum encryption key size in octets between min_key_size and 16. */ + ble_gap_sec_kdist_t kdist_own; /**< Key distribution bitmap: keys that the local device will distribute. */ + ble_gap_sec_kdist_t kdist_peer; /**< Key distribution bitmap: keys that the remote device will distribute. */ +} ble_gap_sec_params_t; + + +/**@brief GAP Encryption Information. */ +typedef struct +{ + uint8_t ltk[BLE_GAP_SEC_KEY_LEN]; /**< Long Term Key. */ + uint8_t lesc : 1; /**< Key generated using LE Secure Connections. */ + uint8_t auth : 1; /**< Authenticated Key. */ + uint8_t ltk_len : 6; /**< LTK length in octets. */ +} ble_gap_enc_info_t; + + +/**@brief GAP Master Identification. */ +typedef struct +{ + uint16_t ediv; /**< Encrypted Diversifier. */ + uint8_t rand[BLE_GAP_SEC_RAND_LEN]; /**< Random Number. */ +} ble_gap_master_id_t; + + +/**@brief GAP Signing Information. */ +typedef struct +{ + uint8_t csrk[BLE_GAP_SEC_KEY_LEN]; /**< Connection Signature Resolving Key. */ +} ble_gap_sign_info_t; + + +/**@brief GAP LE Secure Connections P-256 Public Key. */ +typedef struct +{ + uint8_t pk[BLE_GAP_LESC_P256_PK_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key. Stored in the standard SMP protocol format: {X,Y} both in little-endian. */ +} ble_gap_lesc_p256_pk_t; + + +/**@brief GAP LE Secure Connections DHKey. */ +typedef struct +{ + uint8_t key[BLE_GAP_LESC_DHKEY_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman Key. Stored in little-endian. */ +} ble_gap_lesc_dhkey_t; + + +/**@brief GAP LE Secure Connections OOB data. */ +typedef struct +{ + ble_gap_addr_t addr; /**< Bluetooth address of the device. */ + uint8_t r[BLE_GAP_SEC_KEY_LEN]; /**< Random Number. */ + uint8_t c[BLE_GAP_SEC_KEY_LEN]; /**< Confirm Value. */ +} ble_gap_lesc_oob_data_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONNECTED. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + uint8_t role; /**< BLE role for this connection, see @ref BLE_GAP_ROLES */ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_connected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_DISCONNECTED. */ +typedef struct +{ + uint8_t reason; /**< HCI error code, see @ref BLE_HCI_STATUS_CODES. */ +} ble_gap_evt_disconnected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_PHY_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_phys_t peer_preferred_phys; /**< The PHYs the peer prefers to use. */ +} ble_gap_evt_phy_update_request_t; + +/**@brief Event Structure for @ref BLE_GAP_EVT_PHY_UPDATE. */ +typedef struct +{ + uint8_t status; /**< Status of the procedure, see @ref BLE_HCI_STATUS_CODES.*/ + uint8_t tx_phy; /**< TX PHY for this connection, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phy; /**< RX PHY for this connection, see @ref BLE_GAP_PHYS. */ +} ble_gap_evt_phy_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. */ +typedef struct +{ + ble_gap_sec_params_t peer_params; /**< Initiator Security Parameters. */ +} ble_gap_evt_sec_params_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_INFO_REQUEST. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + ble_gap_master_id_t master_id; /**< Master Identification for LTK lookup. */ + uint8_t enc_info : 1; /**< If 1, Encryption Information required. */ + uint8_t id_info : 1; /**< If 1, Identity Information required. */ + uint8_t sign_info : 1; /**< If 1, Signing Information required. */ +} ble_gap_evt_sec_info_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_PASSKEY_DISPLAY. */ +typedef struct +{ + uint8_t passkey[BLE_GAP_PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ + uint8_t match_request : 1; /**< If 1 requires the application to report the match using @ref sd_ble_gap_auth_key_reply + with either @ref BLE_GAP_AUTH_KEY_TYPE_NONE if there is no match or + @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY if there is a match. */ +} ble_gap_evt_passkey_display_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_KEY_PRESSED. */ +typedef struct +{ + uint8_t kp_not; /**< Keypress notification type, see @ref BLE_GAP_KP_NOT_TYPES. */ +} ble_gap_evt_key_pressed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_KEY_REQUEST. */ +typedef struct +{ + uint8_t key_type; /**< See @ref BLE_GAP_AUTH_KEY_TYPES. */ +} ble_gap_evt_auth_key_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST. */ +typedef struct +{ + ble_gap_lesc_p256_pk_t *p_pk_peer; /**< LE Secure Connections remote P-256 Public Key. This will point to the application-supplied memory + inside the keyset during the call to @ref sd_ble_gap_sec_params_reply. */ + uint8_t oobd_req :1; /**< LESC OOB data required. A call to @ref sd_ble_gap_lesc_oob_data_set is required to complete the procedure. */ +} ble_gap_evt_lesc_dhkey_request_t; + + +/**@brief Security levels supported. + * @note See Bluetooth Specification Version 4.2 Volume 3, Part C, Chapter 10, Section 10.2.1. +*/ +typedef struct +{ + uint8_t lv1 : 1; /**< If 1: Level 1 is supported. */ + uint8_t lv2 : 1; /**< If 1: Level 2 is supported. */ + uint8_t lv3 : 1; /**< If 1: Level 3 is supported. */ + uint8_t lv4 : 1; /**< If 1: Level 4 is supported. */ +} ble_gap_sec_levels_t; + + +/**@brief Encryption Key. */ +typedef struct +{ + ble_gap_enc_info_t enc_info; /**< Encryption Information. */ + ble_gap_master_id_t master_id; /**< Master Identification. */ +} ble_gap_enc_key_t; + + +/**@brief Identity Key. */ +typedef struct +{ + ble_gap_irk_t id_info; /**< Identity Resolving Key. */ + ble_gap_addr_t id_addr_info; /**< Identity Address. */ +} ble_gap_id_key_t; + + +/**@brief Security Keys. */ +typedef struct +{ + ble_gap_enc_key_t *p_enc_key; /**< Encryption Key, or NULL. */ + ble_gap_id_key_t *p_id_key; /**< Identity Key, or NULL. */ + ble_gap_sign_info_t *p_sign_key; /**< Signing Key, or NULL. */ + ble_gap_lesc_p256_pk_t *p_pk; /**< LE Secure Connections P-256 Public Key. When in debug mode the application must use the value defined + in the Core Bluetooth Specification v4.2 Vol.3, Part H, Section 2.3.5.6.1 */ +} ble_gap_sec_keys_t; + + +/**@brief Security key set for both local and peer keys. */ +typedef struct +{ + ble_gap_sec_keys_t keys_own; /**< Keys distributed by the local device. For LE Secure Connections the encryption key will be generated locally and will always be stored if bonding. */ + ble_gap_sec_keys_t keys_peer; /**< Keys distributed by the remote device. For LE Secure Connections, p_enc_key must always be NULL. */ +} ble_gap_sec_keyset_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_STATUS. */ +typedef struct +{ + uint8_t auth_status; /**< Authentication status, see @ref BLE_GAP_SEC_STATUS. */ + uint8_t error_src : 2; /**< On error, source that caused the failure, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ + uint8_t bonded : 1; /**< Procedure resulted in a bond. */ + uint8_t lesc : 1; /**< Procedure resulted in a LE Secure Connection. */ + ble_gap_sec_levels_t sm1_levels; /**< Levels supported in Security Mode 1. */ + ble_gap_sec_levels_t sm2_levels; /**< Levels supported in Security Mode 2. */ + ble_gap_sec_kdist_t kdist_own; /**< Bitmap stating which keys were exchanged (distributed) by the local device. If bonding with LE Secure Connections, the enc bit will be always set. */ + ble_gap_sec_kdist_t kdist_peer; /**< Bitmap stating which keys were exchanged (distributed) by the remote device. If bonding with LE Secure Connections, the enc bit will never be set. */ +} ble_gap_evt_auth_status_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_SEC_UPDATE. */ +typedef struct +{ + ble_gap_conn_sec_t conn_sec; /**< Connection security level. */ +} ble_gap_evt_conn_sec_update_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Source of timeout event, see @ref BLE_GAP_TIMEOUT_SOURCES. */ +} ble_gap_evt_timeout_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_RSSI_CHANGED. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ +} ble_gap_evt_rssi_changed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_REQUEST. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Man In The Middle protection requested. */ + uint8_t lesc : 1; /**< LE Secure Connections requested. */ + uint8_t keypress : 1; /**< Generation of keypress notifications requested. */ +} ble_gap_evt_sec_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SCAN_REQ_REPORT. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ +} ble_gap_evt_scan_req_report_t; + + +/**@brief GAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + union /**< union alternative identified by evt_id in enclosing struct. */ + { + ble_gap_evt_connected_t connected; /**< Connected Event Parameters. */ + ble_gap_evt_disconnected_t disconnected; /**< Disconnected Event Parameters. */ + ble_gap_evt_conn_param_update_t conn_param_update; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_sec_params_request_t sec_params_request; /**< Security Parameters Request Event Parameters. */ + ble_gap_evt_sec_info_request_t sec_info_request; /**< Security Information Request Event Parameters. */ + ble_gap_evt_passkey_display_t passkey_display; /**< Passkey Display Event Parameters. */ + ble_gap_evt_key_pressed_t key_pressed; /**< Key Pressed Event Parameters. */ + ble_gap_evt_auth_key_request_t auth_key_request; /**< Authentication Key Request Event Parameters. */ + ble_gap_evt_lesc_dhkey_request_t lesc_dhkey_request; /**< LE Secure Connections DHKey calculation request. */ + ble_gap_evt_auth_status_t auth_status; /**< Authentication Status Event Parameters. */ + ble_gap_evt_conn_sec_update_t conn_sec_update; /**< Connection Security Update Event Parameters. */ + ble_gap_evt_timeout_t timeout; /**< Timeout Event Parameters. */ + ble_gap_evt_rssi_changed_t rssi_changed; /**< RSSI Event Parameters. */ + ble_gap_evt_sec_request_t sec_request; /**< Security Request Event Parameters. */ + ble_gap_evt_scan_req_report_t scan_req_report; /**< Scan Request Report Parameters. */ + ble_gap_evt_phy_update_request_t phy_update_request; /**< PHY Update Request Event Parameters. */ + ble_gap_evt_phy_update_t phy_update; /**< PHY Update Parameters. */ + } params; /**< Event Parameters. */ +} ble_gap_evt_t; + + +/** + * @brief BLE GAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The connection count for the connection configurations is zero. + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - The sum of conn_count for all connection configurations combined exceeds UINT8_MAX. + * - The event length is smaller than @ref BLE_GAP_EVENT_LENGTH_MIN. + */ +typedef struct +{ + uint8_t conn_count; /**< The number of concurrent connections the application can create with this configuration. + The default and minimum value is @ref BLE_GAP_CONN_COUNT_DEFAULT. */ + uint16_t event_length; /**< The time set aside for this connection on every connection interval in 1.25 ms units. + The default value is @ref BLE_GAP_EVENT_LENGTH_DEFAULT, the minimum value is @ref BLE_GAP_EVENT_LENGTH_MIN. + The event length and the connection interval are the primary parameters + for setting the throughput of a connection. + See the SoftDevice Specification for details on throughput. */ +} ble_gap_conn_cfg_t; + + +/** + * @brief Configuration of maximum concurrent connections in the peripheral role, set with + * @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The periph_role_count is too large. The maximum + * supported sum of concurrent connections is + * @ref BLE_GAP_ROLE_COUNT_COMBINED_MAX. + */ +typedef struct +{ + uint8_t periph_role_count; /**< Maximum number of connections concurrently acting as a peripheral. Default value is @ref BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT. */ +} ble_gap_cfg_role_count_t; + + +/** + * @brief Device name and its properties, set with @ref sd_ble_cfg_set. + * + * @note If the device name is not configured, the default device name will be + * @ref BLE_GAP_DEVNAME_DEFAULT, the maximum device name length will be + * @ref BLE_GAP_DEVNAME_DEFAULT_LEN, vloc will be set to @ref BLE_GATTS_VLOC_STACK and the device name + * will have no write access. + * + * @note If @ref max_len is more than @ref BLE_GAP_DEVNAME_DEFAULT_LEN and vloc is set to @ref BLE_GATTS_VLOC_STACK, + * the attribute table size must be increased to have room for the longer device name (see + * @ref sd_ble_cfg_set and @ref ble_gatts_cfg_attr_tab_size_t). + * + * @note If vloc is @ref BLE_GATTS_VLOC_STACK : + * - p_value must point to non-volatile memory (flash) or be NULL. + * - If p_value is NULL, the device name will initially be empty. + * + * @note If vloc is @ref BLE_GATTS_VLOC_USER : + * - p_value cannot be NULL. + * - If the device name is writable, p_value must point to volatile memory (RAM). + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - Invalid device name location (vloc). + * - Invalid device name security mode. + * @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true: + * - 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_NOT_SUPPORTED Device name security mode is not supported. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vloc:2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t *p_value; /**< Pointer to where the value (device name) is stored or will be stored. */ + uint16_t current_len; /**< Current length in bytes of the memory pointed to by p_value.*/ + uint16_t max_len; /**< Maximum length in bytes of the memory pointed to by p_value.*/ +} ble_gap_cfg_device_name_t; + + +/**@brief Configuration structure for GAP configurations. */ +typedef union +{ + ble_gap_cfg_role_count_t role_count_cfg; /**< Role count configuration, cfg_id is @ref BLE_GAP_CFG_ROLE_COUNT. */ + ble_gap_cfg_device_name_t device_name_cfg; /**< Device name configuration, cfg_id is @ref BLE_GAP_CFG_DEVICE_NAME. */ +} ble_gap_cfg_t; + + +/**@brief Channel Map option. + * Used with @ref sd_ble_opt_get to get the current channel map + * or @ref sd_ble_opt_set to set a new channel map. When setting the + * channel map, it applies to all current and future connections. When getting the + * current channel map, it applies to a single connection and the connection handle + * must be supplied. + * + * @note Setting the channel map may take some time, depending on connection parameters. + * The time taken may be different for each connection and the get operation will + * return the previous channel map until the new one has taken effect. + * + * @note After setting the channel map, by spec it can not be set again until at least 1 s has passed. + * See Bluetooth Specification Version 4.1 Volume 2, Part E, Section 7.3.46. + * + * @retval ::NRF_SUCCESS Get or set successful. + * @retval ::NRF_ERROR_BUSY Channel map was set again before enough time had passed. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied for get. + * @retval ::NRF_ERROR_NOT_SUPPORTED Returned by sd_ble_opt_set in peripheral-only SoftDevices. + * + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle (only applicable for get) */ + uint8_t ch_map[5]; /**< Channel Map (37-bit). */ +} ble_gap_opt_ch_map_t; + + +/**@brief Local connection latency option. + * + * Local connection latency is a feature which enables the slave to improve + * current consumption by ignoring the slave latency set by the peer. The + * local connection latency can only be set to a multiple of the slave latency, + * and cannot be longer than half of the supervision timeout. + * + * Used with @ref sd_ble_opt_set to set the local connection latency. The + * @ref sd_ble_opt_get is not supported for this option, but the actual + * local connection latency (unless set to NULL) is set as a return parameter + * when setting the option. + * + * @note The latency set will be truncated down to the closest slave latency event + * multiple, or the nearest multiple before half of the supervision timeout. + * + * @note The local connection latency is disabled by default, and needs to be enabled for new + * connections and whenever the connection is updated. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t requested_latency; /**< Requested local connection latency. */ + uint16_t * p_actual_latency; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ +} ble_gap_opt_local_conn_latency_t; + +/**@brief Disable slave latency + * + * Used with @ref sd_ble_opt_set to temporarily disable slave latency of a peripheral connection (see @ref ble_gap_conn_params_t::slave_latency). And to re-enable it again. + * When disabled, the peripheral will ignore the slave_latency set by the central. + * + * @note Shall only be called on peripheral links. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint8_t disable : 1; /**< Set to 1 to disable slave latency. Set to 0 enable it again.*/ +} ble_gap_opt_slave_latency_disable_t; + +/**@brief Passkey Option. + * + * Structure containing the passkey to be used during pairing. This can be used with @ref + * sd_ble_opt_set to make the SoftDevice use a preprogrammed passkey for authentication + * instead of generating a random one. + * + * @note Repeated pairing attempts using the same preprogrammed passkey makes pairing vulnerable to MITM attacks. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + */ +typedef struct +{ + uint8_t const * p_passkey; /**< Pointer to 6-digit ASCII string (digit 0..9 only, no NULL termination) passkey to be used during pairing. If this is NULL, the SoftDevice will generate a random passkey if required.*/ +} ble_gap_opt_passkey_t; + + +/**@brief Scan request report option. + * + * This can be used with @ref sd_ble_opt_set to make the SoftDevice send + * @ref BLE_GAP_EVT_SCAN_REQ_REPORT events. + * + * @note Due to the limited space reserved for scan request report events, + * not all received scan requests will be reported. + * + * @note If whitelisting is used, only whitelisted requests are reported. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When advertising is ongoing while the option is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable scan request reports. */ +} ble_gap_opt_scan_req_report_t; + + +/**@brief Authenticated payload timeout option. + * + * This can be used with @ref sd_ble_opt_set to change the Authenticated payload timeout to a value other + * than the default of @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX. + * + * @note The authenticated payload timeout event ::BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD will be generated + * if auth_payload_timeout time has elapsed without receiving a packet with a valid MIC on an encrypted + * link. + * + * @note The LE ping procedure will be initiated before the timer expires to give the peer a chance + * to reset the timer. In addition the stack will try to prioritize running of LE ping over other + * activities to increase chances of finishing LE ping before timer expires. To avoid side-effects + * on other activities, it is recommended to use high timeout values. + * Recommended timeout > 2*(connInterval * (6 + connSlaveLatency)). + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. auth_payload_timeout was outside of allowed range. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t auth_payload_timeout; /**< Requested timeout in 10 ms unit, see @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT. */ +} ble_gap_opt_auth_payload_timeout_t; + + +/**@brief Option structure for GAP options. */ +typedef union +{ + ble_gap_opt_ch_map_t ch_map; /**< Parameters for the Channel Map option. */ + ble_gap_opt_local_conn_latency_t local_conn_latency; /**< Parameters for the Local connection latency option */ + ble_gap_opt_passkey_t passkey; /**< Parameters for the Passkey option.*/ + ble_gap_opt_scan_req_report_t scan_req_report; /**< Parameters for the scan request report option.*/ + ble_gap_opt_auth_payload_timeout_t auth_payload_timeout; /**< Parameters for the authenticated payload timeout option.*/ + ble_gap_opt_slave_latency_disable_t slave_latency_disable; /**< Parameters for the Disable slave latency option */ +} ble_gap_opt_t; +/**@} */ + + +/**@addtogroup BLE_GAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set the local Bluetooth identity address. + * + * The local Bluetooth identity address is the address that identifies this device to other peers. + * The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @note The identity address cannot be changed while advertising. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the ability to + * reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC upon being + * enabled. The address is a random number populated during the IC manufacturing process and remains unchanged + * for the lifetime of each IC. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @param[in] p_addr Pointer to address structure. + * + * @retval ::NRF_SUCCESS Address successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising. + */ +SVCALL(SD_BLE_GAP_ADDR_SET, uint32_t, sd_ble_gap_addr_set(ble_gap_addr_t const *p_addr)); + + +/**@brief Get local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval ::NRF_SUCCESS Address successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + */ +SVCALL(SD_BLE_GAP_ADDR_GET, uint32_t, sd_ble_gap_addr_get(ble_gap_addr_t *p_addr)); + + +/**@brief Set the active whitelist in the SoftDevice. + * + * @note Only one whitelist can be used at a time and the whitelist is shared between the BLE roles. + * The whitelist cannot be set if a BLE role is using the whitelist. + * + * @note If an address is resolved using the information in the device identity list, then the whitelist + * filter policy applies to the peer identity address and not the resolvable address sent on air. + * + * @param[in] pp_wl_addrs Pointer to a whitelist of peer addresses, if NULL the whitelist will be cleared. + * @param[in] len Length of the whitelist, maximum @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * + * @retval ::NRF_SUCCESS The whitelist is successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The whitelist (or one of its entries) provided is invalid. + * @retval ::BLE_ERROR_GAP_WHITELIST_IN_USE The whitelist is in use by a BLE role and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given whitelist size is invalid (zero or too large); this can only return when + * pp_wl_addrs is not NULL. + */ +SVCALL(SD_BLE_GAP_WHITELIST_SET, uint32_t, sd_ble_gap_whitelist_set(ble_gap_addr_t const * const * pp_wl_addrs, uint8_t len)); + + +/**@brief Set device identity list. + * + * @note Only one device identity list can be used at a time and the list is shared between the BLE roles. + * The device identity list cannot be set if a BLE role is using the list. + * + * @param[in] pp_id_keys Pointer to an array of peer identity addresses and peer IRKs, if NULL the device identity list will be cleared. + * @param[in] pp_local_irks Pointer to an array of local IRKs. Each entry in the array maps to the entry in pp_id_keys at the same index. + * To fill in the list with the currently set device IRK for all peers, set to NULL. + * @param[in] len Length of the device identity list, maximum @ref BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The device identity list successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The device identity list (or one of its entries) provided is invalid. + * This code may be returned if the local IRK list also has an invalid entry. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE The device identity list is in use and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE The device identity list contains multiple entries with the same identity address. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given device identity list size invalid (zero or too large); this can + * only return when pp_id_keys is not NULL. + */ +SVCALL(SD_BLE_GAP_DEVICE_IDENTITIES_SET, uint32_t, sd_ble_gap_device_identities_set(ble_gap_id_key_t const * const * pp_id_keys, ble_gap_irk_t const * const * pp_local_irks, uint8_t len)); + + +/**@brief Set privacy settings. + * + * @note Privacy settings cannot be changed while advertising. + * + * @param[in] p_privacy_params Privacy settings. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer to privacy settings is NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + * @retval ::NRF_ERROR_INVALID_PARAM Out of range parameters are provided. + * @retval ::NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while advertising. + */ +SVCALL(SD_BLE_GAP_PRIVACY_SET, uint32_t, sd_ble_gap_privacy_set(ble_gap_privacy_params_t const *p_privacy_params)); + + +/**@brief Get privacy settings. + * + * @note ::ble_gap_privacy_params_t::p_device_irk must be initialized to NULL or a valid address before this function is called. + * If it is initialized to a valid address, the address pointed to will contain the current device IRK on return. + * + * @param[in,out] p_privacy_params Privacy settings. + * + * @retval ::NRF_SUCCESS Privacy settings read. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer given for returning the privacy settings may be NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + */ +SVCALL(SD_BLE_GAP_PRIVACY_GET, uint32_t, sd_ble_gap_privacy_get(ble_gap_privacy_params_t *p_privacy_params)); + + +/**@brief Set, clear or update advertising and scan response data. + * + * @note The format of the advertising data will be checked by this call to ensure interoperability. + * Limitations imposed by this API call to the data provided include having a flags data type in the scan response data and + * duplicating the local name in the advertising data and scan response data. + * + * @note To clear the advertising data and set it to a 0-length packet, simply provide a valid pointer (p_data/p_sr_data) with its corresponding + * length (dlen/srdlen) set to 0. + * + * @note The call will fail if p_data and p_sr_data are both NULL since this would have no effect. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @param[in] p_data Raw data to be placed in advertising packet. If NULL, no changes are made to the current advertising packet data. + * @param[in] dlen Data length for p_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_data is NULL, can be 0 if p_data is not NULL. + * @param[in] p_sr_data Raw data to be placed in scan response packet. If NULL, no changes are made to the current scan response packet data. + * @param[in] srdlen Data length for p_sr_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_sr_data is NULL, can be 0 if p_data is not NULL. + * + * @retval ::NRF_SUCCESS Advertising data successfully updated or cleared. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, both p_data and p_sr_data cannot be NULL. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_FLAGS Invalid combination of advertising flags supplied. + * @retval ::NRF_ERROR_INVALID_DATA Invalid data type(s) supplied, check the advertising data format specification. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid data length(s) supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported data type. + * @retval ::BLE_ERROR_GAP_UUID_LIST_MISMATCH Invalid UUID list supplied. + */ +SVCALL(SD_BLE_GAP_ADV_DATA_SET, uint32_t, sd_ble_gap_adv_data_set(uint8_t const *p_data, uint8_t dlen, uint8_t const *p_sr_data, uint8_t srdlen)); + + +/**@brief Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @note Only one advertiser may be active at any time. + * + * @events + * @event{@ref BLE_GAP_EVT_CONNECTED, Generated after connection has been established through connectable advertising.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Advertisement has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @endmscs + * + * @param[in] p_adv_params Pointer to advertising parameters structure. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or + * @ref BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. If + * @ref ble_gap_adv_params_t::type is @ref BLE_GAP_ADV_TYPE_ADV_NONCONN_IND, + * this is ignored. + * + * @retval ::NRF_SUCCESS The BLE stack has started advertising. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections has been reached; connectable advertiser cannot be started. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check the accepted ranges and limits. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Bluetooth address supplied. + * @retval ::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST Discoverable mode and whitelist incompatible. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_ADV_START, uint32_t, sd_ble_gap_adv_start(ble_gap_adv_params_t const *p_adv_params, uint8_t conn_cfg_tag)); + + +/**@brief Stop advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The BLE stack has stopped advertising. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (most probably not in advertising state). + */ +SVCALL(SD_BLE_GAP_ADV_STOP, uint32_t, sd_ble_gap_adv_stop(void)); + + + +/**@brief Update connection parameters. + * + * @details In the peripheral role, this will send the corresponding L2CAP request and wait for + * the central to perform the procedure. Regardless of success or failure, the application + * will be informed of the result with a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE event. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_PARAM_UPDATE, Result of the connection parameter update procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CPU_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_conn_params Pointer to desired connection parameters. If NULL is provided on a peripheral role, + * the parameters in the PPCP characteristic of the GAP service will be used instead. + * + * @retval ::NRF_SUCCESS The Connection Update procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY Procedure already in progress, wait for pending procedures to complete and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GAP_CONN_PARAM_UPDATE, uint32_t, sd_ble_gap_conn_param_update(uint16_t conn_handle, ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Disconnect (GAP Link Termination). + * + * @details This call initiates the disconnection procedure, and its completion will be communicated to the application + * with a @ref BLE_GAP_EVT_DISCONNECTED event. + * + * @events + * @event{@ref BLE_GAP_EVT_DISCONNECTED, Generated when disconnection procedure is complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CONN_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] hci_status_code HCI status code, see @ref BLE_HCI_STATUS_CODES (accepted values are @ref BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION and @ref BLE_HCI_CONN_INTERVAL_UNACCEPTABLE). + * + * @retval ::NRF_SUCCESS The disconnection procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (disconnection is already in progress). + */ +SVCALL(SD_BLE_GAP_DISCONNECT, uint32_t, sd_ble_gap_disconnect(uint16_t conn_handle, uint8_t hci_status_code)); + + +/**@brief Set the radio's transmit power. + * + * @param[in] tx_power Radio transmit power in dBm (accepted values are -40, -20, -16, -12, -8, -4, 0, 3, and 4 dBm). + * + * @retval ::NRF_SUCCESS Successfully changed the transmit power. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_TX_POWER_SET, uint32_t, sd_ble_gap_tx_power_set(int8_t tx_power)); + + +/**@brief Set GAP Appearance value. + * + * @param[in] appearance Appearance (16-bit), see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_SET, uint32_t, sd_ble_gap_appearance_set(uint16_t appearance)); + + +/**@brief Get GAP Appearance value. + * + * @param[out] p_appearance Pointer to appearance (16-bit) to be filled in, see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_GET, uint32_t, sd_ble_gap_appearance_get(uint16_t *p_appearance)); + + +/**@brief Set GAP Peripheral Preferred Connection Parameters. + * + * @param[in] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure with the desired parameters. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_SET, uint32_t, sd_ble_gap_ppcp_set(ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Get GAP Peripheral Preferred Connection Parameters. + * + * @param[out] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure where the parameters will be stored. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_GET, uint32_t, sd_ble_gap_ppcp_get(ble_gap_conn_params_t *p_conn_params)); + + +/**@brief Set GAP device name. + * + * @note If the device name is located in application flash memory (see @ref ble_gap_cfg_device_name_t), + * it cannot be changed. Then @ref NRF_ERROR_FORBIDDEN will be returned. + * + * @param[in] p_write_perm Write permissions for the Device Name characteristic, see @ref ble_gap_conn_sec_mode_t. + * @param[in] p_dev_name Pointer to a UTF-8 encoded, non NULL-terminated string. + * @param[in] len Length of the UTF-8, non NULL-terminated string pointed to by p_dev_name in octets (must be smaller or equal than @ref BLE_GAP_DEVNAME_MAX_LEN). + * + * @retval ::NRF_SUCCESS GAP device name and permissions set successfully. + * @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_FORBIDDEN Device name is not writable. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len)); + + +/**@brief Get GAP device name. + * + * @note If the device name is longer than the size of the supplied buffer, + * p_len will return the complete device name length, + * and not the number of bytes actually returned in p_dev_name. + * The application may use this information to allocate a suitable buffer size. + * + * @param[out] p_dev_name Pointer to an empty buffer where the UTF-8 non NULL-terminated string will be placed. Set to NULL to obtain the complete device name length. + * @param[in,out] p_len Length of the buffer pointed by p_dev_name, complete device name length on output. + * + * @retval ::NRF_SUCCESS GAP device name retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_GET, uint32_t, sd_ble_gap_device_name_get(uint8_t *p_dev_name, uint16_t *p_len)); + + +/**@brief Initiate the GAP Authentication procedure. + * + * @details In the peripheral role, this function will send an SMP Security Request. + * + * @events + * @event{Depending on the security parameters set and the packet exchanges with the peer\, the following events may be generated:} + * @event{@ref BLE_GAP_EVT_SEC_PARAMS_REQUEST} + * @event{@ref BLE_GAP_EVT_SEC_INFO_REQUEST} + * @event{@ref BLE_GAP_EVT_PASSKEY_DISPLAY} + * @event{@ref BLE_GAP_EVT_KEY_PRESSED} + * @event{@ref BLE_GAP_EVT_AUTH_KEY_REQUEST} + * @event{@ref BLE_GAP_EVT_LESC_DHKEY_REQUEST} + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE} + * @event{@ref BLE_GAP_EVT_AUTH_STATUS} + * @event{@ref BLE_GAP_EVT_TIMEOUT} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_SEC_REQ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_sec_params Pointer to the @ref ble_gap_sec_params_t structure with the security parameters to be used during the pairing or bonding procedure. + * In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_NO_MEM The maximum number of authentication procedures that can run in parallel for the given role is reached. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_AUTHENTICATE, uint32_t, sd_ble_gap_authenticate(uint16_t conn_handle, ble_gap_sec_params_t const *p_sec_params)); + + +/**@brief Reply with GAP security parameters. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_CONFIRM_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_KS_TOO_SMALL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_APP_ERROR_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_REMOTE_PAIRING_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_TIMEOUT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] sec_status Security status, see @ref BLE_GAP_SEC_STATUS. + * @param[in] p_sec_params Pointer to a @ref ble_gap_sec_params_t security parameters structure. + * @param[in,out] p_sec_keyset Pointer to a @ref ble_gap_sec_keyset_t security keyset structure. Any keys generated and/or distributed as a result of the ongoing security procedure + * will be stored into the memory referenced by the pointers inside this structure. The keys will be stored and available to the application + * upon reception of a @ref BLE_GAP_EVT_AUTH_STATUS event. + * Note that the SoftDevice expects the application to provide memory for storing the + * peer's keys. So it must be ensured that the relevant pointers inside this structure are not NULL. The pointers to the local key + * can, however, be NULL, in which case, the local key data will not be available to the application upon reception of the + * @ref BLE_GAP_EVT_AUTH_STATUS event. + * + * @retval ::NRF_SUCCESS Successfully accepted security parameter from the application. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + */ +SVCALL(SD_BLE_GAP_SEC_PARAMS_REPLY, uint32_t, sd_ble_gap_sec_params_reply(uint16_t conn_handle, uint8_t sec_status, ble_gap_sec_params_t const *p_sec_params, ble_gap_sec_keyset_t const *p_sec_keyset)); + + +/**@brief Reply with an authentication key. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_AUTH_KEY_REQUEST or a @ref BLE_GAP_EVT_PASSKEY_DISPLAY, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] key_type See @ref BLE_GAP_AUTH_KEY_TYPES. + * @param[in] p_key If key type is @ref BLE_GAP_AUTH_KEY_TYPE_NONE, then NULL. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY, then a 6-byte ASCII string (digit 0..9 only, no NULL termination) + * or NULL when confirming LE Secure Connections Numeric Comparison. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_OOB, then a 16-byte OOB key value in little-endian format. + * + * @retval ::NRF_SUCCESS Authentication key successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_AUTH_KEY_REPLY, uint32_t, sd_ble_gap_auth_key_reply(uint16_t conn_handle, uint8_t key_type, uint8_t const *p_key)); + + +/**@brief Reply with an LE Secure connections DHKey. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dhkey LE Secure Connections DHKey. + * + * @retval ::NRF_SUCCESS DHKey successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_DHKEY_REPLY, uint32_t, sd_ble_gap_lesc_dhkey_reply(uint16_t conn_handle, ble_gap_lesc_dhkey_t const *p_dhkey)); + + +/**@brief Notify the peer of a local keypress. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] kp_not See @ref BLE_GAP_KP_NOT_TYPES. + * + * @retval ::NRF_SUCCESS Keypress notification successfully queued for transmission. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either not entering a passkey or keypresses have not been enabled by both peers. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy. Retry at later time. + */ +SVCALL(SD_BLE_GAP_KEYPRESS_NOTIFY, uint32_t, sd_ble_gap_keypress_notify(uint16_t conn_handle, uint8_t kp_not)); + + +/**@brief Generate a set of OOB data to send to a peer out of band. + * + * @note The @ref ble_gap_addr_t included in the OOB data returned will be the currently active one (or, if a connection has already been established, + * the one used during connection setup). The application may manually overwrite it with an updated value. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. Can be @ref BLE_CONN_HANDLE_INVALID if a BLE connection has not been established yet. + * @param[in] p_pk_own LE Secure Connections local P-256 Public Key. + * @param[out] p_oobd_own The OOB data to be sent out of band to a peer. + * + * @retval ::NRF_SUCCESS OOB data successfully generated. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_GET, uint32_t, sd_ble_gap_lesc_oob_data_get(uint16_t conn_handle, ble_gap_lesc_p256_pk_t const *p_pk_own, ble_gap_lesc_oob_data_t *p_oobd_own)); + +/**@brief Provide the OOB data sent/received out of band. + * + * @note An authentication procedure with OOB selected as an algorithm must be in progress when calling this function. + * @note A @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST event with the oobd_req set to 1 must have been received prior to calling this function. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_oobd_own The OOB data sent out of band to a peer or NULL if the peer has not received OOB data. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. + * @param[in] p_oobd_peer The OOB data received out of band from a peer or NULL if none received. + * Must correspond to @ref sd_ble_gap_sec_params_reply in the peripheral role. + * + * @retval ::NRF_SUCCESS OOB data accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_SET, uint32_t, sd_ble_gap_lesc_oob_data_set(uint16_t conn_handle, ble_gap_lesc_oob_data_t const *p_oobd_own, ble_gap_lesc_oob_data_t const *p_oobd_peer)); + + +/**@brief Reply with GAP security information. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_INFO_REQUEST, calling it at other times will result in @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * @note Data signing is not yet supported, and p_sign_info must therefore be NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_ENC_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. May be NULL to signal none is available. + * @param[in] p_id_info Pointer to a @ref ble_gap_irk_t identity information structure. May be NULL to signal none is available. + * @param[in] p_sign_info Pointer to a @ref ble_gap_sign_info_t signing information structure. May be NULL to signal none is available. + * + * @retval ::NRF_SUCCESS Successfully accepted security information. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_SEC_INFO_REPLY, uint32_t, sd_ble_gap_sec_info_reply(uint16_t conn_handle, ble_gap_enc_info_t const *p_enc_info, ble_gap_irk_t const *p_id_info, ble_gap_sign_info_t const *p_sign_info)); + + +/**@brief Get the current connection security. + * + * @param[in] conn_handle Connection handle. + * @param[out] p_conn_sec Pointer to a @ref ble_gap_conn_sec_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Current connection security successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_CONN_SEC_GET, uint32_t, sd_ble_gap_conn_sec_get(uint16_t conn_handle, ble_gap_conn_sec_t *p_conn_sec)); + + +/**@brief Start reporting the received signal strength to the application. + * + * A new event is reported whenever the RSSI value changes, until @ref sd_ble_gap_rssi_stop is called. + * + * @events + * @event{@ref BLE_GAP_EVT_RSSI_CHANGED, New RSSI data available. How often the event is generated is + * dependent on the settings of the threshold_dbm + * and skip_count input parameters.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] threshold_dbm Minimum change in dBm before triggering the @ref BLE_GAP_EVT_RSSI_CHANGED event. Events are disabled if threshold_dbm equals @ref BLE_GAP_RSSI_THRESHOLD_INVALID. + * @param[in] skip_count Number of RSSI samples with a change of threshold_dbm or more before sending a new @ref BLE_GAP_EVT_RSSI_CHANGED event. + * + * @retval ::NRF_SUCCESS Successfully activated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Disconnection in progress. Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_START, uint32_t, sd_ble_gap_rssi_start(uint16_t conn_handle, uint8_t threshold_dbm, uint8_t skip_count)); + + +/**@brief Stop reporting the received signal strength. + * + * @note An RSSI change detected before the call but not yet received by the application + * may be reported after @ref sd_ble_gap_rssi_stop has been called. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * + * @retval ::NRF_SUCCESS Successfully deactivated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_STOP, uint32_t, sd_ble_gap_rssi_stop(uint16_t conn_handle)); + + +/**@brief Get the received signal strength for the last connection event. + * + * @ref sd_ble_gap_rssi_start must be called to start reporting RSSI before using this function. @ref NRF_ERROR_NOT_FOUND + * will be returned until RSSI was sampled for the first time after calling @ref sd_ble_gap_rssi_start. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[out] p_rssi Pointer to the location where the RSSI measurement shall be stored. + * + * @retval ::NRF_SUCCESS Successfully read the RSSI. + * @retval ::NRF_ERROR_NOT_FOUND No sample is available. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is not ongoing, or disconnection in progress. + */ +SVCALL(SD_BLE_GAP_RSSI_GET, uint32_t, sd_ble_gap_rssi_get(uint16_t conn_handle, int8_t *p_rssi)); + + +/**@brief Initiate or respond to a PHY Update Procedure + * + * @details This function is used to initiate or respond to a PHY Update Procedure. It will always + * generate a @ref BLE_GAP_EVT_PHY_UPDATE event if successfully executed. + * If this function is used to initiate a PHY Update procedure and the only option + * provided in @ref ble_gap_phys_t::tx_phys and @ref ble_gap_phys_t::rx_phys is the + * currently active PHYs in the respective directions, the SoftDevice will generate a + * @ref BLE_GAP_EVT_PHY_UPDATE with the current PHYs set and will not initiate the + * procedure in the Link Layer. + * If @ref ble_gap_phys_t::tx_phys or @ref ble_gap_phys_t::rx_phys is + * @ref BLE_GAP_PHY_AUTO, then the stack will select a PHY for the respective direction + * based on the peer's PHY preferences and the local stack configuration. + * If the peer does not support the PHY Update Procedure, then the resulting + * @ref BLE_GAP_EVT_PHY_UPDATE event will have a status set to + * @ref BLE_HCI_UNSUPPORTED_REMOTE_FEATURE. + * If the PHY procedure was rejected by the peer due to a procedure collision, the status + * will be @ref BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION or + * @ref BLE_HCI_DIFFERENT_TRANSACTION_COLLISION. + * If the peer responds to the PHY Update procedure with invalid parameters, the status + * will be @ref BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS. + * If the PHY procedure was rejected by the peer for a different reason, the status will + * contain the reason as specified by the peer. + * + * @events + * @event{@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update Procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPHERAL_PHY_UPDATE} + * @endmscs + * + * @param[in] conn_handle Connection handle to indicate the connection for which the PHY Update is requested. + * @param[in] p_gap_phys Pointer to PHY structure. + * + * @retval ::NRF_SUCCESS Successfully requested a PHY Update. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Unsupported PHYs supplied to the call. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY Procedure is already in progress or not allowed at this time. Process pending events and wait for the pending procedure to complete and retry. + * + */ +SVCALL(SD_BLE_GAP_PHY_UPDATE, uint32_t, sd_ble_gap_phy_update(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys)); + + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GAP_H__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatt.h new file mode 100644 index 0000000000..98a7a150bf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatt.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup BLE_GATT_DEFINES Defines + * @{ */ + +/** @brief Default ATT MTU, in bytes. */ +#define BLE_GATT_ATT_MTU_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 Authorization. */ +#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 connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM att_mtu is smaller than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +typedef struct +{ + uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive. + The default and minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + @mscs + @mmsc{@ref BLE_GATTC_MTU_EXCHANGE} + @mmsc{@ref BLE_GATTS_MTU_EXCHANGE} + @endmscs + */ +} ble_gatt_conn_cfg_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; /**< Notification 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gattc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gattc.h new file mode 100644 index 0000000000..ef7dde248f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gattc.h @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" +#include "ble_gatt.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. */ + BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE /**< Write without Response transmission complete. \n See @ref ble_gattc_evt_write_cmd_tx_complete_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. */ +/** @} */ + +/** @defgroup BLE_GATTC_DEFAULTS GATT Client defaults + * @{ */ +#define BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Write without Response that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTC_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTC connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t write_cmd_tx_queue_size; /**< The guaranteed minimum number of Write without Response that can be queued for transmission. + The default value is @ref BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT */ +} ble_gattc_conn_cfg_t; + +/**@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 Event structure for @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of write without response transmissions completed. */ +} ble_gattc_evt_write_cmd_tx_complete_t; + +/**@brief GATTC event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + 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. */ + ble_gattc_evt_write_cmd_tx_complete_t write_cmd_tx_complete; /**< Write without Response transmission complete 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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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 Only one write with response procedure can be ongoing per connection at a time. + * If the application tries to write with response while another write with response procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTC_EVT_WRITE_RSP event will be issued as soon as the write response arrives from the peer. + * + * @note The number of Write without Response that can be queued is configured by @ref ble_gattc_conn_cfg_t::write_cmd_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event will be issued as soon as the transmission of the write without response is complete. + * + * @note The application can keep track of the available queue element count for writes without responses by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE, Write without response transmission complete.} + * @event{@ref BLE_GATTC_EVT_WRITE_RSP, Write response received from the peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_WITHOUT_RESP_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_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 For write with response, GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry. + For write without response it can only mean GATT procedure timeout. + * @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued. + * Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry. + */ +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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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_ATT_MTU_DEFAULT. + * + * @events + * @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP} + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - 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 GATT Client procedure already in progress or blocked because of a previous GATT procedure timeout. + */ +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__ */ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatts.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatts.h new file mode 100644 index 0000000000..e21b7918a5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_gatts.h @@ -0,0 +1,841 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf_svc.h" +#include "nrf_error.h" +#include "ble_hci.h" +#include "ble_ranges.h" +#include "ble_types.h" +#include "ble_err.h" +#include "ble_gatt.h" +#include "ble_gap.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. \n 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 respond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */ + BLE_GATTS_EVT_HVN_TX_COMPLETE /**< Handle Value Notification transmission complete. \n See @ref ble_gatts_evt_hvn_tx_complete_t. */ +}; + +/**@brief GATTS Configuration IDs. + * + * IDs that uniquely identify a GATTS configuration. + */ +enum BLE_GATTS_CFGS +{ + BLE_GATTS_CFG_SERVICE_CHANGED = BLE_GATTS_CFG_BASE, /**< Service changed configuration. */ + BLE_GATTS_CFG_ATTR_TAB_SIZE, /**< Attribute table size configuration. */ +}; + +/** @} */ + +/** @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_SERVICE_CHANGED Service Changed Inclusion Values + * @{ + */ +#define BLE_GATTS_SERVICE_CHANGED_DEFAULT (1) /**< Default is to include the Service Changed characteristic in the Attribute Table. */ +/** @} */ + +/** @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 (1408) /**< Default Attribute Table size. */ +/** @} */ + +/** @defgroup BLE_GATTS_DEFAULTS GATT Server defaults + * @{ + */ +#define BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Handle Value Notifications that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTS_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTS connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t hvn_tx_queue_size; /**< Minimum guaranteed number of Handle Value Notifications that can be queued for transmission. + The default value is @ref BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT */ +} ble_gatts_conn_cfg_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 const *p_uuid; /**< Pointer to the attribute UUID. */ + ble_gatts_attr_md_t const *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 const *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 const *p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */ + ble_gatts_attr_md_t const *p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *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 const *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. */ + uint8_t const *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 Service Changed Inclusion configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t service_changed : 1; /**< If 1, include the Service Changed characteristic in the Attribute Table. Default is @ref BLE_GATTS_SERVICE_CHANGED_DEFAULT. */ +} ble_gatts_cfg_service_changed_t; + +/**@brief Attribute table size configuration parameters, set with @ref sd_ble_cfg_set. + * + * @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. + */ +typedef struct +{ + uint32_t attr_tab_size; /**< Attribute table size. Default is @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, minimum is @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. */ +} ble_gatts_cfg_attr_tab_size_t; + +/**@brief Config structure for GATTS configurations. */ +typedef union +{ + ble_gatts_cfg_service_changed_t service_changed; /**< Include service changed characteristic, cfg_id is @ref BLE_GATTS_CFG_SERVICE_CHANGED. */ + ble_gatts_cfg_attr_tab_size_t attr_tab_size; /**< Attribute table size, cfg_id is @ref BLE_GATTS_CFG_ATTR_TAB_SIZE. */ +} ble_gatts_cfg_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 finalize 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 Event structure for @ref BLE_GATTS_EVT_HVN_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of notification transmissions completed. */ +} ble_gatts_evt_hvn_tx_complete_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. */ + ble_gatts_evt_hvn_tx_complete_t hvn_tx_complete; /**< Handle Value Notification transmission complete Event Parameters. */ + } 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 writable auxiliaries bits, + * readable (no security) and writable (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 whether 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. + * + * @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 NRF_ERROR_RESOURCES. + * The caller can check whether the value has been updated by looking at the contents of *(p_hvx_params->p_len). + * + * @note Only one indication procedure can be ongoing per connection at a time. + * If the application tries to indicate an attribute value while another indication procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from the peer. + * + * @note The number of Handle Value Notifications that can be queued is configured by @ref ble_gatts_conn_cfg_t::hvn_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event will be issued as soon as the transmission of the notification is complete. + * + * @note The application can keep track of the available queue element count for notifications by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTS_EVT_HVN_TX_COMPLETE, Notification transmission complete.} + * @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from the 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} + * @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 For @ref BLE_GATT_HVX_INDICATION, GATT Server procedure already in progress or blocked because of a previous GATT procedure timeout. + Wait for a @ref BLE_GATTS_EVT_HVC event and retry. + For @ref BLE_GATT_HVX_NOTIFICATION it can only mean GATT procedure timeout. + * @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 ::NRF_ERROR_RESOURCES Too many notifications queued. + * Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry. + */ +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_cfg_set and @ref ble_gatts_cfg_service_changed_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 GATT Server procedure already in progress or blocked because of a previous GATT procedure timeout. + * @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_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_BUSY The stack is busy, process pending events and retry. + * @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. + */ +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. + */ +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 persistently 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. Unconditionally 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_ATT_MTU_DEFAULT. + * + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + * used for this connection. + * - 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 GATT Blocked because of a previous GATT procedure timeout. + */ +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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_hci.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_hci.h new file mode 100644 index 0000000000..f0dde9a03a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_hci.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +*/ +#define BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE 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 Advertisement 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_ranges.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_ranges.h new file mode 100644 index 0000000000..50f0d4c358 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_ranges.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__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_.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_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_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_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */ +#define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */ + +#define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */ +#define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */ + +#define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */ +#define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */ + + + +#define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */ + +#define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */ +#define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */ + +#define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */ +#define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */ + +#define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */ +#define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */ + +#define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */ +#define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */ + +#define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */ +#define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */ + +#define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */ +#define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */ + + + + + + +#ifdef __cplusplus +} +#endif +#endif /* BLE_RANGES_H__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_types.h new file mode 100644 index 0000000000..88c93180c8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/ble_types.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#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. */ +#define BLE_UUID_GAP_CHARACTERISTIC_RPA_ONLY 0x2AC9 /**< Resolvable Private Address Only 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 /**< Joystick (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; + +/**@brief Data structure. */ +typedef struct +{ + uint8_t *p_data; /**< Pointer to the data buffer provided to/from the application. */ + uint16_t len; /**< Length of the data buffer, in bytes. */ +} ble_data_t; + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* BLE_TYPES_H__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf52/nrf_mbr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf52/nrf_mbr.h new file mode 100644 index 0000000000..cc5971c7a3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf52/nrf_mbr.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +*/ + +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + +#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, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/ + SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/ + SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/ + SD_MBR_COMMAND_RESERVED, + SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_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 SoftDevice Specification 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 Change the address the MBR starts after a reset + * + * 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 @ref address set to 0. The + * MBR will then start forwarding 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 SoftDevice Specification 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; + +/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR + * + * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not + * change where the MBR starts after reset. + * + * @retval ::NRF_SUCCESS + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_irq_forward_address_set_t; + +/**@brief Input structure containing data used when calling ::sd_mbr_command + * + * Depending on what command value that is set, the corresponding params value type must also be + * set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command + * @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params. + */ +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.*/ + sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/ + } params; /**< Command parameters. */ +} sd_mbr_command_t; + +/** @} */ + +/** @addtogroup NRF_MBR_FUNCTIONS Functions + * @{ */ + +/**@brief Issue Master Boot Record commands + * + * Commands used when updating a SoftDevice and bootloader. + * + * The @ref SD_MBR_COMMAND_COPY_BL and @ref 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 @ref NRF_ERROR_NO_MEM. + * + * @param[in] param Pointer to a struct describing the command. + * + * @note For return values, 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, + * ::sd_mbr_command_irq_forward_address_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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_ble.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_ble.h new file mode 100644 index 0000000000..335e7e6db2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_ble.h @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_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_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. */ + SD_BLE_CFG_SET, /**< Add a configuration to the BLE stack. */ +}; + +/** + * @brief BLE Module Independent Event IDs. + */ +enum BLE_COMMON_EVTS +{ + BLE_EVT_USER_MEM_REQUEST = BLE_EVT_BASE + 0, /**< User Memory request. @ref ble_evt_user_mem_request_t */ + BLE_EVT_USER_MEM_RELEASE = BLE_EVT_BASE + 1, /**< User Memory release. @ref ble_evt_user_mem_release_t */ +}; + +/**@brief BLE Connection Configuration IDs. + * + * IDs that uniquely identify a connection configuration. + */ +enum BLE_CONN_CFGS +{ + BLE_CONN_CFG_GAP = BLE_CONN_CFG_BASE + 0, /**< BLE GAP specific connection configuration. */ + BLE_CONN_CFG_GATTC = BLE_CONN_CFG_BASE + 1, /**< BLE GATTC specific connection configuration. */ + BLE_CONN_CFG_GATTS = BLE_CONN_CFG_BASE + 2, /**< BLE GATTS specific connection configuration. */ + BLE_CONN_CFG_GATT = BLE_CONN_CFG_BASE + 3, /**< BLE GATT specific connection configuration. */ +}; + +/**@brief BLE Common Configuration IDs. + * + * IDs that uniquely identify a common configuration. + */ +enum BLE_COMMON_CFGS +{ + BLE_COMMON_CFG_VS_UUID = BLE_CFG_BASE, /**< Vendor specific UUID configuration */ +}; + +/**@brief Common Option IDs. + * IDs that uniquely identify a common option. + */ +enum BLE_COMMON_OPTS +{ + BLE_COMMON_OPT_PA_LNA = BLE_OPT_BASE + 0, /**< PA and LNA options */ + BLE_COMMON_OPT_CONN_EVT_EXT = BLE_OPT_BASE + 1, /**< 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 The highest value used for @ref ble_gatt_conn_cfg_t::att_mtu in any connection configuration shall be used as a parameter. + * If that value has not been configured for any connections then @ref BLE_GATT_ATT_MTU_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_DEFAULT 10 /**< Default VS UUID count. */ +#define BLE_UUID_VS_COUNT_MAX 254 /**< Maximum VS UUID count. */ +/** @} */ + +/** @defgroup BLE_COMMON_CFG_DEFAULTS Configuration defaults. + * @{ + */ +#define BLE_CONN_CFG_TAG_DEFAULT 0 /**< Default configuration tag, SoftDevice default connection configuration. */ + +/** @} */ + +/** @} */ + +/** @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_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 events not associated with a specific function module. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which this event occurred. */ + union + { + 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. */ + } params; /**< Event parameter union. */ +} ble_common_evt_t; + +/**@brief BLE Event header. */ +typedef struct +{ + uint16_t evt_id; /**< Value from a BLE__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_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. See https://www.bluetooth.org/en-us/specification/assigned-numbers/link-layer for assigned values. */ + 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 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 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 connection configuration as set by @ref ble_gap_conn_cfg_t::event_length. + * 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_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 connection configuration type, wrapping the module specific configurations, set with + * @ref sd_ble_cfg_set. + * + * @note Connection configurations don't have to be set. + * In the case that no configurations has been set, or fewer connection configurations has been set than enabled connections, + * the default connection configuration will be automatically added for the remaining connections. + * When creating connections with the default configuration, @ref BLE_CONN_CFG_TAG_DEFAULT should be used in + * place of @ref ble_conn_cfg_t::conn_cfg_tag. See @ref sd_ble_gap_adv_start() and sd_ble_gap_connect()" + * + * @mscs + * @mmsc{@ref BLE_CONN_CFG} + * @endmscs + + */ +typedef struct +{ + uint8_t conn_cfg_tag; /**< The application chosen tag it can use with the @ref sd_ble_gap_adv_start() and sd_ble_gap_connect() + calls to select this configuration when creating a connection. + Must be different for all connection configurations added and not @ref BLE_CONN_CFG_TAG_DEFAULT. */ + union { + ble_gap_conn_cfg_t gap_conn_cfg; /**< GAP connection configuration, cfg_id is @ref BLE_CONN_CFG_GAP. */ + ble_gattc_conn_cfg_t gattc_conn_cfg; /**< GATTC connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTC. */ + ble_gatts_conn_cfg_t gatts_conn_cfg; /**< GATTS connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTS. */ + ble_gatt_conn_cfg_t gatt_conn_cfg; /**< GATT connection configuration, cfg_id is @ref BLE_CONN_CFG_GATT. */ + } params; /**< Connection configuration union. */ +} ble_conn_cfg_t; + +/** + * @brief Configuration of Vendor Specific UUIDs, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM Too many UUIDs configured. + */ +typedef struct +{ + uint8_t vs_uuid_count; /**< Number of 128-bit Vendor Specific UUID bases to allocate memory for. + Default value is @ref BLE_UUID_VS_COUNT_DEFAULT. Maximum value is + @ref BLE_UUID_VS_COUNT_MAX. */ +} ble_common_cfg_vs_uuid_t; + +/**@brief Common BLE Configuration type, wrapping the common configurations. */ +typedef union +{ + ble_common_cfg_vs_uuid_t vs_uuid_cfg; /**< Vendor specific UUID configuration, cfg_id is @ref BLE_COMMON_CFG_VS_UUID. */ +} ble_common_cfg_t; + +/**@brief BLE Configuration type, wrapping the module specific configurations. */ +typedef union +{ + ble_conn_cfg_t conn_cfg; /**< Connection specific configurations, cfg_id in @ref BLE_CONN_CFGS series. */ + ble_common_cfg_t common_cfg; /**< Global common configurations, cfg_id in @ref BLE_COMMON_CFGS series. */ + ble_gap_cfg_t gap_cfg; /**< Global GAP configurations, cfg_id in @ref BLE_GAP_CFGS series. */ + ble_gatts_cfg_t gatts_cfg; /**< Global GATTS configuration, cfg_id in @ref BLE_GATTS_CFGS series. */ +} ble_cfg_t; + +/** @} */ + +/** @addtogroup BLE_COMMON_FUNCTIONS Functions + * @{ */ + +/**@brief Enable the BLE stack + * + * @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. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note The value of *p_app_ram_base when the app has done no custom configuration of the + * SoftDevice, i.e. the app has not called @ref sd_ble_cfg_set before @ref sd_ble_enable, can + * be found in the release notes. + * + * @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 BLE related function other than @ref + * sd_ble_cfg_set 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_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. + */ +SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base)); + +/**@brief Add configurations for the BLE stack + * + * @param[in] cfg_id Config ID, see @ref BLE_CONN_CFGS, @ref BLE_COMMON_CFGS, @ref + * BLE_GAP_CFGS or @ref BLE_GATTS_CFGS. + * @param[in] p_cfg Pointer to a ble_cfg_t structure containing the configuration value. + * @param[in] app_ram_base The start address of the application RAM region (APP_RAM_BASE). + * See @ref sd_ble_enable for details about APP_RAM_BASE. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note If a configuration is set more than once, the last one set is the one that takes effect on + * @ref sd_ble_enable. + * + * @note Any part of the BLE stack that is NOT configured with @ref sd_ble_cfg_set will have default + * configuration. + * + * @note @ref sd_ble_cfg_set may be called at any time when the SoftDevice is enabled (see @ref + * sd_softdevice_enable) while the BLE part of the SoftDevice is not enabled (see @ref + * sd_ble_enable). + * + * @note Error codes for the configurations are described in the configuration structs. + * + * @mscs + * @mmsc{@ref BLE_COMMON_ENABLE} + * @endmscs + * + * @retval ::NRF_SUCCESS The configuration has been added successfully. + * @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid cfg_id supplied. + * @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by app_ram_base is not + * large enough to fit this configuration's memory requirement. + */ +SVCALL(SD_BLE_CFG_SET, uint32_t, sd_ble_cfg_set(uint32_t cfg_id, ble_cfg_t const * p_cfg, uint32_t 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 must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT. + * 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 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 indexes 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 @ref 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] p_block Pointer to a user memory block structure or NULL if memory is managed by the application. + * + * @mscs + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_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 ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid user memory block length supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no user memory request pending. + */ +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} + * @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__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error.h new file mode 100644 index 0000000000..6badee98e5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_sdm.h new file mode 100644 index 0000000000..530959b9d6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_sdm.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 erroneous SoftDevice flashing). + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_SDM_H__ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_soc.h new file mode 100644 index 0000000000..1e784b8db3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_error_soc.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_nvic.h new file mode 100644 index 0000000000..f5c7e8e028 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_nvic.h @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.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. */ + +#define __NRF_NVIC_ISER_COUNT (2) /**< The number of ISER/ICER registers in the NVIC that are used. */ + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 0-31. */ +#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)SWI5_IRQn) \ + )) + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 32-63. */ +#define __NRF_NVIC_SD_IRQS_1 ((uint32_t)0) + +/**@brief Interrupts available for to application, with IRQn in the range 0-31. */ +#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0) + +/**@brief Interrupts available for to application, with IRQn in the range 32-63. */ +#define __NRF_NVIC_APP_IRQS_1 (~__NRF_NVIC_SD_IRQS_1) + +/**@} */ + +/**@} */ + +/**@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<= (1 << __NVIC_PRIO_BITS)) + { + return 0; + } + if( priority == 0 + || priority == 1 + || priority == 4 + ) + { + return 0; + } + 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; + nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 ); + NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1; + *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]; + NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1]; + 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__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sd_def.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sd_def.h new file mode 100644 index 0000000000..0b4d221d6a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sd_def.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#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__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sdm.h new file mode 100644 index 0000000000..60435ef9df --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_sdm.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.h" +#include "nrf_error_sdm.h" +#include "nrf_soc.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 (1) + +/** @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 SoftDevice unique string size in bytes. */ +#define SD_UNIQUE_STR_SIZE 20 + +/** @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 the offset for the SoftDevice unique string relative to the SoftDevice base address. + * The SD_UNIQUE_STR is stored as an array of uint8_t. The size of array is @ref SD_UNIQUE_STR_SIZE. + */ +#define SD_UNIQUE_STR_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x18) + +/** @brief Defines a macro for retrieving 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 retrieving 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 retrieving 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 retrieving 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 retrieving the actual SoftDevice version 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) + +/** @brief Defines a macro for retrieving the address of SoftDevice unique str based on 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_UNIQUE_STR_ADDR_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_UNIQUE_STR_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \ + ? (((uint8_t *) ((baseaddr) + SD_UNIQUE_STR_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. 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 disallowed 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_ACCURACY Clock accuracy + * @{ */ + +#define NRF_CLOCK_LF_ACCURACY_250_PPM (0) /**< Default: 250 ppm */ +#define NRF_CLOCK_LF_ACCURACY_500_PPM (1) /**< 500 ppm */ +#define NRF_CLOCK_LF_ACCURACY_150_PPM (2) /**< 150 ppm */ +#define NRF_CLOCK_LF_ACCURACY_100_PPM (3) /**< 100 ppm */ +#define NRF_CLOCK_LF_ACCURACY_75_PPM (4) /**< 75 ppm */ +#define NRF_CLOCK_LF_ACCURACY_50_PPM (5) /**< 50 ppm */ +#define NRF_CLOCK_LF_ACCURACY_30_PPM (6) /**< 30 ppm */ +#define NRF_CLOCK_LF_ACCURACY_20_PPM (7) /**< 20 ppm */ +#define NRF_CLOCK_LF_ACCURACY_10_PPM (8) /**< 10 ppm */ +#define NRF_CLOCK_LF_ACCURACY_5_PPM (9) /**< 5 ppm */ +#define NRF_CLOCK_LF_ACCURACY_2_PPM (10) /**< 2 ppm */ +#define NRF_CLOCK_LF_ACCURACY_1_PPM (11) /**< 1 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 (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 (legacy - 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 +/-500 ppm 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 accuracy; /**< External clock accuracy used in the LL to compute timing + windows, see @ref NRF_CLOCK_LF_ACCURACY.*/ +} 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 @ref 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_soc.h new file mode 100644 index 0000000000..ff79844817 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_soc.h @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf.h" +#include "nrf_svc.h" +#include "nrf_error.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 Guaranteed 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) + +/**@brief The maximum processing time to handle a timeslot extension. */ +#define NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US (17) + +/**@brief The latest time before the end of a timeslot the timeslot can be extended. */ +#define NRF_RADIO_MIN_EXTENSION_MARGIN_US (79) + +#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. */ + +#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. + The default interrupt priority for this handler is set to 4 */ +#define RADIO_NOTIFICATION_IRQn (SWI1_IRQn) /**< The radio notification IRQ number. */ +#define RADIO_NOTIFICATION_IRQHandler (SWI1_IRQHandler) /**< The radio notification IRQ handler. + The default interrupt priority for this handler is set to 4 */ +#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_RAM_POWER_SET, + SD_POWER_RAM_POWER_CLR, + SD_POWER_RAM_POWER_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_V17 = 4UL, /**< 1.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V18, /**< 1.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V19, /**< 1.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V20, /**< 2.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V22, /**< 2.2 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V24, /**< 2.4 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V26, /**< 2.6 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V27, /**< 2.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V28 /**< 2.8 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: + @ref NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US. + This action must be started at least + @ref NRF_RADIO_MIN_EXTENSION_MARGIN_US before + the end of the timeslot. */ + 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. + @note The SoftDevice will automatically turn on and off the external crystal, + at the beginning and end of the timeslot, respectively. The crystal may also + intentionally be left running after the timeslot, in cases where it is needed + by the SoftDevice shortly after the end of the timeslot. */ + 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 activities 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 const * p_key; /**< Pointer to the Encryption key. */ + soc_ecb_cleartext_t const * 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 Writes the NRF_POWER->RAM[index].POWERSET register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERSET register to write to. + * @param[in] ram_powerset Contains the word to write to the NRF_POWER->RAM[index].POWERSET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_SET, uint32_t, sd_power_ram_power_set(uint8_t index, uint32_t ram_powerset)); + +/**@brief Writes the NRF_POWER->RAM[index].POWERCLR register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERCLR register to write to. + * @param[in] ram_powerclr Contains the word to write to the NRF_POWER->RAM[index].POWERCLR register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_CLR, uint32_t, sd_power_ram_power_clr(uint8_t index, uint32_t ram_powerclr)); + +/**@brief Get contents of NRF_POWER->RAM[index].POWER register, indicates power status of RAM[index] blocks. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWER register to read from. + * @param[out] p_ram_power Content of NRF_POWER->RAM[index].POWER register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_GET, uint32_t, sd_power_ram_power_get(uint8_t index, uint32_t * p_ram_power)); + +/**@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. + * + * @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. + * + * @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. + * + * @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 application waits for an application event by calling this function, an interrupt that + * is enabled will be taken immediately on pending since this function will wait in thread mode, + * then the execution will return in the application's main thread. + * + * In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M + * MCU's System Control Register (SCR), CMSIS_SCB. In that case, when a disabled interrupt gets + * pended, this function will return to the application's main thread. + * + * @note 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. + * + * @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, the radio + * notifications must be configured 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_ERROR_INVALID_STATE A protocol stack or other SoftDevice is running. Stop all + * running activities and retry. + * @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 50 us 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 the device's Product Specification +* 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 the number of words in one +* flash page. See the device's Product Specification for details. +* +* @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 * p_dst, uint32_t 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 the device's Product Specification +* and the command parameters). +* +* +* @param[in] page_number Page number 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. + This sets the CONFIGx registers of the BPROT peripheral. + * + * @note Not all parameters are valid for all products. Some bits in each parameter may not be + * valid for your product. Please refer your Product Specification for more details. + * + * @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. + * @param[in] block_cfg3 Value to be written to the configuration register. + * + * @retval ::NRF_ERROR_NOT_SUPPORTED Non-zero value supplied to one or more of the unsupported parameters. + * @retval ::NRF_ERROR_FORBIDDEN Tried to protect the flash region used by 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 100 ms 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 const * p_request)); + +/**@} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_SOC_H__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_svc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_svc.h new file mode 100644 index 0000000000..292c692982 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/headers/nrf_svc.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_licence-agreement.txt new file mode 100644 index 0000000000..00c2e54c47 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 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 form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_softdevice.hex b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_softdevice.hex new file mode 100644 index 0000000000..79fc6a560a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S112/hex/s112_nrf52810_5.1.0_softdevice.hex @@ -0,0 +1,5925 @@ +:020000040000FA +:1000000000040020E90800007D050000C908000088 +:1000100087050000910500009B050000000000001E +:100020000000000000000000000000000D090000BA +:10003000A505000000000000AF050000B9050000A4 +:10004000C3050000CD050000D7050000E105000054 +:10005000EB050000F5050000FF05000009060000A3 +:10006000130600001D0600002706000031060000F0 +:100070003B060000450600004F0600005906000040 +:10008000630600006D060000770600008106000090 +:100090008B060000950600009F060000A9060000E0 +:1000A000B3060000BD060000C7060000D106000030 +:1000B000DB060000E5060000EF060000F906000080 +:1000C000030700000D0700001707000021070000CC +:1000D0002B070000350700003F070000490700001C +:1000E000530700005D07000067070000710700006C +:1000F0007B070000850700008F07000099070000BC +:10010000A30700001FB500F003F88DE80F001FBD26 +:1001100000F0E0BB1FB56FF00100009040100390AD +:10012000029001904FF010208069000B420900F00E +:100130001F045DF822300120A04083434DF8223097 +:10014000684600F045F91FBDF0B54FF6FF734FF458 +:10015000B4751A466E1E11E0A94201D3344600E080 +:100160000C46091B30F8027B641E3B441A44F9D14B +:100170009CB204EB134394B204EB12420029EBD17E +:1001800098B200EB134002EB124140EA0140F0BD8F +:10019000DE4992B00446D1E90001CDE91001FF2209 +:1001A0004021684600F03CFB94E80F008DE80F000A +:1001B000684610A902E004C841F8042D8842FAD12B +:1001C00010216846FFF7C0FF1090AA208DF8440068 +:1001D000FFF7A0FF00F0F3F84FF01024A069102201 +:1001E0006946803000F002F9A069082210A900F0E9 +:1001F000FDF800F0D8F84FF080510A6949690068AD +:100200004A43824201D8102070470020704710B541 +:10021000D0E900214FF0805002EB8103026944696C +:100220006243934209D84FF01022536903EB8103D4 +:100230000169406941438B4201D9092010BD5069D1 +:10024000401C01D0002010BD0F2010BD70B501680A +:100250000446AF4D4FF01020072952D2DFE801F0DD +:10026000330419293C1E2500D4E902656468294637 +:10027000304600F0CDF82A462146304600F0B6F868 +:10028000AA002146304600F09FFA002800D0032043 +:1002900070BD00F051FB4FF4805007E0201DFFF7C8 +:1002A000AAFF0028F4D100F047FB60682860002016 +:1002B00070BD241D94E80700920000F085FA002824 +:1002C000F6D00E2070BD8069401C12D0201DFFF7B3 +:1002D0009EFF0028F6D109E08069401C09D0201D4E +:1002E000FFF789FF0028EDD1606820B12046FFF7B5 +:1002F0004FFF042070BDFFF70DFF00F060F800F025 +:1003000052F8072070BD10B50C46182802D0012005 +:10031000086010BD2068FFF799FF206010BD4FF006 +:100320001024A069401C05D0A569A66980353079E4 +:10033000AA2808D06069401C2DD060690068401C64 +:1003400029D060692CE010212846FFF7FDFE3168B6 +:1003500081421CD1A16901F18002C03105E030B1B8 +:1003600008CA51F8040D984201D1012000E0002094 +:100370008A42F4D158B1286810B1042803D0FEE7AE +:10038000284600F057F862496868086008E000F005 +:1003900016F800F008F84FF480500168491C01D0AD +:1003A00000F0A4FAFEE7BFF34F8F5A4801685A4A9B +:1003B00001F4E06111430160BFF34F8FFEE74FF09E +:1003C00010208169491C02D0806900F0AEB87047E6 +:1003D000524A01681160121D416811604F4A8168DC +:1003E00010321160111DC068086070472DE9F0419E +:1003F00017460D460646002406E03046296800F000 +:10040000A7F8641C2D1D361DBC42F6D3BDE8F08153 +:1004100070B50C4605464FF4806608E0284600F0AB +:1004200084F8B44205D3A4F5806405F58055002C0A +:10043000F4D170BD4168044609B1012500E00025F2 +:100440004FF010267069A268920000F0BDF9C8B1A3 +:10045000204600F01AF89DB17669A56864684FF4EB +:10046000002084420AD2854208D229463046FFF74E +:10047000CFFF2A4621463046FFF7B8FFFFF79FFF20 +:10048000FFF791FFFFF746FEF8E72DE9FF414FF038 +:100490001024616980680D0B01EB800000F6FF708D +:1004A000010B0020009001900290024603906846E4 +:1004B00001230BE0560902F01F0C50F8267003FAD6 +:1004C0000CFC47EA0C0740F82670521CAA42F1D3F4 +:1004D0000AE04A0901F01F0650F8225003FA06F616 +:1004E000354340F82250491C8029F2D3A169090BF9 +:1004F0004A0901F01F0150F822408B409C4340F80C +:100500002240FFF765FFBDE8FF8100005C090000A5 +:10051000000000200CED00E00400FA050006004099 +:10052000144801680029FCD07047134A0221116069 +:1005300010490B68002BFCD00F4B1B1D186008687E +:100540000028FCD00020106008680028FCD070470C +:10055000094B10B501221A60064A1468002CFCD021 +:10056000016010680028FCD0002018601068002886 +:10057000FCD010BD00E4014004E5014008208F4993 +:1005800009680958084710208C4909680958084724 +:1005900014208A49096809580847182087490968BA +:1005A0000958084730208549096809580847382004 +:1005B00082490968095808473C2080490968095858 +:1005C000084740207D4909680958084744207B496D +:1005D00009680958084748207849096809580847B0 +:1005E0004C20764909680958084750207349096822 +:1005F0000958084754207149096809580847582084 +:100600006E490968095808475C206C49096809580F +:100610000847602069490968095808476420674904 +:100620000968095808476820644909680958084753 +:100630006C20624909680958084770205F490968B9 +:100640000958084774205D49096809580847782007 +:100650005A490968095808477C20584909680958C7 +:10066000084780205549096809580847842053499C +:1006700009680958084788205049096809580847F7 +:100680008C204E4909680958084790204B49096851 +:10069000095808479420494909680958084798208B +:1006A00046490968095808479C204449096809587F +:1006B0000847A0204149096809580847A4203F4934 +:1006C000096809580847A8203C490968095808479B +:1006D000AC203A49096809580847B02037490968E9 +:1006E00009580847B4203549096809580847B8200F +:1006F0003249096809580847BC2030490968095837 +:100700000847C0202D49096809580847C4202B49CB +:10071000096809580847C82028490968095808473E +:10072000CC202649096809580847D0202349096880 +:1007300009580847D4202149096809580847D82092 +:100740001E49096809580847DC201C4909680958EE +:100750000847E0201949096809580847E420174963 +:10076000096809580847E8201449096809580847E2 +:10077000EC201249096809580847F0200F49096818 +:1007800009580847F4200D49096809580847F82016 +:100790000A49096809580847FC20084909680958A6 +:1007A00008475FF480700549096809580847000048 +:1007B00003480449024A034B704700000000002030 +:1007C000680900006809000040EA010310B59B07B2 +:1007D0000FD1042A0DD310C808C9121F9C42F8D0AB +:1007E00020BA19BA884201D9012010BD4FF0FF305C +:1007F00010BD1AB1D30703D0521C07E0002010BD72 +:1008000010F8013B11F8014B1B1B07D110F8013BFD +:1008100011F8014B1B1B01D1921EF1D1184610BDDE +:1008200002F0FF0343EA032242EA024200F005B865 +:100830007047704770474FF000020429C0F01280E3 +:1008400010F0030C00F01B80CCF1040CBCF1020F83 +:1008500018BF00F8012BA8BF20F8022BA1EB0C0158 +:1008600000F00DB85FEAC17C24BF00F8012B00F84E +:10087000012B48BF00F8012B70474FF0000200B574 +:10088000134694469646203922BFA0E80C50A0E8B3 +:100890000C50B1F12001BFF4F7AF090728BFA0E861 +:1008A0000C5048BF0CC05DF804EB890028BF40F82D +:1008B000042B08BF704748BF20F8022B11F0804F6F +:1008C00018BF00F8012B7047014B1B68DB68184705 +:1008D0000000002009480A497047FFF7FBFFFFF7B7 +:1008E00011FC00BD20BFFDE7064B1847064A10600B +:1008F000016881F30888406800470000680900002B +:10090000680900001F030000000000201EF0040F13 +:100910000CBFEFF30881EFF3098188690238007892 +:10092000182803D100E00000074A1047074A126860 +:100930002C3212681047000000B5054B1B68054AB1 +:100940009B58984700BD00000703000000000020EE +:100950005809000004000000001000000000000022 +:0809600000FFFFFF0090D0032F +:10100000E00C002065730100858B0000D7720100A1 +:10101000858B0000858B0000858B000000000000A0 +:10102000000000000000000000000000BD7301008F +:10103000858B000000000000858B0000858B000080 +:10104000257401002B740100858B0000858B000046 +:10105000858B0000858B0000858B0000858B000050 +:1010600031740100858B0000858B0000377401000E +:10107000858B00003D740100437401004974010038 +:10108000858B0000858B0000858B0000858B000020 +:10109000858B0000858B0000858B0000858B000010 +:1010A000858B00004F740100858B0000858B00004C +:1010B000858B0000858B0000858B0000858B0000F0 +:1010C00055740100858B0000858B0000858B000026 +:1010D000858B0000858B0000858B0000858B0000D0 +:1010E000858B0000858B0000858B0000858B0000C0 +:1010F000858B0000858B0000858B0000858B0000B0 +:10110000858B0000858B000000F002F816F017F9BF +:101110000AA090E8000C82448344AAF10107DA4552 +:1011200001D116F00CF9AFF2090EBAE80F0013F076 +:10113000010F18BFFB1A43F001031847286701008D +:10114000486701000A4410F8014B14F00F0508BF6E +:1011500010F8015B240908BF10F8014B6D1E05D083 +:1011600010F8013B6D1E01F8013BF9D1641E03D05C +:10117000641E01F8015BFBD19142E4D3704700008B +:101180000023002400250026103A28BF78C1FBD890 +:10119000520728BF30C148BF0B6070471FB500F031 +:1011A00031F88DE80F001FBD8269034981614FF05E +:1011B0000100104470470000BD11000001B41EB4CE +:1011C00000B50EF089FE01B40198864601BC01B05D +:1011D0001EBD0000F0B44046494652465B460FB47F +:1011E00002A0013001B50648004700BF01BC864699 +:1011F0000FBC8046894692469B46F0BC7047000073 +:101200000911000016F098B870B51B4C054609206E +:101210002070A01C00F061F85920A08029462046CB +:10122000BDE8704006F05CBD06F065BD70B50C46CB +:101230001249097829B1A0F16001562908D301208B +:1012400013E0602804D0692802D043F201000CE0CA +:1012500020CC0B4E94E80E0006EB8000A0F58050E9 +:10126000241FD0F8806E2846B047206070BD012052 +:101270007047062070470000080000201C00002076 +:101280008474010010B504460021012000F032F8FA +:1012900000210B2000F02EF80421192000F02AF87C +:1012A00004210D2000F026F804210E2000F022F881 +:1012B00004210F2000F01EF80421C84300F01AF8A2 +:1012C0000621162000F016F80621152000F012F86D +:1012D0002046FFF799FF002010BDA621018070472E +:1012E000FFF7A2BF002070470A487047FFF79EBF74 +:1012F000704770474907090E002806DA00F00F0012 +:1013000000F1E02080F8141D704700F1E02080F823 +:101310000014704703F90042FE4810B5017900F14E +:101320000500490805D00AF065FABDE8104006F04E +:1013300080BB0AF046FAF8E702210BF079BB2DE9F1 +:10134000FC411D4690460E460746FFF7F5FF040098 +:101350000AD02078222804D3A07FC0F34010A842EE +:1013600005D10820BDE8FC8143F20200FAE7ADF8A0 +:1013700000703DB101208DF802008DF803608DF8FA +:10138000048002E000208DF8020068460AF060FC4C +:10139000A07F65F34510A0770020E3E730B5044651 +:1013A000A1F120000D460A2847D2DFE800F005072A +:1013B0000C19202532373C41FFDF3FE02078202800 +:1013C0003CD1FFDF3AE0D3480078032836D02078BC +:1013D000242833D0252831D023282FD0FFDF2DE03B +:1013E000207822282AD0232828D8FFDF26E020785A +:1013F000222823D0FFDF21E0207822281ED02428B5 +:101400001CD026281AD0272818D0292816D0FFDF6C +:1014100014E02078252811D0FFDF0FE02078252860 +:101420000CD0FFDF0AE02078252807D0FFDF05E099 +:101430002078282802D0FFDF00E0FFDF257030BDD4 +:101440001FB50022ADF800200C88ADF802404B8893 +:10145000ADF80430CA88ADF808208988ADF80610C8 +:101460000021ADF80A10ADF80C1080B14FF6FF70F6 +:101470000621844201D1ADF80210834201D1ADF8BA +:101480000410824203D14FF44860ADF8080068466A +:101490000AF0AEFA06F0CDFA04B010BD70B51446ED +:1014A0000D4606460EF098FF58B90DB1A54201D978 +:1014B0000C2070BD002408E056F824000EF08CFFCC +:1014C00008B1102070BD641CE4B2AC42F4D300201B +:1014D00070BDF0B50024059D10B1A94203D850E0BD +:1014E00009B90020F0BD0920F0BD055DD5B107198F +:1014F00097F801C0BCF1150F2DD03BDCBCF1150FE6 +:1015000038D2DFE80CF037122020262628282F2F8B +:10151000373737373737373737372000025D22BB49 +:10152000641CE4B28C42F9D3DBE7022DDBD1BD7839 +:101530001D70072D01D26D0701D40A20F0BD15786A +:1015400045F0010515E0EF43FF0707E0012D07D047 +:1015500010E00620F0BD2F07A7F18057002FF5D02F +:101560003046F0BD1578AF0701D50B20F0BD45F032 +:1015700002051570055D641C2C44E4B28C4202D94E +:10158000B1E74FF448568C42AFD3AAE710B50278C2 +:10159000540809D0012243F20223012C07D0022C67 +:1015A0000DD0032C13D10FE00020087005E08079E6 +:1015B0000324B4EB901F0AD10A70002010BD80797B +:1015C000B2EB901F03D1F7E780798009F4D0184679 +:1015D00010BD38B50C460546694600F0D6FF002818 +:1015E0000DD19DF80010207861F34700207055F868 +:1015F000010FC4F80100A888A4F80500002038BD38 +:1016000038B51378C0B1022816D043A46D462468BB +:1016100000944C7905EB9414247864F34703137019 +:1016200003280ED003F0FE0010700868C2F8010015 +:101630008888A2F8050038BD23F0FE031370022845 +:10164000EED1D8B240F00100EEE738B50C4609788B +:10165000222901D2082038BDADF800008DF8022003 +:1016600068460AF003F906F0E4F9050003D12121E8 +:101670002046FFF793FE284638BD1CB500208DF8A4 +:101680000000CDF80100ADF805002248807B02285B +:1016900001D0012000E000208DF8070068460AF024 +:1016A00053F9002800D0FFDF1CBD2DE9FE430400E4 +:1016B00000D1FFDF2078174E20F00F00801C20F0B3 +:1016C000F0007030207060680178091F162930D250 +:1016D000DFE801F0FB2F2F2F52FA2F0BFAFA3FFB16 +:1016E0002F2FFB6BFB2F2FFBFBF986883046FFF774 +:1016F00023FE0546304609F0C2FCE0B160688079FF +:1017000085F83E0021212846FFF748FE304603F0C9 +:10171000A8FB03E0840100200302FF01304604F02F +:101720000FFD314602200EF00BFEA87F20F01000C6 +:10173000A877BDE8FE83207820F0F00020302070EC +:1017400006202072668060688079607206F049FB2E +:10175000D8E785882846FFF7EFFD00B9FFDF60680E +:101760008078012800D0FFDF6068817903B02846C7 +:10177000BDE8F04309F0B3BD86883046FFF7DCFDD5 +:10178000050000D1FFDF06F02CFB60683146C08801 +:10179000288160680089688160684089A88102208A +:1017A0000EF0CEFD0020A875C3E780783C2803D05A +:1017B000002502280CD000E00125002720B13C289C +:1017C00002D0022800D0FFDF27B1FFDFFFDFB0E744 +:1017D0000127F3E706F005FB1DB1B07800F0CBFE62 +:1017E00088E06568A879AD1C00B9FFDF96F8028033 +:1017F000B5F80290404606F0BCF8070000D1FFDFC4 +:101800000022022148460BF00AF9040000D1FFDF54 +:1018100022212046FFF7C2FDA17F012060F30101D4 +:10182000A177298B2181698B6181A98BA18184F8A2 +:1018300022808DF8080002AA032148460BF0EFF839 +:1018400000B9FFDFB888ADF80400B8788DF806005D +:1018500001AA052148460BF0E2F800B9FFDFB8887D +:10186000ADF80000F8788DF802006A460421484679 +:101870000BF0D5F800B9FFDF062105F1120000F0EA +:10188000A1FE18B36879800700D5FFDF6979E07D94 +:1018900061F34700E075D5F80600A0616889A08370 +:1018A000062105F10C0000F08DFEC8B13079410829 +:1018B000607861F347006070D6F80500C4F8020054 +:1018C000B6F8090015E027E021E02CE0E07D20F0EB +:1018D000FE00801CE075D5F81200A061E88ADEE702 +:1018E000607820F0FE00801C6070E868C4F8020098 +:1018F000288AE0803078032800D0FFDF00210846E6 +:101900000EF01EFDBDE8FE43012000F020BE204683 +:10191000BDE8FE4301F037BE06F063FA307C40F0CC +:101920000400307405E7BDE8FE4306F05ABA2DE91D +:10193000F047804600789146002702090C463E4653 +:10194000012A75D000204FF6FF71022A71D0072AB4 +:101950000AD00A2A6ED0FFDFA9F800600CB12780F8 +:1019600066800020BDE8F087D8F804502A78142A51 +:1019700076D006DC082A0BD00F2A17D0132A59D1AB +:101980001EE0172A09D0182A3FD0192AF7D152E0B1 +:1019900012271026A888214683E01C27092664B355 +:1019A0006888A080D8F804000079BDE01B270926CC +:1019B0001CB303202072D8F804004088A080CBE735 +:1019C000A9783C291CD010271826AD1CACB1287969 +:1019D00000B9FFDF6888A080288B6082288B208276 +:1019E000688BA082A88BE082687904F10802A91DA7 +:1019F000FFF706FE0120E073AEE7A9F80060B0E74C +:101A00001B270926002C7DD1F7E720271026002C64 +:101A1000F3D0A180D8F8040004F10902407A2072C2 +:101A2000D8F80410CB1C88781946FFF7E9FD93E736 +:101A30002DE039E07AE021270A26002CDDD06888E5 +:101A4000A080D8F8040000792072D8F8040040790A +:101A50006072F948017C21F0040101747CE7FFE722 +:101A600022270B26002CC8D0A888A080D8F8040014 +:101A700080782072D8F80400807900F0B2FD60729E +:101A8000D8F80400C07900F0ACFDA07264E798F8C3 +:101A90000800022801D0FFDF5EE712271026B8F801 +:101AA000020000F07CFD57E798F80820072A44D28E +:101AB000DFE802F03543433C3C3C04001127092693 +:101AC000002C9AD0B8F802502846FFF735FC90F861 +:101AD00022A0A58098F809002072042128460AF067 +:101AE000B9FF052128460AF0B5FF002128460AF073 +:101AF000B1FF012128460AF0ADFF032128460AF074 +:101B0000A9FF00E010E0022128460AF0A3FF062109 +:101B100028460AF09FFF504600F02DFD1CE71B27CA +:101B20000926002C8AD0A180207215E74A4621465A +:101B30004046BDE8F04701F05BBEFFDF0CE710B5A3 +:101B4000BD4C207801280ED0002009F0B9FF05F027 +:101B500070FF002808D1002108460EF0F1FB207824 +:101B6000032802D004E0082010BDA07800F003FD97 +:101B7000012000F0ECFC002010BD70B5002518B16C +:101B8000022813D0FFDF70BDFFF7D9FF0028FAD17C +:101B900006F024F90028F6D0017821F00F01891C05 +:101BA00021F0F00120310170057218E08EB230464C +:101BB000FFF7C2FB040000D1FFDF20782128E2D02C +:101BC00006F00CF978B1017821F00F01891C21F0A1 +:101BD000F00110310170022101724680A575BDE847 +:101BE000704006F0FEB821463046BDE87040132232 +:101BF0002BE52DE9F04116460C00804600D1FFDFB1 +:101C0000307820F00F00801C20F0F0001030307091 +:101C10002078022802D0FFDFBDE8F0814046FFF7C0 +:101C20008BFB050000D1FFDF61884FF6FF700027B6 +:101C3000814202D1A288824203D0814201D1A08890 +:101C400048B106F0CEF82068B0606068F060208986 +:101C50003082AF75E0E7A87D0128DDD1782300222E +:101C6000414602200EF0C2FA0220A875D4E738B52A +:101C700005460C4608460EF0AFFB70B9203D072D17 +:101C800037D2DFE805F004062328362E1C00062094 +:101C900038BD60680EF0E4FB08B1102038BD6188E3 +:101CA00020886A460AF012F805F0C3FE0028F5D134 +:101CB00061680029F2D0BDF800200A8038BDA07804 +:101CC00000F0010120880AF032F80EE02068BDE83B +:101CD000384001F0C2BF207800F001000AF08AF815 +:101CE00003E06188208809F095FFBDE8384005F0E1 +:101CF000A0BE072038BD70B505460C4608460EF05C +:101D000091FB08B1102070BD203D072D1BD2DFE8EC +:101D100005F0041818181A1A18002088FFF70CFB91 +:101D200020B10078222804D2082070BD43F20200BE +:101D300070BD2088A11C09F0EDFDBDE8704005F0E4 +:101D400078BE062070BD072070BD3B48001D70475F +:101D500038B51421384815F074FA012000F0F7FB6B +:101D6000354C6846611D05F0CFFF9DF800102079C5 +:101D700061F3470020F0010020710020A0734FF4B0 +:101D80006170A0810220E073FFF7C6FA00B1FFDFA7 +:101D900000F032FC01F0CAFB38BD10B50C46402102 +:101DA000204615F04EFAA07F20F00300A0772020F7 +:101DB00020700020A07584F8230010BD70477CB50A +:101DC00005460EF009FB08B110207CBD1A4C211D00 +:101DD00060680090A06801902846FFF7FAFB002891 +:101DE000F3D1FFF799FA0028EFD000996160BDF8B0 +:101DF000041021819DF80610A1727CBD10B5044627 +:101E00000EF010FB08B1102010BD0B4922460879D6 +:101E1000491D4008FFF7F4FB002010BDFEB50D463C +:101E200004004FF0000714D00822FFF737FB00280A +:101E300014D100260BE000008401002054F8260095 +:101E40006946FFF7A3FB002808D1761CF6B2AE4224 +:101E5000F4D309F020FC10B143F20320FEBDF74E8D +:101E6000F770FCB100271AE054F8270002A9FFF729 +:101E70008DFB00B1FFDF9DF808008DF8000054F8DD +:101E8000270050F8011FCDF801108088ADF805003B +:101E9000684609F025FC00B1FFDF7F1CFFB2AF42AE +:101EA000E2D3F5700020FEBD2DE9F0478AB015465B +:101EB000894604001DD00F4608222946FFF7EEFA96 +:101EC000002810D1002612E054F826006946103090 +:101ED00000F05BFB002806D13FB157F826000EF05A +:101EE0007BFA10B110200AB03CE5761CF6B2AE4287 +:101EF000EAD30026A5F101081CE000BF06F1010AA3 +:101F00000AF0FF0712E000BF54F82600017C4A08DF +:101F100054F827100B7CB2EB530F05D10622113079 +:101F2000113115F0E3F858B17F1CFFB2AF42EBD38B +:101F30000AF0FF064645E1DB4E4624B1012003E0EE +:101F400043F20520CFE7002009F0EAFB10B909F0C1 +:101F5000F3FB10B143F20420C5E75CB300270DF199 +:101F6000170825E054F827006946103000F00DFBF3 +:101F700000B1FFDF54F82700102250F8111FCDF8F0 +:101F800001108088ADF8050054F827100DF1070006 +:101F900015F0D8F896B156F827101022404615F0E3 +:101FA000D1F8684609F081FB00B1FFDF7F1CFFB26A +:101FB000AF42D7D3FFF761FB002094E7404601F022 +:101FC00040FEEEE730B585B004460EF005FA18B9CC +:101FD00060680EF04EFA10B1102005B030BD608878 +:101FE0004AF2B811884206D82078944D28B10128C9 +:101FF00006D0022804D00720EFE7FFF78DF917E09D +:102000006078022804D0032802D043F20220E4E7DB +:10201000E873C1B200200090ADF8040002292BD073 +:10202000032926D0FFDF684609F0E4FB05F001FD37 +:102030000028D2D1606801F0F7FD207858B1012066 +:102040008DF800000DF1010001F0FBFD684609F07C +:10205000C0FE00B1FFDF2078A873FFF70EFB608899 +:1020600060B1A88180B209F053FB00B1FFDF00200E +:10207000B3E78DF80500D6E74020FAE74FF461702A +:10208000EFE710B504460EF0CDF920B9606838B11D +:102090000EF0E6F908B1102010BD606801F0D1FD26 +:1020A000664881896180C17B6170807B20700020DF +:1020B00010BD2DE9F04186B0054600208DF80C00DA +:1020C0008DF804008DF808008DF810001E461446A7 +:1020D000884628460EF0CDF918B920460EF0C9F909 +:1020E00010B1102006B097E555EA040018D01F275C +:1020F00002AB03AA414628460097FFF7EAF90028F9 +:10210000F0D104AB01AA314620460097FFF7E1F970 +:102110000028E7D19DF80400C00703D00A20E1E7BA +:102120000720DFE73DB12946404609F0B7FC05F03E +:1021300080FC0028D6D13CB12146304609F0B7FCDE +:1021400005F077FC0028CDD13C499DF80800487087 +:102150000020C7E72DE9F04788B088464FF0000916 +:1021600037A104468DF81090D1E90001CDE90501B1 +:1021700020460EF031F990B92078012803D160682B +:102180000EF02AF958B92D4D4FF0010AA87B50B135 +:10219000E87B022807D160680EF06BF918B11020B7 +:1021A00008B0BDE8F0872878012801D00820F7E7BB +:1021B00006200AF0F1FB20B92078002867D001281A +:1021C00065D00CF041FB06460DF0D5FC301AC6B2C6 +:1021D00006200AF0D9FB074606200AF0DDFB391A73 +:1021E0002878022810D000200844301A10F0FF0F81 +:1021F0000CD0608943F6E172A0F120019142217870 +:102200000AD3012904D07DE00120EDE71320C7E7C0 +:10221000E0BBA189D1BB08E0012906D06978C907D4 +:1022200003D0A18991B3B4296CD8217861B1012977 +:102230000ED002290AD0032964D110E084010020C5 +:102240000706050403020100002609E0022607E054 +:1022500008B9A08908B1042609E0012607E0032691 +:10226000A87B50B1E87B022807D1606828B104A997 +:102270006068FFF78BF9002892D1207A40B10128DD +:1022800008D0022808D003283CD107E03AE03BE020 +:10229000002704E0012702E0022700E003270EB137 +:1022A000022E0ED16FB1E87860B36878800702D053 +:1022B00043F2012074E7022E03D1022F22D0032F14 +:1022C00020D0207808B101280AD1404605F051FB02 +:1022D000C0B14078C0B1404605F027FE85F80280C5 +:1022E0006089ADF800006089ADF802008DF80460E7 +:1022F000A87B0DF1050148B1E87B022818D003281E +:1023000008D119E007204BE7122049E7281D00F00B +:102310003CF900B1FFDF9DF810008DF80600207831 +:1023200001280ED0A87B98B1E87B022807D00FE0E7 +:1023300003208DF80500EEE78DF805A0EBE7606857 +:1023400030B1606850F8011FCDF80710808802E0B6 +:102350004846CDF80790ADF80B008DF80E70A07BC5 +:10236000C0F34002014662F35F01C0F3800041EA1E +:10237000800005A9085C8DF80D000028C2D06846D1 +:1023800009F05BFB05F055FB002893D1012009F013 +:1023900097FB05F04EFB00288CD1052E14D2DFE808 +:1023A00006F0030320200300A87805F0E2FA0500F8 +:1023B00000D1FFDF687800B9FFDF6878401E6870E1 +:1023C0005FF0030000F0C3F8012E0CD0A08950B1DB +:1023D00000228300114610460DF008FF18B10320BB +:1023E000DEE60220EEE70020DAE62DE9FC41804639 +:1023F0000D46032608460EF03CF810B11020BDE84B +:10240000FC814046FEF798FF040004D02078222883 +:1024100004D20820F3E743F20200F0E7A07F00F0C7 +:1024200003073DB1012F0AD000202946FFF708F825 +:102430000600E4D1012F04D0FFDF3046DFE70120A2 +:10244000F3E7A07D2946022801D011B107E0112051 +:10245000D5E7684600F0DDF90028D0D1694640464E +:1024600008F01DFF0600E8D10120A075E5E770B572 +:102470000C460546FEF760FF010005D022462846BF +:10248000BDE87040FFF7E1B843F2020070BD10B53F +:1024900009F070F9BDE8104005F0CBBA0123FEF752 +:1024A0004EBF00231A461946FEF749BF70B50546D0 +:1024B0000C4608460DF0B6FF08B1102070BD284646 +:1024C000FEF73AFF38B10178222902D3807F8006D7 +:1024D00004D4082070BD43F2020070BD2146284696 +:1024E00009F0E0FBBDE8704005F0A3BA38B5054639 +:1024F0000C4608460DF070FF08B1102038BD284684 +:10250000FEF71AFF20B10078222804D2082038BD37 +:1025100043F2020038BD3748007C400701D5112046 +:1025200038BD2078800802D16078800801D007206B +:1025300038BDADF8005020788DF8020060788DF835 +:102540000300684609F045FA05F073FA38BD30B566 +:10255000284D040008D0012C04D0022C06D0032CF6 +:1025600004D0FFDF2C7030BDFFDFFBE728780128A7 +:10257000F8D0FFDFF6E710B505F0FBF9040000D155 +:10258000FFDF6078401C607010BD0278520804D0F4 +:10259000012A02D043F202207047FEF7F7BF70B560 +:1025A0000C0006460DD0FEF7C7FE050000D1FFDF88 +:1025B000A68028892081288960816889A081A889CE +:1025C000E08170BD10B500231A4603E0845C23430C +:1025D000521CD2B28A42F9D30BB1002010BD0120A7 +:1025E00010BD00B5012803D0022801D0FFDF002074 +:1025F00000BD000084010020FE4800210160416010 +:10260000018170472DE9F743044692B09146406836 +:102610000DF026FF40B160680DF02BFF20B9607807 +:1026200000F00300022801D0012000E00020F14E5C +:10263000307248460DF0D0FE18B1102015B0BDE83C +:10264000F08349460120FEF7FBFE0028F6D1012564 +:102650008DF842504FF4C050ADF84000002210A950 +:10266000284604F035F80028E8D18DF842504FF4A0 +:1026700028504FF00008ADF8400047461C2168463E +:10268000CDF81C8014F0FFFD9DF81C0008AA20F076 +:102690000F00401C20F0F00010308DF81C00207856 +:1026A0008DF81D0061789DF81E0061F3420040F036 +:1026B00001008DF81E009DF800000AA940F00200FC +:1026C0008DF800002089ADF83000ADF832706089D7 +:1026D00007AFADF834000B97606810AC0E900A9409 +:1026E000684603F0EAFD0028A8D1BDF8200030803C +:1026F0008DF8425042F60120ADF840009DF81E00D2 +:1027000008AA20F00600801C20F001008DF81E00B1 +:102710000220ADF83000ADF8340013A80E900AA9DD +:10272000684603F0CAFD002888D1BDF820007080FB +:10273000311D484600F033F9002887D18DF842500A +:1027400042F6A620ADF840001C216846CDF81C805A +:1027500014F099FD9DF81C00ADF8345020F00F00E6 +:10276000401C20F0F00010308DF81C009DF81D007A +:1027700008AA20F0FF008DF81D009DF81E000AA990 +:1027800020F0060040F00100801C8DF81E009DF82E +:1027900000008DF8445040F002008DF80000CDE9B3 +:1027A0000A4711A80E90ADF83050684603F085FD39 +:1027B000002899D1BDF82000F08000203EE73EB50A +:1027C00004460820ADF8000020460DF005FE08B1D3 +:1027D00010203EBD21460120FEF732FE0028F8D130 +:1027E0002088ADF804006088ADF80600A088ADF838 +:1027F0000800E088ADF80A007E4801AB6A46808890 +:10280000002104F05FF9BDF800100829E1D0032091 +:102810003EBD1FB50446002002900820ADF8080018 +:10282000CDF80CD020460DF0D7FD10B1102004B02B +:1028300010BD704802AA81884FF6FF7004F084FB37 +:102840000028F4D1BDF80810082901D00320EEE7D4 +:10285000BDF800102180BDF802106180BDF80410A1 +:10286000A180BDF80610E180E1E701B582B0022049 +:10287000ADF800005F4802AB6A464088002104F0D2 +:1028800021F9BDF80010022900D003200EBD1CB5AF +:10289000002100910221ADF8001001900DF0C2FD61 +:1028A00008B110201CBD53486A4641884FF6FF709E +:1028B00004F04AFBBDF800100229F3D003201CBD30 +:1028C000FEB54C4C06461546207A0F46C00705D08B +:1028D00008460DF081FD18B11020FEBD0F20FEBD91 +:1028E000F82D01D90C20FEBD30460DF075FD18BB4A +:1028F000208801A903F027FA0028F4D130788DF858 +:102900000500208801A904F0BCF80028EBD1009054 +:102910009DF800009DF8051040F002008DF80000C1 +:10292000090703D040F008008DF8000020886946B0 +:1029300004F044F80028D6D1ADF8085020883B4672 +:1029400002AA002104F0BEF8BDF80810A942CAD0BE +:102950000320FEBD7CB5054600200090019008884C +:10296000ADF800000C46284601950DF079FD18B928 +:1029700020460DF057FD08B110207CBD15B1BDF803 +:10298000000050B11B486A4601884FF6FF7004F002 +:10299000DBFABDF8001021807CBD0C207CBD30B579 +:1029A00093B0044600200D460090142101A814F0B5 +:1029B0006AFC1C2108A814F066FC9DF80000CDF804 +:1029C00008D020F00F00401C20F0F00010308DF8EF +:1029D00000009DF8010020F0FF008DF801009DF837 +:1029E000200040F002008DF8200001208DF8460004 +:1029F00002E000009801002042F60420ADF84400F7 +:102A000011A801902088ADF83C006088ADF83E0028 +:102A1000A088ADF84000E088ADF842009DF80200C3 +:102A200006AA20F00600801C20F001008DF80200AC +:102A30000820ADF80C00ADF810000FA8059001A912 +:102A400008A803F03AFC002803D1BDF8180028803C +:102A5000002013B030BD00004FF0E0224FF40041E1 +:102A60000020C2F880111D4908701D4990020860BD +:102A7000704770B5194D04462878A04202D00CB1B9 +:102A800000B1FFDF2878A0420DD01649144A2C70FF +:102A90000020CCB1134E144B1436151F012C03D05B +:102AA000022C08D0FFDF70BD086002200860336090 +:102AB0004FF0407005E008600320086033604FF479 +:102AC00000001060286070BD086008604FF0607002 +:102AD000106070BD00B5FFDF00BD000018000020D1 +:102AE00008F5014000F500401802002070B50B20E9 +:102AF00000F0AFF9082000F0ACF900210B2000F045 +:102B0000BEF90021082000F0BAF9E54C0125656006 +:102B1000A5600020C4F84001C4F84401C4F848018D +:102B20000B2000F0A1F9082000F09EF90B2000F026 +:102B300085F9256070BD10B50B2000F08AF90820DA +:102B400000F087F9D648012141608160D5490A68C3 +:102B5000002AFCD10021C0F84011C0F84411C0F88F +:102B600048110B2000F080F9BDE81040082000F06B +:102B70007BB910B50B2000F077F9BDE810400820B4 +:102B800000F072B900B530B1012806D0022806D095 +:102B9000FFDF002000BDC44800BDC44800BDC348DD +:102BA000001D00BD70B5C2494FF000400860C14D26 +:102BB000C00BC5F80803C04800240460C5F84041B4 +:102BC0000820C43500F045F9C5F83C41BB48047005 +:102BD00070BD08B5B24A002128B1012811D00228E1 +:102BE0001CD0FFDF08BD4FF48030C2F80803C2F8E4 +:102BF0004803AC483C300160C2F84011BDE80840D1 +:102C0000D0E74FF40030C2F80803C2F84803A548E3 +:102C100040300160C2F84411A4480CE04FF4802019 +:102C2000C2F80803C2F848039E4844300160C2F865 +:102C300048119E48001D0068009008BD70B51646FA +:102C40000D460446022800D9FFDF002294480123E4 +:102C500004F110018B4000EB8401C1F8405526B10E +:102C6000C1F84021C0F8043303E0C0F80833C1F8CC +:102C70004021C0F8443370BD2DE9F0411C46154693 +:102C800030B1012834D0022839D0FFDFBDE8F0810F +:102C9000891E002221F07F411046FFF7CFFF012C53 +:102CA00024D00020854E834F012470703C618249FE +:102CB00000203C3908600220091D08607E4904207C +:102CC000303908607C483D350560C7F8004208206F +:102CD00000F0CAF82004C7F80403082000F0AEF89A +:102CE0007349E007091F08603470CFE70120D9E776 +:102CF000012B02D00022012005E00122FBE7012B7D +:102D000004D000220220BDE8F04197E70122F9E754 +:102D100064480068704770B5614CD4F840010025E4 +:102D2000012809D1D4F80803C00305D54FF4803039 +:102D3000C4F80803C4F84051D4F8440101280CD168 +:102D4000D4F80803800308D54FF40030C4F8080312 +:102D5000C4F8445101200CF0D0FBD4F848010128FC +:102D60000ED1D4F8080340030AD54FF48020C4F8EC +:102D70000803C4F84851BDE8704002200CF0BDBB08 +:102D800070BD10B54D4C207850B1FFF70BFF607847 +:102D9000002807D000206070BDE810400CF0ADBBEB +:102DA0000320F9E710BD4FF0E0214FF40010C1F807 +:102DB00000027047152000F057B83E490120086115 +:102DC000082000F051B83B494FF47C10C1F80803CB +:102DD0000020024601EB8003C3F84025C3F84021E0 +:102DE000401CC0B20628F5D37047410A43F6095289 +:102DF0005143C0F3080010FB02F000F5807001EBB6 +:102E00005020704710B5430B48F2376463431B0CE6 +:102E10005C020C602A4C03FB04002A4B4CF2F724A2 +:102E200043435B0D13FB04F404EB402000F580707A +:102E30004012107008681844086010BD00F01F02AE +:102E4000012191404009800000F1E020C0F800110C +:102E5000704700F01F02012191404009800000F1FD +:102E6000E020C0F88011704700F01F02012191405E +:102E70004009800000F1E020C0F880127047490747 +:102E8000090E002806DA00F00F0000F1E02080F8BB +:102E9000141D704700F1E02080F800147047000016 +:102EA00000B0004004B500404081004044B1004003 +:102EB00008F50140008000404085004030000020BF +:102EC000F7C2FFFF6F0C01000CF0ABBB0449002000 +:102ED00008604FF0E0210220C1F880027047000036 +:102EE000FC1F004010B50D2000F067F8C4B26FF071 +:102EF000040000F062F8C0B2844200D0FFDF36491F +:102F00000120086010BD70B50D2000F040F8334C72 +:102F10000020C4F800010125C4F804530D2000F07E +:102F200041F825604FF0E0216014C1F8000170BD48 +:102F300010B50D2000F02BF8284801214160002138 +:102F4000C0F80011BDE810400D2000F02BB8234957 +:102F500010B5D1F80001012801D0FFDF10BD1E48D7 +:102F6000001D00680022C0B2C1F80021BDE8104079 +:102F70000CF02CBF10B51948D0F800110029FBD077 +:102F8000FFF7E5FFBDE810400D2000F00BB800F0A2 +:102F90001F02012191404009800000F1E020C0F8AB +:102FA0008011704700F01F0201219140400980000C +:102FB00000F1E020C0F880127047002806DA00F027 +:102FC0000F0000F1E02090F8140D03E000F1E02084 +:102FD00090F800044009704704D5004000D000403C +:102FE0007047704770477047704770477047704729 +:102FF0007047704770477047704770477047704719 +:103000002CFFFFFFDBE5B15100800100A600FFFFB0 +:1030100070000000284F4C00DA0D499A2F95338438 +:1030200077AC2F1307CD6F7D177A70DE10B504468D +:103030000DF0D2F908B1102010BD2078C0F30210B5 +:10304000042807D86078072804D3A178102901D86C +:10305000814201D2072010BDE078410706D42179D2 +:103060004A0703D4000701D4080701D5062010BD84 +:10307000002010BD70B514460D46064604F0AEFEA5 +:1030800080B10178182221F00F01891C21F0F00194 +:10309000A03100F8081B214614F099F8BDE87040F3 +:1030A00004F09FBE29463046BDE870401322FEF76B +:1030B000CCBA2DE9F047064608A8894690E83004C6 +:1030C0001F4690461421284614F0DDF80021CAF866 +:1030D0000010B8F1000F03D0B9F1000F03D114E0D4 +:1030E0003878C00711D020680DF09CF9C0BBB8F14A +:1030F000000F07D120681230286020681430686003 +:103100002068A8602168CAF800103878800724D5A4 +:1031100060680DF0A5F918BBB9F1000F21D0FEF7DA +:1031200014FE0168C6F868118188A6F86C118079D0 +:1031300086F86E0101F02FFAF74FEF60626862B116 +:1031400096F8680106F2691140081032FEF758FA45 +:1031500010223946606813F0F5FF0020BDE8F087C3 +:1031600006E0606820B1E8606068C6F86401F4E7D2 +:103170001020F3E730B5054608780C4620F00F0024 +:10318000401C20F0F001103121700020607095F893 +:10319000230030B104280FD0052811D0062814D000 +:1031A000FFDF20780121B1EB101F04D295F8200039 +:1031B00000F01F00607030BD21F0F000203002E010 +:1031C00021F0F00030302070EBE721F0F0004030CB +:1031D000F9E7F0B591B0022715460C4606463A4687 +:1031E000ADF80870082103AB07F04EFE04900028EC +:1031F00010D004208DF804008DF80170E034099699 +:1032000005948DF818500AA968460BF003F900B12F +:10321000FFDF012011B0F0BD2DE9F84F0646808A8E +:103220000C4680B28246FEF787F80546BA4F3078E2 +:10323000203F4FF005094FF000080F287CD2DFE84F +:1032400000F07BA39D082C5B6A7CBADAFC97489758 +:1032500097000121504609F0EBFB040000D1FFDF8D +:1032600097F85C00C00701D0386E0BE0032104F131 +:103270001D000CF08CFDD4F81D00A849B0FBF1F244 +:1032800001FB1200C4F81D0070686067B068A06799 +:103290002878252872D0FFDF70E00121504609F020 +:1032A000C7FB060000D1FFDF3078810702D52978FF +:1032B000252904D040F001003070BDE8F88F0220CD +:1032C0002070307F207106F11D002D36C4E9020602 +:1032D000F3E70121504609F0ABFB050000D1FFDF09 +:1032E0002878C10604D5072020703D356560E4E7E5 +:1032F00040F008002870E0E7E87FC00600D5FFDF57 +:10330000307CB28800F0010301B05046BDE8F04FB8 +:10331000082107F0EFBE05B9FFDF716821B1102267 +:1033200005F1240013F00EFF28212846FEF736F899 +:10333000307A85F82000C0E7F6E00121504609F018 +:1033400077FB050000D1FFDF022105F185000CF0BD +:103350001EFD0420207005F5B4706060B5F885008E +:1033600020826D4810387C356561C4E90270A4E79D +:103370000121504609F05CFB00B9FFDF32462946C7 +:103380005046BDE8F84F75E605B9FFDF28782128DB +:1033900093D93079012803D1E87F40F01000E87715 +:1033A000324629465046FFF765FE2846BDE8F84FED +:1033B0002321FDF7F3BF3279A28004F1080308212D +:1033C000504607F061FDE06010B184F8009074E7AA +:1033D00045460121504609F02BFB040000D1FFDFD8 +:1033E00004F1620102231022081F09F0C6F90570DA +:1033F0003179417061E70121504609F019FB040061 +:1034000000D1FFDF94F8840000F00300012857D1B9 +:10341000E87FC0F340021AB994F8A000C00729D091 +:10342000D4F8601129B394F88330087C63F38700E3 +:103430000874EB7F63F3410000E071E0D4F86011A1 +:103440000874D4F8601162F30000087492B1D4F8E3 +:103450006001102205F12401883413F073FE207EF0 +:1034600040F001002076207820F0010004F888095F +:1034700018E0BAB994F88800C00713D0D4F85C11EA +:1034800081B194F88330087C63F387000874EB7F84 +:10349000D4F85C1163F341000874D4F85C1162F352 +:1034A0000000087494F88800800709D594F87C001F +:1034B000D4F86421400804F17D011032FEF7A0F831 +:1034C0008DF8009094F884006A4600F003008DF8AF +:1034D000010094F888108DF8021094F8A0008DF87F +:1034E00003002946504601F03FF82878252805D0EA +:1034F000212807D0FFDF2878222803D92221284657 +:10350000FDF74CFF0121504609F0A4FA00283FF4D2 +:10351000DFAEFFDFD1E60000C401002040420F0013 +:10352000716881F80180C8E6FFDFC6E670B5FD4C22 +:10353000002584F85C5025660AF039FF04F110017B +:10354000204604F007FC84F8305070BD70B50D467D +:10355000FDF7F2FE040000D1FFDF4FF4B8712846FA +:1035600013F091FE2434012105F1E0002C610AF0F2 +:103570001FFF002800D0FFDF70BD0A46014602F1A0 +:10358000E0000AF035BF70B50546406886B00178A6 +:10359000092906D00C2933D00D292FD0FFDF06B022 +:1035A00070BD46883046FDF7C7FE040000D1FFDF3E +:1035B00020782128F3D028281BD1686802210C30FC +:1035C00000F09DFFA8B168680821001D00F097FF7A +:1035D00078B104F12401304608F0E1FA04F029FA48 +:1035E00000B1FFDF06B02046BDE870402921FDF79D +:1035F000D5BE06B0BDE8704004F0F3BB0121817177 +:10360000686886883046FDF797FE040000D1FFDF2A +:1036100020782128C3D06868817909B1807808B101 +:10362000FFDFBCE704F0DDFBE07FC10721D08007AE +:1036300005D594F8200000F01F00102817D00520B1 +:1036400084F823002078292815D02428A7D13146D2 +:1036500005200CF075FE22212046FDF79FFE01217A +:10366000304609F0F7F9002899D0FFDF97E70620E8 +:10367000E6E70420E4E70121304609F0D9F9050026 +:1036800000D1FFDF25212046FDF788FE03208DF8BD +:103690000000694605F1E0000AF0A1FE0228C0D052 +:1036A0000028BED0FFDF7AE72DE9F04788B09A46C0 +:1036B000164688468146FDF73FFE05003AD0287839 +:1036C000222837D3232835D0E87FC00632D40027FC +:1036D0000121484609F0ACF9040005D1012100227E +:1036E000484609F09CF90446694600F064FF0098DA +:1036F00000B9FFDF00983CB1E0340461287822284B +:1037000004D0242802D005E0076103E025212846E3 +:10371000FDF744FE009801214170C0F82490868096 +:10372000C0E9028A01A90AF075FE022802D0002829 +:1037300000D0FFDF08B011E570B586B00546FDF793 +:10374000FBFD0078222814D90121284609F070F9E0 +:1037500004002CD1FFDF2AE0B4F85E0004F1620619 +:1037600030440178427829B121462846FFF731FDDF +:10377000B0B914E7ADF804200821284602AB07F0E1 +:1037800083FB03900028F4D005208DF800006946E3 +:1037900004F1E0000AF023FE022801D000B1FFDFAF +:1037A00002231022314604F15E0009F01CF8B4F83F +:1037B00060000028D0D1F2E610B586B00446FDF7CF +:1037C000BBFD0078222811D90121204609F030F9EB +:1037D000040000D1FFDF06208DF80000694604F1E7 +:1037E000E0000AF0FCFD002800D0FFDF06B010BDAD +:1037F0002DE9F84F054600780C460027010904F131 +:10380000080090463E46BA46009002297ED007291D +:1038100002D00A2909D142E068680178092905D057 +:103820000C292CD00D292AD0FFDF73E114271C2688 +:10383000002C6CD04088A080FDF77EFD5FEA000977 +:1038400000D1FFDF99F8170009F118014008009A2C +:10385000FDF7D6FE68688089208269684868C4F8E8 +:1038600012008868C4F81600A07E20F0060040F020 +:103870000100A07699F81E0040F040014FE01A27A1 +:103880000A26002CD5D08088A080FDF755FD0500C4 +:1038900000D1FFDF28460099FFF76CFC3AE10CB13C +:1038A000A88BA080287A4FF0010B0B287ED006DC75 +:1038B00001287CD0022808D0032804D137E00D2845 +:1038C00076D00E2875D0FFDF24E11E270926002CB4 +:1038D000AFD0A088FDF730FD5FEA000900D1FFDF1F +:1038E000287B00F003000128207A1DD020F0010081 +:1038F0002072297B890861F341002072297BC90865 +:1039000061F382002072297B090901E0F7E0AEE053 +:1039100061F3C300207299F81E0040F0800189F81D +:103920001E10F7E0A401002040F00100E0E713279B +:103930000D26002CA6D0A088FDF7FEFC81460121B3 +:10394000A08809F075F8050000D1FFDF686F817865 +:1039500001F003010129217A50D021F001012172E7 +:1039600083789B0863F3410121728378DB0863F35A +:103970008201217283781B0963F3C30121720378EA +:1039800063F306112172437863F3C711217284F83F +:1039900009A0C178A1720279E17A62F30001E172B3 +:1039A0000279520862F34101E17203E029E067E025 +:1039B0004EE05FE00279920862F38201E1720279DF +:1039C000D20862F3C301E1724279217B62F3000104 +:1039D00021734279520862F34101217342799208BE +:1039E00062F3820121734079C00860F3C30121733F +:1039F00099F8000023282AD9262139E041F0010155 +:103A0000ADE71827102694B3A088FDF795FC009029 +:103A10000121A08809F00CF85FEA000900D1FFDF5E +:103A2000E868A06099F8000040F0040189F80010EF +:103A300099F80100800708D584F80CB00098007848 +:103A4000232867D92721009852E084F80CA061E070 +:103A500015270F265CB1A088FDF76EFC8146062273 +:103A6000E868009907F096F984F80EB086E042E025 +:103A700048463DE016270926ECB3287B207249E032 +:103A8000287B19270E26B4B3C4F808A0A4F80CA00C +:103A9000012807D0022808D003280CD004280AD017 +:103AA000FFDF15E084F808B001E002202072607AA0 +:103AB00020F003000BE0697B042801F00F0141F0C6 +:103AC00080012172F3D1607A20F00300401C607203 +:103AD000A088FDF731FC0546007821281AD023285C +:103AE00000D0FFDF0121A08808F0B4FF2221284682 +:103AF000FDF754FC0EE0FFE7A8F800600FE00CB102 +:103B00006888A080287A032822D0042809D00528B4 +:103B10003AD0FFDFA8F800600CB127806680002053 +:103B200009E415270F26002CE6D0A088FDF704FC39 +:103B30000121A08808F07CFF050000D1FFDFD5F847 +:103B40001D000622009907F025F984F80EA0E1E790 +:103B500017270926002CCFD0A088FDF7EDFB814662 +:103B60000121A08808F064FF050000D1FFDF68781C +:103B7000800701D5022000E00120207299F80000A2 +:103B80002328C7D9272173E719270E26002CB3D085 +:103B9000A088FDF7D1FB5FEA000900D1FFDFC4F880 +:103BA00008A0A4F80CA084F808A0A07A40F00300B4 +:103BB000A07299F81F1061F38200A07299F81F108B +:103BC000C1F34002114205D099F8201001F01F0105 +:103BD000102926D020F00800A07299F81F00410893 +:103BE000607A61F3C3006072697A01F00301012910 +:103BF00090D140F004006072E97A207B61F300000C +:103C00002073AA7A617B62F300016173EA7A520839 +:103C100062F341002073A87A400860F341016173A8 +:103C200078E740F00800D7E710B5F94C30B101460D +:103C3000102204F1200013F085FA012084F83000EE +:103C400010BD10B5044600F0A6FCF1492046102234 +:103C5000BDE81040203113F075BA70B5EC4D060088 +:103C60004FF0000412D00CF0B7FB08B110240BE0A9 +:103C70000621304607F075F8411C04D02866012063 +:103C800085F85C0000E00724204670BD0020F7E7BF +:103C9000007810F00F0204D0012A05D0022A0CD1BE +:103CA00010E0000909D10AE00009012807D0022824 +:103CB00005D0032803D0042801D0072070470870DE +:103CC000002070470620704705282AD2DFE800F060 +:103CD00003070F171F00087820F0FF001EE0087888 +:103CE00020F00F00401C20F0F000103016E00878A3 +:103CF00020F00F00401C20F0F00020300EE008788B +:103D000020F00F00401C20F0F000303006E0087872 +:103D100020F00F00401C20F0F00040300870002020 +:103D20007047072070472DE9F043804687B00D4665 +:103D30004FF0000908460CF09CFBA8B94046FDF77F +:103D4000FBFA060003D0307822280BD104E043F2BE +:103D5000020007B0BDE8F08335B1B07FC10601D4E1 +:103D6000000703D50820F4E71020F2E7F07FC00633 +:103D700001D50D20EDE700270121404608F058FE4F +:103D8000040006D101210022404608F048FE04004C +:103D900005D0694600F00FFC009818B901E0042036 +:103DA000D7E7FFDF00980221E0344170C0F824809B +:103DB0004461078101210171297801F00102017E2E +:103DC00062F3010101762A78520862F382010176DA +:103DD0002A78920862F3C30101762A78D20862F346 +:103DE0000411017624213046FDF7D8FA01A9009884 +:103DF0000AF010FB022801D000B1FFDF4846A8E717 +:103E00002DE9FF4F9046834A0D4699B09A4607CA5E +:103E100015AB4FF0000983E807001998FDF78CFAFD +:103E2000060006D03078262806D008201DB0BDE850 +:103E3000F08F43F20200F9E725B94046FFF7F6F8A4 +:103E40000028F3D10121199808F0F2FD040000D1F7 +:103E5000FFDF852D27D007DCEDB1812D1DD0822D10 +:103E60001DD0832D08D11CE0862D1ED0882D1ED09C +:103E7000892D1ED08A2D1ED00F2020710F281CD016 +:103E800003F0ACFFD8B101208DF82800201D0B9065 +:103E90002079B0B12EE10020EFE70120EDE702200C +:103EA000EBE70320E9E70520E7E70620E5E7082040 +:103EB000E3E70920E1E70A20DFE70720B6E7112062 +:103EC000B4E798F80000D4E91D754208F07F00219E +:103ED00062F30000F07798F80020920862F3410046 +:103EE000F07798F80000C209607862F341006070D2 +:103EF00098F800000209207862F34710207098F8C3 +:103F00000000C208607862F30000607098F8010059 +:103F1000607198F8000000F00102A87862F30100D7 +:103F2000A870F27F62F38200A870F27F520862F3F9 +:103F3000C300A870627862F30410A8702278C0F3FE +:103F4000C00052092A706278C2F340026A7098F881 +:103F50000220EA7069712971B978C1F3C001084083 +:103F60005FEA000B2ED050460CF036FA98BBDAF818 +:103F70000C000CF031FA70BBDAF81C000CF02CFAD3 +:103F800048BBDAF80C00A060DAF81C00E060797831 +:103F9000607801F0010140EA41006070B978C0B278 +:103FA000C1F30011891E084060700020207706F1DF +:103FB00017006061701CA061A87800F00300012860 +:103FC0000AD049E07978607801F00101FD2242EAE7 +:103FD00041010840E1E719E0B87800F0030001284A +:103FE0003AD12A1D691D404600F094FA28793979A2 +:103FF00008408DF84C0069797A7911408DF81810D5 +:10400000084329D050460CF0E7F928B110200DE7FD +:10401000A4010020D87501000AF1100004F5AE7368 +:1040200004F18C028DE80D00002113AB5A462046A6 +:10403000FFF73FF80028EAD104F5B07204F1A403B9 +:10404000CDF800A0CDE90132012106AB5A46204649 +:10405000FFF72FF80028DAD16078800722D4A878FB +:10406000B978C0F38000C1F3800108431AD02978E1 +:1040700015AA387832F811204300DA4002F003091B +:10408000B9F1030F01D14FF00209BBF1000F09D0C4 +:10409000012901D0042905D1012801D0042801D12A +:1040A0004FF00409F07F40F001006BF34100F0771E +:1040B000607881074FF003000CD5A071BBF1000FB1 +:1040C00018D100BF8DF8500014AA3146199800F09D +:1040D0004BFA0FE00221B9F1020F1AD0B9F1010F2A +:1040E00019D0B9F1040F22D00020A071F07F20F088 +:1040F0000100F07725213046FDF750F90AA904F1B7 +:10410000E0000AF06CF910B1022800D0FFDF0020B7 +:104110008CE6A171D6E7A1710D2104F1200013F006 +:10412000B2F8207840F0020020700420CAE7012095 +:10413000A071DFE72DE9F04387B090468946044639 +:104140000025FDF7F9F8070004D03878272804D0B7 +:104150000820FEE543F20200FBE50121204608F0BD +:1041600067FC040000D1FFDFA6795FEA090005D0F3 +:10417000012821D0B9F1020F26D110E0B8F1000FCB +:1041800022D1012E05D0022E05D0032E05D0FFDF4F +:104190002DE00C252BE0012529E0022527E04046F3 +:1041A0000CF01AF9B0B9032E0ED11022414604F1D9 +:1041B0001D0012F0C7FF1AE0012E02D0022E03D11B +:1041C00004E0B8F1000F12D00720C2E540460CF021 +:1041D00003F908B11020BCE5102104F11D0013F013 +:1041E00030F80621404606F0BCFDC4F81D002078DA +:1041F000252140F0020020703846FDF7CFF82078E6 +:10420000C10713D020F00100207002208DF80000BB +:1042100004F11D0002908DF804506946C3300AF085 +:10422000DEF8022803D010B1FFDF00E02577002080 +:104230008FE530B587B00D460446FDF77DF860B1D7 +:104240000121204608F0F4FB04000CD028460CF0B5 +:10425000C3F828B1102007B030BD43F20200FAE7DE +:104260002078400701D40820F5E7294604F13D00F5 +:104270002022054612F066FF207840F010002070E2 +:1042800001070FD520F00800207007208DF80000EE +:10429000694604F1E00001950AF0A1F8022801D076 +:1042A00000B1FFDF0020D6E770B50D460646FDF7EA +:1042B00043F818B10078272817D102E043F2020032 +:1042C00070BD0121304608F0B3FB040000D1FFDFD0 +:1042D000A079022809D16078C00706D02A46214675 +:1042E0003046FEF776FF10B10FE0082070BDB4F83D +:1042F00060000E280BD204F1620102231022081F75 +:1043000008F03BFA012101704570002070BD1120BA +:1043100070BD70B5064614460D4608460CF05CF8B4 +:1043200018B920460CF07EF808B1102070BDA6F533 +:104330007F40FF380ED03046FCF7FEFF38B14178A1 +:1043400022464B08811C1846FDF75AF907E043F254 +:10435000020070BD2046FDF751FD0028F9D1102163 +:10436000E01D0BF014FDE21D294604F1170000F0DA +:1043700032F9002070BD2DE9F04104468AB015469F +:104380000E46002708460CF074F818B928460CF0C1 +:1043900070F818B110200AB0BDE8F0812046FCF793 +:1043A000CBFF5FEA000804D098F80000272810D15E +:1043B00002E043F20200EEE70121204608F038FB5C +:1043C000040000D1FFDF2078400702D56078800725 +:1043D00001D40820DFE7D4E91D01497801B18DB18E +:1043E000407800B176B1ADB1EA1D06A8E16800F0F1 +:1043F000F2F8102206A905F1170012F077FE18B1A5 +:10440000042707E00720C6E71022E91D04F12D006C +:1044100012F098FE2EB11022F11D04F11D0012F0D1 +:1044200091FE2078252140F0020020704046FCF7E4 +:10443000B5FF2078C10715D020F0010020700220C0 +:104440008DF8000004F11D000290103003908DF8EB +:1044500004706946B33009F0C2FF022803D010B1DE +:10446000FFDF00E02777002095E770B50D46064690 +:104470000BB1072070BDFCF75FFF040007D0207868 +:10448000222802D3A07F400604D4082070BD43F246 +:10449000020070BDA5B12946304607F080FB03F04D +:1044A000C8FA297C4A08E17F62F30001E1772A7C9F +:1044B00062F34101E177297C890884F8201004E047 +:1044C000304607F08FFB03F0B4FAA17F21F04001E2 +:1044D000A17770BD70B50D46FCF72EFF040005D026 +:1044E00028460BF09FFF20B1102070BD43F2020060 +:1044F00070BD29462046FEF73DFE002070BD04E059 +:1045000010F8012B0AB100207047491E89B2F7D27A +:104510000120704710B5C4780B7864F300030B706A +:10452000C478640864F341030B70C478A40864F38E +:1045300082030B70C478E40864F3C3030B7003793F +:10454000117863F30001117003795B0863F3410193 +:10455000117003799B0863F3820111700079C00820 +:1045600060F3C301117010BD70B51546064603F027 +:1045700035FC040000D1FFDF207820F00F00801C04 +:1045800020F0F0002030207066802868A060BDE830 +:10459000704003F026BC10B5134C94F8300000288E +:1045A00008D104F12001A1F1100009F05AFF012007 +:1045B00084F8300010BD10B190F8B9202AB10A4833 +:1045C00090F8350018B1002003E0B83001E006484B +:1045D00034300860704708B50023009313460A463C +:1045E00008F021FC08BD0000A4010020F0B5007B0C +:1045F000059F1E4614460D46012800D0FFDF0C2003 +:1046000030803A203880002C08D0287A032806D041 +:10461000287B012800D0FFDF17206081F0BDA8892A +:10462000FBE72DE9F04786B0144691F80C900E9AFE +:104630000D46B9F1010F0BD01021007B2E8A884660 +:10464000052807D0062833D0FFDF06B0BDE8F08785 +:104650000221F2E7E8890C2100EB400001EB400069 +:10466000188033201080002CEFD0E889608100276B +:104670001AE00096688808F1020301AA696900F04F +:1046800085FF06EB0800801C07EB470186B204EBB0 +:104690004102BDF8040090810DF1060140460E3242 +:1046A00009F048FF7F1CBFB26089B842E1D8CCE76F +:1046B00034201080E889B9F1010F11D0122148434C +:1046C0000E301880002CC0D0E88960814846B9F1CE +:1046D000010F00D00220207300270DF1040A1FE013 +:1046E0000621ECE70096688808F1020301AA6969CF +:1046F00000F04CFF06EB0800801C86B2B9F1010FF8 +:1047000012D007EBC70004EB4000BDF80410C181D4 +:1047100010220AF10201103012F014FD7F1CBFB20A +:104720006089B842DED890E707EB470104EB41020D +:10473000BDF80400D0810AF102014046103209F0B0 +:10474000F9FEEBE72DE9F0470E4688B090F80CC073 +:1047500096F80C80378AF5890C20109902F10C0428 +:104760004FF0000ABCF1030F08D0BCF1040F3ED09B +:10477000BCF1070F7DD0FFDF08B067E705EB850CC4 +:1047800000EB4C00188031200880002AF4D0A8F1FA +:10479000060000F0FF09558125E0182101A812F05C +:1047A00072FD00977088434601AA716900F0EEFE21 +:1047B000BDF804002080BDF80600E080BDF80800C8 +:1047C0002081A21C0DF10A01484609F0B3FEB9F19F +:1047D000000F00D018B184F804A0A4F802A007EBE1 +:1047E000080087B20A346D1EADB2D6D2C4E705EB1D +:1047F000850C00EB4C00188032200880002ABBD0CA +:10480000A8F1050000F0FF09558137E00097708896 +:10481000434601AA716900F0B9FE9DF80600BDF893 +:104820000410E1802179420860F3000162F3410144 +:10483000820862F38201C20862F3C301020962F3D3 +:104840000411420962F34511820962F38611217154 +:10485000C0096071BDF80700208122460DF10901F1 +:10486000484609F067FE18B184F802A0A4F800A039 +:1048700000E007E007EB080087B20A346D1EADB216 +:10488000C4D279E7A8F1020084B205FB08F000F178 +:104890000E0CA3F800C035230B80002AA6D055814A +:1048A0009481009783B270880E32716900F06EFEB9 +:1048B00062E72DE9F84F1E460A9D0C4681462AB153 +:1048C000607A00F58070D080E089108199F80C0042 +:1048D0000C274FF000084FF00E0A0D2873D2DFE8C6 +:1048E00000F09E070E1C28303846556A737373001B +:1048F000214648460095FFF779FEBDE8F88F207BFA +:104900009146082802D0032800D0FFDF37803020EE +:104910000AE000BFA9F80A80EFE7207B914604284F +:1049200000D0FFDF378031202880B9F1000FF1D1AE +:10493000E3E7207B9146042800D0FFDF3780322058 +:10494000F2E7207B9146022800D0FFDF378033203A +:10495000EAE7207B1746022800D0FFDF3420A6F8C4 +:1049600000A02880002FC8D0A7F80A80C5E7207BC8 +:104970001746042800D0FFDF3520A6F800A02880C5 +:10498000002FBAD04046A7F80A8012E0207B1746D5 +:10499000052802D0062800D0FFDF10203080362006 +:1049A0002880002FA9D0E0897881A7F80E80B9F877 +:1049B0000E00B881A1E7207B9146072800D0FFDFD9 +:1049C00037803720B0E72AE04FF0120018804FF010 +:1049D00038001700288090D0E0897881A7F80E80F1 +:1049E000A7F8108099F80C000A2805D00B2809D0E8 +:1049F0000C280DD0FFDF80E7207B0A2800D0FFDFE6 +:104A000001200AE0207B0B2800D0FFDF042004E017 +:104A1000207B0C2800D0FFDF052038736DE7FFDF17 +:104A20006BE770B50C460546FCF786FC20B10078B4 +:104A3000222804D2082070BD43F2020070BD052177 +:104A4000284607F0F5FF206008B1002070BD032064 +:104A500070BD30B44880087820F00F00C01C20F0F2 +:104A6000F000903001F8080B1DCA81E81D0030BC31 +:104A700003F0B7B92DE9FF4784B0002782460297BB +:104A8000079890468946123004F0D8F8401D20F06F +:104A90000306079828B907A95046FFF7C2FF002868 +:104AA00053D1B9F1000F05D00798017B19BB05253B +:104AB00004681BE098F80000092803D00D2812D0E4 +:104AC000FFDF45E0079903254868B0B3497B42887A +:104AD0007143914238D98AB2B3B2011D07F039FE51 +:104AE0000446078002E0079C042508340CB12088A6 +:104AF00010B1032D28D02BE007980121123004F0CB +:104B0000CFF8ADF80C00024602AB2946504606F03D +:104B1000BBF9070001D1A01C029007983A46123059 +:104B2000C8F80400A8F802A003A94046029B04F0BC +:104B3000C4F8C0B1072814D200E005E0DFE800F0B7 +:104B4000060811110F0A0C00132015E6002013E6C9 +:104B5000112011E608200FE643F203000CE60720BF +:104B60000AE6032008E6BDF80C002346CDE90070F4 +:104B70002A465046079900F019FD57B9032D08D170 +:104B80000798B3B2417B406871438AB2011D07F0B8 +:104B9000F4FDB9F1000FD9D0079981F80C90D5E751 +:104BA0002DE9FE4F91461A881C468A468046FAB186 +:104BB00002AB494606F068F9050019D04046A61C2C +:104BC000278808F079F83246072629463B460096A2 +:104BD00007F0A5FC20882346CDE900504A465146FF +:104BE000404600F0E3FC002020800120BDE8FE8F5D +:104BF0000020FBE710B586B01C46AAB104238DF84F +:104C000000301388ADF808305288ADF80A208A7851 +:104C10008DF80E200988ADF80C1000236A46214655 +:104C2000FFF728FF06B010BD1020FBE770B50D465A +:104C3000052107F0FDFE040000D1FFDF294604F145 +:104C40001200BDE8704004F014B82DE9F8430D4699 +:104C50008046002603F0C2F804462878102878D24F +:104C6000DFE800F0773B3453313112313131083114 +:104C7000313131312879001FC0B2022801D010280B +:104C800010D114BBFFDF35E004B9FFDF052140463A +:104C900007F0CEFE007B032806D004280BD007289F +:104CA00028D0FFDF072655E02879801FC0B20228F0 +:104CB00020D050B1F6E72879401FC0B2022819D0A1 +:104CC000102817D0EEE704B9FFDF13E004B9FFDFC7 +:104CD000287901280ED1172137E00521404607F039 +:104CE000A7FE070000D1FFDF07F11201404603F0E5 +:104CF0009DFF2CB12A4621464046FFF7AAFE29E037 +:104D000013214046FDF7B3FB24E004B9FFDF052182 +:104D1000404607F08DFE060000D1FFDF694606F130 +:104D2000120003F08DFF060000D0FFDFA9881729CD +:104D300001D2172200E00A46BDF80000824202D9E3 +:104D4000014602E005E01729C5D3404600F03EFCCD +:104D5000D0E7FFDF3046BDE8F883401D20F00302B6 +:104D600019B102FB01F0001D00E000201044704763 +:104D700013B5009850B100244FEA0D0007F093FCE2 +:104D8000002C02D1F74A009911601CBD01240020BB +:104D9000F4E72DE9F0470C4615462421204612F091 +:104DA00072FA05B9FFDFA87860732888DFF8B4A32A +:104DB000401D20F00301AF788946DAF8000007F0C3 +:104DC00090FC060000D1FFDF4FF000082660A6F837 +:104DD000008077B109FB07F1091D0AD0DAF800005D +:104DE00007F07FFC060000D1FFDF6660C6F8008098 +:104DF00001E0C4F80480298804F11200BDE8F047FE +:104E000003F006BF2DE9F047804601F112000D4680 +:104E1000814603F013FF401DD24F20F003026E7B4A +:104E200014462968386807F087FC3EB104FB06F297 +:104E3000121D03D06968386807F07EFC052007F072 +:104E4000A3FD0446052007F0A7FD201A012802D182 +:104E5000386807F03BFC49464046BDE8F04703F0A0 +:104E6000ECBE70B50546052107F0E2FD040000D157 +:104E7000FFDF04F112012846BDE8704003F0D6BE02 +:104E80002DE9F04F91B04FF0000BADF834B0ADF814 +:104E900004B047880C46054692460521384607F07F +:104EA000C7FD060000D1FFDF24B1A780A4F806B03B +:104EB000A4F808B0297809220B20B2EB111F7DD18C +:104EC0002A7A04F1100138274FF00C084FF001093D +:104ED0000391102A73D2DFE802F072F2F1F07F083A +:104EE000D2888D9F3DDBF3EEB6B6307B022800D032 +:104EF000FFDFA88908EBC001ADF804103021ADF840 +:104F00003410002C25D06081B5F80E9000271DE0EC +:104F100004EBC708317C88F80E10F189A8F80C1052 +:104F2000CDF800906888042304AA296900F02EFBBC +:104F3000BDF81010A8F8101009F10400BDF8121007 +:104F40007F1C1FFA80F9A8F81210BFB26089B8421E +:104F5000DED80DE1307B022800D0FFDFE98908EBC5 +:104F6000C100ADF804003020ADF83400287B0A9071 +:104F7000001FC0B20F90002CEBD06181B5F81090EB +:104F8000002725E0CDF800906888696903AA0A9B8C +:104F900000F0FCFA0A9804EBC70848441FFA80F9AD +:104FA00008F10C0204A90F9809F0C4FA18B188F8A6 +:104FB0000EB0A8F80CB0BDF80C1001E0D4E0CFE0C2 +:104FC000A8F81010BDF80E107F1CA8F81210BFB280 +:104FD0006089B842D6D8CBE00DA8009001AB22463C +:104FE00029463046FFF71DFBC2E0307B082805D07C +:104FF000FFDF03E0307B082800D0FFDFE8891030B6 +:10500000ADF804003620ADF83400002C3FD0A9895B +:105010006181F189A18127E0307B092800D0FFDF81 +:10502000A88900F10C01ADF804103721ADF8341057 +:10503000002C2CD06081E8890090AB89688804F14D +:105040000C02296956E0E8893921103080B2ADF8A8 +:105050000400ADF83410002C74D0A9896181287A3D +:105060000E280AD002212173E989E181288A009063 +:10507000EB8968886969039A3CE00121F3E70DA890 +:10508000009001AB224629463046FFF75BFB6FE0FC +:10509000307B0A2800D0FFDF1220ADF80400ADF805 +:1050A00034704CB3A9896181A4F810B0A4F80EB093 +:1050B00084F80C905CE020E002E031E039E042E06E +:1050C000307B0B2800D0FFDF288AADF83470123017 +:1050D000ADF8040084B104212173A9896181E989B3 +:1050E000E181298A2182688A00902B8A688804F1EC +:1050F0001202696900F04AFA3AE0307B0C2800D0CD +:10510000FFDF1220ADF80400ADF834703CB3052188 +:105110002173A4F80AB0A4F80EB0A4F810B027E0E8 +:105120000DA8009001AB224629463046FFF75EFAF3 +:105130001EE00DA8009001AB224629463046FFF73D +:10514000B8FB15E036E03B21ADF80400ADF83410B3 +:1051500084B3A4F80690A4F808B084F80AB007E075 +:10516000FFDF05E010000020297A012919D0FFDFB8 +:10517000BDF80400AAF800007CB1BDF8340020801E +:10518000BDF804006080BDF83400392805D03B2804 +:1051900003D03C2801D086F80CB011B00020BDE847 +:1051A000F08F3C21ADF80400ADF8341014B1697AE9 +:1051B000A172DDE7FFE7AAF80000EEE72DE9F8436A +:1051C00056880F46804615460521304607F030FCCC +:1051D000040000D1FFDF123400943B4641463046C4 +:1051E0006A6803F09CFEB6E570B50D46052107F030 +:1051F0001FFC040000D1FFDF294604F11200BDE8C6 +:10520000704003F028BD70B50D46052107F010FC75 +:10521000040000D1FFDF294604F11200BDE8704010 +:1052200003F046BD70B50546052107F001FC0400FA +:1052300000D1FFDF04F1080321462846BDE8704095 +:105240000422ADE470B50546052107F0F1FB04002A +:1052500000D1FFDF214628462368BDE870400522C3 +:105260009EE470B50646052107F0E2FB040000D17C +:10527000FFDF04F1120003F0E1FC401D20F0030504 +:1052800011E0011D00880322431821463046FFF734 +:1052900087FC00280BD0607BABB2684382B26068A9 +:1052A000011D07F0A0FA606841880029E9D170BDAE +:1052B00070B50E46054602F091FD040000D1FFDFF7 +:1052C0000120207266726580207820F00F00C01CDB +:1052D00020F0F00030302070BDE8704002F081BD59 +:1052E0002DE9F0438BB00D461446814606A9FFF721 +:1052F00098FB002814D14FF6FF7601274FF4205871 +:105300008CB103208DF800001020ADF8100007A824 +:10531000059007AA204604A909F02BF978B10720C7 +:105320000BB0BDE8F0830820ADF808508DF80E7082 +:105330008DF80000ADF80A60ADF80C800CE006981E +:10534000A17801742188C1818DF80E70ADF80850E4 +:10535000ADF80C80ADF80A606A4602214846069B0B +:10536000FFF788FBDCE708B501228DF8022042F642 +:105370000202ADF800200A4603236946FFF73AFC13 +:1053800008BD08B501228DF8022042F60302ADF8EF +:1053900000200A4604236946FFF72CFC08BD00B52F +:1053A00087B079B102228DF800200A88ADF8082074 +:1053B0004988ADF80A1000236A460521FFF75AFB19 +:1053C00007B000BD1020FBE709B1072312E4072056 +:1053D000704770B588B00D461446064606A9FFF71B +:1053E00020FB00280ED17CB10620ADF808508DF8C6 +:1053F0000000ADF80A40069B6A460821DC81304671 +:10540000FFF738FB08B070BD05208DF80000ADF83F +:105410000850F0E700B587B059B107238DF8003088 +:10542000ADF80820039100236A460921FFF722FB0B +:10543000C6E71020C4E770B588B00C4606460025C4 +:1054400006A9FFF7EEFA0028DCD1069801211230F8 +:1054500003F026FC9CB12178062921D2DFE801F077 +:10546000200505160318801E80B2C01EE28880B297 +:105470000AB1A3681BB1824203D90C20C2E71020F5 +:10548000C0E7042904D0A08850B901E00620B9E79C +:10549000012913D0022905D004291CD005292AD0BE +:1054A0000720AFE709208DF800006088ADF80800FC +:1054B000E088ADF80A00A068039023E00A208DF888 +:1054C00000006088ADF80800E088ADF80A00A06828 +:1054D0000A25039016E00B208DF800006088ADF8D7 +:1054E0000800A088ADF80A00E088ADF80C00A068BC +:1054F0000B25049006E00C208DF8000060788DF8F4 +:1055000008000C256A4629463046069BFFF7B2FA8A +:1055100078E700B587B00D228DF80020ADF80810AF +:1055200000236A461946FFF7A5FA49E700B587B098 +:1055300071B102228DF800200A88ADF80820498850 +:10554000ADF80A1000236A460621FFF793FA37E701 +:10555000102035E770B586B0064601200D46ADF83F +:1055600008108DF80000014600236A463046FFF718 +:1055700081FA040008D12946304601F0BDFA002125 +:10558000304601F0D7FA204606B070BDF8B51C468B +:1055900015460E46069F07F07DFB2346FF1DBCB255 +:1055A00031462A46009406F086FFF8BD30B4114615 +:1055B000DDE902423CB1032903D0002330BC05F0F1 +:1055C00099BD0123FAE71A8030BC704770B50C46CC +:1055D0000546FFF72BFB2146284601F09CFA28469A +:1055E000BDE87040012101F0A5BA000018B1817832 +:1055F000012938D101E010207047018842F60112DC +:10560000881A914231D018DC42F60102A1EB020067 +:1056100091422AD00CDC41B3B1F5C05F25D06FF4C4 +:10562000C050081821D0A0F57060FF381BD11CE0D5 +:1056300001281AD002280AD117E0B0F5807F14D0D3 +:1056400008DC012811D002280FD003280DD0FF2834 +:1056500009D10AE0B0F5817F07D0A0F5807003384A +:1056600003D0012801D0002070470F2070470A287E +:105670001ED007DC18D2DFE800F0191B1F1F171F10 +:10568000231D1F21102815D008DC0B2812D00C2850 +:1056900010D00D2816D00F2806D10DE011280BD000 +:1056A00084280BD087280FD0032070470020704734 +:1056B00005207047072070470F207047042070476F +:1056C000062070470C20704743F20200704738B53F +:1056D0000C46050041D06946FEF7DAFA002819D1D8 +:1056E0009DF80010607861F3020060706946681CE4 +:1056F000FEF7CEFA00280DD19DF80010607861F316 +:10570000C5006070A978C1F34101012903D00229C5 +:1057100005D0072038BD217821F0200102E0217852 +:1057200041F020012170410704D0A978C90861F334 +:1057300086106070607810F0380F07D0A9780909DA +:1057400061F3C710607010F0380F02D16078400626 +:1057500003D5207840F040002070002038BD70B59F +:1057600004460020088015466068FFF7B0FF002857 +:1057700016D12089A189884211D860688078C00735 +:105780000AD0B1F5007F0AD840F20120B1FBF0F257 +:1057900000FB1210288007E0B1F5FF7F01D90C2033 +:1057A00070BD01F201212980002070BD10B5047880 +:1057B000137864F3000313700478640864F34103FE +:1057C00013700478A40864F3820313700478E40867 +:1057D00064F3C30313700478240964F3041313708F +:1057E0000478640964F3451313700078800960F34A +:1057F0008613137031B10878C10701D1800701D534 +:10580000012000E0002060F3C713137010BD427840 +:10581000530702D002F0070306E012F0380F02D05F +:10582000C2F3C20300E001234A7863F302024A7024 +:10583000407810F0380F02D0C0F3C20005E04307F3 +:1058400002D000F0070000E0012060F3C5024A70BA +:1058500070472DE9F04F95B00D00824612D012210D +:10586000284611F0EEFC4FF6FF7B05AA01215846B1 +:1058700005F0B7F80024264637464FF420586FF459 +:10588000205972E0102015B0BDE8F08F9DF81E0081 +:1058900001280AD1BDF81C1041450BD011EB0900BD +:1058A0000AD001280CD002280CD0042C0ED0052CD4 +:1058B0000FD10DE0012400E00224BDF81A6008E0D9 +:1058C000032406E00424BDF81A7002E0052400E079 +:1058D0000624BDF81A10514547D12C74BEB34FF0C1 +:1058E000000810AA4FF0070ACDE90282CDE900A80E +:1058F0000DF13C091023CDF8109042463146584630 +:1059000005F022F908BBBDF83C002A46C0B210A938 +:1059100008F010FEC8B9AE81CFB1CDE900A80DF1F5 +:10592000080C0AAE40468CE8410213230022394697 +:10593000584605F009F940B9BDF83C00F11CC01EFD +:10594000C0B22A1D08F0F6FD10B103209BE70AE063 +:10595000BDF82900E881062C05D19DF81E00A8722B +:10596000BDF81C00288100208DE705A805F045F84A +:1059700000288BD0FFF77BFE85E72DE9F0471C461A +:10598000DDE90978DDF8209015460E00824600D149 +:10599000FFDF0CB1208818B1D5B11120BDE8F08728 +:1059A000022D01D0012100E0002106F1140003F0D6 +:1059B00009FFA8F8000002463B462946504605F07C +:1059C00063FAC9F8000008B9A41C3C600020E5E7B0 +:1059D0001320E3E7F0B41446DDE904528DB100234F +:1059E00014B1022C09D101E0012306E00D7CEE0781 +:1059F00003D025F0010501230D742146F0BC05F00C +:105A000079BB1A80F0BC70472DE9FE4F91461A8889 +:105A10001C468A468046FAB102AB494605F034FA84 +:105A2000050019D04046A61C278807F045F93246E4 +:105A3000072629463B46009606F071FD208823463E +:105A4000CDE900504A4651464046FFF7C3FF0020CB +:105A500020800120BDE8FE8F0020FBE72DE9F04704 +:105A600086B09146DDE90E460F46824603AA05A997 +:105A700004A8109D8DE807009846324621465046FE +:105A8000FFF77BFF049909B1012200E000222A7090 +:105A9000002817D1F84A03AB1060059A009104F171 +:105AA0001400CDE901204A463946504604F041FA37 +:105AB00090B108280ED2DFE800F00407040D0D09AC +:105AC0000B0B002006B069E71120FBE70720F9E780 +:105AD0000820F7E70320F5E7BDF80C100498CDE99E +:105AE00000014346324621465046FFF773FFE8E780 +:105AF0002DE9F04389B00D46DDE9108781461C464B +:105B00001646142103A811F0BEFB012002218DF8D6 +:105B100010108DF80C008DF81170ADF8146064B1A0 +:105B2000A278D20709D08DF81600E088ADF81A00E7 +:105B3000A088ADF81800A068079008A80095CDE9E6 +:105B40000110424603A948466B68FFF787FF09B07A +:105B5000BDE8F083F0B58BB00024064606940794A8 +:105B60000727089405A80994019400970294CDE9A9 +:105B700003400D4610232246304604F0E5FF78B975 +:105B80000AA806A9019400970294CDE90310BDF874 +:105B9000143000222946304604F0ACFD002801D024 +:105BA000FFF765FD0BB0F0BD04F04CBC2DE9FC41E6 +:105BB0000C468046002602F011F9054620780D2893 +:105BC0007ED2DFE800F0BC0713B325BD49496383EB +:105BD000AF959B00A848006820B1417841F01001C2 +:105BE0004170ADE0404602F029F9A9E004214046A9 +:105BF00006F01EFF070000D1FFDF07F11401404649 +:105C000003F074FDA5BB13214046FCF730FC97E080 +:105C10000421404606F00CFF070000D1FFDFE088BA +:105C2000ADF800000020B8819DF80000010704D500 +:105C3000C00602D5A088B88105E09DF801004006A5 +:105C40007ED5A088F88105B9FFDF22462946404667 +:105C500001F066FC022673E0E188ADF800109DF8C3 +:105C6000011009060FD5072803D006280AD00AE03C +:105C700024E00421404606F0DBFE060000D1FFDFF1 +:105C8000A088F0810226CDB9FFDF17E0042140464D +:105C900006F0CEFE070000D1FFDF07F1140004F08C +:105CA00008FC90F0010F02D1E079000648D5387C5D +:105CB000022640F00200387405B9FFDF224600E0FA +:105CC0003DE02946404601F02BFC39E004214046E6 +:105CD00006F0AEFE017C002D01F00206C1F340018A +:105CE0006171017C21F002010174E7D1FFDFE5E77A +:105CF00002260121404602F0D3F821E0042140466B +:105D000006F096FE0546606800902089ADF8040014 +:105D100001226946404602F0E4F8287C20F00200A7 +:105D200028740DE0002DC9D1FFDFC7E7022600214E +:105D30004046FFF768FA002DC0D1FFDFBEE7FFDF66 +:105D40003046BDE8FC813EB50C0009D001466B46EB +:105D500001AA002004F07AFF20B1FFF788FC3EBDC5 +:105D600010203EBD00202080A0709DF8050002A9F3 +:105D700000F00700FDF7A8FF50B99DF8080020705B +:105D80009DF8050002A9C0F3C200FDF79DFF08B110 +:105D900003203EBD9DF8080060709DF80500C10914 +:105DA000A07861F30410A0709DF80510890961F3D3 +:105DB000C300A0709DF80410890601D5022100E0FF +:105DC000012161F342009DF8001061F30000A07012 +:105DD00000203EBD70B5144606460D4651EA04004B +:105DE00005D075B108460AF03BFB78B901E0072001 +:105DF00070BD2946304604F08AFF10B1BDE87040FE +:105E000035E454B120460AF02BFB08B1102070BDD8 +:105E100021463046BDE8704095E7002070BD2DE971 +:105E2000FC5F0C4690460546002701780822007A60 +:105E30003E46B2EB111F7DD104F10A0100910A31F7 +:105E4000821E4FF0020A04F1080B0191092A72D256 +:105E5000DFE802F0EDE005F528287BAACE0068888F +:105E6000042106F0E5FD060000D1FFDFB08928B16E +:105E700052270726C3E00000080200205127102601 +:105E8000002C7DD06888A0800120A071A889002204 +:105E90000099FFF79FFF002873D1A8892081288AE5 +:105EA000E081D1E0B5F81290072824D1E87B000604 +:105EB00021D5512709F1140086B2002CE1D0A88920 +:105EC00000220099FFF786FF00285AD16888A08039 +:105ED00084F806A0A88920810120A073288A208246 +:105EE000A4F81290A88A009068884B46A969019A84 +:105EF00001F0F3FAA8E0502709F1120086B2002C55 +:105F00003ED0A88900225946FFF764FF002838D107 +:105F10006888A080A889E080287A072813D002200A +:105F20002073288AE081E87BC0096073A4F8109090 +:105F3000A88A01E085E082E0009068884B4604F181 +:105F40001202A969D4E70120EAE7B5F812905127B7 +:105F500009F1140086B2002C66D06888042106F08E +:105F600067FD83466888A080A88900220099FFF712 +:105F700031FF00286ED184F806A0A889208101E0B5 +:105F800052E067E00420A073288A2082A4F81290CF +:105F9000A88A009068884B46A969019A01F09DFA89 +:105FA000A989ABF80E104FE06888FBF7C5F90746E2 +:105FB0006888042106F03CFD064607B9FFDF06B9F4 +:105FC000FFDF687BC00702D05127142601E050276D +:105FD00012264CB36888A080502F06D084F806A003 +:105FE000287B594601F089FA2EE0287BA11DF9E7AC +:105FF000FE49A8894989814205D1542706269CB1CA +:106000006888A08020E053270BE06888A080A889DA +:10601000E08019E06888042106F00AFD00B9FFDF7E +:1060200055270826002CF0D1A8F8006011E056276B +:106030000726002CF8D06888A080002013E0FFDF3E +:1060400002E0012808D0FFDFA8F800600CB127802B +:1060500066800020BDE8FC9F57270726002CE3D070 +:106060006888A080687AA071EEE7401D20F00300E8 +:1060700009B14143091D01EB4000704713B5DB4AEC +:1060800000201071009848B10024684606F00BFB10 +:10609000002C02D1D64A009911601CBD01240020B9 +:1060A000F4E770B50D46064686B014465C212846D6 +:1060B00011F0E9F804B9FFDFA0786874A2782188AC +:1060C000284601F044FA0020A881E881228805F1E1 +:1060D0001401304603F0EFFA6A460121304604F01D +:1060E00080FC19E09DF80300000715D5BDF80610E7 +:1060F0003046FFF72FFD9DF80300BDF8061040F075 +:1061000010008DF80300BDF80300ADF81400FF2364 +:106110003046059A04F0C6FD684604F06EFC00287F +:10612000E0D006B070BD10B50C4601F1140003F0CC +:10613000F9FA0146627C2046BDE8104001F03CBA05 +:1061400070B50546042106F073FC040000D1FFDFA2 +:1061500004F114010C46284603F0C8FA21462846EB +:10616000BDE8704003F0C9BA70B58AB00C46064667 +:10617000FBF7E2F8050014D02878222827D30CB1C9 +:10618000A08890B101208DF80C0003208DF810003C +:1061900000208DF8110054B1A088ADF818002068D7 +:1061A00007E043F202000AB070BD0920FBE7ADF83A +:1061B000180005900421304606F03AFC040000D196 +:1061C000FFDF04F1140003F0C4FA000701D4082033 +:1061D000E9E701F003FE60B108A802210094CDE9CF +:1061E000011095F8232003A930466368FFF736FCB9 +:1061F000D9E71120D7E72DE9F04FB2F802A0834686 +:1062000089B0154689465046FBF796F807460421A3 +:10621000504606F00DFC0026044605964FF0020895 +:106220000696ADF81C6007B9FFDF04B9FFDF4146F1 +:10623000504605F0DEF860B907AA06A905A88DE862 +:1062400007004246214650466368FFF796FB00B1BF +:10625000FFDF664807AB0660DDE9051204F11400B4 +:10626000CDF80090CDE90320CDE9013197F8232046 +:10627000594650466B6803F0B5FA06000AD0022E64 +:1062800004D0032E14D0042E00D0FFDF09B0304616 +:10629000BDE8F08FBDF81C000028F7D00599CDE9C6 +:1062A00000104246214650466368FFF793FBEDE736 +:1062B000687840F008006870E8E72DE9F04F9BB07F +:1062C00004464FF000084948ADF85480ADF83080DE +:1062D000ADF85080A0F80880ADF81480ADF81880B3 +:1062E000ADF82080ADF81C80007916460D46474673 +:1062F000012808D0022806D0032804D0042802D0A0 +:1063000008201BB0C4E720460AF066F8D0BB284638 +:106310000AF062F8B0BB60680AF0ABF890BB606846 +:1063200048B160892189884202D8B1F5007F01D93E +:106330000C20E6E780460BAA06A92846FFF70FFACD +:106340000028DED168688078C0F34100022808D1B7 +:106350009DF8190010F0380F03D028690AF080F872 +:1063600080B905A92069FFF7B2F90028C9D12069D1 +:1063700050B1607880079DF8150000F0380002D514 +:10638000C0B301E011E0A8BB9DF8140080060ED553 +:106390009DF8150010F0380F03D060680AF060F81F +:1063A00018B960680AF065F808B11020A9E707A9D4 +:1063B0006069FFF78CF90028A3D1606940B19DF8AE +:1063C0001D0000F0070101293FD110F0380F3CD02B +:1063D00008A9A069FFF77BF9002892D19DF81C005D +:1063E000800632D49DF82000800604E008020020D8 +:1063F0001400002029E028D4A06940B19DF82100B4 +:1064000000F00701012920D110F0380F1DD0E068FD +:1064100018B10078C8B11C2817D20EAA611C2046FA +:10642000FFF7C4F90120B94660F30F27BA460746C3 +:106430008DF84E0042F60300ADF84C000DF13B0222 +:1064400017A9286808F095F808B1072059E79DF8C2 +:106450005C0016A9CDF80090C01CCDE9019100F0B8 +:10646000FF0B00230BF20122514613A804F0FCF9A4 +:10647000F0BBBDF858000990FE482A8929690092AE +:10648000CDE901106B89BDF82C202868069904F02D +:10649000EBF901007ED120784FF0020AC10601D449 +:1064A00080062BD5ADF80C90606950B907A906A8F5 +:1064B000FFF7ADF99DF81D0020F00700401C8DF896 +:1064C0001D009DF81C008DF84E7040F0C8008DF83E +:1064D0001C0042F60210ADF84C000CA903AACDF83E +:1064E00000A0CDE90121002340F2032213A800E01F +:1064F0001EE0079904F0B8F901004BD1DD484D4684 +:1065000008385B460089ADF839000EA8CDE9029045 +:10651000CDF80490CDF810904FF007090022CDF887 +:106520000090BDF858104FF6FF7004F0E3F810B17A +:10653000FFF79DF8E5E69DF83800000625D52946C9 +:10654000012060F30F218DF84E704FF42450ADF808 +:106550004C00ADF8105062789DF81000002362F3F3 +:1065600000008DF810006278CDF800A0520862F3A8 +:1065700041008DF8100004AACDE9012540F2032264 +:1065800013A804F071F9010004D1606888B3206990 +:10659000A8B900E086E005A906A8FFF738F96078F9 +:1065A000800706D49DF8150020F038008DF81500FE +:1065B00005E09DF8140040F040008DF814008DF8BF +:1065C0004E7042F60110ADF84C00208940F20121D6 +:1065D000B0FBF1F201FB1202606814ABCDF8008051 +:1065E000CDE90103002313A8059904F03DF901004A +:1065F00058D12078C00729D0ADF80C50A06950B907 +:1066000008A906A8FFF703F99DF8210020F007006C +:10661000401C8DF821009DF820008DF84E7040F050 +:1066200040008DF8200042F60310ADF84C0015A98B +:1066300003AACDF800A0CDE90121002340F20322F6 +:1066400013A8089904F010F901002BD1E06868B391 +:106650002946012060F30F218DF84E7042F6041098 +:10666000ADF84C00E068002302788DF86020407897 +:106670008DF86100E06818AA4088ADF86200E06813 +:1066800000798DF86400E068C088ADF86500CDF849 +:106690000090CDE901254FF4027213A804F0E4F84C +:1066A000010003D0099800F0B3FF2AE671480321E6 +:1066B0000838017156B100893080BDF850007080F3 +:1066C000BDF83000B080BDF85400F080002018E61E +:1066D00070B501258AB016460B46012802D0022863 +:1066E00016D104E08DF80E504FF4205003E08DF8E1 +:1066F0000E5042F60100ADF80C005BB10024601CA6 +:1067000060F30F2404AA08A9184607F032FF18B155 +:10671000072048E5102046E504A99DF820205548AB +:10672000CDE90021801E02900023214603A802F239 +:10673000012204F099F810B1FEF799FF33E54D48B6 +:1067400008380EB1C1883180057100202BE5F0B505 +:1067500093B0074601268DF83E6041F60100ADF882 +:106760003C0012AA0FA93046FFF7B2FF002848D11B +:10677000404C0025083CE7B31C2102A810F083FD23 +:106780009DF808008DF83E6040F020008DF808006C +:1067900042F60520ADF83C000E959DF83A001195A3 +:1067A00020F00600801C8DF83A009DF838006A46FB +:1067B00020F0FF008DF838009DF8390009A920F07D +:1067C000FF008DF839000420ADF82C00ADF8300042 +:1067D0000EA80A9011A80D900FA80990ADF82E50A0 +:1067E00002A8FFF76AFD00280BD1BDF80000608108 +:1067F00000E008E0BDF80400A081401CE0812571A4 +:10680000002013B0F0BD6581A581BDF84800F4E714 +:106810002DE9F74F1749A0B00024083917940A79D9 +:10682000A146012A04D0022A02D0082023B02FE575 +:10683000CA88824201D00620F8E721988A4682421F +:1068400001D10720F2E701202146ADF848004FF6BC +:10685000FF7860F30F21ADF84A808DF86E0042F6A4 +:10686000020B06918DF87240ADF86CB0ADF8704037 +:106870001CA901E0100200201391ADF8508012A86D +:1068800004F0DFF800252E462F460DAB072212A993 +:10689000404604F0D9F878B10A285DD195B38EB39B +:1068A000ADF86450ADF866609DF85E008DF8144058 +:1068B00019AC012864D06BE09DF83A001FB30128A1 +:1068C00059D1BDF8381059451FD118A809A901940C +:1068D0000294CDE9031007200090BDF83610102374 +:1068E0000022404604F030F9B0BBBDF86000042837 +:1068F00001D006284AD1BDF82410219881423AD10E +:106900000F2093E73AE0012835D1BDF83800B0F503 +:10691000205F03D042F6010188422CD1BAF806006C +:10692000BDF83610884201D1012700E0002705B1EB +:106930009EB1219881421ED118A809AA01940294FF +:10694000CDE90320072000900D4610230022404689 +:1069500004F0FAF800B902E02DE04E460BE0BDF875 +:106960006000022801D0102810D1C0B217AA09A9CE +:1069700007F0E0FD50B9BDF8369086E7052055E7F1 +:1069800005A917A8221D07F0F4FD08B103204DE763 +:106990009DF814000023001DC2B28DF81420229827 +:1069A0000092CDE901401BA8069903F05DFF10B9E4 +:1069B00002228AF80420FEF75AFE37E710B50B468C +:1069C000401E88B084B205AA00211846FEF7EEFEEC +:1069D00000200DF1080C06AA05A901908CE807001B +:1069E000072000900123002221464FF6FF7003F09C +:1069F00081FE0446BDF81800012800D0FFDF2046C4 +:106A0000FEF735FE08B010BDF0B5FF4F044687B065 +:106A100038790E46032804D0042802D0082007B095 +:106A2000F0BD04AA03A92046FEF799FE0500F6D1A1 +:106A300060688078C0F3410002280AD19DF80D00FB +:106A400010F0380F05D0206909F00AFD08B11020B8 +:106A5000E5E7208905AA21698DE807006389BDF86B +:106A600010202068039903F0FFFE10B1FEF7FFFD30 +:106A7000D5E716B1BDF814003080042038712846DF +:106A8000CDE7F8B50C0006460BD001464FF6FF7572 +:106A900000236A46284604F0D9F820B1FEF7E7FD46 +:106AA000F8BD1020F8BD69462046FEF710FE00280C +:106AB000F8D1A078314600F001032846009A04F08E +:106AC000F1F8EBE730B587B0144600220DF1080C61 +:106AD00005AD01928CE82C00072200920A4601467F +:106AE00023884FF6FF7003F005FEBDF814102180D7 +:106AF000FEF7BDFD07B030BD70B50D46042105F0B1 +:106B000097FF040000D1FFDF294604F11400BDE81F +:106B1000704002F017BE70B50D46042105F088FFE5 +:106B2000040000D1FFDF294604F11400BDE87040E5 +:106B300002F02BBE70B50D46042105F079FF04006C +:106B400000D1FFDF294604F11400BDE8704002F0D7 +:106B500043BE70B50546042105F06AFF040000D16C +:106B6000FFDF214628462368BDE870400122FEF77A +:106B70004BBF70B50646042105F05AFF040000D152 +:106B8000FFDF04F1140002F0CDFD401D20F00305ED +:106B900011E0011D00880022431821463046FEF70F +:106BA00033FF00280BD0607CABB2684382B2A06890 +:106BB000011D05F018FEA06841880029E9D170BDCB +:106BC00070B50546042105F033FF040000D1FFDF56 +:106BD000214628466368BDE870400222FEF714BFD4 +:106BE00070B50E46054601F0F9F8040000D1FFDF4C +:106BF0000120207266726580207820F00F00001D51 +:106C000020F0F00040302070BDE8704001F0E9B89D +:106C100010B50446012900D0FFDF2046BDE8104032 +:106C20000121FEF7F0BA2DE9F04F97B04FF0000ABE +:106C30000C008346ADF814A0D04619D0E06830B1FE +:106C4000A068A8B10188ADF81410A0F800A05846BB +:106C5000FAF772FB070043F2020961D03878222864 +:106C60005CD30421584605F0E3FE050005D103E09E +:106C7000102017B0BDE8F08FFFDF05F1140002F01F +:106C800051FD401D20F00306A078012803D0022802 +:106C900001D00720EDE7218807AA584603F0A1FE9E +:106CA00030BB07A803F0A9FE10BB07A803F0A5FEA0 +:106CB00048B99DF82600012805D1BDF82400A0F5AB +:106CC0002451023902D04FF45050D2E7E068B0B1FD +:106CD000CDE902A00720009005AACDF804A00492F7 +:106CE000A2882188BDF81430584603F003FD10B186 +:106CF000FEF7BDFCBDE7A168BDF8140008809DF853 +:106D00001F00C00602D543F20140B2E70B9838B12C +:106D1000A1780078012905D080071AD40820A8E7B7 +:106D20004846A6E7C007F9D002208DF83C00A868C5 +:106D30004FF00009A0B1697C4288714391420FD99C +:106D40008AB2B3B2011D05F004FD8046A0F800A090 +:106D500006E003208DF83C00D5F800804FF00109D3 +:106D60009DF8200010F0380F00D1FFDF9DF82000C3 +:106D70002649C0F3C200084497F8231010F8010C0C +:106D8000884201D90F2074E72088ADF8400014A98B +:106D90000095CDE90191434607220FA95846FEF719 +:106DA0005DFE002891D19DF8500050B9A0780128CF +:106DB00007D1687CB3B2704382B2A868011D05F0A8 +:106DC000DCFC002055E770B5064615460C46084623 +:106DD000FEF70CFC002805D12A4621463046BDE8C6 +:106DE000704075E470BD13E570B51E4614460D0085 +:106DF0000ED06CB1616859B160B10349C988814254 +:106E000008D0072070BD000008020020E2750100D4 +:106E10001020F7E72068FEF7E9FB0028F2D13246A0 +:106E200021462846BDE87040FFF747BA70B51546C1 +:106E30000C0006D038B1FE490989814203D00720F1 +:106E4000E0E71020DEE72068FEF7D0FB0028D9D16C +:106E500029462046BDE87040D6E570B5064686B0A6 +:106E60000D461446104609F0DDFAD0BB606809F003 +:106E700000FBB0BBA6F57F40FF3803D03046FAF7E1 +:106E80005BFA80B128466946FEF7E3FC00280CD186 +:106E90009DF810100F2008293CD2DFE801F0080609 +:106EA0000606060A0A0843F2020006B0AAE7032013 +:106EB000FBE79DF80210012908D1BDF80010B1F5DB +:106EC000C05FF2D06FF4C052D142EED09DF80610F0 +:106ED00001290DD1BDF80410A1F52851062907D2CA +:106EE00000E028E0DFE801F0030304030303DCE72C +:106EF0009DF80A1001290ED1BDF80810B1F5245FE4 +:106F0000D3D0A1F524510239CFD00129CDD0022907 +:106F100001D1CAE7FFDF606878B9002305AA2946D6 +:106F2000304603F093FE10B1FEF7A1FBBDE79DF8DC +:106F30001400800601D41020B7E761882246284655 +:106F40006368FFF7BFFDB0E72DE9F043814687B0E6 +:106F500088461446104609F065FA18B1102007B0AB +:106F6000BDE8F083002306AA4146484603F06EFEC2 +:106F700018B100BFFEF77BFBF1E79DF81800C006D3 +:106F800002D543F20140EAE70025072705A801954D +:106F900000970295CDE9035062884FF6FF73414692 +:106FA000484603F0D1FD060013D1606809F03AFAB3 +:106FB00060B960680195CDE9025000970495238877 +:106FC00062884146484603F0BFFD0646BDF81400FE +:106FD00020803046CEE739B1954B0A889B899A428A +:106FE00002D843F2030070471DE610B586B0904CFE +:106FF0000423ADF81430638943B1A4898C4201D2D3 +:10700000914205D943F2030006B010BD0620FBE70C +:10701000ADF81010002100910191ADF8003002216F +:107020008DF8021005A9029104A90391ADF8122070 +:107030006946FFF7F8FDE7E72DE9FC4781460E4674 +:10704000084609F0C9F988BB4846FAF775F95FEABE +:1070500000080AD098F80000222829D304214846C5 +:1070600005F0E6FC070005D103E043F20200BDE8AD +:10707000FC87FFDF07F1140002F06BFB0546307858 +:10708000012803D0022804D00720F0E7A8070FD575 +:1070900002E015F01C0F0BD0B079341DC00709D0E9 +:1070A000E08838B1A06809F097F918B11020DEE740 +:1070B0000820DCE732782088002628B3A0F20113EC +:1070C0000721112B18D20CD2DFE803F00B090D0BAE +:1070D0001D0B121D100B0B1D1D1D1D0B1D00022A6B +:1070E00011D10846C3E7012AFBD00CE02A0700E0D3 +:1070F000EA06002AF5DA06E0A0F5C0721F2A02D9D6 +:107100007D3A022AEDD8C6B200F068FE50B198F878 +:107110002300CDE90006FA89234639464846FEF7A2 +:10712000E7FCA4E71120A2E72DE9F04F8BB01F4642 +:1071300015460C4683460026FAF7FEF828B100787B +:10714000222805D208200BB094E543F20200FAE7AA +:10715000B80801D00720F6E7032F00D100274FF62B +:10716000FF79CCB1022D73D3204609F082F930B9F2 +:1071700004EB0508A8F1010009F07BF908B1102023 +:10718000E1E7AD1EAAB22146484603F014FE38F8E6 +:10719000021C88425CD1ADB22549B80702D5888966 +:1071A000401C00E001201FFA80F8F80701D08F8909 +:1071B00000E04F4605AA4146584603F012FC4FF046 +:1071C000070A4FF00009ACB3204608E040881028B9 +:1071D0003ED8361D304486B2AE4239D2A01902885C +:1071E0004245F3D354E000BF9DF8170002074FD586 +:1071F00084B304EB0608361DB8F80230B6B2102B83 +:1072000026D89A19AA4223D8B8F8002091421FD153 +:10721000C00620D5CDE900A90DF1080C0AAAA119D4 +:1072200048468CE80700B8F800100022584603E0F2 +:10723000080200202CE00BE003F05CFA10B1FEF72E +:1072400016FA80E7B8F80200BDF82810884202D08C +:107250000B2078E704E0B8F80200304486B206E07C +:10726000C00604D55846FEF775FC002888D19DF865 +:107270001700BDF81A1020F010008DF81700BDF8A7 +:107280001700ADF80000FF235846009A03F00AFDEE +:1072900005A803F0B2FB18B9BDF81A10B942A3D97A +:1072A0000421584605F0C4FB040000D1FFDFA28989 +:1072B0005AB1CDE900A94D46002321465846FEF7B4 +:1072C00017FC0028BDD1A5813DE700203BE72DE953 +:1072D000FF4F8BB01E4617000D464FF0000412D032 +:1072E000B00802D007200FB0C4E4032E00D100265E +:1072F0005DB1084609F0B4F828B93888691E084419 +:1073000009F0AEF808B11020EDE7C74AB00701D583 +:10731000D18900E00121F0074FF6FF7802D0D08933 +:10732000401E00E0404686B206AA0B9803F059FBC7 +:107330004FF000094FF0070B0DF1140A39E000BFC0 +:107340009DF81B00000734D5CDF80490CDF800B0AF +:10735000CDF80890CDE9039A434600220B9803F03C +:10736000F3FB60BB05B3BDF814103A88214428191B +:10737000091D8A4230D3BDF81E2020F8022BBDF82B +:10738000142020F8022BCDE900B9CDE90290CDF808 +:1073900010A0BDF81E10BDF8143000220B9803F0A9 +:1073A000D3FB08B103209EE7BDF814002044001D64 +:1073B00084B206A803F021FB20B10A2806D0FEF70C +:1073C00056F990E7BDF81E10B142B9D934B17DB17C +:1073D0003888A11C884203D20C2084E7052082E76C +:1073E00022462946404603F0E6FC01462819018062 +:1073F000A41C3C80002076E710B5044609F012F882 +:1074000008B1102010BD8848C0892080002010BD20 +:10741000F0B58BB00D460646142103A80FF033FFDC +:1074200001208DF80C008DF8100000208DF811005F +:10743000ADF814503046F9F77FFF48B100782228A4 +:1074400012D30421304605F0F3FA040005D103E01D +:1074500043F202000BB0F0BDFFDF04F11400074659 +:1074600002F077F9800601D40820F3E7207C02219E +:1074700040F00100207409A80094CDE90110072212 +:1074800003A930466368FEF7E9FA20B1217C21F0B8 +:1074900001012174DEE729463046FDF7A5FE08A963 +:1074A000384602F045F900B1FFDFBDF82040172C47 +:1074B00001D2172000E02046A84201D92C4602E064 +:1074C000172C00D2172421463046FFF724FB214613 +:1074D0003046FDF7ABFB0020BCE7F8B51C4615466F +:1074E0000E46069F05F0D6FB2346FF1DBCB2314673 +:1074F0002A46009404F0DFFFF8BD70B50C4605463F +:107500000E2120460FF09DFE002020802DB1012D80 +:1075100001D0FFDF76E4062000E00520A07171E4D1 +:1075200010B548800878134620F00F00001D20F0A9 +:10753000F00080300C4608701422194604F108004F +:107540000FF045FE00F04DFC3748046010BD2DE9FA +:10755000F047DFF8D890491D064621F00301174691 +:107560000C46D9F8000005F0BCF8050000D1FFDF9B +:107570004FF000083560A5F800802146D9F80000DA +:1075800005F0AFF8050000D1FFDF7560A5F80080B9 +:107590007FB104FB07F1091D0BD0D9F8000005F0FD +:1075A000A0F8040000D1FFDFB460C4F80080BDE89B +:1075B000F087C6F80880FAE72DE9F0411746491D23 +:1075C00021F00302194D064601681446286805F0AB +:1075D000B3F822467168286805F0AEF83FB104FBA5 +:1075E00007F2121D03D0B168286805F0A5F8042041 +:1075F00005F0CAF90446042005F0CEF9201A012846 +:1076000004D12868BDE8F04105F060B8BDE8F0811C +:1076100010B50C4603F0B1F900B1FFDF2046BDE81C +:107620001040FEF724B800000802002014000020DB +:1076300038B582880A800C46C188121D90B26A460D +:1076400004F0A2FBBDF80000032800D30320C1B260 +:10765000208800F06BFF38BD38B582880A800C4660 +:10766000C188121D90B26A4604F08EFBBDF800007E +:10767000022800D30220C1B2208800F057FF401C2E +:10768000C0B238BD2DE9FF5F0C46F94981462C2276 +:10769000D1E90201CDE9020109F1030020F0030163 +:1076A000C91C21F0030100916846114604F0FBFF5C +:1076B000F04E002C02D1F049009A8A6000990144F2 +:1076C0000091357E05F1010504D1E8B206F0D8FE3F +:1076D00000B1FFDF00984FF0000B00EB0510C01C5D +:1076E00020F00301009144B9327A81F800B0B08BE8 +:1076F00080B202F0CAFF00B1FFDF0098F1690844D0 +:1077000000902146684600F0D4FE0098C01C20F08E +:1077100003000090317A04B1002005F0AEF8009922 +:10772000084400902146684600F00BFF00273D46C4 +:10773000B24696F801800CE0284600F09DFE064611 +:1077400081788088FDF709FB71786D1C00FB01775B +:10775000EDB24545F0D10098C01C20F00300009028 +:1077600004B100203946FDF703FB009900270844C7 +:1077700000903D469AF801800CE0284600F07CFE1F +:107780000646C1788088FEF770FC71786D1C00FB9E +:107790000177EDB24545F0D10098C01C20F0030000 +:1077A000009004B100203946FEF768FC00990844B7 +:1077B00000210090084603F046FC0098C01D20F010 +:1077C00007020092F4BBAD490020FBF70DFC03F06B +:1077D000BDFAA9484178C06803F0F1FEA648103010 +:1077E000C0788DF8040010B1012804D005E0012014 +:1077F0008DF8040001E08DF804B001A803F0EEFF5D +:10780000FAF7A6FA9B4802AA00210C30FAF7FAFE12 +:1078100000B1FFDF9AF81900FEF799FF00B1FFDF12 +:1078200094484FF4F6713C300FF02DFD914804213F +:107830003C3080F8E91180F8EA11062180F8EB115C +:10784000032100E000E00171009904B0A1EB090000 +:10785000BDE8F09F70B5874C06463C34207804EBB9 +:107860004015E078083590B9A01990F8E801002893 +:107870000ED0A0780F2800D3FFDF202128460FF07C +:1078800002FD687866F3020068700120E070284607 +:1078900070BD2DE9F04105460C4600270078052112 +:1078A00090463E46B1EB101F00D0FFDF287A58B15A +:1078B00001280FD0FFDF00BFA8F800600CB12780BF +:1078C00066800020BDE8F0810127092674B1688830 +:1078D000A08008E00227142644B16888A0802869A7 +:1078E000E060A88A2082287B2072E5E7A8F8006083 +:1078F000E7E710B5604C6068C11D21F007018142C7 +:1079000000D0FFDF5B48012200210270417002724B +:107910000173052181821F21C182427358A1016137 +:107920000A21017642764FF4B061C161616841601D +:1079300010BD30B5504C1568636808339D4202D2C3 +:107940000420136030BD4B4B5D785A6802EBC502D2 +:10795000107051700320D080172090800120D070CB +:1079600090705878401C5870606808306060002043 +:1079700030BD70B506463F480024457807E02046F4 +:1079800000F07AFD0178B14204D0641CE4B2AC424C +:10799000F5D1002070BDF7B5064608780C46F8B161 +:1079A000FFF7E7FF0546202E06D0212E1AD0222E03 +:1079B00018D0232E14D110E000F069FD0DB16978C4 +:1079C00000E00021401A81B2A0780144FF2907D8C5 +:1079D00030B1A088022805D202E06088172801D2C1 +:1079E0000720FEBD65B9207802AA0121FFF7A1FF9B +:1079F0000028F6D12078FFF7BCFF050000D1FFDF9B +:107A0000202E08D0212E0ED0222E0FD0232E07D0CC +:107A1000FFDF0020FEBDA0786870A088E880F8E74E +:107A20006088A880F5E7A078A870F2E7A078E870F1 +:107A3000EFE71E2835D00EDC0C282ED008DC0928F4 +:107A400031D2DFE800F0133021303028282426001E +:107A5000122828D125E0302823D024DDA0F13A00D7 +:107A6000032820D2DFE800F01B1F1500002070471C +:107A7000E8750100440200201C00002000000020E6 +:107A80006E5246357800000043F20200EFE7042012 +:107A9000EDE70D20EBE70F20E9E70820E7E71120ED +:107AA000E5E70720E3E70320E1E710B5007800F001 +:107AB000010004F064F9BDE81040BAE70EB50178A2 +:107AC00001F001018DF80010417801F001018DF8FD +:107AD00001100178C1F340018DF802104178C1F323 +:107AE00040018DF80310017889088DF80410417861 +:107AF00089088DF8051081788DF80610C1788DF809 +:107B0000071000798DF80800684603F080FEFFF743 +:107B100090FF0EBD2DE9F84FDFF8F883FE4C0026EC +:107B20001FE0012000F050FD0120FFF793FE054605 +:107B30002C214746D8F8080004F0D3FD686000B94E +:107B4000FFDF686803F065FDA8B12846F9F7ADFDD1 +:107B5000284600F03FFD20B92C226968B86804F07F +:107B6000EBFD94F9E9010428DBDA022004F00CFFB4 +:107B700007460025A5E02C226968D8F8080004F023 +:107B8000DBFDF2E7B8F802104046491C89B2A8F8BC +:107B90000210B94201D3002141800221B8F802004D +:107BA00004F046FF002864D0B8F80200694604F0EB +:107BB0006AF8FFF73EFF00B1FFDF9DF8000078B1E3 +:107BC000B8F8020005F078F85FEA000900D1FFDF9D +:107BD000484604F004FB18B1B8F8020003F0F8FBC3 +:107BE000B8F8020005F056F85FEA000900D1FFDF9F +:107BF000484604F0ECFAE0BB0321B8F8020004F0B8 +:107C000017FF5FEA000B47D1FFDF45E0DBF80C0010 +:107C100010B10078FF2849D0022000F0D5FC0220E6 +:107C2000FFF718FE8246484604F0DDFBCAF8040060 +:107C300000B9FFDFDAF8040004F0A5FC0021009091 +:107C40000170B8F802105046AAF8021003F099FA31 +:107C5000484604F09AFC00B9FFDF504600F0BAFC39 +:107C600018B99AF80100000704D50099CBF80C1058 +:107C700012E024E0DBF80C0038B10178491C11F067 +:107C8000FF01017008D1FFDF06E0002211464846DF +:107C900000F0F0FB00B9FFDF94F9EA01022805DBF0 +:107CA000B8F8020003F048FA0028AFD194F9E901CE +:107CB000042804DB484604F0CCFC00B101266D1C0E +:107CC000EDB2BD4204D294F9EA010228BFF65AAFE0 +:107CD000002E7FF424AFBDE8F84F032000F074BC01 +:107CE00010B58C4CE06008682061AFF2D71000F04E +:107CF000DCFE607010BD884800213C38017085486A +:107D0000017086494160B2E670B505464FF080507B +:107D10000C46D0F8A410491C05D1D0F8A810C943CE +:107D20000904090C0BD050F8A01F01F001012970C3 +:107D3000416821608068A080287830B970BD062134 +:107D4000204608F024F801202870607940F0C00037 +:107D5000607170BD70B54FF080540D46D4F880103E +:107D6000491C0BD1D4F88410491C07D1D4F88810D1 +:107D7000491C03D1D4F88C10491C0CD0D4F88010C5 +:107D80000160D4F884104160D4F888108160D4F880 +:107D90008C10C16002E0102107F0F9FFD4F89000C8 +:107DA000401C0BD1D4F89400401C07D1D4F89800A3 +:107DB000401C03D1D4F89C00401C09D054F8900F0B +:107DC000286060686860A068A860E068E86070BDCE +:107DD0002846BDE87040102107F0D9BF4E48007911 +:107DE00038E570B54C4CE07830B3207804EB4010A7 +:107DF000407A00F00700204490F9E801002800DCF8 +:107E0000FFDF2078002504EB4010407A00F00700E7 +:107E1000011991F8E801401E81F8E8012078401C22 +:107E2000C0B220700F2800D12570A078401CA0702F +:107E300007F0E8FEE57070BDFFDF70BD3EB505469A +:107E4000032104F0F5FD0446284604F023FF05460F +:107E500004B9FFDFE06818B10078FF2800D1FFDF28 +:107E600001AA6946284600F005FB60B9FFDF0AE079 +:107E7000002202A9284600F0FDFA00B9FFDF9DF8B4 +:107E8000080000B1FFDF9DF80000411E8DF80010D2 +:107E9000EED2E0680199884201D10020E0603EBD49 +:107EA00070B50546A0F57F400C46FF3800D1FFDFD6 +:107EB000012C01D0FFDF70BDFFF790FF040000D15F +:107EC000FFDF207820F00F00401D20F0F000503040 +:107ED000207065800020207201202073BDE8704072 +:107EE0007FE72DE9F04116460D460746FFF776FF7E +:107EF000040000D1FFDF207820F00F00401D20F0AB +:107F0000F0005030207067800120207228682061C6 +:107F1000A88805E01C00002080020020600D0020E1 +:107F2000A0822673BDE8F0415BE77FB5FFF721FD36 +:107F3000040000D1FFDF02A92046FFF779FB0546C8 +:107F400003A92046FFF788FB8DF800508DF801004B +:107F5000BDF80800001DADF80200BDF80C00001DC2 +:107F6000ADF80400E088ADF80600684603F0F1FEC5 +:107F7000002800D0FFDF7FBD2DE9F04FFD4E044605 +:107F80008BB030784FF0000A18B108200BB0BDE874 +:107F9000F08F204608F046FA08B11020F6E7F64DBB +:107FA000287808B9FFF7A5FC2D7A00F070FAA842EE +:107FB00008D2281AC1B222460020FFF7BAFC5FEAB5 +:107FC000000AE3D1EB484FF00009C84641684F462C +:107FD000C91C21F003014160E748CDF80890CDF8B5 +:107FE00000904E464D4690F801B00EE0284600F055 +:107FF00043FA4178827809F10109884412FB01773C +:10800000C07810FB01666D1CEDB25D45EED10098A5 +:10801000029900EB890000EBC80000EB8700D64D09 +:1080200000EB860000EBC100297ADFF8488300EB03 +:10803000C100D8F80410471801213846FFF722FB89 +:10804000064621683844884202D8B6F5803F15D3E9 +:1080500020600020FFF78DFC04000DD004F10B0020 +:10806000D8F8041020F003004646884200D0FFDF15 +:108070006878401E68707460042087E700213846E5 +:10808000FFF700FB0546AE4200D0FFDFE919C8F854 +:10809000041021604FF6FF71A8F80210012188F842 +:1080A0000010504672E72DE9F0410446B1481746EA +:1080B0000D46007808B1082004E4084608F08CF961 +:1080C00008B11020F8E7AC4E307808B9FFF711FC82 +:1080D000601E1E2807D8012C38D12878FE2835D8F4 +:1080E00030760020E8E7A4F120001F2805D8E0B290 +:1080F0003A462946BDE8F0414DE4A4F140004FF076 +:1081000000081F281AD8402C02D0412C1ED110E0A4 +:108110002C78FF2C08D806F097FB074607F02BFDBC +:10812000381A401EA04201DA1220C5E728783072C2 +:1081300024E02846BDE8F04100F074BAA4F1A000A4 +:108140001F2803D8A02C03D0A12C06D00720B3E70A +:10815000287800F00100707610E029680920F829DD +:10816000AAD38A07A8D1727B02F00302012A04D1A4 +:10817000F28AD73293B28B429ED8F16140469BE798 +:108180002DE9F04781460E46084608F04BF948B9FC +:10819000484608F065F928B909F1030020F0030109 +:1081A000494502D01020BDE8F08773484FF0000A1F +:1081B0003C30817869B14178804600EB4114083445 +:1081C000378832460021204600F012FA050004D01C +:1081D00027E0A6F800A00520E5E7B9F1000F24D0BC +:1081E0003088B84201D90C251FE0607800F00705FF +:1081F000284600F0E9F908EB0507324697F8E80150 +:108200004946401C87F8E801204607F5F47700F05E +:10821000EFF905463878401E3870032000F0D4F995 +:108220002DB10C2D01D0A6F800A02846BBE7607840 +:10823000504E00F00701012923D002290CD0032958 +:1082400033D0FFDF98F801104046491CC9B288F8C6 +:1082500001100F2934D035E0616821B1000702D444 +:108260006088FFF7EBFD98F8EA014746012802D144 +:10827000707800F039FC97F9EA010428E2DBFFDFAF +:10828000E0E7616819B12C22B06804F055FA98F85B +:10829000E9014746032802D1707800F025FC97F9E0 +:1082A000E9010428CEDBFFDFCCE7C00602D56088F9 +:1082B000FFF7C4FD98F9EB010628C3DBFFDFC1E738 +:1082C00080F801A08178491E8170617801F0070172 +:1082D00001EB080090F8E811491C80F8E811A4E7C8 +:1082E00070B50D46044608F077F818B9284608F02E +:1082F00099F808B1102070BD29462046BDE87040AD +:1083000006F0F5B870B5044615460E46084608F066 +:1083100063F818B9284608F085F808B1102070BD38 +:10832000022C03D0102C01D0092070BD2A46314602 +:10833000204606F0FFF80028F7D0052070BD70B584 +:1083400014460D46064608F047F838B9284608F0A6 +:1083500069F818B9204608F083F808B1102070BDFC +:1083600022462946304606F004F90028F7D00720B7 +:1083700070BD00001C000020440200203EB50446F1 +:1083800008F050F808B110203EBD684603F0E1F94E +:10839000FFF74FFB0028F7D19DF806002070BDF8CD +:1083A00008006080BDF80A00A08000203EBD70B5C6 +:1083B00005460C46084608F053F820B93CB1206841 +:1083C00008F030F808B11020D2E7A08828B1214683 +:1083D0002846BDE87040FDF7C7BE0920C8E770B564 +:1083E00004460D46084607F0F7FF30B9601E1E2808 +:1083F00014D8284607F0F0FF08B11020B8E7022C87 +:1084000001D90720B4E704B9FFDFAC4800EB8400D2 +:1084100050F8041C2846BDE870400847A4F120002D +:108420001F28EED829462046BDE87040F9F71FBC4A +:1084300070B504460D46084607F0F4FF30B9601EDB +:108440001E280DD8284607F0C7FF08B110208FE777 +:10845000012C01D0022C01D1062089E7072087E7F3 +:10846000A4F120001F28F9D829462046BDE8704015 +:10847000F9F741BC03F07ABE30B5914D04466878F7 +:10848000A04200D8FFDF686800EBC40030BD70B5C3 +:108490008B4800252C46467807E02046FFF7ECFF86 +:1084A0004078641C2844C5B2E4B2B442F5D12846F1 +:1084B0005EE72DE9F041054681480C46027A501CE2 +:1084C000104410448618761CFF2E00D9FFDF286860 +:1084D000F6B2C01C20F003022A6014BB7848334671 +:1084E0000721203007F052FE002407E0072C10D2AD +:1084F000DFE804F004060408080A0400714804E0F8 +:10850000714802E0714800E0714807F05FFE0746DD +:1085100000E0FFDFA74200D0FFDF641CE4B2072CBD +:10852000E4D3286800EB06102860C5E5021D51431E +:10853000452900D245210844C01CB0FBF2F0C0B26E +:1085400070472DE9FC5F06465D484FF000088B46FA +:108550004746444690F8019022E02046FFF78CFF02 +:10856000050000D1FFDF687869463844C7B2284665 +:10857000FFF75EF8824601A92846FFF76DF803462B +:10858000BDF804005246001D81B2BDF80000001D78 +:1085900080B204F0CBFA6A78641C00FB0288E4B273 +:1085A0004C45DAD13068C01C20F003003060BBF1CC +:1085B000000F00D000204246394604F0C5FA316869 +:1085C00008443060BDE8FC9F3D493C310871002003 +:1085D000C87070473A493C31CA782AB10A7801EB31 +:1085E00042110831814201D00120704700207047BC +:1085F0002DE9F04106460078154600F00F040020F2 +:108600001080601E0F46052800D3FFDF2B482A4646 +:10861000103000EB8400394650F8043C3046BDE889 +:10862000F041184738B50446407800F003000128AF +:1086300003D002280BD0072038BD606858B107F07E +:1086400018FFD0B9606807F00BFF20B915E060682B +:1086500007F0C2FE88B969462046FBF719FB0028DF +:10866000EAD1607800F00300022808D19DF80000EC +:1086700028B1606807F0F4FE08B1102038BD6189A8 +:10868000F8290DD8208988420AD8607800F00302C2 +:108690000B48012A06D1D731C26989B28A4201D278 +:1086A000092038BD94E80E0000F10C0585E80E00A5 +:1086B0000AB900218182002038BD0000E875010060 +:1086C000440200207B1B000091B00000C98B000019 +:1086D00073E2000010B5EFF3108000F0010472B6F1 +:1086E000E7484178491C41704078012801D107F0E2 +:1086F000A9FA002C00D162B610BD70B5E04CE0784C +:1087000048B90125E570FFF7E5FF07F0A3FA20B1AE +:10871000002007F07EFA002070BD4FF080406571A8 +:10872000C0F80453F7E770B5EFF3108000F00105CF +:1087300072B6D34C607800B9FFDF6078401E60707D +:10874000607808B907F082FA002D00D162B670BDDA +:10875000CB4810B5C17821B100214171C170FFF73C +:10876000E2FF002010BD10B5044607F073FAC449BB +:10877000C978084000D001202060002010BD2DE9FC +:10878000F05FDFF8FC924278817889F806200026B5 +:1087900089F80710074689F808600078354620B147 +:1087A00001280FD002280FD0FFDF07F060FA98B140 +:1087B00007F064FAB0420FD1304607F063FA0028A0 +:1087C000FAD047E00126F0E7FFF784FF07F042FA0E +:1087D0000028FBD00226E8E701208407E060C4F807 +:1087E0000451A8490E600107D1F84412A54AC1F30B +:1087F000423124321160A349343108604FF0020B3A +:10880000C4F804B3A060DFF880A2DAF80010C9430E +:1088100041F3001101F10108DAF8001041F01001F4 +:10882000CAF8001000E020BFD4F804010028FAD0F4 +:10883000304607F027FA0028FAD0B8F1000F05D12A +:10884000DAF8001021F01001CAF80010C4F808B3DB +:10885000C4F8045199F807004C4670B1387860B9F3 +:1088600007F0F8F9074607F059FB6FF0004117B120 +:10887000C4E9031001E0C4E9030116B12571BDE8A4 +:10888000F09F0127BE0727714FF01908C6F808832B +:10889000B761C6F80051C6F80C51C6F8105107F080 +:1088A000D9F910B1A770376100E02770FFF712FF08 +:1088B0007449A07920310860C6F80483DFE770B5F9 +:1088C000050000D1FFDF4FF080424FF0FF30C2F8CB +:1088D00008030021C2F80011C2F80411C2F80C11FB +:1088E000C2F81011664C617007F0BAF910B101209E +:1088F000E07060702846BDE8704040E72DE9F04721 +:108900004FF08044D4F8080110B14FF0010801E0A5 +:108910004FF00008D4F8000100B101208146D4F8DE +:10892000040108B1012600E00026D4F80C0100B1D2 +:1089300001208246D4F8100108B1012700E0002789 +:1089400048EA090126EA010020EA0A00B84300D0FB +:10895000FFDF0025B8F1000F04D0C4F80851012052 +:1089600007F057F95FEA0900DFF814814FF00109B9 +:1089700013D0C4F8005198F8050020B188F80550CC +:10898000002007F046F998F8000030B107F062F9CE +:1089900018B188F80290C4F810900EB1C4F80451D0 +:1089A000BAF1000F0CD0C4F80C5198F802004646FA +:1089B00000B9FFDFB5703570C4F81490FFF7B3FE4F +:1089C000002F09D0C4F8105198F80400002803D0F3 +:1089D000BDE8F04700F01EB8BDE8F08770B5284D3F +:1089E000E87808B907F032F901208407A061A87877 +:1089F00058B100BFD4F80C0120B9002007F042F9AB +:108A00000028F7D10020C4F80C014FF0FF30C4F863 +:108A1000080370BD2DE9F041194C4FF08047012546 +:108A2000E079F0B1012803D0217A401E814218DAA2 +:108A300007F010F9064607F071FAE179012902D929 +:108A4000217A491C21720EB1216900E0E168411AC6 +:108A5000022902DA11F1020F0BDC0EB1206100E0F5 +:108A6000E060FFF737FE07F0F5F828B13D61A5702B +:108A700003E07D61BDE8F081257000202072F9E7F8 +:108A8000340000201805004010ED00E04FF0E02118 +:108A90004FF00070C1F88001C1F88002334B802292 +:108AA00083F80024C1F80001704700B50246042095 +:108AB0002F4903E001EBC0031B792BB1401EC0B26C +:108AC000F8D2FFDFFF2000BD41F8302001EBC001EC +:108AD00000224A718A7101220A7100BD244A0021D4 +:108AE00002EBC0000171704710B50446042800D3A2 +:108AF000FFDF1F4800EBC4042079012800D0FFDF0E +:108B00006079A179401CC0B2814200D060714FF001 +:108B1000E0214FF00070C1F8000210BD70B513489D +:108B2000042590F80004124E4009124C042818D075 +:108B3000FFDF16E0217806EBC1000279012A08D197 +:108B4000427983799A4204D04279827156F8310091 +:108B500080472078401CC0B22070042801D3002038 +:108B600020706D1EEDB2E5D270BD000019E000E08E +:108B70006C040020480000200F4A12680D498A4208 +:108B80000CD118470C4A12680A4B9A4206D101B51B +:108B900007F096F9FAF726FABDE801400749096897 +:108BA0000958084706480749054A064B7047000020 +:108BB00000000000BEBAFECAA4000020040000208D +:108BC000E00C0020E00C002070B50C46054600F0DB +:108BD00043FB21462846BDE8704001F026BC00005A +:108BE000F8B51D46DDE906470E000AD004F064F82A +:108BF0002346FF1DBCB231462A46009403F08FFC89 +:108C0000F8BDD019224619460EF09CFA2046F8BD50 +:108C100070B50D46044610210EF013FB2581172078 +:108C20006081A07B40F00A00A07370BD4FF6FF7218 +:108C30000A800146032007F083BB70470089704714 +:108C4000827BD30701D1920703D48089088000205A +:108C5000704705207047827B920700D5818170475D +:108C600001460020098841F6FE52114200D0012041 +:108C7000704700B50346807BC00701D0052000BDCA +:108C800059811846FFF7ECFFC00703D0987B40F0EE +:108C900004009873987B40F001009873002000BD99 +:108CA000827B520700D509B1408970471720704771 +:108CB000827B61F3C302827370472DE9FC5F0E462D +:108CC000044601789646012000FA01F14DF6FF5264 +:108CD00001EA020962684FF6FF7B1188594506D008 +:108CE000B9F1000F06D041F6FE55294202D001200D +:108CF000BDE8FC9F41EA090111801D0014D04FF02E +:108D0000000C85F800C023780521032267464FF048 +:108D1000020A0E2B74D2DFE803F0F809252F476210 +:108D20006974479092B3D0D70420E1E76168208945 +:108D30008B7B9B077DD5172848D30B89834245D36E +:108D40008989172901D3814240D185F800A0A5F86F +:108D500001003280616888816068817B21F00201B6 +:108D60008173C5E0042028702089A5F8010060897E +:108D7000A5F803003180BBE0208A3188C01D1FFAAE +:108D800080F8414522D3062028702089A5F80100EB +:108D90006089A5F80300A089A5F805000721208AAD +:108DA000CDE9000163693EE0082B10D0082028704F +:108DB0002089A5F801006089A5F8030031806A1DAB +:108DC000694604F10C0005F0D4FB10B15FE01020FF +:108DD000EDE730889DF800100844308088E00A20D4 +:108DE00028702089A5F80100328045E00C20287009 +:108DF0002089A5F801006089A5F8030031803BE0D7 +:108E000083E02189338800EB41021FFA82F8434551 +:108E10003DD3B8F1050F3AD30E222A700BEA410177 +:108E2000CDE90010E36860882A467146FFF7D8FE56 +:108E300000E04DE0A6F800805AE0402028706089EC +:108E40003188C01C1FFA80F8414520D3287871462C +:108E500020F03F00123028702089A5F801006089B9 +:108E6000CDE9000260882A46E368FFF7B9FEA6F85C +:108E70000080287840063BD461682089888037E0EC +:108E8000A0893288401D1FFA80F8424501D204278C +:108E90003EE0162028702089A5F801006089A5F819 +:108EA0000300A089CDE9000160882A467146236944 +:108EB000FFF796FEA6F80080DEE718202870207ADB +:108EC0006870A6F800A013E061680A88920401D4D3 +:108ED00005271DE0C9882289914201D0062717E0A5 +:108EE0001E21297030806068018821F400510180C2 +:108EF000B9F1000F0CD0618878230022032007F01D +:108F000075F961682078887007E0A6F800C003272B +:108F10006068018821EA090101803846E8E62DE908 +:108F2000FF4F85B01746129C0D001E461CD03078AE +:108F3000C10703D000F03F00192801D9012100E04A +:108F400000212046FFF7ACFEA8420DD32088A0F5F3 +:108F50007F41FF3908D03078410601D4000605D59D +:108F6000082009B0BDE8F08F0720FAE700208DF84F +:108F700000008DF8010030786B1E00F03F0C0121DD +:108F8000A81E4FF0050A4FF002094FF0030B9AB2EA +:108F9000BCF1200F75D2DFE80CF08B10745E7468A2 +:108FA000748C749C74B674BB74C974D574E2747494 +:108FB00074F274F074EF74EE748B052D78D18DF823 +:108FC0000090A0788DF804007088ADF80600307924 +:108FD0008DF80100707800F03F000C2829D00ADCE1 +:108FE000A0F10200092863D2DFE800F012621562E6 +:108FF0001A621D622000122824D004DC0E281BD027 +:109000001028DBD11BE016281FD01828D6D11FE06E +:109010002078800701E020784007002848DAEFE058 +:1090200020780007F9E72078C006F6E72078800668 +:10903000F3E720784006F0E720780006EDE7208887 +:10904000C005EAE720884005E7E720880005E4E757 +:109050002088C004E1E72078800729D5032D27D197 +:109060008DF800B0B6F8010082E0217849071FD5DD +:10907000062D1DD381B27078012803D0022817D1A4 +:1090800002E0CAE0022000E0102004228DF8002057 +:1090900072788DF80420801CB1FBF0F2ADF8062048 +:1090A00092B242438A4203D10397ADF80890A7E0F9 +:1090B0007AE02078000777D598B282088DF800A072 +:1090C000ADF80420B0EB820F6ED10297ADF8061018 +:1090D00096E02178C90667D5022D65D381B20620B6 +:1090E0008DF80000707802285ED300BFB1FBF0F26B +:1090F0008DF80400ADF8062092B242438A4253D163 +:10910000ADF808907BE0207880064DD5072003E07D +:10911000207840067FD508208DF80000A088ADF8A3 +:109120000400ADF80620ADF8081068E020780006CD +:1091300071D50920ADF804208DF80000ADF80610B7 +:1091400002975DE02188C90565D5022D63D381B200 +:109150000A208DF80000707804285CD3C6E72088C8 +:10916000400558D5012D56D10B208DF80000A08860 +:10917000ADF8040044E021E026E016E0FFE7208897 +:10918000000548D5052D46D30C208DF80000A08899 +:10919000ADF80400B6F803006D1FADF80850ADF847 +:1091A0000600ADF80AA02AE035E02088C00432D5D8 +:1091B000012D30D10D208DF8000021E020888004A1 +:1091C00029D4B6F80100E080A07B000723D5032D49 +:1091D00021D3307800F03F001B2818D00F208DF8E5 +:1091E0000000208840F40050A4F80000B6F8010008 +:1091F000ADF80400ED1EADF80650ADF808B00397C9 +:1092000069460598FBF721FD050008D016E00E2001 +:109210008DF80000EAE7072510E008250EE0307819 +:1092200000F03F001B2809D01D2807D00320059916 +:1092300007F086F8208800F400502080A07B4007CB +:1092400008D52046FFF70CFDC00703D1A07B20F016 +:109250000400A073284684E61FB5032806D1012028 +:109260008DF8000088B26946FBF7EFFC1FBD0000D7 +:10927000F8B51D46DDE906470E000AD003F01CFDD7 +:109280002346FF1DBCB231462A46009403F047F93D +:10929000F8BDD019224619460DF054FF2046F8BDFE +:1092A0002DE9FF4F8DB09B46DDE91B57DDF87CA013 +:1092B0000C46082B05D0E06901F000F950B11020F0 +:1092C000D2E02888092140F0100028808AF8001098 +:1092D000022617E0E16901208871E2694FF420510C +:1092E0009180E1698872E06942F601010181E069DB +:1092F000002181732888112140F0200028808AF8FD +:109300000010042638780A900A2038704FF00209BD +:1093100004F118004D460C9001F093FBB04681E03B +:10932000BBF1100F0ED1022D0CD0A9EB0800801C50 +:1093300080B20221CDE9001005AB52461E990D986E +:10934000FFF796FFBDF816101A98814203D9F74827 +:1093500000790F9004E003D10A9808B138702FE02B +:109360004FF00201CDE900190DF1160352461E9986 +:109370000D98FFF77DFF1D980088401B801B83B26E +:10938000C6F1FF00984200D203461E990BA8D9B13E +:109390005FF00002DDF878C0CDE9032009EB06019B +:1093A00089B2CDE901C10F980090BDF816100022D6 +:1093B0000D9801F0C9FB387070B1C0B2832807D096 +:1093C000BDF8160020833AE00AEB09018A19E1E7AB +:1093D000022011B0BDE8F08FBDF82C00811901F01A +:1093E000FF08022D0DD09AF80120424506D1BDF8A4 +:1093F0002010814207D0B8F1FF0F04D09AF8018005 +:109400001FE08AF80180C94800680178052902D167 +:10941000BDF81610818009EB08001FFA80F905EBF2 +:10942000080085B2DDE90C1005AB0F9A01F00CFBCA +:1094300028B91D980088411B4145BFF671AF022D28 +:1094400013D0BBF1100F0CD1A9EB0800801C81B226 +:109450000220CDE9000105AB52461E990D98FFF799 +:1094600007FF1D980580002038700020B1E72DE926 +:10947000F8439C46089E13460027B26B9AB3491FD7 +:109480008CB2F18FA1F57F45FF3D05D05518AD8811 +:109490002944891D8DB200E000252919B6F83C80C9 +:1094A0000831414520D82A44BCF8011022F8021B9B +:1094B000BCF8031022F8021B984622F8024B914692 +:1094C00003F0E8FB4FF00C0C41464A462346CDF82A +:1094D00000C002F0F0FFF587B16B00202944A41D05 +:1094E0002144088003E001E0092700E08327384693 +:1094F000BDE8F88310B50B88848F9C420CD9846B2F +:10950000E018048844B1848824F40044A41D234452 +:109510000B801060002010BD0A2010BD2DE9F0471F +:109520008AB00025904689468246ADF81850072734 +:109530004BE0059806888088000446D4A8F80060AF +:1095400007A8019500970295CDE903504FF40073E9 +:1095500000223146504601F0F7FA04003CD1BDF834 +:109560001800ADF82000059804888188B44216D10F +:109570000A0414D401950295039521F40041009743 +:10958000049541F4804342882146504601F0B2F8E8 +:1095900004000BD10598818841F40041818005AA1F +:1095A00008A94846FFF7A6FF0400DCD000970598FD +:1095B00002950195039504950188BDF81C300022A1 +:1095C000504601F097F80A2C06D105AA06A948468C +:1095D000FFF790FF0400ACD0ADF8185004E00598F8 +:1095E000818821F40041818005AA06A94846FFF739 +:1095F00081FF0028F3D00A2C03D020460AB0BDE832 +:10960000F0870020FAE710B50C46896B86B051B19F +:109610000C218DF80010A18FADF80810A16B0191FD +:109620006946FCF7C3FA00204FF6FF71A063E1879B +:10963000A08706B010BD2DE9F0410D460746896BA5 +:109640000020069E1446002911D0012B0FD132466E +:1096500029463846FFF762FF002808D1002C06D0C3 +:10966000324629463846BDE8F04100F036BFBDE835 +:10967000F0812DE9FC411446DDE9087C0E46DDE968 +:109680000A15521DBCF800E092B2964502D207209E +:10969000BDE8FC81ACF8002017222A70A5F8016013 +:1096A000A5F803300522CDE900423B462A46FFF7E4 +:1096B000DFFD0020ECE770B50C461546482120463A +:1096C0000DF0E1FD04F1080044F81C0F00204FF6F6 +:1096D000FF71E06161842084A5841720E08494F800 +:1096E0002A0040F00A0084F82A0070BD4FF6FF728D +:1096F0000A800146042006F023BE30B585B00C4632 +:109700000546FFF780FFA18E284629B101218DF87B +:1097100000106946FCF74AFA0020E06220636063AB +:1097200005B030BDB0F84000704700004C0000208C +:1097300090F84620920703D4408808800020F3E781 +:109740000620F1E790F846209207EDD5A0F84410E6 +:10975000EAE70146002009880A0700D5012011F038 +:10976000F00F01D040F00200CA0501D540F004001E +:109770008A0501D540F008004A0501D540F01000E7 +:109780000905D1D540F02000CEE700B5034690F89A +:109790004600C00701D0062000BDA3F842101846BD +:1097A000FFF7D7FF10F03E0F05D093F8460040F0CA +:1097B000040083F8460013F8460F40F001001870CB +:1097C000002000BD90F84620520700D511B1B0F836 +:1097D0004200A9E71720A7E710F8462F61F3C3025C +:1097E0000270A1E72DE9FF4F9BB00E00DDE92B349D +:1097F000DDE92978289D24D02878C10703D000F01E +:109800003F00192801D9012100E000212046FFF77F +:10981000D9FFB04215D32878410600F03F010CD49F +:109820001E290CD0218811F47F6F0AD13A8842B1E9 +:10983000A1F57F42FF3A04D001E0122901D10006D0 +:1098400002D504201FB0C5E5F9491D984FF0000A64 +:1098500008718DF818A08DF83CA00FAA0A60ADF829 +:109860001CA0ADF850A02978994601F03F02701F66 +:109870005B1C04F1180C4FF0060E4FF0040BCDF8F2 +:1098800058C01F2A7ED2DFE802F07D7D107D267D44 +:10989000AC7DF47DF37DF27DF17DF47DF07D7D7D09 +:1098A000EF7DEE7D7D7D7D7DED0094F84610B5F871 +:1098B0000100890701D5032E02D08DF818B022E3EC +:1098C0004FF40061ADF85010608003218DF83C101A +:1098D000ADF84000D8E2052EEFD1B5F801002083A5 +:1098E000ADF81C00B5F80310618308B1884201D9B6 +:1098F00001207FE10020A07220814FF6FF702084BC +:10990000169801F09EF8052089F8000002200290C8 +:1099100083460AAB1D9A16991B9801F095F890BBE7 +:109920009DF82E00012804D0022089F801001020A3 +:1099300003E0012089F8010002200590002203A91C +:109940000BA804F016FEE8BB9DF80C0005998142B7 +:109950003DD13A88801CA2EB0B01814237DB029992 +:109960000220CDE900010DF12A034A4641461B9829 +:10997000FFF77EFC02980BF1020B801C80B217AA45 +:1099800003A901E0A0E228E002900BA804F0F1FD99 +:1099900002999DF80C00CDE9000117AB4A464146FB +:1099A0001B98FFF765FC9DF80C100AAB0BEB010050 +:1099B0001FFA80FB02981D9A084480B20290169903 +:1099C0001B9800E003E001F03FF80028B6D0BBF19F +:1099D000020F02D0A7F800B053E20A208DF8180059 +:1099E0004FE200210391072EFFF467AFB5F80100A5 +:1099F0002083ADF81C00B5F80320628300283FF4F3 +:109A000077AF90423FF674AF0120A072B5F8050021 +:109A100020810020A073E06900F050FD78B9E16971 +:109A200001208871E2694FF420519180E1698872C8 +:109A3000E06942F601010181E06900218173F01FB4 +:109A400020841E98606207206084169800F0F9FF59 +:109A5000072089F800000120049002900020ADF852 +:109A60002A0028E01DE2A3E13AE1EAE016E2AEE0D6 +:109A700086E049E00298012814D0E0698079012845 +:109A800003D1BDF82800ADF80E00049803ABCDE972 +:109A900000B04A4641461B98FFF7EAFB0498001DB8 +:109AA00080B20490BDF82A00ADF80C00ADF80E00AD +:109AB000059880B202900AAB1D9A16991B9800F087 +:109AC000C3FF28B902983988001D05908142D1D280 +:109AD0000298012881D0E0698079012805D0BDF87D +:109AE0002810A1F57F40FF3803D1BDF82800ADF85C +:109AF0000E00049803ABCDE900B04A4641461B98DE +:109B0000FFF7B6FB0298BBE1072E02D0152E7FF4BB +:109B1000D4AEB5F801102183ADF81C10B5F80320C0 +:109B2000628300293FF4E4AE91423FF6E1AE0121A9 +:109B3000A1724FF0000BA4F808B084F80EB0052E07 +:109B400007D0C0B2691DE26904F0F4FC00287FF47C +:109B500044AF4FF6FF70208401A906AA14A8CDF8DF +:109B600000B081E885032878214600F03F031D9A64 +:109B70001B98FFF795FB8246208BADF81C0080E117 +:109B80000120032EC3D14021ADF85010B5F80110CB +:109B90002183ADF81C100AAAB8F1000F00D00023F1 +:109BA000CDE9020304921D98CDF804800090388816 +:109BB0000022401E83B21B9800F0C6FF8DF81800EB +:109BC00090BB0B2089F80000BDF8280037E04FF06B +:109BD000010C052E9BD18020ADF85000B5F8011086 +:109BE0002183B5F803002084ADF81C10B0F5007F88 +:109BF00003D907208DF8180085E140F47C422284C7 +:109C00000CA8B8F1000F00D00023CDE90330CDE956 +:109C1000018C1D9800903888401E83B21B9800F07C +:109C200093FF8DF8180028B18328A8D10220BDE049 +:109C30004C0000200D2189F80010BDF83000401CB8 +:109C40001EE1032E04D248067FF537AE002017E14F +:109C5000B5F80110ADF81C102878400602D58DF833 +:109C60003CE002E007208DF83C004FF000080320A4 +:109C7000CDE902081E9BCDF810801D980193A6F136 +:109C8000030B00901FFA8BF342461B9800F032FD45 +:109C90008DF818008DF83C80297849060DD520886C +:109CA000C00506D5208BBDF81C10884201D1C4F830 +:109CB000248040468DF81880E2E0832801D14FF0DF +:109CC000020A4FF48070ADF85000BDF81C002083EC +:109CD000A4F820B01E986062032060841321CCE0B9 +:109CE000052EFFF4EAADB5F80110ADF81C10A28FF7 +:109CF00062B3A2F57F43FE3B28D008228DF83C20BA +:109D00004FF0000B0523CDE9023BDDF878C0CDF81C +:109D100010B01D9A80B2CDF804C040F40043009208 +:109D2000B5F803201B9800F0E5FC8DF83CB04FF42B +:109D300000718DF81800ADF85010832810D0F8B1DC +:109D4000A18FA1F57F40FE3807D0DCE00B228DF813 +:109D50003C204FF6FE72A287D2E7A4F83CB0D2E0D6 +:109D600000942B4631461E9A1B98FFF780FB8DF816 +:109D7000180008B183284BD1BDF81C00208355E79B +:109D800000942B4631461E9A1B98FFF770FB8DF806 +:109D90001800E8BBE18FA06B0844811D8DE88203A9 +:109DA0004388828801881B98FFF763FC824668E03D +:109DB00095F80180022E70D15FEA080002D0B8F158 +:109DC000010F6AD109208DF83C0007A800908DF89A +:109DD00040804346002221461B98FFF72CFC8DF85B +:109DE00042004FF0000B8DF843B050B9B8F1010FAD +:109DF00012D0B8F1000F04D1A18FA1F57F40FF3838 +:109E00000AD0A08F40B18DF83CB04FF4806000E0E4 +:109E100037E0ADF850000DE00FA91B98FBF7C6FE28 +:109E200082468DF83CB04FF48060ADF85000BAF136 +:109E3000020F06D0FB480068C07928B18DF81800E1 +:109E400027E0A4F8188044E0BAF1000F03D0812085 +:109E50008DF818003DE007A80090434601222146F6 +:109E60001B98FFF7E8FB8DF8180021461B98FFF7B9 +:109E7000CAFB9DF8180020B9192189F800100120AB +:109E800038809DF83C0020B10FA91B98FBF78EFE8F +:109E90008246BAF1000F33D01BE018E08DF818E0CD +:109EA00031E02078000712D5012E10D10A208DF85C +:109EB0003C00E088ADF8400004201B9906F040FA11 +:109EC0000820ADF85000C1E648067FF5F6AC4FF02B +:109ED000040A2088BDF8501008432080BDF85000C7 +:109EE00080050BD5A18FA1F57F40FE3806D11E98C5 +:109EF000E06228982063A6864FF0030A5046A1E44A +:109F00009DF8180078B1012089F80000297889F8B7 +:109F10000110BDF81C10A9F802109DF8181089F85E +:109F20000410052038802088BDF850108843208018 +:109F3000E4E72DE9FF4F8846087895B0012181407C +:109F40004FF20900249C0140ADF820102088DDF874 +:109F50008890A0F57F424FF0000AFF3A02D029B165 +:109F6000000703D5012019B0BDE8F08F239E4FF004 +:109F7000000B0EA886F800B018995D460988ADF868 +:109F80003410A8498DF81CB0179A0A718DF838B0B2 +:109F9000086098F8000001283BD0022809D0032867 +:109FA0006FD1307820F03F001D303070B8F80400D9 +:109FB000E08098F800100320022904D1317821F0C4 +:109FC0003F011B31317094F84610090759D505AB94 +:109FD000B9F1000F13D0002102AA82E80B0007207C +:109FE000CDE90009BDF83400B8F80410C01E83B2F2 +:109FF0000022159800F0A8FD0028D1D101E0F11C45 +:10A00000EAE7B8F80400A6F80100BDF81400C01C87 +:10A0100004E198F805108DF81C1098F80400012848 +:10A0200006D04FF4007A02282CD00328B8D16CE176 +:10A030002188B8F8080011F40061ADF8201020D094 +:10A0400017281CD3B4F84010814218D3B4F8441038 +:10A05000172901D3814212D1317821F03F01C91C67 +:10A060003170A6F801000321ADF83410A4F84400C3 +:10A0700094F8460020F0020084F8460065E10525CA +:10A080007EE177E1208808F1080700F4FE60ADF872 +:10A09000200010F0F00F1BD010F0C00F03D0388854 +:10A0A000228B9042EBD199B9B878C00710D0B9682B +:10A0B0000720CDE902B1CDF804B00090CDF810B082 +:10A0C000FB88BA883988159800F014FB0028D6D18F +:10A0D0002398BDF82010401C80294ED006DC1029A2 +:10A0E0000DD020290BD0402987D124E0B1F5807F05 +:10A0F0006ED051457ED0B1F5806F97D1DEE0C806B5 +:10A1000001D5082000E0102082460DA907AA0520ED +:10A11000CDE902218DF83800ADF83CB0CDE90496C8 +:10A1200008A93888CDE90001534607222146159831 +:10A13000FFF7B6F8A8E09DF81C2001214FF00A0AAD +:10A14000002A9BD105ABB9F1000F00D00020CDE96A +:10A1500002100720CDE90009BDF834000493401E29 +:10A1600083B2218B0022159800F0EEFC8DF81C00C4 +:10A170000B203070BDF8140020E09DF81C20012158 +:10A180004FF00C0A002A22D113ABB9F1000F00D016 +:10A190000020CDE902100720CDE900090493BDF8A5 +:10A1A0003400228C401E83B2218B159800F0CCFC29 +:10A1B0008DF81C000D203070BDF84C00401CADF82F +:10A1C000340005208DF83800208BADF83C00BCE051 +:10A1D0003888218B88427FF452AF9DF81C004FF0E5 +:10A1E000120A00281CD1606AA8B1B878C0073FF4F1 +:10A1F00046AF00E018E0BA680720CDE902B2CDF81A +:10A2000004B00090CDF810B0FB88BA88159800F023 +:10A2100071FA8DF81C00132030700120ADF8340065 +:10A2200093E000004C0000203988208B8142D2D17D +:10A230009DF81C004FF0160A0028A06B08D0E0B370 +:10A240004FF6FF7000215F46ADF808B0019027E09F +:10A2500068B1B978C907BED1E18F0DAB0844821D42 +:10A2600003968DE80C0243888288018809E0B8785B +:10A27000C007BCD0BA680DAB03968DE80C02BB8852 +:10A28000FA881598FFF7F5F905005ED0072D72D012 +:10A2900076E0019005AA02A92046FFF72BF90146B6 +:10A2A000E28FBDF80800824201D00029F1D0E08F92 +:10A2B000A16B084407800198E08746E09DF81C00E8 +:10A2C0004FF0180A40B1208BC8B13888208321464E +:10A2D0001598FFF798F938E004F118000090237EF4 +:10A2E000012221461598FFF7A6F98DF81C000028D9 +:10A2F000EDD1192030700120ADF83400E7E70525D5 +:10A3000021461598FFF77FF93AE0208800F40070A5 +:10A31000ADF8200050452DD1A08FA0F57F41FE392A +:10A3200001D006252CE0D8F808004FF0160A48B1F5 +:10A33000A063B8F80C10A1874FF6FF71E187A0F871 +:10A3400000B002E04FF6FF70A087BDF8200030F4A7 +:10A350007F611AD0782300220420159905F046FF6A +:10A3600098F8000020712088BDF820100843208054 +:10A370000EE000E007252088BDF8201088432080EB +:10A38000208810F47F6F1CD03AE02188814321801F +:10A390009DF8380020B10EA91598FBF707FC05467B +:10A3A0009DF81C000028EBD086F801A00120307039 +:10A3B000208B70809DF81C0030710520ADF83400B2 +:10A3C000DEE7A18EE1B118980DAB0088ADF834003E +:10A3D0002398CDE90304CDE90139206B0090E36AAD +:10A3E000179A1598FFF7FEF9054601208DF83800F9 +:10A3F0000EA91598FBF7DAFB00B10546A4F834B0B6 +:10A4000094F8460040070AD52046FFF7A2F910F05D +:10A410003E0F04D114F8460F20F004002070189865 +:10A42000BDF83410018028469DE500B585B00428AC +:10A4300006D102208DF8000088B26946FBF7B6FB12 +:10A4400005B000BD10B5384C0B782268012B02D046 +:10A45000022B2AD111E013780BB1052B01D1042373 +:10A46000137023688A889A802268CB88D3802268F8 +:10A470000B891381498951810DE08B889380226873 +:10A48000CB88D38022680B8913814B8953818B89B8 +:10A490009381096911612168FBF788FB226800211B +:10A4A0000228117003D0002800D0812010BD832025 +:10A4B00010BD806B002800D00120704781780129F1 +:10A4C00009D10088B0F5205F03D042F6010188422F +:10A4D00001D10020704707207047F0B587B00024F5 +:10A4E00015460E460746ADF8144010E00698018860 +:10A4F0002980811DCDE90241072101940494009136 +:10A50000838842880188384600F0F4F830B906AAFA +:10A5100005A93046FEF7EEFF0028E7D00A2800D153 +:10A52000002007B0F0BD00004C00002010B58B7873 +:10A5300083B102789A4205D10B885BB102E08B7936 +:10A54000091D4BB18B789A42F9D1B0F801300C88D3 +:10A55000A342F4D1002010BD812010BD072826D0D1 +:10A5600012B1012A27D103E0497801F0070102E086 +:10A570004978C1F3C20105291DD2DFE801F00318B3 +:10A58000080C12000AB1032070470220704704280B +:10A590000DD250B10DE0052809D2801E022808D343 +:10A5A00003E0062803D0032803D0052070470020CD +:10A5B00070470F20704781207047C0B282060BD4CD +:10A5C000000607D5FE48807A4143C01D01EBD0004C +:10A5D00080B27047084670470020704770B51388F6 +:10A5E0000B800B781C0625D5F54CA47A844204D840 +:10A5F00043F010000870002070BD956800F0070659 +:10A6000005EBD0052D78F54065F304130B70137836 +:10A61000D17803F0030341EA032140F20123B1FBA7 +:10A62000F3F503FB15119268E41D00FB012000EB1C +:10A63000D40070BD906870BD37B51446BDF80410E5 +:10A6400011809DF804100A061ED5C1F30013DC49E1 +:10A65000A568897A814208D8FE2811D1C91DC90888 +:10A660005A4228460CF0E5FD0AE005EBD00100F067 +:10A670000702012508789540A843934018430870C5 +:10A68000207820F0100020703EBD2DE9F0410746F3 +:10A69000C81C0E4620F00300B04202D08620BDE860 +:10A6A000F081C74D002034462E60AF802881AA7209 +:10A6B000E8801AE0E988491CE980810614D4E17831 +:10A6C00000F0030041EA002040F20121B0FBF1F26A +:10A6D00001FB12012068FFF770FF2989084480B24E +:10A6E0002881381A3044A0600C3420784107E1D426 +:10A6F0000020D4E72DE9FF4F89B01646DDE9168A20 +:10A700000F46994623F44045084600F00DFB04002F +:10A710000FD0099802F056F90290207800060AD569 +:10A72000A748817A0298814205D887200DB0BDE8FC +:10A73000F08F0120FAE7224601A90298FFF74EFFA9 +:10A74000834600208DF80C004046B8F1070F1AD060 +:10A7500001222146FFF702FF0028E7D120784006BA +:10A7600011D502208DF80C00ADF81070BDF8040072 +:10A77000ADF81200ADF814601898ADF81650CDF889 +:10A780001CA0ADF818005FEA094004D500252E464C +:10A79000A84601270CE02178E07801F0030140EAA7 +:10A7A000012040F20121B0FBF1F2804601FB12874B +:10A7B0005FEA494009D5B84507D1A178207901F071 +:10A7C000030140EA0120B04201D3BE4201D9072073 +:10A7D000ACE7A8191FFA80F9B94501D90D20A5E702 +:10A7E0009DF80C0028B103A90998FBF7DDF90028B2 +:10A7F0009CD1B84507D1A0784FEA192161F3010037 +:10A80000A07084F804901A9800B10580199850EA55 +:10A810000A0027D0199830B10BEB06002A46199987 +:10A820000CF090FC0EE00BEB06085746189E0998BA +:10A8300002F030FA2B46F61DB5B239464246009575 +:10A8400001F039FE224601A90298FFF7C7FE9DF8E4 +:10A850000400224620F010008DF80400DDE901100C +:10A86000FFF7EAFE002061E72DE9FF4FDFF8509186 +:10A8700082461746B9F80610D9F8000001EB4101ED +:10A8800000EB810440F20120B2FBF0F185B000FB47 +:10A8900011764D46DDF84C8031460698FFF78DFE67 +:10A8A00029682A898B46611A0C3101441144AB880E +:10A8B00089B28B4202D8842009B038E70699CDB21C +:10A8C000290603D5A90601D50620F5E7B9F806C083 +:10A8D0000CF1010C1FFA8CFCA9F806C0149909B1FF +:10A8E000A1F800C0A90602D5C4F8088007E010440A +:10A8F00080B2A9F80800191A01EB0B00A0602246EB +:10A90000FE200699FFF798FEE77026712078390A35 +:10A9100061F30100320AA17840F0040062F3010102 +:10A92000A17020709AF802006071BAF80000E0800F +:10A9300000262673280602D599F80A7000E0012740 +:10A94000A80601D54FF000084D4600244FF0070936 +:10A950000FE0CDE902680196CDF800900496E988F1 +:10A960002046129B089AFFF7C5FE0028A4D1641C5C +:10A97000E4B2BC42EDD300209EE72DE9F0478046CB +:10A9800000F0D2F9070005D0002644460C4D40F2F5 +:10A99000012919E00120BDE8F087204600F0C4F944 +:10A9A0000278C17802F0030241EA0222B2FBF9F315 +:10A9B00009FB13210068FFF700FE304486B201E076 +:10A9C0008C040020641CA4B2E988601E8142E4DC8F +:10A9D000A8F10100E8802889801B288100203870B8 +:10A9E000D9E710B5144631B1491E218001F0EAFFC4 +:10A9F000A070002010BD012010BD10B5D249044642 +:10AA00000088CA88904201D30A2010BD096800EB73 +:10AA1000400001EB80025079A072D08820819178AB +:10AA2000107901F0030140EA0120A081A078E11C27 +:10AA3000FFF7D4FD20612088401C2080E0800020AA +:10AA400010BD0121018270472DE9FF4F85B04FF6FF +:10AA5000FF788246A3F8008048681F460D4680783C +:10AA60008DF8060048680088ADF8040000208DF8D5 +:10AA70000A00088A0C88A04200D304462C8241E0D8 +:10AA8000288A401C2882701D6968FFF74FFDB8BBFB +:10AA90003988414501D1601E38806888A04236D38C +:10AAA000B178307901F0030140EA012901A9701D54 +:10AAB000FFF73CFD20BB298941452CD000223146BF +:10AAC0000798FFF74BFDD8B92989494518D1E9689E +:10AAD0000391B5F80AC0D6F808B05046CDF800C0CA +:10AAE00002F0D8F8DDF800C05A460CF1070C1FFA46 +:10AAF0008CFC4B460399CDF800C001F0A6FC50B188 +:10AB0000641CA4B2204600F00FF90600B8D1641E00 +:10AB10002C820A20D0E67C807079B871F088B880E9 +:10AB20003178F07801F0030140EA01207881A7F83C +:10AB30000C90504601F046FF324607F10801FFF73E +:10AB40004DFD38610020B7E62DE9FF4F87B0814603 +:10AB50001C469246DDF860B0DDF85480089800F09D +:10AB6000E3F805000CD0484601F02CFF29780906CF +:10AB700008D57549897A814204D887200BB0D6E57B +:10AB80000120FBE7CAF309062A4601A9FFF726FDC3 +:10AB90000746149807281CD000222946FFF7DEFC40 +:10ABA0000028EBD12878400613D501208DF8080045 +:10ABB0000898ADF80C00BDF80400ADF80E00ADF833 +:10ABC0001060ADF8124002A94846FAF7EDFF0028E0 +:10ABD000D4D12978E87801F0030140EA0121AA786C +:10ABE000287902F0030240EA0220564507D0B1F569 +:10ABF000007F04D9611E814201DD0B20BEE7864241 +:10AC000001D90720BAE7801B85B2A54200D92546A5 +:10AC1000BBF1000F01D0ABF80050179818B1B9196B +:10AC20002A460CF08FFAB8F1000F0DD03E4448468A +:10AC30004446169F02F040F82146FF1DBCB2324642 +:10AC40002B46009401F06BFC002097E72DE9F041C2 +:10AC500007461D461646084600F066F804000BD06D +:10AC6000384601F0AFFE2178090607D53649897AC2 +:10AC7000814203D8872012E5012010E522463146A3 +:10AC8000FFF7ACFC65B12178E07801F0030140EA00 +:10AC90000120B0F5007F01D8012000E000202870DD +:10ACA0000020FCE42DE9F04107461D461646084603 +:10ACB00000F03AF804000BD0384601F083FE21780A +:10ACC000090607D52049897A814203D88720E6E41E +:10ACD0000120E4E422463146FFF7AEFCFF2D14D0FC +:10ACE0002178E07801F0030240EA022040F20122DC +:10ACF000B0FBF2F302FB130015B900F2012080B2A1 +:10AD0000E070000A60F3010121700020C7E410B573 +:10AD10000C4600F009F828B1C18821804079A07064 +:10AD2000002010BD012010BD0749CA88824209D306 +:10AD300040B1096800EB40006FF00B0202EB8000AD +:10AD400008447047002070478C04002010B505F0BF +:10AD5000F6FCF7F781FE05F0B7FBBDE8104005F003 +:10AD600045BC70B50346002002466FF02F050EE08B +:10AD70009C5CA4F130060A2E02D34FF0FF3070BD68 +:10AD800000EB800005EB4000521C2044D2B28A4206 +:10AD9000EED370BD30B50A240AE0B0FBF4F304FB37 +:10ADA00013008D18303005F8010C521E1846D2B22F +:10ADB000002AF2D130BD30B500234FF6FF7510E008 +:10ADC000040A44EA002084B2C85C6040C0F3031463 +:10ADD000604005EA00344440E0B25B1C84EA401065 +:10ADE0009BB29342ECD330BD70B514460B88012260 +:10ADF000A240134207D113430B8001230922011DF6 +:10AE000001F0BBFC047070BD2DE9FF4F81B00878E4 +:10AE1000DDE90E7B9A4691460E4640072CD40198F8 +:10AE200001F04AFF040000D1FFDF07F104082046CB +:10AE30001FFA88F101F0A7F8050000D1FFDF2046D6 +:10AE400029466A4601F0F1FA0098A0F80370A0F8CC +:10AE500005A0284601F097FB017869F306016BF322 +:10AE6000C711017020461FFA88F101F0CFF800B930 +:10AE7000FFDF019800F04CFB06EB0900017E491C46 +:10AE8000017605B0BDE8F08F2DE9F84F0E469A46E1 +:10AE900091460746032101F0CBFD0446808CDFF884 +:10AEA0009085002518B198F80000B0421ED13846B0 +:10AEB00001F002FF070000D1FFDF09F1040138466D +:10AEC00089B201F060F8050010D0384629466A467C +:10AED00001F0ABFA009800210A460180817000F071 +:10AEE00089FB0098C01DCAF8000021E098F8000016 +:10AEF000B04216D104F1220734F8301F012000FAC5 +:10AF000006F911EA090F00D0FFDF2088012340EA8B +:10AF1000090020800922391D384601F049FC0670DD +:10AF200006E0324604F1300104F12200FFF75CFF35 +:10AF3000092188F800102846BDE8F88FFEB51446B0 +:10AF40000D46064602AB0C220621FFF79DFF0028A6 +:10AF500026D00299687812220A70801C4870082254 +:10AF60004A80A870208888806088C880A08808816E +:10AF7000E088488100240C20CDE900040523062246 +:10AF800029463046FFF740FF214666F31F41F02374 +:10AF90000022012005F02AF96878801C68700120E1 +:10AFA000FEBD10B50446032101F042FD014600F14B +:10AFB00010022046BDE81040C0E72DE9FE4381465F +:10AFC00050781646884640B1FFDF3168C8F8041053 +:10AFD0007168C8F80810BDE8FE83B778022417B17D +:10AFE000022F13D0FFDF251D2A4602AB072148465A +:10AFF000FFF74AFF0028E8D002980121022F0170D4 +:10B00000317841704480878002D005E00624EAE769 +:10B01000B188C180F18801810024CDE90054052365 +:10B02000072241464846FFF7EFFE88F80440D2E782 +:10B0300010B50446032101F0FBFC0146021D204629 +:10B04000BDE81040B9E7FA4A0020092111707047A5 +:10B0500070B50C461546342120460CF014F9012039 +:10B060006070092104F118000CF00DF905B9FFDF3B +:10B070002978207861F30100207070BD70470021AD +:10B0800010B560F31F41012005F05AF9002010BDF2 +:10B09000FEB506460F0CFCF7A1FE050007D06F8039 +:10B0A0000321384601F0C4FC040008D106E003B0D7 +:10B0B0003846BDE8F0401321F7F7D9B9FFDF012E7C +:10B0C00001D0FFDFFEBD20782A4620F00800207066 +:10B0D00002208DF800004FF6FF70ADF80200ADF8C9 +:10B0E000040069463846F6F784FDFEBD00B5FFDF73 +:10B0F000002000BD2DE9FC410C461E461746804647 +:10B10000032101F095FC0546092C0AD2DFE804F082 +:10B1100005050505050509090700042303E00623C5 +:10B1200001E0FFDF0023CDE90076224629464046B4 +:10B13000FFF76AFEBDE8FC8138B50546A0F57F4003 +:10B14000FF381CD0284601F0A5FD040000D1FFDF28 +:10B15000204601F048F9002810D001466A462046F2 +:10B1600001F063F900980321B0F80540284601F08A +:10B170005FFC052C03D1007908B1002038BD012007 +:10B1800038BD2DE9F041044686B0408801F082FDCB +:10B19000050000D1FFDF03AA2846616800F038F9F6 +:10B1A000039D001F80B235F8032F698882420AD1BF +:10B1B00004290BD0052918D0062904D16088291D3F +:10B1C0006368F8F771FA06B0BDE8F08116462D1DE8 +:10B1D000224629463046F9F7F1FF0828F3D12246E6 +:10B1E00029463046FBF707F8EDE71646608803214D +:10B1F00001F01EFC00218DF80010042EE3D36A79C3 +:10B20000002AE0D02B7902274FF6FF78012B28D0B7 +:10B21000122B01D0132B0BD00491059169798DF875 +:10B2200010106388014604AA1846FFF7C6FECAE755 +:10B2300083789342C7D102781307C4D5062EC2D1B2 +:10B2400022F008020270608860F31F41012005F0BF +:10B2500077F88DF80070ADF802802889ADF8040009 +:10B2600017E0062EAFD383789342ACD10278130750 +:10B27000A9D522F008020270608860F31F41012006 +:10B2800005F05EF88DF800702889ADF80200ADF881 +:10B290000480608822466946F6F7ABFC93E770B5F8 +:10B2A0000D460646032101F0C3FB040004D02078BC +:10B2B000000704D5112070BD43F2020070BD2A467C +:10B2C00021463046FFF73AFE18B9286820616868C1 +:10B2D0006061207840F008002070002070BD2DE9EA +:10B2E000F04F0E4691B08046032101F0A1FB0446C9 +:10B2F000404601F0E1FC07460020079008900990C5 +:10B30000ADF830000A9002900390049004B9FFDF7A +:10B310000DF10809FFB9FFDF1DE038460BA9002237 +:10B3200000F024FF9DF82C0000F07F05092D00D3CC +:10B33000FFDF6019017E491E01769DF82C00000692 +:10B3400009D52A460CA907A8FFF74EFD19F80510E4 +:10B35000491C09F80510761EF6B2DED204F1300061 +:10B36000334D04F1220BDFF8CCA004F12607069040 +:10B3700010E05846069900F04DF806462870092856 +:10B3800000D3FFDF5AF8261040468847608CC05D26 +:10B39000B04202D0A08C0028EBD109202870254DA6 +:10B3A0004E4624350EE00CA907A800F033F80446F9 +:10B3B000375D55F8240000B9FFDF55F824203946E1 +:10B3C00040469047BDF81E000028ECD111B059E569 +:10B3D00010B5032101F02CFB040000D1FFDF09218F +:10B3E00004F118000BF04FFF207840F004002070AB +:10B3F00010BD10B50C46032101F01AFB01190A7E9D +:10B4000001211AB9008EA140084000D0012010BDD2 +:10B4100001F00BB810B50C4601230922011D01F003 +:10B42000E2F900782188012282409143218010BDF9 +:10B4300054000020107601002DE9FC470C4606461A +:10B44000694600F01DFD002860D106F07BF8B0428F +:10B450005CD02146304608F029FC28BB019D95F8B8 +:10B46000E400383518B9A87E08B1012000E00020BA +:10B47000814695F835004FF000084FF0010AA0B161 +:10B4800095F83600800710D584F8018084F800A074 +:10B4900084F80280A68095F83710A171298F218148 +:10B4A000698F618185F835802DE0304601F004FC1C +:10B4B000070000D1FFDF384600F032FE40B184F8CB +:10B4C00001800E212170A680E08084F802A01AE09D +:10B4D000304601F0DFFB070000D1FFDFB9F1000FBC +:10B4E00014D0384600F073FE80B1304605F0F5FE0A +:10B4F00084F801800B21217084F80280A680E97E07 +:10B50000A17185F81A800120BDE8FC870020FBE7C7 +:10B510001CB5694600F0B4FC00B1FFDF684600F0DE +:10B52000BCFCFA4900208968A1F8AA001CBD2DE9DD +:10B53000FC4104460E46062001F026FA0025074687 +:10B54000A846064417E02088401C80B22080B04204 +:10B5500002D34046A4F8008080B2B84204D3B0427F +:10B5600002D20020BDE8FC81694600F089FC002879 +:10B57000F8D06D1CEDB2AE42E5D84FF6FF702080DA +:10B580001220EFE710B505F019FF09F0EBFEE048D7 +:10B590004FF6FF711B228182C182002101708170F0 +:10B5A00082804FF4A471C18002814181032303731F +:10B5B000042141730146CA810A82438210BD70B5DD +:10B5C000D24C0D466060217005F085FE00F071FCE4 +:10B5D000FFF7D8FF207809F0B9F9284607F051F9AC +:10B5E00005F0F0FF2178606808F021FCBDE87040AC +:10B5F00009F0B8BE10B501240AB1002010BD21B178 +:10B60000012903D00024204610BD02210AF0DCFBF2 +:10B61000F9E72DE9F041040000D1FFDFBC48022129 +:10B6200016308046FFF783FF00B1FFDFB84D0620DC +:10B63000EF8A01F0A9F90646E88AB0421AD12046FD +:10B6400005F038FFE8B12078132817D1A0783C28FE +:10B6500014D1A088062101F0EBF9050000D1FFDF2D +:10B66000288805F03AFEA088062101F0F3F928B1F8 +:10B67000FFDF03E02146FFF7DFFE10B10120BDE848 +:10B68000F08102214046FFF752FF10B9E88AB84224 +:10B69000D2D10020F3E710B500F0CEFB08B10C20AA +:10B6A00010BD09F096FE002010BD10B504460078CC +:10B6B00018B1012801D0122010BD00F0C8FB20B144 +:10B6C00009F0E4FE08B10C2010BD207800F09EFBCC +:10B6D000E21D04F11703611CBDE8104009F08EBEA5 +:10B6E00010B50446007818B1012801D0122010BD11 +:10B6F00000F0A2FB08B10C2010BD207800F086FB02 +:10B70000611C09F042FE08B1002010BD072010BDE9 +:10B7100010B509F0BFFE08B1002010BD302010BDEB +:10B7200010B5044600F093FB08B10C2010BD204674 +:10B7300009F0A8FE002010BD10B500F088FB20B174 +:10B7400009F0A4FE08B10C2010BD09F08DFE002008 +:10B7500010BDFF2181704FF6FF7181806B494968F0 +:10B760000A7882718A880281498841810121417069 +:10B770000020704710B510F1080F17D00CDC10F145 +:10B78000280F13D010F1140F10D010F1100F0DD09E +:10B7900010F10C0F08D109E010F1040F06D028B108 +:10B7A000032803D0042801D0122010BD05F0B7F8FB +:10B7B000002010BD10B5134601220AF097F80020B2 +:10B7C00010BD10B5044600F042FB08B10C2010BDBE +:10B7D0002146002005F0F3FD002010BD10B5044601 +:10B7E00007F091FA20B1207807F07CF8002010BD16 +:10B7F0000C2010BD10B5044600F029FB08B10C2048 +:10B8000010BD2146012005F0DAFD002010BD38B53D +:10B8100004464FF6FF70ADF80000A079E179884248 +:10B8200013D021791F2910D861791F290DD8002242 +:10B8300011460AF023FF40B90022E07911460AF0D0 +:10B840001DFF10B9207A072801D9122038BD07F052 +:10B8500066FA48B900216846FFF769FE20B1204624 +:10B8600004F09CFF002038BD0C2038BD2DE9FC41C0 +:10B87000817804461A2925D00EDC16292DD2DFE85E +:10B8800001F02C2C2C2C2C212C2C2C2C2C2C2C2C6A +:10B890002C2C2C2C2C2121212A291ED00BDCA1F1AF +:10B8A0001E010C2919D2DFE801F018181818181811 +:10B8B00018181818180D3A3904290ED2DFE801F0CB +:10B8C0000D020D022088B0F5706F06D2012769467F +:10B8D00000F0D6FA18B1022044E6122042E6019D9B +:10B8E00068462E4605F5A37506F2471600F0B6FA2F +:10B8F00008B1287808B10C2034E62F70A078307099 +:10B90000684600F0CAFA00202CE60000580000202B +:10B91000980400201CB50C46694600F0B1FA0021DD +:10B9200018B12160217102201CBD019802463830F7 +:10B9300080F83E1093682360137B237190F83E30AB +:10B94000002BF5D100201CBD10B5044600F07FFA95 +:10B9500020B109F09BFD08B10C2010BD207800F04B +:10B9600055FAE279611C09F06AFE08B1002010BDA9 +:10B97000022010BD7CB504460088694600F080FABC +:10B98000020025D1A17801B90321E07800B9032094 +:10B99000019D0024012385F86931019D95F89A5194 +:10B9A0003DB9019D95F868511DB9019D95F85B5011 +:10B9B0000DB13A2208E0019D85F86831019B83F8BA +:10B9C0006A11019981F86B01019880F8694110466C +:10B9D0007CBD8178CA0802D1C278D30801D0122078 +:10B9E0007047490701D4510701D511207047C1E7BD +:10B9F00030B5428840F67B43911F994219D2818825 +:10BA00008C1F9C4215D28A4213D8C288B2F5FA7FA5 +:10BA10000FD2038940F67745A3F10A04AC4208D25D +:10BA2000521C4A43B2EB830F03DA41898089814279 +:10BA300001D9302030BD002030BD10B5044607F0DC +:10BA40006EF908B10C2010BD6079032824D8A179C3 +:10BA5000012921D8A17B03291ED8617BE1B10729E7 +:10BA60001AD82179052917D2DFE801F0030C030366 +:10BA700003002288202A0FD361888A420CD8B1F5AE +:10BA8000804F09D805F0F8FDFA4920794870204622 +:10BA9000BDE8104005F0B8BE122010BD10B51F283B +:10BAA00001D9122010BD05F029FF002010BD10B5EE +:10BAB0001F2801D9122010BD05F00FFF002010BD76 +:10BAC0007CB5012802D0002853D066E005F084FD43 +:10BAD000002862D005F0B6FD00285ED007F01FF9FF +:10BAE000F0BB05F02FFDA0F57F41FF3947D105F0F0 +:10BAF00041FEE04E707848B1012807D0042805D0F7 +:10BB0000002006F0F2FE60B3FFDF44E000220621D1 +:10BB100001A800F05FFF050029D0D7480321856008 +:10BB2000284609F03AFE284605F0EDFFD14C708A10 +:10BB3000012106F099FF0146A8620022284606F07E +:10BB4000E0FA228AE189707B0090337B288801F03B +:10BB50002AF800B1FFDF288805F0BEFB284601E087 +:10BB60000DE018E006F0C1FEA8B1FFDF13E00920E8 +:10BB70007CBD06F0A7FA044606F05CFE08B10C2076 +:10BB80007CBD44B1208805F0A8FB2088062100F088 +:10BB900061FF00B1FFDF00207CBD12207CBD70B5CD +:10BBA0000D46062100F044FF040003D094F849013B +:10BBB00010B10AE0022070BD94F84400142801D0AE +:10BBC000152802D194F8800108B10C2070BD102214 +:10BBD000294604F5A5700BF0B5FA012084F8490157 +:10BBE000002070BD10B5062100F022FF18B190F8BA +:10BBF000491111B107E0022010BD90F8441014293A +:10BC000003D0152901D00C2010BD022180F8491164 +:10BC1000002010BD2DE9FC410D464BF6803212216B +:10BC2000954213D895B1694600F02AF900280CD145 +:10BC3000019EB41C383627882A463946304609F01A +:10BC4000A2FD2088B842F6D100208BE4084689E4A2 +:10BC50001CB504460088694600F012F9002811D18D +:10BC600001987F22014680F8402080F84120002280 +:10BC700080F84220A07801F82C0FE07848702079F5 +:10BC8000887010461CBD1CB50C46694600F0F8F8DB +:10BC9000002806D1019890F8520000B101202070D0 +:10BCA00000201CBD1CB50C46694600F0E9F80028D0 +:10BCB00005D1019890F82C00012801D00C201CBD62 +:10BCC000019890F84000207000201CBD70B50D4612 +:10BCD0001646062100F0ACFE18B381880124C38803 +:10BCE000428804EB4104AC4217D842F2107463431B +:10BCF000A4106243B3FBF2F2521E94B24FF4FA72F4 +:10BD0000944200D91446A54200D22C46491C641C1A +:10BD1000B4FBF1F24A43521E91B290F86C211AB969 +:10BD200001E0022070BD01843180002070BD10B59B +:10BD30000C46062100F07CFE48B180F8B74024B1E3 +:10BD400090F8B51009B106F0ACFE002010BD02203D +:10BD500010BD017889B1417879B141881B290CD394 +:10BD600081881B2909D3C188022906D34149026869 +:10BD7000CA6040680861002070471220704710B503 +:10BD800006F041FE002010BD70B514460A46064676 +:10BD900000250121104606F067FE002800D828463D +:10BDA00005460121304600F038F806460121002002 +:10BDB00000F033F83118012296318D4206D901F195 +:10BDC0009600691AB1FBF0F0401C82B2228000207C +:10BDD00070BD10B5044600F03AF808B10C2010BD53 +:10BDE000601C09F019FC207800F0010005F047FC08 +:10BDF000002010BD10B5044606F091FF08B10C20DC +:10BE000010BD204605F08AFD002010BD18B10228A3 +:10BE100001D0012070470020704710B5012904D0DF +:10BE2000022905D0FFDF204610BDC000503001E0E0 +:10BE300080002C3084B2F6E710B506F070FF20B118 +:10BE400005F0F9FB08B1012010BD002010BD10B5B0 +:10BE500006F065FF002800D0012010BD416891F870 +:10BE6000E40091F8521049B940B1042806D00120ED +:10BE70007047000098040020580000200020F7E7D9 +:10BE800010B50C46062100F0D3FD606018B101200A +:10BE90002070002010BD022010BD416891F8B5202F +:10BEA000002AE5D0002281F8B520406806F0F9BDEF +:10BEB000DEE708B54FF6FF70ADF8000006E006219A +:10BEC000BDF8000000F0C6FD00B1FFDF00216846AC +:10BED000FFF72DFB0028F2D008BD000030B5058823 +:10BEE00025F4004421448CB24FF4004194420AD21C +:10BEF000121B92B21B339A4201D2A94307E005F408 +:10BF00000041214303E0A21A92B2A94311430180E8 +:10BF100030BD0844083050434A31084480B270476D +:10BF200070B51D4616460B46044629463046049A0F +:10BF3000FFF7EFFF0646B34200D2FFDF282120467D +:10BF40000BF0A1F94FF6FF70A082283EB0B26577E2 +:10BF50006080B0F5004F00D9FFDF618805F13C003B +:10BF6000814200D2FFDF60880835401B343880B240 +:10BF700020801B2800D21B2020800020A07770BDCD +:10BF80008161886170472DE9F05F0D46C1880446E4 +:10BF900000F12809008921F4004620F4004800F04F +:10BFA00062FB10B10020BDE8F09F4FF0000A4FF097 +:10BFB000010BB0450CD9617FA8EB0600401A083888 +:10BFC000854219DC09EB06000021058041801AE05A +:10BFD0006088617F801B471A083F0DD41B2F00DA51 +:10BFE000FFDFBD4201DC294600E0B9B2681A020455 +:10BFF000120C04D0424502DD84F817A0D2E709EB09 +:10C0000006000180428084F817B0CCE770B5044682 +:10C0100000F12802C088E37D20F400402BB11044D9 +:10C020000288438813448B4201D2002070BD002552 +:10C030008A4202D30180458008E0891A0904090C6C +:10C04000418003D0A01D00F01EFB08E0637F008844 +:10C050000833184481B26288A01DFFF73FFFE575E1 +:10C06000012070BD70B5034600F12804C5888088A2 +:10C0700020F400462644A84202D10020188270BD58 +:10C0800098893588A84206D3401B75882D1A20440C +:10C09000ADB2C01E05E02C1AA5B25C7F204430442E +:10C0A000401D0C88AC4200D90D809C8924B100242D +:10C0B00014700988198270BD0124F9E770B504462F +:10C0C00000F12801808820F400404518208A0028CB +:10C0D00025D0A189084480B2A08129886A881144AA +:10C0E000814200D2FFDF2888698800260844A189A0 +:10C0F000884212D1A069807F2871698819B1201DFA +:10C1000000F0C1FA08E0637F28880833184481B240 +:10C110006288201DFFF7E2FEA6812682012070BD05 +:10C120002DE9F041418987880026044600F1280561 +:10C13000B94218D004F10A0821F40040284441888B +:10C1400019B1404600F09FFA08E0637F0088083389 +:10C15000184481B262884046FFF7C0FE761C6189B0 +:10C16000B6B2B942E8D13046BDE8F0812DE9F041E0 +:10C1700004460B4627892830A68827F40041B4F8E6 +:10C180000A8001440D46B74201D10020ECE70AB114 +:10C19000481D106023B1627F691D18460AF0D2FF66 +:10C1A0002E88698804F1080021B18A1996B200F03E +:10C1B0006AFA06E0637F62880833991989B2FFF74B +:10C1C0008DFE474501D1208960813046CCE78188CA +:10C1D000C088814201D10120704700207047018949 +:10C1E0008088814201D1012070470020704770B5DE +:10C1F0008588C38800F1280425F4004223F4004117 +:10C2000014449D421AD08389058A5E192588638863 +:10C21000EC18A64214D313B18B4211D30EE0437F26 +:10C2200008325C192244408892B2801A80B22333CB +:10C23000984201D211B103E08A4201D1002070BDC1 +:10C24000012070BD2DE9F0478846C1880446008969 +:10C2500021F4004604F1280720F4004507EB060905 +:10C2600000F001FA002178BBB54204D9627FA81B17 +:10C27000801A002503E06088627F801B801A0838DE +:10C2800023D4E28962B1B9F80020B9F802303BB199 +:10C29000E81A2177404518DBE0893844801A09E024 +:10C2A000801A217740450ADB607FE18908303044FD +:10C2B00039440844C01EA4F81280BDE8F087454503 +:10C2C00003DB01202077E7E7FFE761820020F4E746 +:10C2D0002DE9F74F044600F12805C088884620F470 +:10C2E000004A608A05EB0A0608B1404502D20020E8 +:10C2F000BDE8FE8FE08978B13788B6F8029007EB89 +:10C300000901884200D0FFDF207F4FF0000B50EA88 +:10C31000090106D088B33BE00027A07FB946307101 +:10C32000F2E7E18959B1607F29440830504408445C +:10C33000B4F81F1020F8031D94F821108170E289D1 +:10C3400007EB080002EB0801E1813080A6F802B09B +:10C3500002985F4650B1637F30880833184481B239 +:10C360006288A01DFFF7BAFDE78121E0607FE189C7 +:10C3700008305044294408442DE0FFE7E089B4F830 +:10C380001F102844C01B20F8031D94F82110817051 +:10C3900009EB0800E28981B202EB0800E0813780F6 +:10C3A00071800298A0B1A01D00F06DF9A4F80EB044 +:10C3B000A07F401CA077A07D08B1E088A08284F80F +:10C3C00016B000BFA4F812B084F817B001208FE7B0 +:10C3D000E0892844C01B30F8031DA4F81F108078A2 +:10C3E00084F82100EEE710B5818800F1280321F4DC +:10C3F00000442344848AC288A14212D0914210D0C2 +:10C40000818971B9826972B11046FFF7E8FE50B9AF +:10C410001089283220F400401044197900798842AC +:10C4200001D1002010BD184610BD00F12803407F47 +:10C4300008300844C01E1060088808B9DB1E13606D +:10C4400008884988084480B270472DE9F04100F11E +:10C450002806407F1C4608309046431808884D88BF +:10C46000069ADB1EA0B1C01C80B2904214D9801A7B +:10C47000A04200DB204687B298183A4641460AF0AF +:10C4800035FE002816D1E01B84B2B844002005E038 +:10C49000ED1CADB2F61EE8E7101A80B20119A942F0 +:10C4A00006D8304422464146BDE8F0410AF01EBE9F +:10C4B0004FF0FF3058E62DE9F04100F12804407FAD +:10C4C0001E46083090464318002508884F88069A73 +:10C4D000DB1E90B1C01C80B2904212D9801AB042CB +:10C4E00000DB304685B299182A4640460AF02AFEFB +:10C4F000701B86B2A844002005E0FF1CBFB2E41EFA +:10C50000EAE7101A80B28119B94206D821183246DA +:10C5100040460AF017FEA81985B2284624E62DE900 +:10C52000F04100F12804407F1E4608309046431831 +:10C53000002508884F88069ADB1E90B1C01C80B287 +:10C54000904212D9801AB04200DB304685B298186A +:10C550002A4641460AF0F6FD701B86B2A844002028 +:10C5600005E0FF1CBFB2E41EEAE7101A80B2811991 +:10C57000B94206D82044324641460AF0E3FDA819E4 +:10C5800085B22846F0E5401D704710B5044600F11D +:10C590002801C288808820F400431944904206D0C4 +:10C5A000A28922B9228A12B9A28A904201D100201E +:10C5B00010BD0888498831B1201D00F064F80020C2 +:10C5C0002082012010BD637F62880833184481B245 +:10C5D000201DFFF783FCF2E70021C1810177418232 +:10C5E000C1758175704703881380C28942B1C288C2 +:10C5F00022F4004300F128021A440A60C0897047FF +:10C600000020704710B50446808AA0F57F41FF39AD +:10C6100000D0FFDFE088A082E08900B10120A07592 +:10C6200010BD4FF6FF71818200218175704710B5F2 +:10C630000446808AA0F57F41FF3900D1FFDFA07D4D +:10C6400028B9A088A18A884201D1002010BD01200C +:10C6500010BD8188828A914201D1807D08B100207D +:10C6600070470120704720F4004221F400439A42B1 +:10C6700007D100F4004001F40041884201D00120BC +:10C6800070470020704730B5044600880D4620F4FE +:10C690000040A84200D2FFDF21884FF400408843C9 +:10C6A0002843208030BD70B50C00054609D0082C09 +:10C6B00000D2FFDF1DB1A1B2286800F044F8201DB0 +:10C6C00070BD0DB100202860002070BD00210268FF +:10C6D00003E093881268194489B2002AF9D100F066 +:10C6E00032B870B500260D460446082900D2FFDF97 +:10C6F000206808B91EE0044620688188A94202D05B +:10C7000001680029F7D181880646A94201D1006855 +:10C710000DE005F1080293B20022994209D32844A2 +:10C72000491B0260818021680968216001602060E6 +:10C7300000E00026304670BD00230B608A8002684E +:10C740000A600160704700234360021D018102609E +:10C750007047F0B50F460188408815460C181E46F4 +:10C76000AC4200D3641B3044A84200D9FFDFA019BB +:10C77000A84200D9FFDF3819F0BD2DE9F041884605 +:10C7800006460188408815460C181F46AC4200D367 +:10C79000641B3844A84200D9FFDFE019A84200D941 +:10C7A000FFDF70883844708008EB0400BDE8F0813A +:10C7B0002DE9F041054600881E461746841B884631 +:10C7C000BC4200D33C442C8068883044B84200D935 +:10C7D000FFDFA019B84200D9FFDF688830446880C5 +:10C7E00008EB0400E2E72DE9F04106881D46044607 +:10C7F000701980B2174688462080B84201D3C01B0A +:10C8000020806088A84200D2FFDF7019B84200D9AA +:10C81000FFDF6088401B608008EB0600C6E7000071 +:10C820002DE9F041BF4D04469046A8780E46A0423F +:10C8300000D8FFDF05EB8607786A50F8240000B1C6 +:10C84000FFDFB868002816D0304600F032F9014604 +:10C85000B868FFF746FF05000CD0786A072E40F84D +:10C86000245000D3FFDFB0484246294650F8263016 +:10C87000204698472846BDE8F0812DE9F843050099 +:10C880000C46009524D00026E81C20F00300A842A6 +:10C8900000D0FFDFDFF88C820027314688F8007077 +:10C8A00088F8014088F8024088F8034088F804407E +:10C8B00088F8054088F80640684600F003F9002033 +:10C8C00042460099C91C21F00301009116B10FE006 +:10C8D0000126D9E702EB80035962002106E000BF80 +:10C8E000D3F824C04CF82170491CC9B2A142F7D337 +:10C8F0000099401C01EB8401C0B200910728E0D3ED +:10C90000481BBDE8F88310B5044603F08BFD08B161 +:10C91000102010BD2078834A618802EB8000927855 +:10C920000EE0436A53F8213043B14A1C6280A18073 +:10C93000406A50F82100A060002010BD491C89B257 +:10C940008A42EED86180052010BD70B505460C46C0 +:10C95000084603F067FD08B1102070BD072D01D314 +:10C96000072070BD25700020608070BD0EB569463F +:10C97000FFF7EBFF00B1FFDF6846FFF7C4FF08B128 +:10C9800000200EBD01200EBD10B50446072800D3BF +:10C99000FFDF6448005D10BD3EB5054600246946D2 +:10C9A000FFF7D3FF18B1FFDF01E0641CE4B2684673 +:10C9B000FFF7A9FF0028F8D02846FFF7E5FF001B86 +:10C9C000C0B23EBD57498978814201D9C0B2704793 +:10C9D000FF2070472DE9F04106291BD1514C00275B +:10C9E0003B464FF6FF7604EB810514F801C00AE0E0 +:10C9F000DC19D5F824E0A4B25EF824E0BEF1000F03 +:10CA000004D05B1C9BB29C45F2D83446048020467F +:10CA1000B44201D100202EE7BDE8F04100E7A0F5C7 +:10CA20007F43FF3B01D0072901D300207047F7E681 +:10CA3000A0F57F42FF3A0BD0072909D2394A9378F3 +:10CA4000834205D902EB8101496A51F82000704701 +:10CA5000002070472DE9F04104460D46A4F57F41C2 +:10CA600043F20200FF3902D0072D01D3072002E76D +:10CA70002C494FF000088A78A242F8D901EB8506CC +:10CA8000726A52F82470002FF1D0274839461C30C2 +:10CA900050F8252020469047716A284641F82480A6 +:10CAA00000F007F802463946B068FFF745FE00205F +:10CAB000E1E61D49383131F810004FF6FC71C01C19 +:10CAC000084070472DE9F843164E88460546002475 +:10CAD0002868C01C20F0030028602046FFF7E9FF0B +:10CAE000315D4843B8F1000F01D0002200E02A6810 +:10CAF0000146009232B100274FEA0D00FFF7D3FD47 +:10CB00001FB106E001270020F8E706EB8401009A38 +:10CB10008A602968641C0844E4B22860072CD7D3D3 +:10CB2000EFE60000B00400205876010070B50E4614 +:10CB30001D46114600F0D4F804462946304600F060 +:10CB4000D8F82044001D70BD2DE9F04190460D46F7 +:10CB500004004FF0000610D00027E01C20F0030076 +:10CB6000A04200D0FFDFDDB141460020FFF79BFD72 +:10CB70000C3000EB850617B112E00127EDE7614F9D +:10CB800004F10C00A9003C602572606000EB850098 +:10CB9000206060680AF077FB41463868FFF783FD44 +:10CBA0003046BDE8F0812DE9FF4F564C804681B0FC +:10CBB00020689A46934600B9FFDF2068027A424512 +:10CBC00003D9416851F8280020B143F2020005B0B2 +:10CBD000BDE8F08F5146029800F082F886B25846C0 +:10CBE0000E9900F086F885B27019001D87B2206892 +:10CBF000A14639460068FFF774FD04001FD0678026 +:10CC000025802946201D0E9D07465A460123009582 +:10CC1000FFF786F92088314638440123029ACDF87F +:10CC200000A0FFF77DF92088C1193846FFF7A8F961 +:10CC3000D9F800004168002041F82840C7E70420E7 +:10CC4000C5E770B52F4C0546206800B9FFDF2068A6 +:10CC5000017AA9420ED9426852F8251051B1002339 +:10CC600042F825304A880068FFF766FD21680020F9 +:10CC70000A7A08E043F2020070BD4B6853F8203096 +:10CC800033B9401CC0B28242F7D80868FFF71EFDD6 +:10CC9000002070BD70B51B4E05460024306800B9F9 +:10CCA000FFDF3068017AA94204D9406850F82500B6 +:10CCB00000B1041D204670BD70B5124E054600241B +:10CCC000306800B9FFDF3068017AA94206D94068B0 +:10CCD00050F8251011B131F8040B4418204670BDEE +:10CCE00010B50A460121FFF714F9C01C20F003001B +:10CCF00010BD10B50A460121FFF70BF9C01C20F04A +:10CD0000030010BD6400002070B50446C2F1100598 +:10CD100028190AF017FA15F0FF0108D0491EC9B208 +:10CD2000802060542046BDE870400AF08ABA70BD89 +:10CD300030B505E05B1EDBB2CC5CD55C6C40C45406 +:10CD4000002BF7D130BD10B5002409E00B78521E3E +:10CD500044EA430300F8013B11F8013BD2B2DC097D +:10CD6000002AF3D110BD2DE9F04389B01E46DDE95C +:10CD7000107990460D00044622D002460846F94933 +:10CD8000FEF718FD102221463846FFF7DCFFE07B56 +:10CD9000000606D5F34A3946102310320846FFF73D +:10CDA000C7FF102239464846FFF7CDFFF87B000643 +:10CDB00006D5EC4A4946102310320846FFF7B8FF63 +:10CDC000102120460AF03DFA0DE0103EB6B208EB05 +:10CDD0000601102322466846FFF7AAFF224628468E +:10CDE0006946FEF7E7FC102EEFD818D0F2B24146A4 +:10CDF0006846FFF789FF10234A46694604A8FFF7F3 +:10CE000097FF1023224604A96846FFF791FF2246A8 +:10CE100028466946FEF7CEFC09B0BDE8F083102332 +:10CE20003A464146EAE770B59CB01E4605461346B1 +:10CE300020980C468DF80800202219460DF10900B3 +:10CE40000AF080F9202221460DF129000AF07AF932 +:10CE500017A913A8CDE90001412302AA31462846AB +:10CE6000FFF781FF1CB070BD2DE9FF4F9FB014AEDE +:10CE7000DDE92D5410AFBB49CDE9007620232031E8 +:10CE80001AA8FFF770FF4FF000088DF808804FF0E8 +:10CE900001098DF8099054F8010FCDF80A00A08817 +:10CEA000ADF80E0014F8010C1022C0F340008DF80C +:10CEB000100055F8010FCDF81100A888ADF8150045 +:10CEC00015F8010C2C99C0F340008DF8170006A846 +:10CED00082460AF037F90AA88346102222990AF0FE +:10CEE00031F9A0483523083802AA40688DF83C8003 +:10CEF000CDE900760E901AA91F98FFF734FF8DF840 +:10CF000008808DF809902068CDF80A00A088ADF857 +:10CF10000E0014F8010C1022C0F340008DF8100030 +:10CF20002868CDF81100A888ADF8150015F8010C97 +:10CF30002C99C0F340008DF8170050460AF002F912 +:10CF40005846102222990AF0FDF886483523083801 +:10CF500002AA40688DF83C90CDE900760E901AA99F +:10CF60002098FFF700FF23B0BDE8F08FF0B59BB02D +:10CF70000C460546DDE922101E461746DDE9203243 +:10CF8000D0F801C0CDF808C0B0F805C0ADF80CC0AD +:10CF90000078C0F340008DF80E00D1F80100CDF804 +:10CFA0000F00B1F80500ADF8130008781946C0F37A +:10CFB00040008DF815001088ADF8160090788DF8B7 +:10CFC00018000DF1190010220AF0BCF80DF129002B +:10CFD000102231460AF0B6F80DF139001022394618 +:10CFE0000AF0B0F817A913A8CDE90001412302AA5D +:10CFF00021462846FFF7B7FE1BB0F0BDF0B5A3B041 +:10D0000017460D4604461E46102202A828990AF02B +:10D0100099F806A8202239460AF094F80EA8202292 +:10D0200029460AF08FF81EA91AA8CDE9000150235D +:10D0300002AA314616A8FFF796FE1698206023B084 +:10D04000F0BDF0B589B00446DDE90E070D4639782C +:10D05000109EC1F340018DF8001031789446C1F361 +:10D0600040018DF801101968CDF802109988ADF8CB +:10D07000061099798DF808100168CDF8091081889B +:10D08000ADF80D1080798DF80F0010236A466146C7 +:10D0900004A8FFF74DFE2246284604A9FEF78AFBA6 +:10D0A000D6F801000090B6F80500ADF80400D7F8F6 +:10D0B0000100CDF80600B7F80500ADF80A00002021 +:10D0C000039010236A46214604A8FFF731FE22464A +:10D0D000284604A9FEF76EFB09B0F0BD1FB51C6819 +:10D0E00000945B68019313680293526803920246AE +:10D0F00008466946FEF75EFB1FBD10B588B00446C2 +:10D10000106804905068059000200690079008462B +:10D110006A4604A9FEF74EFBBDF80000208008B067 +:10D1200010BD1FB51288ADF800201A88ADF8022096 +:10D130000022019202920392024608466946FEF7D7 +:10D1400039FB1FBD7FB5074B14460546083B9A1CAB +:10D150006846FFF7E6FF224669462846FFF7CDFFFF +:10D160007FBD0000A676010070B5044600780E462B +:10D17000012813D0052802D0092813D10EE0A06899 +:10D1800061690578052003F0DBF8052D0AD07823C6 +:10D1900000220520616903F029F803E00520616998 +:10D1A00003F0CEF831462046BDE8704001F086B865 +:10D1B00010B500F12D02C3799478411D64F0030489 +:10D1C0002340C371DB070DD04B79547923404B7159 +:10D1D0000B79127913400B718278C9788A4200D991 +:10D1E000817010BD00224A710A71F5E7417801296A +:10D1F00000D00C21017070472DE9F04F93B04FF033 +:10D20000000B0C690D468DF820B0097801260C2022 +:10D2100017464FF00D084FF0110A4FF008091B296F +:10D2200075D2DFE811F01B00C30206031E035D0385 +:10D230007003A203B703F803190461049304A00464 +:10D24000EC042A05340552055D05EE053106340669 +:10D2500063067F06F9061D07E606EB0614B1207883 +:10D260001D282AD0D5F808805FEA08004FD0012099 +:10D270008DF82000686A02220D908DF824200A2083 +:10D280008DF82500A8690A90A8880028EED098F8A3 +:10D29000001091B10F2910D27ED2DFE801F07D138A +:10D2A00049DEFEFDFCFBFAF938089CF8F70002287D +:10D2B0002DD124B120780C2801D00026EFE38DF881 +:10D2C0002020CBE10520696A03F03AF8A8880728F6 +:10D2D000EED1204600F0EDFF022809D0204600F0F4 +:10D2E000E8FF032807D9204600F0E3FF072802D211 +:10D2F0000120207004E0002CB8D020780128D7D17C +:10D3000098F80400C11F0A2902D30A2061E0C4E191 +:10D31000A070D8F80010E162B8F80410218698F8DF +:10D32000060084F83200012028700320207044E0B9 +:10D330000728BDD1002C99D020780D28B8D198F8B5 +:10D34000031094F82F20C1F3C000C2F3C0021042B2 +:10D3500001D0062000E00720890707D198F80510C2 +:10D360000142D2D198F806100142CED194F8312072 +:10D3700098F8051020EA02021142C6D194F8322032 +:10D3800098F8061090430142BFD198F80400C11FDD +:10D390000A29BAD2617D00E006E281427ED8D8F83F +:10D3A00000106160B8F80410218198F80600A0729E +:10D3B000012028700E20207003208DF82000686A5C +:10D3C0000D9004F12D000990601D0A900F300B9014 +:10D3D00022E12875FDE3412891D1204600F069FF44 +:10D3E000042802D1E078C00704D1204600F061FF94 +:10D3F0000F2884D1A88CD5F80C8080B24FF0400B58 +:10D40000E669FFF747FC324641465B464E46CDF89B +:10D410000090FFF750F80B208DF82000686A0D90FF +:10D42000E0690990002108A8FFF79EFE20780428F3 +:10D4300006D0A07D58B1012809D003280AD049E3BD +:10D4400005202070032028708DF82060CDE184F83D +:10D4500000A032E712202070E9E11128BCD120465B +:10D4600000F027FF042802D1E078C00719D0204639 +:10D4700000F01FFF062805D1E078C00711D1A07D7C +:10D4800002280ED0204600F014FF08E0CAE081E038 +:10D490006FE14EE121E101E1E7E017E0ADE11128A4 +:10D4A0009AD1102208F1010104F13C0009F04AFE72 +:10D4B000607801287ED012202070E078C00760D00C +:10D4C000A07D0028C8D00128C6D05AE0112890D1EC +:10D4D000204600F0EEFE082804D0204600F0E9FEC9 +:10D4E000132886D104F16C00102208F101010646D0 +:10D4F00009F028FE207808280DD014202070E1784B +:10D50000C8070DD0A07D02280AD06278022A04D074 +:10D510000328A1D035E00920F0E708B1012837D170 +:10D52000C80713D0A07D02281DD000200090D4E9A8 +:10D53000062133460EA8FFF776FC10220EA904F14F +:10D540003C0009F0D3FDC8B1042042E7D4E9091238 +:10D55000201D8DE8070004F12C0332460EA8616BF4 +:10D56000FFF76FFDE9E7606BC1F34401491E0068F6 +:10D57000C84000F0010040F08000D7E7207809287B +:10D5800006D185F800908DF8209033E32870ECE305 +:10D590000920FBE711289AD1204600F08AFE0A28CC +:10D5A00002D1E078C00704D1204600F082FE1528A1 +:10D5B0008DD100E08DE104F13C00102208F1010161 +:10D5C000064609F0BFFD20780A2816D016202070E4 +:10D5D000D4E90932606B611D8DE80F0004F15C0332 +:10D5E00004F16C0247310EA8FFF7C0FC10220EA90F +:10D5F000304609F07BFD18B1F5E20B20207071E296 +:10D600002046FFF7D5FDA078216A0A18C0F1100165 +:10D61000104609F016FE23E3394608A8FFF7A4FDDB +:10D6200006463BE20228B6D1204600F042FE04281E +:10D6300004D3204600F03DFE082809D3204600F020 +:10D6400038FE0E2829D3204600F033FE122824D2BB +:10D65000A07D02289FD10E208DF82000686A0D90D1 +:10D6600098F801008DF82400F0E3022893D12046B9 +:10D6700000F01FFE002810D0204600F01AFE0128FE +:10D68000F9D0204600F015FE0C28F4D004208DF8C7 +:10D69000240098F801008DF825005EE21128FCD1E5 +:10D6A000002CFAD020781728F7D16178606A022917 +:10D6B00011D0002101EB4101182606EBC101102217 +:10D6C000405808F1010109F03DFD0520696A00F0AC +:10D6D000E3FD2670F1E50121ECE70B28DDD1002CFC +:10D6E000DBD020781828D8D16078616A02281CD055 +:10D6F0005FF0000000EB4002102000EBC200095870 +:10D70000B8F8010008806078616A02280FD0002014 +:10D7100000EB4002142000EBC2000958404650F8CC +:10D72000032F0A604068486039E00120E2E70120E9 +:10D73000EEE71128B1D1002CAFD020781928ACD158 +:10D740006178606A022912D05FF0000101EB4101AB +:10D750001C2202EBC1011022405808F1010109F01E +:10D76000F1FC0520696A00F097FD1A20B6E001215E +:10D77000ECE7082891D1002C8FD020781A288CD182 +:10D78000606A98F80120017862F347010170616ACC +:10D79000D8F8022041F8012FB8F80600888005204B +:10D7A000696A00F079FD8EE2072012E638780128D8 +:10D7B00094D1182204F11400796809F008FDE07989 +:10D7C000C10894F82F0001EAD001E07861F300006D +:10D7D000E070217D002974D12178032909D0C00788 +:10D7E00025D0032028708DF82090686A0D90412084 +:10D7F00004E3607DA178884201D90620E9E502268C +:10D800002671E179204621F0E001E171617A21F091 +:10D81000F0016172A17A21F0F001A172FFF7C8FC5A +:10D820002E708DF82090686A0D900720E6E20420A3 +:10D83000ACE6387805289DD18DF82000686A0D90F7 +:10D84000B8680A900720ADF824000A988DF830B027 +:10D850006168016021898180A17A81710420207032 +:10D86000F4E23978052985D18DF82010696A0D9187 +:10D87000391D09AE0EC986E80E004121ADF824100D +:10D880008DF830B01070A88CD7F80C8080B240268C +:10D89000A769FFF711FA41463A463346C846CDF824 +:10D8A0000090FEF73CFE002108A8FFF75DFCE07841 +:10D8B00020F03E00801CE0702078052802D00F2068 +:10D8C0000CE049E1A07D20B1012802D0032802D05C +:10D8D00002E10720BFE584F80080EEE42070ECE46C +:10D8E000102104F15C0002F052FA606BB0BBA07D25 +:10D8F00018B1012801D00520FDE006202870F74866 +:10D900006063A063BEE23878022894D1387908B108 +:10D910002875B3E3A07D022802D0032805D022E0B9 +:10D92000B8680028F5D060631CE06078012806D054 +:10D93000A07994F82E10012805D0E84806E0A179D6 +:10D9400094F82E00F7E7B8680028E2D06063E0782A +:10D95000C00701D0012902D0E04803E003E0F868E5 +:10D960000028D6D0A063062010E68DF82090696AC2 +:10D970000D91E1784846C90709D06178022903D1A1 +:10D98000A17D29B1012903D0A17D032900D0072061 +:10D99000287031E138780528BBD1207807281ED0BF +:10D9A00084F800A005208DF82000686A0D90B86802 +:10D9B0000A90ADF824A08DF830B003210170E17811 +:10D9C000CA070FD0A27D022A1AD000210091D4E903 +:10D9D000061204F15C03401CFFF725FA67E384F8A4 +:10D9E0000090DFE7D4E90923211D8DE80E0004F142 +:10D9F0002C0304F15C02401C616BFFF722FB56E331 +:10DA0000626BC1F34401491E1268CA4002F0010171 +:10DA100041F08001DAE738780528BDD18DF8200083 +:10DA2000686A0D90B8680A90ADF824A08DF830B0FF +:10DA3000042100F8011B102204F15C0109F082FBB3 +:10DA4000002108A8FFF790FB2078092801D01320B7 +:10DA500044E70A2020709BE5E078C10742D0A17D11 +:10DA6000012902D0022927D038E0617808A80129CD +:10DA700016D004F16C010091D4E9061204F15C03A4 +:10DA8000001DFFF7BBFA0A20287003268DF82080BE +:10DA9000686A0D90002108A8FFF766FBDDE2C3E28B +:10DAA00004F15C010091D4E9062104F16C03001D2E +:10DAB000FFF7A4FA0026E9E7C0F3440114290DD2C8 +:10DAC0004FF0006101EBB0104FEAB060E070607899 +:10DAD000012801D01020BEE40620FFE6607801286E +:10DAE0003FF4B7AC0A2051E5E178C90708D0A17D21 +:10DAF000012903D10B20287004202FE028702DE08D +:10DB00000E2028706078616B012817D004F15C0347 +:10DB100004F16C020EA8FFF7E1FA2046FFF748FB7C +:10DB2000A0780EAEC0F11001304409F08AFB062047 +:10DB30008DF82000686A09960D909AE004F16C0354 +:10DB400004F15C020EA8FFF7C9FAE9E73978022967 +:10DB500003D139790029D1D029758FE28DF82000C1 +:10DB6000686A0D9058E538780728F6D1D4E909217C +:10DB70006078012808D004F16C00CDE90002029120 +:10DB800005D104F16C0304E004F15C00F5E704F155 +:10DB90005C0304F14C007A680646216AFFF764F9D9 +:10DBA0006078012821D1A078216A0A18C0F11001FB +:10DBB000104609F046FBD4E90923606B04F12D01FE +:10DBC0008DE80F0004F15C0304F16C0231460EA8ED +:10DBD00000E055E2FFF7CAF910220EA904F13C005B +:10DBE00009F084FA08B10B20AFE485F8008000BF8B +:10DBF0008DF82090686A0D908DF824A00CE5387897 +:10DC00000528AAD18DF82000686A0D90B8680A909E +:10DC1000ADF824A08DF830B080F80080617801293B +:10DC20001AD0D4E9093204F12D01A66B03920096B3 +:10DC3000CDE9011304F16C0304F15C0204F14C0121 +:10DC4000401CFFF793F9002108A8FFF78DFA6078D0 +:10DC5000012805D0152041E6D4E90923611DE4E738 +:10DC60000E20287006208DF82000686ACDF824B0B8 +:10DC70000D90A0788DF82800CEE438780328C0D124 +:10DC8000E079C00770D00F202870072066E7387849 +:10DC900004286BD11422391D04F1140009F097FAFD +:10DCA000616A208CA1F80900616AA078C871E179E5 +:10DCB000626A01F003011172616A627A0A73616A31 +:10DCC000A07A81F82400162060E485F800A08DF881 +:10DCD0002090696A50460D9190E00000A676010000 +:10DCE0003878052842D1B868A8616178606A02294D +:10DCF00001D0012100E0002101EB4101142606EBD7 +:10DD0000C1014058082102F042F86178606A022996 +:10DD100001D0012100E0002101EB410106EBC1012E +:10DD2000425802A8E169FFF70DFA6078626A02289A +:10DD300001D0012000E0002000EB4001102000EBAA +:10DD4000C1000223105802A90932FEF7F1FF626AEE +:10DD5000FD4B0EA80932A169FFF7E3F96178606A0B +:10DD6000022904D0012103E042E18BE0BDE0002163 +:10DD700001EB4101182606EBC101A27840580EA91B +:10DD800009F0E0F96178606A022901D0012100E020 +:10DD9000002101EB410106EBC1014058A178084484 +:10DDA000C1F1100109F04DFA05208DF82000686AD4 +:10DDB0000D90A8690A90ADF824A08DF830B0062126 +:10DDC00001706278616A022A01D0012200E000221B +:10DDD00002EB420206EBC202401C8958102209F0F5 +:10DDE000B1F9002108A8FFF7BFF91220C5F818B053 +:10DDF00028708DF82090686A0D900B208DF8240013 +:10DE00000AE43878052870D18DF82000686A0D90F2 +:10DE1000B8680A900B20ADF824000A980721017019 +:10DE20006178626A022901D0012100E0002101EB42 +:10DE30004103102101EBC30151580988A0F80110DA +:10DE40006178626A022902D0012101E02FE10021FC +:10DE500001EB4103142101EBC30151580A6840F85A +:10DE6000032F4968416059E01920287001208DF87E +:10DE7000300077E6162028708DF830B0002108A811 +:10DE8000FFF772F9032617E114202870B0E63878FE +:10DE900005282AD18DF82000686A0D90B8680A908C +:10DEA000ADF824A08DF830B080F800906278616AF7 +:10DEB0004E46022A01D0012200E0002202EB42027B +:10DEC0001C2303EBC202401C8958102209F03AF9C6 +:10DED000002108A8FFF748F9152028708DF8206068 +:10DEE000686A0D908DF824603CE680E0387805285B +:10DEF0007DD18DF82000686A0D90B8680A90ADF861 +:10DF000024900921017061690978490841706169AB +:10DF100051F8012FC0F802208988C18020781C2880 +:10DF2000A8D1A1E7E078C00702D04FF0060C01E0CD +:10DF30004FF0070C607802280AD04FF0000000BFB5 +:10DF400000EB040101F1090105D04FF0010004E0EC +:10DF50004FF00100F4E74FF000000B78204413EA83 +:10DF60000C030B7010F8092F02EA0C02027004D1A6 +:10DF70004FF01B0C84F800C0D2B394F801C0BCF180 +:10DF8000010F00D09BB990F800C0E0465FEACC7C5E +:10DF900004D028F001060670102606E05FEA887CAF +:10DFA00005D528F00206067013262E70032694F875 +:10DFB00001C0BCF1020F00D092B991F800C05FEA35 +:10DFC000CC7804D02CF001060E70172106E05FEA31 +:10DFD0008C7805D52CF002060E70192121700026D0 +:10DFE0000078D0BBCAB3C3BB1C20207035E012E060 +:10DFF00002E03878062841D11A2019E42078012857 +:10E000003CD00C283AD02046FFF7F0F809208DF8D4 +:10E010002000686A0D9031E03878052805D0062088 +:10E02000387003261820287046E005218DF820104E +:10E03000686A0D90B8680A900220ADF824000120AB +:10E040008DF830000A980170297D4170394608A882 +:10E05000FFF78AF8064618202870012E0ED02BE014 +:10E0600001208DF82000686A0D9003208DF82400AF +:10E07000287D8DF8250085F814B012E0287D80B148 +:10E080001D202070172028708DF82090686A0D9050 +:10E0900002208DF82400394608A8FFF765F80646E7 +:10E0A0000AE00CB1FE2020709DF8200020B1002174 +:10E0B00008A8FFF759F810E413B03046BDE8F08F18 +:10E0C0002DE9F04387B00C464E6900218DF804100D +:10E0D00001202578034602274FF007094FF0050C71 +:10E0E00085B1012D53D0022D39D1FE2030708DF82D +:10E0F0000030606A059003208DF80400207E8DF8C2 +:10E10000050063E02179012925D002292DD00329BA +:10E1100028D0042923D1B17D022920D131780D1FC7 +:10E12000042D04D30A3D032D01D31D2917D12189C4 +:10E13000022914D38DF80470237020899DF80410EF +:10E1400088421BD2082001E09E7601008DF8000075 +:10E15000606A059057E070780128EBD0052007B081 +:10E16000BDE8F0831D203070E4E771780229F5D115 +:10E1700031780C29F3D18DF80490DDE7083402F8EA +:10E1800004CB94E80B0082E80B000320E7E7157846 +:10E19000052DE4D18DF800C0656A05959568029556 +:10E1A0008DF8101094F80480B8F1010F13D0B8F175 +:10E1B000020F2DD0B8F1030F1CD0B8F1040FCED14F +:10E1C000ADF804700E202870207E6870002168462B +:10E1D000FEF7CAFF0CE0ADF804700B202870207E1B +:10E1E000002100F01F0068706846FEF7BDFF377021 +:10E1F0000020B4E7ADF804708DF8103085F800C049 +:10E20000207E6870277011466846FEF7ADFFA6E7CE +:10E21000ADF804902B70207F6870607F00F00100E3 +:10E22000A870A07F00F01F00E870E27F2A71C0078D +:10E230001CD094F8200000F00700687194F82100C9 +:10E2400000F00700A87100216846FEF78DFF2868DE +:10E25000F062A8883086A87986F83200A0694078F4 +:10E2600070752879B0700D203070C1E7A97169719F +:10E27000E9E700B587B005280CD101208DF8000032 +:10E280008DF80400002005918DF8050001466846D0 +:10E29000FEF76AFF07B000BD70B50C46054602F0F8 +:10E2A0004FF821462846BDE870407823002201F04F +:10E2B0009DBF08B1007870470C20704770B50C0006 +:10E2C00005784FF000010CD021702146F4F7A4FF2F +:10E2D00069482178405D884201D1032070BD022049 +:10E2E00070BDF4F799FF002070BD0279012A05D0B6 +:10E2F00000220A704B78012B02D003E00420704703 +:10E300000A758A6102799300521C0271C150032080 +:10E310007047F0B587B00F4605460124287905EB14 +:10E32000800050F8046C7078411E02290AD25249CC +:10E330003A46083901EB8000314650F8043C284643 +:10E34000984704460CB1012C11D12879401E10F0D9 +:10E35000FF00287101D00324E0E70A208DF80000B7 +:10E36000706A0590002101966846FFF7A7FF032C0D +:10E37000D4D007B02046F0BD70B515460A46044615 +:10E3800029461046FFF7C5FF064674B12078FE28DF +:10E390000BD1207C30B100202870294604F10C00FC +:10E3A000FFF7B7FF2046FEF721FF304670BD7047EC +:10E3B00070B50E4604467C2108F065FF0225012E4B +:10E3C00003D0022E04D0052070BD0120607000E053 +:10E3D00065702046FEF70AFFA575002070BD28B1C4 +:10E3E000027C1AB10A4600F10C01C5E70120704712 +:10E3F00010B5044686B0052001F0A2FF2078FE2863 +:10E4000006D000208DF8000069462046FFF7E7FFA0 +:10E4100006B010BD7CB50E4600218DF80410417881 +:10E42000012903D0022903D0002405E0046900E09B +:10E4300044690CB1217C89B16D4601462846FFF73D +:10E4400054FF032809D1324629462046FFF794FF9E +:10E450009DF80410002900D004207CBD04F10C05B7 +:10E46000EBE730B40C460146034A204630BC034B70 +:10E470000C3AFEF756BE0000E47601009E760100DD +:10E4800070B50D46040011D085B12101284608F071 +:10E49000D8FE10224E49284608F054FE4C4801216F +:10E4A0000838018044804560002070BD012070BDA7 +:10E4B00070B5474E00240546083E10E07068AA7B00 +:10E4C00000EB0410817B914208D1C17BEA7B914231 +:10E4D00004D10C22294608F009FE30B1641C3088B2 +:10E4E0008442EBDB4FF0FF3070BD204670BD70B54D +:10E4F0000D46060006D02DB1FFF7DAFF002803DB3A +:10E50000401C14E0102070BD314C083C208862880B +:10E51000411C914201D9042070BD6168102201EBB9 +:10E520000010314608F00EFE2088401C2080287024 +:10E53000002070BD70B514460D0018D0BCB100218C +:10E54000A170022802D0102811D105E0288870B1EE +:10E550000121A170108008E02846FFF7A9FF0028DC +:10E5600005DB401CA070A8892080002070BD012020 +:10E5700070BD70B5054614460E000BD000203070FB +:10E58000A878012808D005D91149A1F108010A8805 +:10E5900090420AD9012070BD24B1287820702888C3 +:10E5A000000A5070022008700FE064B14968102220 +:10E5B00001EB00112046103908F0C4FD28782073C3 +:10E5C0002888000A607310203070002070BD0000A1 +:10E5D000700000202DE9F04190460C4607460025CA +:10E5E000FE48072F00EB881607D2DFE807F0070781 +:10E5F000070704040400012500E0FFDF06F814709B +:10E60000002D13D0F548803000EB880191F82700E9 +:10E61000202803D006EB4000447001E081F826403A +:10E6200006EB44022020507081F82740BDE8F081BD +:10E63000F0B51F4614460E460546202A00D1FFDFDE +:10E64000E649E648803100EB871C0CEB440001EB07 +:10E650008702202E07D00CEB460140784B7848709B +:10E66000184620210AE092F82530407882F82500EB +:10E67000F6E701460CEB410005704078A142F8D165 +:10E6800092F82740202C03D00CEB4404637001E087 +:10E6900082F826300CEB41042023637082F82710A7 +:10E6A000F0BD30B50D46CE4B44190022181A72EB5E +:10E6B000020100D2FFDFCB48854200DDFFDFC94801 +:10E6C0004042854200DAFFDFC548401C844207DA39 +:10E6D000002C01DB204630BDC148401C201830BD55 +:10E6E000BF48C043FAE710B504460168407ABE4A05 +:10E6F00052F82020114450B10220084420F07F40FD +:10E70000F4F773FB94F90810BDE81040C9E7042042 +:10E71000F3E72DE9F047B14E803696F82D50DFF83B +:10E72000BC9206EB850090F8264034E009EB851793 +:10E730004FF0070817F81400012806D004282ED03F +:10E7400005282ED0062800D0FFDF01F0E3F80146AF +:10E7500007EB4400427806EB850080F8262090F80D +:10E760002720A24202D1202280F82720084601F06B +:10E77000DCF82A4621460120FFF72CFF9B48414642 +:10E7800000EB041002682046904796F82D5006EBE7 +:10E79000850090F82640202CC8D1BDE8F0870220E3 +:10E7A00000E003208046D0E710B58C4C2021803457 +:10E7B00084F8251084F8261084F82710002084F8A7 +:10E7C000280084F82D0084F82E10411EA16044F822 +:10E7D000100B2074607420736073A0738449E07719 +:10E7E00020750870487000217C4A103C02F8110026 +:10E7F000491CC9B22029F9D30120F4F7EAF9002015 +:10E80000F4F7E7F9012084F82200FAF73FF9794894 +:10E81000FAF74BF9764CA41E20707748FAF745F9C1 +:10E820006070BDE81040F4F761B910B5F4F783F9F2 +:10E830006F4CA41E2078FAF751F96078FAF74EF978 +:10E84000BDE8104001F09EB8202070472DE9F34F3D +:10E85000624E0025803606EB810A89B09AF82500C1 +:10E86000202822D0691E02916049009501EB00101A +:10E870008146D0E90112C0680391CDE90420B08B34 +:10E88000ADF81C00B07F8DF81E009DF81500C8B1D2 +:10E890000227554951F820400399E219114421F00B +:10E8A0007F41019184B102210FE00120F4F791F939 +:10E8B0000020F4F78EF9F4F75CF901F063F886F8BC +:10E8C0002F50A0E00427E4E700218DF8181002285B +:10E8D00001D0012820D10398391901440998081A58 +:10E8E0009DF81C1020F07F4001B10221333181429C +:10E8F0000BD203208DF815000398C4F13201401AA1 +:10E9000020F07F40322403900CE096F8240018B9E0 +:10E9100001F0A0F900284CD0322C03D214B101F040 +:10E9200025F801E001F02EF8314A107818B393462B +:10E930005278039B121B00219DF81840984601282D +:10E940001AD0032818D000208DF81E00002A04DDFC +:10E95000981A039001208DF818009DF81C0000B152 +:10E9600002210398254A20F07F40039003AB0998C9 +:10E9700001F014F810B110E00120E5E79DF81D004A +:10E9800018B99BF80000032812D08DF81C50CDF860 +:10E990000C808DF818408DF81E509DF8180058B165 +:10E9A00003980123C11900221846F4F765F906E01F +:10E9B00000200BB0BDE8F08F0120F4F70AF999F9B7 +:10E9C0000C20012300200199F4F756F9012086F864 +:10E9D0002F008AF828502022694611E0F006002016 +:10E9E000FF7F841E0020A107F4760100F0040020C0 +:10E9F000820000209B00010013E70000FFFF3F00A2 +:10EA0000F94808F0E4FB0120D3E72DE9F05FDFF8D7 +:10EA1000D883064608EB860090F82550202D1FD09D +:10EA2000A8F180002C4600EB8617A0F50079DFF8EE +:10EA3000BCB305E0A24607EB4A004478202C0AD07C +:10EA4000F4F766F909EB04135A4601211B1D00F087 +:10EA5000A5FF0028EED0AC4202D0334652461EE05D +:10EA6000E34808B1AFF30080F4F752F998F82F208B +:10EA70006AB1D8F80C20411C891A0902CA1701EBA7 +:10EA800012610912002902DD0020BDE8F09F314625 +:10EA9000FFF7DCFE08B10120F7E733462A462021C4 +:10EAA0000420FFF7C5FDEFE72DE9F041CE4C2569C5 +:10EAB000F4F72EF9401B0002C11700EB11600012A1 +:10EAC00000D4FFDF94F8220000B1FFDF012784F8B3 +:10EAD000227094F82E00202800D1FFDF94F82E60D9 +:10EAE000202084F82E00002584F82F5084F8205030 +:10EAF00084F82150BF4825600078022833D00328CD +:10EB000031D000202077A068401C05D04FF0FF30A6 +:10EB1000A0600120F4F75DF80020F4F75AF8F4F74C +:10EB200052F9F4F74AF9F4F724F807F043FEB24833 +:10EB3000056005604FF0E0214FF40040B846C1F891 +:10EB40008002F4F7C3F994F82D703846FFF75DFFA3 +:10EB50000028FAD0A448803800EB871010F816007F +:10EB6000022802D006E00120CCE73A4631460620D2 +:10EB7000FFF730FD84F8238004EB870090F826002F +:10EB8000202804D09B48801E4078F9F7ADFF207FF5 +:10EB9000002803D0F4F707F92577657746E50146A5 +:10EBA000914810B590F82D200024803800EB821099 +:10EBB00010F814302BB1641CE4B2202CF8D32020C0 +:10EBC00010BD8E4800EB0410016021460120FFF7C4 +:10EBD00001FD204610BD10B5012801D0032800D149 +:10EBE00071B3814A92F82D307F4C0022803C04EBB7 +:10EBF000831300BF13F812400CB1082010BD521C43 +:10EC0000D2B2202AF6D37B4A48B1022807D007297E +:10EC100016D2DFE801F01506080A0C0E10000021DC +:10EC20000AE01B2108E03A2106E0582104E07721A0 +:10EC300002E0962100E0B52151701070002010BD57 +:10EC4000072010BD6B4810B54078F4F7CEF880B2BD +:10EC500010BD10B5202811D2634991F82D30A1F1D3 +:10EC6000800202EB831414F810303BB191F82D3080 +:10EC700002EB831212F81020012A01D0002010BDEF +:10EC800091F82D2001460020FFF7A4FC012010BDC3 +:10EC900010B5F4F73DF8BDE81040F4F7A6B82DE93B +:10ECA000F0410E46504F01782025803F0C4607EB7F +:10ECB000831303E0254603EB45046478944202D0B5 +:10ECC000202CF7D108E0202C06D0A14206D103EB7E +:10ECD00041014978017007E00020A7E403EB4400FC +:10ECE00003EB450140784870454F7EB127B10021C4 +:10ECF00040F2DA30AFF300803078A04206D127B17D +:10ED0000002140F2DD30AFF30080357027B10021E3 +:10ED100040F2E230AFF30080012087E410B5426892 +:10ED20000B689A1A1202D41702EB1462121216D44C +:10ED3000497A91B1427A82B9324A006852F8211078 +:10ED4000126819441044001D891C081A0002C117DA +:10ED500000EB11600012322801DB012010BD002001 +:10ED600010BD2DE9F04781461F48244E00EB81007D +:10ED7000984690F825402020107006F50070154642 +:10ED800000EB81170BE000BF06EB04104946001DA5 +:10ED9000FFF7C4FF28B107EB44002C704478202C07 +:10EDA000F2D1297888F8001013E000BF06EB0415B3 +:10EDB000291D4846FFF7B2FF68B988F80040A97BD3 +:10EDC00099F80A00814201D80020E6E407EB4400EC +:10EDD0004478202CEAD10120DFE42DE9FC410E46E5 +:10EDE00007460024054D18E070070020FFFF3F0094 +:10EDF000000000008200002000F50040F004002028 +:10EE000000000000F47601009DF8000005EB001002 +:10EE10008168384600F0D6FD01246B4601AA3146D0 +:10EE20003846FFF79EFF0028EED02046BDE8FC8163 +:10EE300070B50446FF480125A54300EB841100EBA3 +:10EE40008510402208F07EF9FB4E26B1002140F2E9 +:10EE50005C40AFF30080F748803000EB850100EBA9 +:10EE60008400D0F82500C1F8250026B100214FF418 +:10EE70008C60AFF30080284670BD2DE9FC418446CC +:10EE8000EC481546089C00EB85170E4617F8140051 +:10EE9000012803D0022801D00020C7E70B46E74A2B +:10EEA0000121604600F07AFDA8B101AB6A4629460F +:10EEB0003046FFF756FF70B1DE489DF804209DF8FC +:10EEC0000010803000EB85068A4208D02B460520D2 +:10EED000FFF7AEFB0BE02A462146042014E0202970 +:10EEE00003D007EB4100407801E096F8250007EBDE +:10EEF000440148709DF80000202809D007EB40002D +:10EF000044702A4621460320FFF764FB01208DE769 +:10EF100006F8254F0120F070F3E7C94901EB001016 +:10EF2000001DFFF7E0BB7CB51D46134604460E46A8 +:10EF300000F1080221461846F3F764FF94F908002F +:10EF40000F2804DD1F3820722068401C206096B115 +:10EF50000220BC4951F82610461820686946801BDB +:10EF600020F07F40206094F908002844C01C1F282E +:10EF700003DA012009E00420EBE701AAF3F742FFDE +:10EF80009DF8040010B10098401C00900099206882 +:10EF900031440844C01C20F07F4060607CBD2DE9F6 +:10EFA000FE430C46064609786079907220799846AF +:10EFB0001546507241B19F48803090F82E1020299C +:10EFC0000AD00069401D0BE0D4E90223217903B087 +:10EFD0002846BDE8F043A6E79B484178701D0844E9 +:10EFE00020F07F47217900222846A368FFF79BFF86 +:10EFF0003946284600F0E6FCD4E902322179684619 +:10F00000FFF791FF41462846019CFFF7E6FE2B469D +:10F0100022460021304600F0C1FC002803D13146D1 +:10F02000284600F0CFFCBDE8FE832DE9FE4F814667 +:10F0300000F084FC30B1002799F8000020B10020D6 +:10F04000BDE8FE8F0127F7E77A4D7B4C4FF0000AB1 +:10F05000803524B1002140F2D340AFF3008095F811 +:10F060002D8085F823A0002624B100214FF49B6059 +:10F07000AFF300801FB94046FFF7DAFE804624B1A7 +:10F0800000214FF49C60AFF30080F3F741FE43464C +:10F090006A464946FFF783FF24B1002140F2E6406B +:10F0A000AFF3008095F82E0020280CD02969009835 +:10F0B000401A0002C21700EB1260001203D5684626 +:10F0C00000F080FC012624B100214FF49E60AFF3D4 +:10F0D000008095F823000028BBD124B1002140F224 +:10F0E000F640AFF30080F3F713FE6B46534A00215E +:10F0F00000F054FC0028A3D027B941466846FFF72A +:10F100006CFE064326B16846FFF7EDFAC9F8080021 +:10F1100024B1002140F20950AFF3008001208FE7B5 +:10F120002DE9FF5F8A46814600F008FC414C80349F +:10F1300010B39AF80000002710B1012800D0FFDFBB +:10F140003D4D25B1002140F27F50AFF300800120FA +:10F15000A84600905FEA080604D0002140F28750DC +:10F16000AFF30080009800F0E0FB94F82D500020F1 +:10F1700084F8230067B119E094F82E0001272028B5 +:10F1800000D1FFDF9AF800000028D9D0FFDFD7E7D1 +:10F190002846FFF74DFE054626B1002140F291506A +:10F1A000AFF3008094F823000028D3D126B10021CA +:10F1B00040F29B50AFF30080F3F7AAFD83462B4645 +:10F1C00001AA5146FFF7EBFE5FEA060804D00021D2 +:10F1D00040F2A250AFF300803B462A4601A95846B0 +:10F1E000CDF80090FFF749FE064604EB850090F845 +:10F1F00028B0B8F1000F04D0002140F2A950AFF3BD +:10F20000008000F087FB0090B8F1000F04D00021CF +:10F2100040F2AF50AFF3008094F82300002899D15A +:10F22000B8F1000F04D0002140F2B750AFF30080D6 +:10F2300003490BE0F006002000000000FFFF3F0044 +:10F24000F0040020F47601008200002001EB091098 +:10F250000DF1040C00F104009CE80E0080E80E00A3 +:10F260004EB35FEA080604D0002140F2C450AFF369 +:10F2700000803BEA070012D094F82E0020280ED11F +:10F2800026B1002140F2C950AFF300802846FFF7B5 +:10F29000BCFB20B99AF80000D8B3012849D0B8F1D6 +:10F2A000000F04D0002140F2E650AFF30080284662 +:10F2B00000F029FB01265FEA080504D0002140F296 +:10F2C000EF50AFF30080009800F02FFB25B1002134 +:10F2D00040F2F350AFF300808EB194F82D0004EBB0 +:10F2E000800090F82600202809D025B1002140F2A6 +:10F2F000FA50AFF30080F9484078F9F7F5FB25B1F3 +:10F30000002140F2FF50AFF3008004B03046BDE86A +:10F31000F09FFFE7B8F1000F04D0002140F2D15078 +:10F32000AFF3008094F82D2049460420FFF752F9EE +:10F33000C0E7002E3FF40EAF002140F2DC50AFF3E7 +:10F34000008007E72DE9F84FE54D814695F82D003F +:10F350004FF00008E34C4FF0010B474624B1002169 +:10F3600040F20D60AFF30080584600F0DEFA85F8F9 +:10F37000237024B1002140F21260AFF3008095F8B1 +:10F380002D00FFF755FD064695F8230028B1002C07 +:10F39000E4D000214FF4C3604BE024B1002140F2DF +:10F3A0001C60AFF30080CE48803800EB861111F866 +:10F3B0001900032856D1334605EB830A4A469AF8CA +:10F3C0002500904201D1012000E0002000900AF1C8 +:10F3D00025000021FFF763FC01460098014203D09D +:10F3E00001228AF82820AF77E1B324B1002140F24E +:10F3F0002160AFF30080324649460120FFF7EAF86A +:10F400009AF828A024B1002140F22C60AFF30080CC +:10F4100000F080FA834624B1002140F23160AFF35E +:10F42000008095F8230038B1002C97D0002140F2DD +:10F430003560AFF3008091E7BAF1000F07D095F87F +:10F440002E00202803D13046FFF7DFFAE0B124B1C7 +:10F45000002140F24960AFF30080304600F053FADB +:10F460004FF0010824B1002140F25260AFF3008058 +:10F47000584600F05AFA24B1002140F25660AFF32A +:10F4800000804046BDE8F88F002CF1D0002140F20A +:10F490004460AFF30080E6E70020F3F773BB012080 +:10F4A000F3F770BB8D48007870472DE9F0418C4C24 +:10F4B00094F82E0020281FD194F82D6004EB8607C5 +:10F4C00097F82550202D00D1FFDF8549803901EBC9 +:10F4D000861000EB4500407807F8250F0120F870F2 +:10F4E00084F82300294684F82E5032460220223424 +:10F4F000FFF770F8002020700FE42DE9F0417A4EFC +:10F50000774C012538B1012821D0022879D0032871 +:10F510007DD0FFDFF0E700F029FAFFF7C6FF207E7D +:10F5200000B1FFDF84F821500020F3F752FBA168FF +:10F53000481C04D0012300221846F3F79DFB14F861 +:10F540002E0F217806EB01110A68012154E0FFF724 +:10F55000ACFF0120F3F73DFB94F8210050B1A06807 +:10F56000401C07D014F82E0F217806EB01110A6811 +:10F57000062141E0207EDFF86481002708F10208BF +:10F58000012803D002281ED0FFDFB5E7A777F3F7E5 +:10F590000AFC98F80000032801D165772577607D83 +:10F5A000524951F8200094F8201051B948B16168CF +:10F5B0000123091A00221846F3F75EFB0220207689 +:10F5C0009AE7277698E784F8205000F0CFF9A07FDB +:10F5D00050B198F8010061680123091A0022184609 +:10F5E000F3F74AFB257600E0277614F82E0F2178F2 +:10F5F00006EB01110A680021BDE8F041104700E068 +:10F6000005E036480078BDE8F041F9F76DBAFFF73C +:10F610004CFF14F82E0F217806EB01110A68052122 +:10F62000EAE710B52E4C94F82E00202800D1FFDF19 +:10F6300014F82E0F21782C4A02EB01110A68BDE85C +:10F640001040042110477CB5254C054694F82E0047 +:10F65000202800D1FFDFA068401C00D0FFDF94F815 +:10F660002E00214901AA01EB0010694690F90C0017 +:10F670002844F3F7C7FB9DF904000F2801DD0120A2 +:10F6800000E00020009908446168084420F07F41B0 +:10F69000A16094F82100002807D002B00123BDE842 +:10F6A000704000221846F3F7E7BA7CBD30B5104A27 +:10F6B0000B1A541CB3EB940F1ED3451AB5EB940FE1 +:10F6C0001AD3934203D9101A43185B1C14E09542D5 +:10F6D00010D9511A0844401C43420DE0800000201C +:10F6E0007007002000000000F0040020F476010004 +:10F6F000FF7F841EFFDF0023184630BD0123002258 +:10F7000001460220F3F7B8BA0220F3F762BAF3F722 +:10F71000FFBA2DE9FC47B14C054694F82E0020288D +:10F7200000D1FFDF642D58D3AD4A0021521B71EB8D +:10F73000010052D394F82E20A0462046DFF8A49270 +:10F7400090F82D7009EB0214D8F8000001AA2844A3 +:10F750006946F3F757FB9DF90400002802DD009885 +:10F76000401C0090A068009962684618B21A22F006 +:10F770007F42B2F5800F30D208EB8702444692F800 +:10F780002520202A0AD009EB02125268101A000222 +:10F79000C21700EB1260001288421EDBA068401CFA +:10F7A00010D0F3F7B5FAA168081A0002C11700EBF0 +:10F7B00011600012022810DD0120F3F70AFA4FF061 +:10F7C000FF30A06020682844206026F07F40206140 +:10F7D000012084F82300BDE8FC870020FBE72DE929 +:10F7E000F0477E4C074694F82D00A4F1800606EB06 +:10F7F000801010F8170000B9FFDF94F82D50A046D4 +:10F80000794C24B1002140F66500AFF3008040F64A +:10F81000710940F67A0A06EB851600BF16F8170044 +:10F82000012818D0042810D005280ED006280CD0A6 +:10F830001CB100214846AFF3008020BF002CEDD062 +:10F8400000215046AFF30080E8E72A463946012000 +:10F85000FEF7C0FEF2E74FF0010A4FF000094546FF +:10F8600024B1002140F68100AFF30080504600F043 +:10F870005CF885F8239024B1002140F68600AFF3B0 +:10F88000008095F82D00FFF7D3FA064695F823007F +:10F8900028B1002CE4D0002140F68C001FE024B1F8 +:10F8A00000214FF40960AFF3008005EB860000F102 +:10F8B000270133463A462630FFF7F1F924B10021FB +:10F8C00040F69400AFF3008000F024F8824695F8EB +:10F8D000230038B1002CC3D0002140F69A00AFF3CA +:10F8E0000080BDE785F82D60012085F82300504693 +:10F8F00000F01BF8002C04D0002140F6A700AFF365 +:10F900000080BDE8F087354981F82D00012081F89D +:10F910002300704710B5354808B1AFF30080EFF30E +:10F92000108000F0010072B610BD10B5002804D19F +:10F930002F4808B1AFF3008062B610BD2D480068B3 +:10F94000C005C00D10D0103840B2002806DA00F013 +:10F950000F0000F1E02090F8140D03E000F1E0202A +:10F9600090F80004400970470820704710B51B4C00 +:10F9700094F82400002804D1F8F7ACFE012084F8A4 +:10F98000240010BD10B5154C94F82400002804D0B4 +:10F99000F8F7C9FE002084F8240010BD10B51C68DB +:10F9A0005B68241A181A24F07F4420F07F40A1429B +:10F9B00006D8B4F5800F03D2904201D8012010BDC3 +:10F9C000002010BDD0E90032D21A21F07F4311444B +:10F9D00021F07F41C0E9003170470000700700202E +:10F9E000FF1FA107F004002000000000000000003D +:10F9F0000000000004ED00E02DE9F041044680071E +:10FA00004FF000054FF0010604D55C480560066024 +:10FA100024F00204E0044FF0FF3705D55848466053 +:10FA2000C0F8087324F48054600003D5554805607D +:10FA300024F08044E0050FD55348C0F80052C0F8C8 +:10FA4000087352490D60091D0D60504A04210C32A3 +:10FA50001160066124F48074A00409D54C48466006 +:10FA6000C0F80052C0F808734A48056024F40054F6 +:10FA7000C4F38030C4F3C031884200D0FFDF14F4F7 +:10FA8000404F14D044484660C0F80873434886602D +:10FA9000C0F80052C0F8087341490D600A1D166095 +:10FAA0008660C0F808730D60166024F44044200599 +:10FAB0000AD53C4846608660C0F80873C0F84873B1 +:10FAC0003948056024F4006406F04EFE37480442CD +:10FAD00000D0FFDFBDE8F08170B52025002213467D +:10FAE00020FA02F1C90719D051B201F01F06012412 +:10FAF000B4404E09B60006F1E026C6F88041C6F8CB +:10FB00008042002906DA01F00F0101F1E02181F8BD +:10FB1000143D03E001F1E02181F80034521CAA42B7 +:10FB2000DED370BD70B5224C0D462060FFF764FF38 +:10FB30002068FFF7D1FF2846F8F7C1FE06F04AFA21 +:10FB400000F0D5F806F010FE06F05BFDF8F79EFF1A +:10FB5000BDE8704006F0ECBA10B5154C2068FFF710 +:10FB60004BFF2068FFF7B8FF06F0FEFDF8F736FF01 +:10FB70000020206010BD0A2070470000FC1F0040DC +:10FB800000C0004004E501400080004004850040C2 +:10FB900000D0004004D5004000E0004000F00040EC +:10FBA00000F5004000B0004008B50040FEFF0FFD2A +:10FBB0008400002070B522490A680AB30022154665 +:10FBC00001244B685B1C4B60092B00D34D600E7900 +:10FBD00004FA06F30E681E420FD0EFF3108212F003 +:10FBE000010272B600D001220C689C430C6002B97D +:10FBF00062B649680160002070BD521C092AE0D33A +:10FC0000052070BD4FF0E0214FF48000C1F80002E4 +:10FC10007047EFF3108111F0010F72B64FF001023F +:10FC200002FA00F20648036842EA0302026000D1C9 +:10FC300062B6E7E7024800210160416070470000BA +:10FC4000880000200120810708607047012081079B +:10FC50004860704712480068C00700D00120704714 +:10FC60000F48001F0068C00700D0012070470C48F3 +:10FC700008300068C00700D00120704708481030E5 +:10FC80000068704706490C310A68D20306D5096836 +:10FC900001F00301814201D101207047002070472B +:10FCA0000C0400402DE9F04115460E46044600279D +:10FCB00000F0E7F8A84215D3002341200FE000BF71 +:10FCC00094F84220A25CF25494F84210491CB1FB13 +:10FCD000F0F200FB12115B1C84F84210DBB2AB4265 +:10FCE000EED3012700F0D9F83846BDE8F08170491D +:10FCF00010B5802081F800046E49002081F8420090 +:10FD000081F84100433181F8420081F841004331DC +:10FD100081F8420081F84100674806F0BBFB664865 +:10FD2000401C06F0B7FBF3F7DDF8BDE8104000F02B +:10FD3000B4B8402070475F4800F0A3B80A460146B7 +:10FD40005C48AFE7402070475A48433000F099B80C +:10FD50000A46014657484330A4E74021017000207D +:10FD6000704710B504465348863000F08AF820707A +:10FD7000002010BD0A4601464E4810B58630FFF7F8 +:10FD800091FF08B1002010BD42F2070010BD70B510 +:10FD90000C460546412900D9FFDF48480068103865 +:10FDA00040B200F050F8C6B20D2000F04CF8C0B2DE +:10FDB000864203D2FFDF01E0F3F7DCF82246294652 +:10FDC0003C48FFF76FFF0028F6D070BD2DE9F041E9 +:10FDD000394F002506463F1D57F82540204600F0C4 +:10FDE00041F810B36D1CEDB2032DF5D3314843300B +:10FDF00000F038F8002825D02E4800F033F800280D +:10FE000020D02C48863000F02DF800281AD0F3F7C7 +:10FE10008FF8294806F046FBB0F5005F00D0FFDF01 +:10FE2000BDE8F041244806F053BB94F8410041215D +:10FE3000265414F8410F401CB0FBF1F201FB1200F4 +:10FE40002070D3E751E7002806DA00F00F0000F138 +:10FE5000E02090F8140D03E000F1E02090F8000499 +:10FE60004009704710F8411F4122491CB1FBF2F3D1 +:10FE700002FB13114078814201D10120704700201C +:10FE8000704710F8411F4078814201D3081A02E000 +:10FE9000C0F141000844C0B2704710B5064806F0F2 +:10FEA00001FB002803D1BDE81040F3F72CB810BDCA +:10FEB0000DE000E0A00700209000002004ED00E02D +:10FEC00070B5154D2878401CC4B26878844202D0C1 +:10FED000F3F78BF82C7070BD2DE9F0410E4C4FF00C +:10FEE000E02600BFF3F77FF820BF40BF20BF677850 +:10FEF00020786070D6F80052F1F7F6F9854305D105 +:10FF0000D6F8040210B92078B842EBD0F3F76AF8BB +:10FF10000020BDE8F0810000A00000202DE9F041A4 +:10FF2000012528034FF0E0210026C1F880011E4C76 +:10FF3000C4F800610C2000F02CF81C48016802682D +:10FF4000C94341F3001142F010020260C4F80453A7 +:10FF50002560491C00E020BFD4F80021002AFAD017 +:10FF600019B9016821F01001016011480768656046 +:10FF7000C4F80853C4F800610C2000F00AF83846B1 +:10FF8000BDE8F08110B50446FFF7C8FF20600020EF +:10FF900010BD00F01F02012191404009800000F1D6 +:10FFA000E020C0F88012704700C0004010ED00E073 +:10FFB00008C500402DE9F047FF4C0646FF21A06828 +:10FFC00000EB061211702178FF2910D04FF00809BC +:10FFD00009EB011109EB06174158C05900F0F4F97B +:10FFE000002807DDA168207801EB06110870267053 +:10FFF000BDE8F08794F8008045460DE0A06809EB65 +:020000040001F9 +:1000000005114158C05900F0DFF9002806DCA0684E +:10001000A84600EB08100578FF2DEFD1A06800EB93 +:10002000061100EB08100D700670E1E7F0B5E24B29 +:100030000446002001259A680C269B780CE000BF3E +:1000400005EB0017D75DA74204D106EB0017D7597F +:100050008F4204D0401CC0B28342F1D8FF20F0BDD3 +:1000600070B5FFF754FBD44C08252278A16805EB46 +:100070000212895800F0A8F9012808DD2178A0684B +:1000800005EB01114058BDE87040FFF737BBFFF7A3 +:1000900009FABDE87040F8F727BD2DE9F041C64CDC +:1000A0002578FFF734FBFF2D6ED04FF00808A268CB +:1000B00008EB0516915900F087F90228A06801DDC8 +:1000C00080595DE000EB051109782170022101EBF8 +:1000D0000511425C5AB1521E4254815901F580010A +:1000E00021F07F4181512846FFF764FF34E004236B +:1000F000012203EB051302EB051250F803C0875CE5 +:10010000BCF1000F10D0BCF5007F10D9CCF3080271 +:1001100050F806C00CEB423C2CF07F4C40F806C077 +:10012000C3589A1A520A09E0FF2181540AE0825901 +:1001300002EB4C3222F07F42825100224254284688 +:10014000FFF738FF0C21A06801EB05114158E0686A +:1001500050F82720384690472078FF2814D0FFF722 +:10016000D6FA2278A16808EB02124546895800F0B9 +:100170002BF9012893DD2178A06805EB0111405887 +:10018000BDE8F041FFF7BABABDE8F081F0B51D4611 +:1001900014460E460746FF2B00D3FFDFA00700D012 +:1001A000FFDF8548FF210022C0E90247C5700671C4 +:1001B0000170427082701046012204E002EB0013CD +:1001C000401CE154C0B2A842F8D3F0BD70B57A4CDF +:1001D000064665782079854200D3FFDFE06840F865 +:1001E00025606078401C6070284670BD2DE9FF5F77 +:1001F0001D468B460746FF24FFF789FADFF8B891C2 +:10020000064699F80100B84200D8FFDF00214FF000 +:1002100001084FF00C0A99F80220D9F808000EE006 +:1002200008EB0113C35CFF2B0ED0BB4205D10AEBD8 +:10023000011350F803C0DC450CD0491CC9B28A42F6 +:10024000EED8FF2C02D00DE00C46F6E799F803102B +:100250008A4203D1FF2004B0BDE8F09F1446521C2F +:1002600089F8022008EB04110AEB0412475440F805 +:1002700002B00421029B0022012B01EB04110CD0DF +:1002800040F801204FF4007808234FF0020C454558 +:1002900013D9E905C90D02D002E04550F2E7414605 +:1002A00006EB413203EB041322F07F42C250691A7D +:1002B0000CEB0412490A81540BE005B9012506EB49 +:1002C000453103EB041321F07F41C1500CEB0411C5 +:1002D000425499F800502046FFF76CFE99F8000050 +:1002E000A84201D0FFF7BCFE3846B4E770B50C4613 +:1002F0000546FFF70CFA064621462846FFF796FE0C +:100300000446FF281AD02C4D082101EB0411A868DF +:100310004158304600F058F800F58050C11700EB06 +:10032000D14040130221AA6801EB0411515C09B1CC +:1003300000EB4120002800DC012070BD002070BDD2 +:100340002DE9F04788468146FFF770FE0746FF28F3 +:100350001BD0194D2E78A8683146344605E0BC42C2 +:1003600006D0264600EB06121478FF2CF7D10CE0DD +:10037000FF2C0AD0A6420CD100EB011000782870A7 +:10038000FF2804D0FFF76CFE03E0002030E6FFF703 +:10039000BBF941464846FFF7A9FF0123A968024679 +:1003A00003EB0413FF20C854A878401EB84200D1C4 +:1003B000A87001EB041001E06C08002001EB0611AD +:1003C00000780870104613E6081A0002C11700EB07 +:1003D000116000127047000070B50446A0F50000DF +:1003E0002D4EB0F1786F02D23444A4F500042B48AE +:1003F000844201D2012500E0002500F043F848B115 +:1004000025B9B44204D32648006808E0012070BD35 +:10041000002070BD002DF9D1B442F9D321488442A7 +:10042000F6D2F3E710B50446A0F50000B0F1786FFE +:1004300003D219480444A4F5000400F023F84FF057 +:10044000804130B11648006804E08C4204D201209B +:1004500003E014488442F8D2002080F0010010BD6F +:1004600010B520B1FFF7DEFF08B1012010BD00205C +:1004700010BD10B520B1FFF7AFFF08B1012010BDCE +:10048000002010BD084809490068884201D10120B8 +:10049000704700207047000000000020008001002D +:1004A0002000002008000020A4000020BEBAFECAE0 +:1004B0000348044A0168914201D10021016070475C +:1004C000A4000020BEBAFECA43480021017041705A +:1004D00010218170704770B5054616460C46022003 +:1004E000F2F7C7FA3C490120F61E08703B48066047 +:1004F0003A4808380560001F046070BD10B502203E +:10050000F2F7B7FA34490120087035480021C0F8E5 +:100510000011C0F80411C0F8081132494FF400006E +:10052000086010BD10B52C4C207888B12D494FF4CF +:100530000000091D086000F041F8002120B10120F1 +:1005400060702948006801E061701020A07021707F +:10055000BDE810400020F2F78CBA1F4810B50178B2 +:1005600059B11F48D0F8000128B100F027F8002841 +:1005700000D0012010BD022010BD407810BD10B584 +:10058000C824641EE4B2FFF7E8FF022803D0012864 +:1005900000D0002010BD002CF3D1FFDFF9E70E489A +:1005A00010B5017841B100F009F818B10E480068A3 +:1005B000C0B210BD102010BD807810BD0848D0F822 +:1005C000001129B1D0F8041111B1D0F8080108B117 +:1005D0000020704701207047A800002010F500405F +:1005E00000F0004004F5014000F4004044480021C0 +:1005F00001704170704770B5064614460D460120E3 +:10060000F2F737FA3F480660001D0460001D0560E0 +:1006100070BD70B53A4A012540EA01411570394A6A +:10062000121F1160384C0026C4F80461374A4FF09D +:100630004071116058B1012800D0FFDFC4F800629A +:10064000256032494FF00070091F086070BDC4F882 +:100650000052256070BD2A48017871B12B4A4FF0D5 +:10066000407111602849D1F8042100211AB1284AAB +:100670001268427000E0417001700020F2F7F9B991 +:100680001F48017841B12048D0F80401002802D069 +:100690001F480068C0B270474078704770B50028A6 +:1006A00028D01748007800B9FFDF1748D0F80411A8 +:1006B00000291FD10223C0F8043316490A680C68C8 +:1006C000D24342F3001244F010040C609C034FF03C +:1006D000E025521C03E000BFC5F8804220BFD0F8DF +:1006E0000461002EF8D01AB90A6822F010020A60DC +:1006F000C0F8083370BD04490120886070470000CD +:10070000AB00002008F5004000F0004008F5014073 +:1007100000F4004010ED00E0FC4808B50021C0F8EE +:100720000011C0F80C11C0F81011C0F80411C0F885 +:100730001411C0F81811F6480068009008BD70B593 +:10074000F44D00246C702C7000F088FD85F8214079 +:10075000AC626C636C77092105F1140006F093FD1F +:10076000ED49601E0860091D0860091D0C60091D27 +:100770000860091D0C60091D0860091D0860091D3D +:100780000860091D0860091D0860091D0860091D31 +:100790000860091D0860091D086070BD70B5DD495D +:1007A0000268DE4C4A6142688A61007A08770C3C34 +:1007B0000A7DDA4B251F012042B10E7E00FA06F2B7 +:1007C0001A608E7D0EB1226000E02A604A7D002A08 +:1007D00005D04A7E90401860C97D09B1206070BD87 +:1007E000286070BDCF49CE480860091DCE4808601A +:1007F000704710B50446012902D0022902D0FFDF5C +:10080000002101E04FF08071C8480143C5480160F4 +:10081000C549E0B225390843C249091D0860BB48F3 +:10082000D0F80001002800D0FFDF10BD70B5012016 +:1008300000F0FEFCBE4900240C6001200860BD49A8 +:100840000A68BD4B22F077021A430A60091D0A6844 +:1008500022F47F4242F4B0520A60B24A40F25B6135 +:1008600024321160121F40F203111160111F086041 +:10087000AC490320091F0860AA499620303108605E +:10088000A44D95F91D0006F0A5F8AD49AB480860E8 +:10089000AB49AC489C3108609D480838091F086086 +:1008A000012000F0D0FC99491020C1F8040385F81C +:1008B0002D4070BD974A0368C2F802308088D0800E +:1008C00011727047934890F821007047914A517017 +:1008D00010707047F0B5054684008C488B88204422 +:1008E000C0F820360B78D1F8011043EA0121C0F896 +:1008F000001605F1080001278E4C07FA00F6FC3CB3 +:1009000052B1012A00D0FFDF206830432060206808 +:10091000AF4038432060F0BD2068B043F6E710B523 +:10092000044606F057F87B48447710BD794890F8A4 +:100930002E0070477B4AC1781032116000687949F7 +:100940000002083108607047252807D0262807D004 +:10095000272807D00A2807D8042206E0022107E04A +:100960001A2105E0502103E0062202EB4001C9B242 +:100970006C4A0C3A11606B49403108607047654819 +:10098000817A012915D0022912D1417D00290FD089 +:10099000827E0121C37E01FA02F299400A4368492E +:1009A0000A60007F684A002102EB8000C0F8101541 +:1009B0007047017DEAE7F0B5564B9C7A012C12D0C6 +:1009C000022C67D15D7D002D64D0604F4FF47A76A4 +:1009D000012C0AD05D7EDC7D04B1012401291FD0E9 +:1009E000022A1FD020E01D7DEDE71D7E9C7D04B115 +:1009F00001244FF4C86C012902D0022A07D008E074 +:100A0000022A00D1B44649F6FC61614405E0504F2A +:100A1000B44607EB0C0101F5FA71B1FBF6F107E002 +:100A2000292105E04A4F643F07F2E147B7FBF6F1A1 +:100A3000491F084447490860424900204039C1F82D +:100A40004C01280284F0010140EA015040F00312F9 +:100A5000197F3D4800EB8104C4F810259C7E3E4A76 +:100A600000EB810102EBC400C0F814153B4DC0F847 +:100A70001055DB7E02EBC300C0F814152449083979 +:100A8000C0F81015012000FA04F1984001432C48E9 +:100A9000001F0160F0BD2DE9F0410F461B490546DE +:100AA00003201646C1F80002254C2448241F20606C +:100AB000384605F0D9FF304605F0B6FF154815B1A8 +:100AC000012D09D011E001218172416B41F48011A7 +:100AD00041634FF4801007E002218172416B41F4C1 +:100AE000001141634FF40010206032463946BDE8E2 +:100AF000F04100205FE708B5FF208DF800000348B3 +:100B00000021C0F81011012101612EE00010004009 +:100B1000181100407C080020000E0040180500500D +:100B20000601020014150040250003020801100010 +:100B3000FC1F00403C1700408800008000000404B7 +:100B400008F501404080004000600040A2240200FF +:100B5000683602004C85004000F001404C810040A6 +:100B60009DF80010491E8DF800109DF8001019B175 +:100B7000D0F810110029F3D09DF80000002800D112 +:100B8000FFDF08BD2DE9FF5FFC4D0746002603206F +:100B90009B468946C5F80002DFF8E883F849C8F8A3 +:100BA0000010029805F060FF584605F03DFFF5483B +:100BB000F54CA8304FF0010A17B1012F1DD026E0E7 +:100BC000056094F82D00012805D002280BD0FFDF26 +:100BD00084F80AA01BE094F82C205B464846029952 +:100BE00005F096FF06E094F82C305A4648460299E4 +:100BF00005F045FFA16A4618EAE7E049091D0160D2 +:100C000094F82D00012838D0FFDF0220A072DF48C1 +:100C10000660DC49DE48A4310860606B40F40020C7 +:100C20006063D5F800724FF01009C5F808930020F2 +:100C3000C5F80002D3484FF48024001D046005F578 +:100C40000075FFF758FFFFF767FD2F60C8F80040F9 +:100C5000C5F804916100C8F80010CE49C1F84CA055 +:100C6000CA48001D0068B04200D3FFDF029904B0FB +:100C70005A463046BDE8F05F9DE694F82C205B466E +:100C80004846029905F022FFA16A4618BDE72DE902 +:100C9000F041BA4CD4F8000220F00306D4F8040363 +:100CA0001027C0F30015C4F808734FF00008C4F80B +:100CB0000082B449B248091D086004F50074FFF7CA +:100CC0005EFEFFF718FF44F8F08C00F0C7FA2660CC +:100CD000A4F50074002D01D0C4F80473BDE8F081C0 +:100CE0000068AD4920F07F400860704710B50120D2 +:100CF00000F09EFABDE81040012000F0A4BA4FF0C9 +:100D0000E0210220C1F800017047A4490870704733 +:100D1000A14938390860704770B59B4D0446A86AF0 +:100D2000A04200D3FFDF012028739A4900202C61E4 +:100D3000C1F844019548001F0460BDE8704000F010 +:100D400094BA70B5904C05460220207305F07AFEE7 +:100D5000024694F82C10284605F002FF8D4A002127 +:100D60002061C2F84411A16A08448849091F08603B +:100D700070BD84494FF48000091D08608248416BB2 +:100D800021F48001416300210173704781480121F2 +:100D90004160C1600021C0F844117C48001F01601F +:100DA0007948816270477C4940202431086073484B +:100DB000D0F8001241F04001C0F8001270476F48AF +:100DC000D0F8001221F04001C0F800127249002052 +:100DD0002431086070476948D0F8001221F01001F2 +:100DE000C0F8001201218161704764480021C0F8F9 +:100DF0001C11D0F8001241F01001C0F80012704729 +:100E00005E4908B5D1F81C21012A01D0002008BD97 +:100E1000614A0C32126802F07F02524202700020D6 +:100E2000C1F81C015E4800680090012008BDF8B5BB +:100E3000554C584D207B18B1D5F8440101280AD0F3 +:100E400000264E49D1F81001012806D00022A07AD0 +:100E5000012804D007E00126F3E74022F7E7D1F8A4 +:100E60000C31012B04D000231343012802D005E0EC +:100E70002023F9E7D1F80421012A05D000221A43E2 +:100E8000484F022802D008E01022F8E73B68012B07 +:100E900003D1D1F80C31012B04D0002313430228D5 +:100EA00002D007E00823F9E73A681AB9D1F80C2113 +:100EB000012A04D000221A43022802D004E00422AE +:100EC000F9E70EB1022300E000231343022809D101 +:100ED000D1F80401012805D1D5F84401012801D039 +:100EE000012600E0002630481E43026812F0FF0F82 +:100EF00003D0D1F81421012A00D0002284F82E203A +:100F0000006810F0FF0F03D0D1F81801012800D0BD +:100F1000002084F82F0023481030006884F8300047 +:100F20001D4824300068402803D1FFF716FB012834 +:100F300000D0002084F83100FFF7EEFB0020C5F858 +:100F400044011348001F006800903046F8BD30B5DA +:100F50000C00054600D1FFDFE00702D0012C00D0D5 +:100F6000FFDF55B10221084801294172C4720348CC +:100F70001ED0022921D0FFDF30BD17E00010004055 +:100F80000000040404F501407C080020488500406E +:100F900048810040008000403C150040AD0000202A +:100FA0001C11004000140040401600400121DAE707 +:100FB000D0F8001241F0040103E0D0F8001241F033 +:100FC0000801C0F80012D7E770B5AD4C0022E17AF5 +:100FD0008B0701D5430711D4CB0605D594F82F30E4 +:100FE00013B194F831304BB10B0702D594F820308F +:100FF00023B9490703D594F8211001B90122637A76 +:10100000A049012533B100F0020010430DD0BDE826 +:1010100070403CE69D4A9C481060D1F8000220F0E8 +:101020000300C1F80002E57270BD0026012B09D053 +:10103000022B17D0FFDFA06A01223044BDE87040C8 +:101040000021B8E4D1F8000220F00400C1F8000249 +:1010500000F004F90123A5721A460021962005F03C +:101060000EFD0FE0D1F8000220F00800C1F80002E8 +:1010700000F0F4F80220A07201231A460021962005 +:1010800005F024FD0646D6E72DE9F047DFF800A27B +:10109000DAF84C0108B1FFF772FC794C7B49606BC0 +:1010A000086000266663FFF7C2FEDFF8E8810546A8 +:1010B000D8F800006062A8F104000068A06205F0A2 +:1010C000C1FC84F82C00A07ADFF8CC9184F82D00C4 +:1010D000022808D1607830B1D9F8001009780140B1 +:1010E000207888430DD084F820606C4FE8070CD03E +:1010F00039786B4A4908606A52F821108847012103 +:101100000AE0012084F82000EFE7A80601D50221BB +:1011100002E0A80707D50021614A3B783832A06A6F +:1011200052F8232090473878C00713D1D9F800101F +:101130000622A01C093105F0D9FF40B9217AD9F85F +:1011400000000078B1EBD01F01D1012000E00020A9 +:1011500084F821002846FFF737FFA80705D5504837 +:101160003978083050F82100804715F00C0F07D06F +:101170004B483978183050F82110C5F3C000884723 +:10118000A80605D546483978283050F82100804710 +:101190003878042800D3FFDFA07A02281AD1207BF8 +:1011A000002817D0CAF8446102280FD0012800D0C7 +:1011B000FFDFA16A2069884200D8FFDFD4F8101051 +:1011C000C8F80010BDE8F04700F04FB82169A06AE8 +:1011D0000144F5E7BDE8F08700B5012802D00228F8 +:1011E00002D0FFDF282000BD182000BD10B541F659 +:1011F000A474012802D0022802D0FFDF204610BDCF +:1012000041F2883010BD10B541F2D474012802D0EB +:10121000022802D0FFDF204610BD41F2040010BDBD +:1012200000B5012802D0022800D0FFDF002000BD59 +:1012300000F01F02012191404009800000F1E020F0 +:10124000C0F88011704700F01F0201219140400951 +:10125000800000F1E020C0F88012704708480021AB +:10126000417281720121C17270470548416B41F49E +:101270008001416305494FF48000091F08607047F1 +:101280007C080020001000400000040408F5014024 +:10129000008000404485004004150040AD0000205F +:1012A0000C77010010B54348222105F0CAFF4148E0 +:1012B0000024017821F010010170012104F084FD67 +:1012C0003C494FF6FF70263981F8224088843A491C +:1012D0000880488010BDE5E7704700F05FB83549E9 +:1012E00001607047344908807047324926398A8C3A +:1012F000A2F57F43FF3B02D00021016008E091F896 +:1013000022202C492639012A02D001600120704791 +:10131000002070472748263810F8221F012908D0DE +:10132000012101702448234926390088888401203E +:101330007047002070472049488070471D491E4B68 +:1013400026398A8C5B889A4205D191F8222012B105 +:10135000016001207047002070471648164A263861 +:10136000818C5288914209D14FF6FF71818410F827 +:10137000221F19B100210170012070470020704721 +:101380000C480D4A2638818C5288914204D190F83D +:10139000220008B100207047012070470549263916 +:1013A0008A8C824205D1002081F822004FF6FF701E +:1013B00088847047DA080020AE00002070473C4A5D +:1013C000012338B1012804D113700868906088881F +:1013D0009081704753700868C2F802008888D080F6 +:1013E0007047334A10B1012807D00EE0507860B141 +:1013F000D2F802000860D08804E0107828B1906824 +:101400000860908988800120704700207047284933 +:1014100010B1012802D005E0487800E0087808B152 +:10142000012070470020704730B50C4605468DB04E +:101430004FF0030104F1030012B1FEF789FC01E053 +:10144000FEF7A5FC60790D2120F0C00040F04000BF +:10145000607104A805F017FFE0788DF81F0020796F +:101460008DF81E0060798DF81D001022294668460F +:1014700005F068FE684604F047FE9DF82F002070D6 +:101480009DF82E0060709DF82D00A0700DB030BD4D +:1014900010B5002904464FF0060102D0FEF758FCB3 +:1014A00001E0FEF774FC607920F0C000607110BDAF +:1014B000B200002070B5FC4E044696F8921000254C +:1014C00006F18000012909D096F88C10012912D06C +:1014D00096F86A00012818D0002070BD65701821A8 +:1014E000217050F8131FC4F802104068C4F80600B9 +:1014F00086F8925024E0657006212170D0F80E0025 +:10150000C4F8020086F88C501AE065701320E64992 +:10151000207020226C31A01C05F014FE0120A07167 +:1015200006F86A5FB188B184E04949684A7B86F869 +:10153000262086F822000888FBF7ACFBFBF771F841 +:10154000012070BDD84890F86A1011B1B0F86E0053 +:1015500070474FF6FF70704770B5D448017811B1ED +:101560000C26304670BDD04C0026354684F86260AB +:1015700084F8636084F8646084F8656084F85E6071 +:1015800084F8606084F8566084F8366084F8676098 +:101590007F21817094F8660028B1FFF710FCFEF7F8 +:1015A000C1FF84F8665084F86A5084F88C5084F83F +:1015B0009250BD489C3004F067FBBB48C43004F037 +:1015C00063FBCEE7B94910B500200870FFF7C4FFF0 +:1015D000002800D0FFDF10BDB34890F862007047CC +:1015E000B14900B591F8580091F85710C0F3800246 +:1015F000C0F340031A4400F001001044052910D242 +:10160000DFE801F00A050A030700A94906E0A94836 +:1016100000BDA749083101E0A549083931F810009B +:1016200000BDFFDF002000BD9F4840F27121B0F8EF +:101630005A00484370479C4890F86800002800D042 +:101640000120704710B5984C207A00F0EDFC40B1B5 +:10165000207C04F1110103F02DFF082801D00120A6 +:1016600010BD207A30B1022804D00120BDE810401E +:10167000FFF7CDBE0020F9E78B49087270478A4911 +:1016800081F8600070477CB50546874890F85D009A +:1016900003F025FF040013D0102104F00BF90028FB +:1016A0000ED12A4669462046FFF7BEFE7E486946AF +:1016B0009C3004F015FB7C4801219C3004F01FFB9A +:1016C0007CBD70B578490A310D4601F1920004F0F5 +:1016D00001FB754C04F19C00617A04F007FB29467C +:1016E00004F1C40004F0F6FA617A04F1C400BDE824 +:1016F000704004F0FBBA2DE9F0416B4C074694F8BA +:101700005D0003F0E2FE064694F85F0004F10A056E +:1017100028B126B11021304604F0CCF8A0B194F8DD +:101720006000002824D094F85E00002820D0607A61 +:10173000294600F08AFCA8B103F073FF3A46294617 +:10174000BDE8F041FFF770BE012060723A462946BD +:101750003046FFF769FE94F85D102846BDE8F04179 +:1017600003F04ABF39462846BDE8F041FFF790BE76 +:10177000BDE8F08170B54C4C207AB0B1022814D08D +:101780000120494960720A310D46FFF72AFE207A8E +:1017900000F04AFC84F85F00082084F85D00607A5D +:1017A000294600F049FC38B901E00020E9E7607AF9 +:1017B000294600F04AFC00B1012084F85E0094F84C +:1017C0005F0028B994F85700012801D0042806D1F9 +:1017D0003549207C113103F06DFE84F85D00002056 +:1017E0002060FDF755FA60600020FFF784FFFFF7E7 +:1017F00068FF94F85700012801D0042803D1BDE800 +:10180000704000203FE770BD70B5274C417B84F8E5 +:101810005810017984F85710012925D0B0F800201C +:10182000A4F85A20827B84F868208279F2B1022AD7 +:101830001CD00122227450F8072FC4F81120808890 +:10184000A4F8150094F85600012508B184F86350F7 +:1018500094F8360008B184F86450052933D2DFE8E3 +:1018600001F0070D2B2D0D000022D9E70022E1E742 +:101870000D4800219C3004F00AFA0FE00A480121CB +:101880009C3004F004FA0849113101F18B0004F096 +:1018900027FA0548217C9C3004F031FA02480121E6 +:1018A0009C3000F0DDFB0FE0FC080020C0000020B1 +:1018B00064770100D0891300062100E00221FA4874 +:1018C00004F0E5F900E0FFDFF7480421283004F0D8 +:1018D000DEF984F86250002070BD70B50546F24C08 +:1018E00000209C3C04F8640FEF482A46853805F038 +:1018F00029FC04F82E5C0120207070BD10B5EA4C64 +:1019000000229C3C84F8632004F8560F0246E64807 +:10191000653805F017FC0120607310BDE2499C3961 +:1019200081F86700704770B500F0ADFBDE4C9C3C61 +:10193000002694F8660028B1FFF741FAFEF7F2FDA1 +:1019400084F86660D94D2E7094F85700012804D0B1 +:10195000BDE87040002001F07EB9022001F07BF963 +:1019600094F86A0000B1FFDF6878002817D0207C67 +:1019700084F87100D4F81100C4F87200B4F81500AE +:10198000A4F876003C2084F86C0068680088A4F80D +:101990006E00012084F86A0000F06BFB6E7070BD71 +:1019A00010B50024C20701D0CA0708D082070BD5A2 +:1019B0008A0709D42620FEF7C7FF02240CE0252061 +:1019C000FEF7C2FF012407E0400705D5480703D40E +:1019D0002720FEF7B9FF0424FEF704FF204610BDC0 +:1019E0002DE9F041B148017859BBAF4C9C3C94F8CB +:1019F000621031B3002584F8615045702846583490 +:101A0000FFF783F9FEF712FFFEF7ECFEA848FEF79A +:101A100091FFA748C01EFFF763F920780021FFF768 +:101A2000BFFF2071FFF76BF9002101220846FFF785 +:101A300032F80F210520FEF749FFA079583C58B92C +:101A400001E00C2094E694F85F0028B994F8570060 +:101A5000012801D0042828D1FDF71AF9064631469D +:101A60006068FDF723FE934990FBF1F701FB170037 +:101A700041423046FCF715FE606020683844206023 +:101A800003F014FD216888420FD8C4E900560120F4 +:101A9000FFF731FEFFF715FE94F85700012801D03B +:101AA000042802D10120FFF7EEFD7F48617A9238C9 +:101AB000FEF700FF94F8570001280DD004280BD042 +:101AC00094F8630040B1784994F856206539764817 +:101AD00004F01CF984F8635094F8640048B172492A +:101AE00094F83620853901F1AD0004F025F984F829 +:101AF000645003F03BFD6C48503003F06CFD84F8FB +:101B00006600002034E669494860704770B5664C4D +:101B10000500A4F19C040AD094F85C1014F8580F46 +:101B2000FFF73EFF14F8041F084304F85C0994F81B +:101B3000610038B194F85700012800D1FFDFBDE8FB +:101B40007040F0E635B1002201234FF49671104643 +:101B5000FFF718F85448FFF7DBF894F8570005280A +:101B600009D2DFE800F0030303090300012108465E +:101B7000FFF7EDF900E0FFDF94F8581094F85C00EF +:101B800081434FF0010005D194F85710012904D08A +:101B900084F861004549087070BD002184F85C102C +:101BA000F8E7424810B5007848B93F489C3890F8AB +:101BB000620020B10020FFF7A9FF002010BD00F057 +:101BC00062FA0C2010BD394901204870704736492F +:101BD0009C3981F86500704770B5002500F016FF4C +:101BE00048B1324E3078012808D0022801D00328AD +:101BF00033D0FFDF70BDBDE8704094E62A4C9C3CBA +:101C000094F85700032828D094F8660018B1FEF71E +:101C100075FCFFF7C8F824485030FFF779F8962094 +:101C2000FFF78FF894F8570001280DD004280BD047 +:101C300094F86800012801D0032800D1102545F050 +:101C40000E010020FFF783F994F86700012801D105 +:101C5000FFF7CBF80220307070BDBDE87040012066 +:101C600054E710B5104C9C3C94F86700012801D152 +:101C700000F014FA94F8660018B1FFF7A0F8FEF728 +:101C800051FC00F0C3FEB8B1084C2078022800D007 +:101C9000FFDF0120FFF73AFF2078002803D02078EB +:101CA000012800D0FFDF10BD98090020C0000020EF +:101CB0005777010040420F00BDE8104033E610B5F1 +:101CC00003F0F8FB044603F0AEFC38B1204603F005 +:101CD00006FC18B1102103F0EDFD08B10020E2E789 +:101CE0000120E0E72DE9F84F04460026FEF71EFE2E +:101CF000DFF8C493074699F80000022800D0FFDF00 +:101D0000DFF8B8A39AF86700012801D100F0C6F9FE +:101D1000EA48EC3003F0DAFFFF258046002C78D04B +:101D2000E648EC3004F01EF8002872D0FEF7CAFD39 +:101D300000286ED0E14C9AF86600EC3460B103F0F4 +:101D4000FBFB0546FF2807D00146E01C03F0E8FB3B +:101D5000284603F0FBFB0743DFF860B3B8F1060F3A +:101D60000BF1800B55D2DFE808F097979703975552 +:101D70009AF8571001294CD0D046042949D067B9A8 +:101D800098F8680008B1022843D12078E11CC0F31C +:101D90008010FFF794FF00287ED198F8670047462F +:101DA00001282ED197F8920058BB012087F89200A5 +:101DB000FF2D0DD0C14A28469432511E03F099FBE5 +:101DC00000B9FFDF17F8930F40F0020038700CE005 +:101DD0002078C0F3801088F89300DBF86F10CBF800 +:101DE0001410BBF87310ABF81810B44D99F802003A +:101DF0009A354C467F2800D1FFDFA07828707F20DD +:101E0000A070AE48C430FEF783FF032189F80010AC +:101E100043E041E020789AF81010A046C0F380100B +:101E20005446884207D1A5490622113108F1030022 +:101E300005F05CF920B10020FF2D08D088B901E041 +:101E40000120F9E794F85D00A8420AD00FE070B1D4 +:101E500098F8000008F10301C0F38010FFF72FFF8E +:101E600028B994F85700012813D0042811D094F809 +:101E7000570088B96FB994F8680008B101280BD1F0 +:101E800098F8000008F10301C0F38010FFF717FF76 +:101E900010B994F86500C8B101269AF8660018B127 +:101EA000FEF78DFFFEF73EFB16B10120FFF72EFE79 +:101EB00099F800104846002906D00178012903D07E +:101EC0000078032800D0FFDFBDE8F88F7B49D9F800 +:101ED00004008031C34651F87B2FC0F80E208A8859 +:101EE00042828979017598F816204275B8F8172052 +:101EF000C282B8F819204280B8F81B208280B8F856 +:101F00001D20C2806E4A4146D2F80B308360D27BDE +:101F1000027311F8242F02F01F02027611F81F2914 +:101F2000520980F8442111F8051C427BC1F340118D +:101F30000A40427394F86A0000B1FFDF002784F87A +:101F40006C70D9F80400C8460188A4F86E10418866 +:101F5000A4F884108188A4F88610C188A4F8881099 +:101F600090F8440184F88A00544894F85F100A30CD +:101F7000009021B1607A009900F067F838B994F8C0 +:101F8000600058B1607A009900F056F830B1D4F88A +:101F90000A00A067E089A4F87C0002E0A767A4F823 +:101FA0007C709BF80000454AC0F38011D8F804000B +:101FB0008032FF2D417652F86F1FC0F81A109288B8 +:101FC000C28313D0C4F87E103C4AC08BA4F88200B0 +:101FD0007232511E284603F08CFA00B9FFDF94F8E4 +:101FE000710040F0020084F871000DE0C4F87E70CA +:101FF000A4F88270417E84F87110D0F81A10C4F8E9 +:102000007210C08BA4F87600012084F86A0000F0FA +:1020100030F888F8007000F036F8012000F01BFE60 +:102020003BE7012200F03FBE022803D0032801D085 +:102030000020704701207047012802D148798009AB +:1020400001D00020704701207047012806D148794F +:102050000121B1EB901F01D1012070470020704792 +:102060000278202322F0200203EA41110A43027081 +:102070007047114810B540680088FAF70BFEBDE8BC +:102080001040FAF7BFBA10B5FEF780FEFEF771FEFA +:10209000FEF7FDFDBDE81040FEF728BE064810B56E +:1020A000801CFEF7ADFE10B903497F208870BDE8A3 +:1020B0001040FEF790BE0000C0000020FC08002089 +:1020C000FC090020FE484068704770B506460D4682 +:1020D00014461046FFF78AF8022C10D0F94908443C +:1020E0004FF47A7100F2E140B0FBF1F000EB4600F2 +:1020F00005442046FFF770F82844603070BDF2496F +:10210000EDE72DE9F0410D46064601461746012050 +:1021100003F0B3FC044696F83200FFF767F896F830 +:102120003210022914D0E74940F2712208444FF4DA +:102130007A7100F2E140B0FBF1F170885043C1EBDD +:102140004000C01BA0F55970A54203D2214602E011 +:10215000DD49E9E72946814204D2A54201D2204661 +:1021600000E028467062BDE8F0812DE9FF4F89B09C +:10217000044690F83200DDF858909A46039049EAF8 +:102180000A00089094F844000025164619460D28C8 +:1021900003D00020069011B131E00120FAE794F855 +:1021A000E40003282BD1069848B3B4F85C01B04290 +:1021B00025D1D4F8EC00C4F8D800608840F2E241A0 +:1021C0004843C4F8DC00B4F83201B4F8BE10084447 +:1021D000C4F8E000204602F06CF9B4F86001E08237 +:1021E00094F85E016075B4F862016080B4F864012F +:1021F000A080B4F86601E080022084F8E400D4F8FE +:102200003C010290B4F8BE00D4F838810090B4F8D4 +:102210003011D4F82C010590BAF1000F04D094F8D5 +:10222000F80000287DD108E004F59670049004F5CC +:102230008C7704F1B80B001D07E004F5887004905A +:1022400004F1FC0704F5867B001D0790208F301AEF +:1022500000B20190701A00B2002805DAD4F8280103 +:10226000059001200890019894F8E410E9B1012943 +:102270007DD002297CD003297BD0FFDF2946059839 +:10228000FCF70FFA049908600798012106800020E6 +:102290003870397104980068B8608C48D0E905201E +:1022A000824267D9CBF8000081E1B8F1000F00D17C +:1022B000FFDFE08A40F271214843490001EB400012 +:1022C0000A9900F065FDC4F8E800608840F2E24138 +:1022D00048430A9900F05CFDC4F8EC0082B2204645 +:1022E000A16AFFF70EFF14F8320FFEF799FF4FF4C3 +:1022F0007A7100F2E140B0FBF1F101EB08000090CF +:102300002078FEF78DFF14F83219024602293FD0DB +:102310006C4815180846FEF769FF29184FF47A70C3 +:1023200000E075E101F2DB51B1FBF0F1E08A40F22F +:1023300071225043C1EB4001D4F8E80040F2E2437F +:102340000A1A0099551894F83220617D11FB03F1A7 +:1023500005F2C245FFF7B9FE5C49801C48618861FF +:1023600094F83200FEF75CFF4FF47A7103E087E0E7 +:1023700010E0BDE018E100F2E140B0FBF1F101EB4B +:102380000800281AB0F53D7FBFF478AFFFDF75E78E +:102390004D48BEE7E08A40F27122D4F8DC10504389 +:1023A00001EB40000A9900F0F3FCC4F8E8006088F3 +:1023B00040F2E24148430A9900F0EAFCC4F8EC001C +:1023C00082B22046A16AFFF79CFE009848BBB9F193 +:1023D000000F26D094F83200FEF708FF94F8321070 +:1023E000024602291BD0374840F2712510444FF4B1 +:1023F0007A7200F2E140B0FBF2F0D4F8E820D4F8B1 +:10240000DC300244E08A684303EB4000851A08464A +:10241000FEF7E2FE0299081A0544203D0CE02A4826 +:10242000E2E7E08A40F27122D4F8DC10504301EB7D +:102430004000D4F8E810451AD4F8E020D4F8D810B9 +:10244000D4F8E80040F2E24301FB020094F83220A5 +:10245000617D11FB03F1C834FFF737FE01461B48CD +:1024600040F27123416134F8C61C626A5943C2EBE1 +:102470004101A1F21331816101202077C83CFDE6C2 +:10248000628840F27123D4F8EC105A43C1EB420544 +:102490004543DDE900021044D4F8E020D4F8D8C068 +:1024A000801AD4F8E830401E0CFB023200FB0120F9 +:1024B00094F83220617D40F2E24311FB03F107E022 +:1024C000100A0020A224020004360200C8000020E6 +:1024D000FFF7FBFD0146FE48B9F1000F4161A5F28F +:1024E00013318161CBD0B8F1000FC8D1FFDFC5E651 +:1024F000618840F27123D4F8EC205943C2EB4105C6 +:10250000454394F84300212803D094F8440021283F +:1025100009D1B4F85C01301A00B2002803DB94F84A +:102520005F0100B10390089828B100980028029834 +:102530001AD000B1FFDFDDE900010844D4F8EC1047 +:10254000039A48430021FFF7C0FD0146E04840F2EE +:10255000712341616188D4F8EC205943C2EB4101F9 +:10256000A1F21331816189E610B1B8F1000F00D1F9 +:10257000FFDF0398FEF73AFE01460398022811D0C8 +:10258000D44808444FF47A7100F2E140B0FBF1F016 +:102590002D1A94F83200FEF71FFE0299081A05441E +:1025A000203DC8E7CC48ECE71046CBF80020626A33 +:1025B000104400F28310F8607971B4F8A800801B11 +:1025C00000B2002801DD03207871069820B3B9F12C +:1025D000000F17D0B4F8D020C2B3B4F8D20000BFB7 +:1025E000A4F8D20094F8D430401C4343934209D25B +:1025F0007879401E002805DD7971B4F8D200401CBE +:10260000A4F8D200BAF1000F27D094F8F80000B374 +:1026100002200DB0BDE8F08FB9F1000FDAD194F8C7 +:10262000E4000028EED0608840F27122D4F8EC106B +:102630005043C1EB4001384603F0E3F90004000CBD +:10264000E0D0179901B108800120E2E7FFE7002000 +:10265000C6E794F83401FCF775FE94F83401394666 +:1026600000F07CFB18B18AF0010084F8F90000202A +:10267000CFE7FEB50446FCF70BFB0146D4F8280172 +:10268000FDF714F8214600F08DFB94F844100D2955 +:1026900009D0228FB4F8F6101318994206DB491CB2 +:1026A000A4F8F61006E0B4F8F6000CE0401C104464 +:1026B000A4F8F60094F8FA0040B9B4F8F600B4F8BB +:1026C000AC10884202D1401CA4F8F600B4F83201E4 +:1026D0007F4D401CA4F83201B4F85E00B4F85C10E1 +:1026E000401A218F401E084486B216E07B482978A4 +:1026F00002AF002330F81110CDE9003794F84431CF +:1027000030F813000023084481B22046FFF72DFD66 +:10271000002821D0012817D0FFDFB4F8F620B01A26 +:1027200000B20028E2DA082084F85300012084F87F +:102730005200204601F07FFB204600F011FB287973 +:10274000BDE8FE40F6F7D0B9B4F8F600BDF80810C1 +:102750000844A4F8F600E0E7FEBD2DE9F041604C26 +:1027600003270125277500202074E07A04F1100664 +:1027700050B14FF47A71A069FBF793FFA06100217B +:10278000304603F03EF910E0002000F04AFB054619 +:10279000FEF74AFF05442946A069FBF782FFA061C6 +:1027A0002946304603F02DF9451C208C411C0A298E +:1027B00001D228442084606830B1208C401C0A2853 +:1027C00002D30220607500E06775607A002806D1A8 +:1027D000207B314600F0C2FA002800D1FFDFC2E4BE +:1027E0002DE9F04106463E480F460178384D032951 +:1027F00009D1017BB14206D1406828613846BDE865 +:10280000F04100F023BB304600F09EFA0621FAF7B3 +:102810000FF9040000D1FFDF304600F095FA21885F +:10282000884200D0FFDF214638462C61BDE8F041E8 +:1028300000F0C5BA10B52A4C207848B1012060726A +:10284000FFF7C5F92078032804D0207A002800D0AB +:102850000C2010BD207BFCF775FD207BFCF7BFFF33 +:10286000207BFCF7F6F900B9FFDF0020207010BDD7 +:1028700010B5FFF7DFFF00F016FB19490020C87202 +:1028800010BD70B50446012000F04FFAC5B20B2010 +:1028900000F04BFAC0B2854200D0FFDF6FF00400B9 +:1028A00000F043FAC5B2192000F03FFAC0B28542E9 +:1028B00000D0FFDF0649002001220C7188700A70E9 +:1028C0004870C87006490870BDE87040D0E7000045 +:1028D000C8000020A2240200043602007477010020 +:1028E000100A0020F749087070472DE9F041F64CB6 +:1028F00006462078E8BBF548FCF751F920732028FC +:1029000042D04FF00308666084F8008000256572AD +:1029100025727EB1012106F1D400FDF738FA0620B8 +:10292000FAF732F816F8D41FB1FBF0F200FB1210E0 +:10293000401C3070FCF786F940F2F651884200D214 +:10294000084600F23D1086B2FEF74AFEE061FEF74F +:102950006BFE0127D0B1A772002000F062FA064496 +:10296000FCF796F93146FBF79CFEA06184F81480D1 +:1029700000E009E084F81580D3492574207B1031EC +:1029800000F0ECF960B90AE00C2028E7FCF780F9C8 +:102990003146FBF786FEA061A572E772E6E7FFDF2E +:1029A00025840020FFF713F9002018E77CB50025E7 +:1029B000044680F8E450A0F83051C24900950195D2 +:1029C000C348097894F844212B4630F8111030F8A8 +:1029D00012002A46084481B22046FFF7C6FB00B128 +:1029E000FFDF44F8E05F012044F8085C2071E582D5 +:1029F000A582A57634F8A80C401E24F8A80CA4F8EB +:102A0000525000207CBDAF4948707047AE4810B5A9 +:102A1000417A012409B1002408E0C17A31B1406A49 +:102A2000AC49884202D90024FFF7CDF8204610BDFA +:102A300070B5A44C0646E088401CE080D4E9020151 +:102A40006278D6F8385112B12A4603F004F8A06033 +:102A5000854205D896F8E400012801D0E07808B155 +:102A6000002070BD012070BD70B504460D460846BB +:102A7000FEF7BCFB022D10D0974908444FF47A7141 +:102A800000F2E140B0FBF1F040F2E2414C4300F5CE +:102A90004D70844203D9201A70BD9049EDE70020A3 +:102AA00070BDFEB50025044680F8F85090F8B600D9 +:102AB000002849D194F8E400032845D1FCF7E8F850 +:102AC0000146D4F82801FCF7F1FD00283CDD214641 +:102AD00000F068F9411C208F0144A4F8F410B4F808 +:102AE000F410B4F8AC20511A09B200292CDD0121F0 +:102AF00084F8FA10B4F85E10B4F85C20891A491E04 +:102B0000084486B21AE06F49714802AA097830F881 +:102B10001110CDE90052B4F8F42094F8443130F8A3 +:102B200013000123084481B22046FFF71EFB002852 +:102B30000AD0012809D0022806D0FFDFB4F8F4003B +:102B4000301A00B20028DEDAFEBDB4F8F400BDF899 +:102B500008100844A4F8F400F0E77CB5002504460A +:102B6000012902D15748C17861B1042084F8E400FA +:102B7000FBF79AFFA4F83251208FA4F8F60084F8EE +:102B8000FA507CBD5249007894F8E42031F81000E6 +:102B90000123032A14D0012AEAD100BFCDE9003570 +:102BA00094F84431B4F8AC2031F8131000230844F1 +:102BB00081B22046FFF7D9FA0028D9D0FFDFD7E746 +:102BC000C4F8E050C4F8D850E8E770B53E4C002691 +:102BD0003546E07A08B1E57219E0A07A18B1012013 +:102BE00000F01FF90646FEF71FFD8119A069FBF7EB +:102BF00058FDA061257403206075607A30B93249B0 +:102C0000207B103100F0AAF800B9FFDF2584FBF724 +:102C10004BFF2C480079BDE87040F5F765BF10B553 +:102C2000062916D2DFE801F00509030C0C0D00217E +:102C300000E00121BDE810408FE7032180F8E41097 +:102C400010BDB0F8EC108AB2816ABDE81040FFF701 +:102C500058BAFFDF10BD10B548B1012803D00228D3 +:102C600005D0FFDF10BDBDE8104000F048B9BDE859 +:102C70001040AAE770B5134CA178022912D1E1885F +:102C800000290FD12569C5F83C0195F83200C035FF +:102C9000FEF7A2FAE96F081AA1680144A160E16891 +:102CA0000844E06070BD70B5054606488378022B85 +:102CB00016D0054C2434C1B1012915D0022916D0F3 +:102CC000FFDF70BDC8000020100A0020E1270100CE +:102CD00074770100DB821300A22402000436020094 +:102CE000046904F59C74E6E76D1E2560E9E710466B +:102CF000FEF789FA4FF47A7100F2E140B0FBF1F08F +:102D0000281A2060DDE7D24810B5007808B100200D +:102D100010BD0620F9F72AFE80F0010010BDCC4856 +:102D20000078002800D001207047002806DA00F063 +:102D30000F0000F1E02090F8140D03E000F1E02016 +:102D400090F800044009704710B50446202800D3CD +:102D5000FFDFBF48283030F8140010BDFCF7E0B9A1 +:102D600070B50446002084F8E40094F834514FF61E +:102D7000FF76202D00D3FFDFB548283020F81560FE +:102D800094F83401FBF765FF202084F8340198E7BC +:102D900002460020002904D0AE485143B1FBF0F0B8 +:102DA000401C7047002809D0D1F8EC20498840F237 +:102DB00071235943C2EB4101B0FBF1F0704770B58C +:102DC0000125A54E0C46082829D2DFE800F0040FA3 +:102DD00017171228281B204600F0FAF8204600F0AA +:102DE000BAF884F8F8500220B0706AE701F05FFB8F +:102DF00001E0FEF749F984F8F85062E72046BDE8A3 +:102E0000704036E494F8E400042800D0FFDF204648 +:102E1000FFF7A6FF3079BDE87040F5F765BEFFDF2C +:102E20004FE708B500284FF00101684602D0FCF7D3 +:102E30008FFF01E0FCF782FF9DF8000042F2107165 +:102E40000002B0FBF1F201FB120008BD70B5804C2E +:102E500005462078032800D0FFDF0026082D20D269 +:102E6000DFE805F0040D1717131F1F1A6662FEF73F +:102E7000B7FD00B1FFDF78490320887021E7FEF736 +:102E800090FE0028FAD0FFDF1BE7BDE87040FEF798 +:102E9000FBB8BDE8704060E4207BFBF7DAFE2670EB +:102EA0000FE7FFDF0DE7FEB56B4C0120E0704FF63A +:102EB000FF750CE00621F9F7BBFD060000D1FFDF2E +:102EC00096F83401FCF78BFC3046FFF749FF694662 +:102ED0000620F9F73AFD50B1FFDF08E0029830B163 +:102EE00090F8E41019B10088A842E3D104E06846E4 +:102EF000F9F709FD0028F1D00020E070FEBD70B5A3 +:102F0000534C0020E072A66920700120207200213D +:102F1000606802F042FC6068C0F82861257B80F898 +:102F20003451616AC0F82C61C0F838110688202D30 +:102F300000D3FFDF4648283020F815606068FFF7AF +:102F400035FD00B1FFDFFBF7AFFD43480079BDE879 +:102F50007040F5F7C9BD70B50546FBF773FE95F8EF +:102F6000326004463046FEF741F9022E26D03B4936 +:102F700040F2712208444FF47A7100F2E140B0FB54 +:102F8000F1F0D5F8EC10014468885043C1EB4006DD +:102F9000303EB72C00D8B7242946012002F06DFD41 +:102FA0002044341A29460120A4F2193402F065FDA8 +:102FB000696A9C30814203D9081A02E02849D7E7A0 +:102FC00000202549A042CC6000D32046886078E6E6 +:102FD00010B5044620490020C4F83801C880C4F860 +:102FE0003C0194F8F90038B9FBF752FED4F804110B +:102FF000FCF75CFB002811DCB4F8F610208F81424E +:1030000001D1B4F8AC10081AA4F8AE002187D4F8A6 +:103010002001C4F80401C4F8280114E034F8F40FC6 +:1030200034F8BC1C401A24F8460C208824F8BC0C48 +:103030002069E0626063A06944F83C0CE069A06329 +:10304000208CA087F43C2046BDE8104001F027B951 +:10305000100A002040420F00C8000020A2240200F5 +:1030600004360200012806D0022807D0042808D020 +:10307000082808D105E0012907D004E0022904D07E +:1030800001E0042901D0002070470120704770B58D +:10309000F74CE06890F844001B2800D0FFDFE068A0 +:1030A000002580F86B5090F8780100B1FFDFE068F0 +:1030B00090F86C1041B180F86C500188A0F87C1138 +:1030C00080F87A510D2108E00188A0F87C1180F881 +:1030D0007A51012180F87E110C2180F87811008846 +:1030E000F9F7D8FDF9F78EFAE078F5F7FDFCE0681E +:1030F00080F8445070BD70B5DD4C2079800725D52F +:103100006078002822D1226920460125D378C16841 +:103110009B1E01F13800162B7CD2DFE803F00B97E1 +:103120004D596A18973597436D6097979760717CF2 +:103130009797828F91F846200123194602F029FCC7 +:10314000002803D1E168082081F8460070BD10799D +:1031500091F843200A2A09D191F8A220824205D190 +:10316000002081F8430081F8660070BD91F84500A9 +:10317000020707D520F0080081F84500BDE870403F +:1031800001F02ABAFFDF70BD91F84500C00700D1F9 +:10319000FFDF01F021FAE06810F8451F21F001017E +:1031A000017070BD91F84400102800D0FFDFE06886 +:1031B000112180F86B5008E091F84400142800D0E9 +:1031C000FFDFE068152180F86B5080F8441070BD77 +:1031D00091F84400152800D0FFDF172005E091F892 +:1031E0004400152800D0FFDF1920E16881F8440071 +:1031F00070BDBDE870404AE7BDE8704001F0F8B925 +:1032000091F843200123002102F0C3FB00B9FFDF46 +:103210000E200FE01AE011F8450F20F004000870AE +:10322000ACE791F843200123002102F0B2FB00B982 +:10323000FFDF1C20E16881F8430070BD91F8440075 +:103240001E2801D000B1FFDF1F20CEE7FFDF70BDD9 +:103250008748C16891F84520130702D501214170C4 +:10326000704742F0080281F845204069C07881F833 +:10327000A10001F0A8B910B57D4CE1680A88A1F859 +:10328000A42181F8A20191F8310001F049F9E16827 +:1032900081F8A60191F8320001F042F9E16881F865 +:1032A000A701012081F8A001002081F86801E078E1 +:1032B000BDE81040F5F718BC10B56D4C012309218D +:1032C000E06890F84320383002F063FB38B1E168E1 +:1032D000002001F85A0F087301F8170C10BD0120E7 +:1032E000607010BD2DE9F843614CE06890F8431020 +:1032F0001D2909D05FF0000790F844101F2905D060 +:1033000077B300F1430503E00127F5E700F1440539 +:1033100010F8741F41F004010170606902F00DFEA5 +:103320004FF001080026F8B13946606901F00AF94A +:10333000D0B16A466169E06802F0C7FB80B360699A +:1033400002F0F9FDE168A1F85C01098F01F0DCF8F9 +:1033500038B3E068282180F8531080F8528041E0AB +:1033600002206070BDE8F883E06890F8680110B151 +:103370001E20FFF780FFAFB16069E168C07881F877 +:10338000A20008FA00F1C1F3006000B9FFDFE068B5 +:103390000A2180F8431090F8660040B9FFDF06E08C +:1033A00009E014E02E7001F017F9FFF751FFE06813 +:1033B00080F85B60D6E7E06890F8680110B1002003 +:1033C000FFF759FF2E70E06880F85B600AE0E06864 +:1033D0009DF8001080F85E119DF8011080F85F11D3 +:1033E00021202870E06800F144018D4203D1BDE83E +:1033F000F84301F0F1B880F86660B3E770B51C4C93 +:1034000001230B21E06890F84420383002F0C1FA23 +:10341000202650BBE0680123002190F8442038307A +:1034200002F0B7FA0125F0B1E06890F843002128D6 +:103430001BD0606902F071FDE0B1E06890F8741093 +:1034400041F0040180F8741061694A7902F00702C2 +:1034500080F83020097901F0070180F82F1090F8EA +:10346000693133BB09E0657070BD667070BD0000E6 +:10347000E4000020BDE87040EAE690F86831C3B986 +:1034800000F131035E788E4205D11978914202D164 +:1034900080F85B500DE000F5CD710D7002884A8018 +:1034A00090F82F200A7190F830004871E078F5F715 +:1034B0001BFBE1681E2081F84400BDE8704001F06C +:1034C00082B870B5FE4CE06890F84510890707D5C2 +:1034D00090F8432001230821383002F05AFAE8B16D +:1034E000E06890F86E00800712D4606902F009FD70 +:1034F000E16881F86F00606930F8052FA1F870204D +:103500004088A1F8720011F86E0F40F002000870B8 +:10351000E06890F86E10C90703D00FE001206070DA +:10352000A4E790F84500800700D5FFDFE06810F8B9 +:10353000451F41F00201017001F045F8E0680025E7 +:1035400090F84310062906D180F8435080F8665061 +:10355000E078F5F7C9FAE06890F85A11042985D1A6 +:1035600080F85A51E078F5F7BFFAE06890F8431018 +:103570000029D5D180F8665078E770B5D04C01238A +:103580000021E06890F84420383002F002FA01256A +:1035900078B9E06890F84420122A0AD00123052166 +:1035A000383002F0F6F910B1082060705EE76570FF +:1035B0005CE7E06890F86C0008B901F004F8E16895 +:1035C0006069C03102F08BFCE1686069983102F0FB +:1035D0008CFCE06890F8800100B1FFDFE1680888AA +:1035E000A1F8820101F5C271606902F070FCE16826 +:1035F000606901F5C67102F06FFCE06880F88051E7 +:10360000142180F84410E078BDE87040F5F76CBAFA +:1036100070B5AB4C01230021E06890F844203830AD +:1036200002F0B7F90125A0B1606902F026FC90B163 +:103630006069E168B0F80D00A1F85C01098F00F045 +:1036400063FF58B1E068282180F8531080F8525089 +:103650000CE765700AE7BDE87040F9E56069E1686C +:10366000027981F85E21B0F80520A1F8602102F00E +:10367000FBFBE168A1F86201606902F0F8FBE16818 +:10368000A1F86401606902F0F5FBE168A1F8660148 +:103690000D2081F84400E9E67CB5894C2079C0070B +:1036A00033D0606901230521C578E06890F8442093 +:1036B000383002F06EF968B1022D0BD00A2D09D016 +:1036C0000B2D07D0032D05D0062D03D0607840F0D8 +:1036D000080060706078002817D160690226C578FC +:1036E0001DB1012D01D0162D18D1E06890F84300CE +:1036F00002F042F990B1E16891F843001C280DD026 +:103700001D2803D0162D1AD066707CBD222081F8AA +:103710004300162D70D02A20FFF7ADFD192D6CD275 +:10372000DFE805F0262310358C8C3889498C292C4C +:10373000468C8C8C8C866F6C8C8C808C83002020CB +:1037400060707CBDE0680123194690F8462038304F +:1037500002F01FF920BB606902F0B7FBE16881F855 +:103760004801072081F846006AE000F0E9FF67E0C1 +:10377000FFF74EFF64E000F0C3FF61E0E06890F8FF +:10378000441011290BD1122180F8441058E0FFF7A2 +:10379000F4FE55E0E06890F84400172801D0667008 +:1037A0004EE000F019FFE1681B2081F8440047E07B +:1037B000FFF787FE44E0E06890F84500C00703D0BB +:1037C000607840F0010022E06946606902F09BFBEE +:1037D0009DF8000000F00501E06800F8741F9DF8F6 +:1037E000011001F04101417000F0EDFEE06810F8B9 +:1037F000451F41F0010113E014E01FE0FFF75CFDFD +:103800001EE0E06890F84500400702D50120607096 +:1038100016E000F0D8FEE06810F8451F41F0040102 +:1038200001700DE0FFF7EAFD0AE0FFF75BFD07E03E +:1038300000F045FF04E000F007FF01E0FFF708FD9E +:10384000E168F1E92002401C42F10002C1E90002F6 +:103850007CBD70B51A4C2079000743D560780028EC +:1038600040D1E06890F8A300FF2800D1FFDFE068B6 +:10387000FF2180F8A31090F84410192907D10025E2 +:1038800080F86B5000F0A8FEE06880F84450E068D3 +:1038900090F843101C291CD190F8440002F06CF8F9 +:1038A00098B1E0682221012380F8431090F8442069 +:1038B0000B21383002F06DF858B92A2002E00000E0 +:1038C000E4000020FFF7D7FC03E0E1681D2081F849 +:1038D0004300E06890F84610082903D102212170C6 +:1038E00080F8A310C2E5FA49C96891F85E210AB9C7 +:1038F00091F8312081F8312091F85F210AB991F8CF +:10390000322081F83220002801D00020B3E4704733 +:1039100070B5EF4C06460D46E06890F8A300FF280E +:1039200000D0FFDFE268002082F8A36015B1A2F8A2 +:1039300068009BE522F8620F0120107196E510B532 +:10394000E34C01230021E06890F84320383002F076 +:1039500020F800283ED0E06890F86811002939D09E +:1039600090F86911002935D190F8442001230B21EA +:10397000383002F00EF800282CD1E06890F86A1177 +:1039800090F83100FFF76EFB58B1E06890F86B11CA +:1039900090F83200FFF766FB18B1BDE81040002038 +:1039A00069E4E0680123032190F84420383001F0F5 +:1039B000F0FF00280ED1E0680123022190F8442096 +:1039C000383001F0E6FF002804D10021BDE81040A6 +:1039D00016209DE710BD70B5BD4CE06890F8A310AF +:1039E000FF296FD1617800296CD190F8462001231E +:1039F0001946383001F0CDFF002863D1E06890F817 +:103A0000461149B10021A0F8601090F8471180F8E4 +:103A1000A4100021022041E090F844200123042159 +:103A2000383001F0B6FF054600F0EDFE002849D120 +:103A3000284600F012FF002844D1E068012300214D +:103A400090F84320383001F0A4FF78B1E0680123FA +:103A5000042190F84420383001F09BFF30B9E06831 +:103A600090F85A0010B10021122017E0E06890F899 +:103A700043200A2A0DD0002D24D101230021383003 +:103A800001F087FF88B1E06890F85A1104290CD141 +:103A900007E010F8A21F817000210720BDE87040E8 +:103AA00036E790F86E00800702D0BDE8704046E728 +:103AB00000210C20FFF72CFFE06810F86E1F41F08A +:103AC00001010170D2E43EB505466846FDF70DFCE4 +:103AD00000B9FFDF2221009803F0B3FB0321009817 +:103AE00002F087F90098017821F010010170294651 +:103AF00002F0AEF9764CAD1E162D5BD2DFE805F074 +:103B00000B5A335B5B0B5A3E5A5B10265A5A5A1DAE +:103B10005B5B5A5A2A4FE168009891F8A41017E0AD +:103B2000A26800981178017191884171090A817128 +:103B30005188C171090A01723DE00321009802F029 +:103B400014FA0621009802F014FA34E000980621D5 +:103B5000017130E00098E16891F86A21027191F8F2 +:103B60006B11417127E0E1680098C83102F0C1F99A +:103B7000E16800989C3102F0C1F91CE05549D1E997 +:103B80000001CDE90101E06801A990F8740000F09E +:103B900005008DF80400009802F0BAF90BE0E16826 +:103BA00091F8680100280098D6D111F8312F0271E0 +:103BB0004978D6E7FFDFFDF7ADFB002800D1FFDF36 +:103BC0003EBD434810B5C06890F8491041B990F81F +:103BD000442001230621383001F0DBFE002800D00C +:103BE000012010BD70B53A4DE86890F8471039B122 +:103BF000012905D0022906D0032904D0FFDF35E4CE +:103C0000B0F8AC1041E090F84610082934D0B0F874 +:103C10005C10B0F85E2000248B1C9A4206D3511A27 +:103C2000891E0C04240C01D0641EA4B290F85A1012 +:103C300039B190F8432001230921383001F0A9FE61 +:103C400030B3FFF7BEFF78B1E9680020B1F8562025 +:103C5000B1F854108B1C9A4203D3501A801E00D026 +:103C6000401EA04200D284B20CB1641EA4B2E86827 +:103C7000B0F8AC10214408E0B0F85C100329BFD3C1 +:103C8000018FB0F85E201144491CA0F8A81047E449 +:103C90000024ECE770B50C4605464FF4D47120467D +:103CA00003F0F1FA25803BE4F8F7CBBF2DE9F041B2 +:103CB0000D4607460621F8F7BBFE040042D094F8F3 +:103CC0006C010026E0B16E700820287012E0000040 +:103CD000E40000208C770100268484F86C61D4F81D +:103CE0006E01C5F80200D4F87201C5F80600B4F8F8 +:103CF0007601688194F86C010028EDD1AE7094E0F3 +:103D000094F8780190B394F878010C2813D00D281A +:103D100001D0FFDF89E02088F8F7BCFF0746F8F7FD +:103D200086FC78B96E700D20287094F87A01A8701E +:103D30002088A88014E02088F8F7ACFF0746F8F741 +:103D400076FC10B10020BDE8F0816E700C20287068 +:103D500094F87A01A8702088A88094F87E01A87150 +:103D600084F878613846F8F75CFC5EE0FFE794F889 +:103D7000980130B16E700F20287084F898616F80C0 +:103D800053E094F8800180B16E700920287020887B +:103D90006880D4F884116960D4F88811A960B4F8F7 +:103DA0008C01A88184F880613FE094F88E0140B1D5 +:103DB0006E7016202870B4F89001688084F88E61C7 +:103DC00033E094F8920170B16E701720287005E00E +:103DD00084F89261D4F89401C5F8020094F8920135 +:103DE0000028F5D121E094F89A0140B119202870FB +:103DF00084F89A61D4F89C01C5F8020015E094F8A3 +:103E0000A00100289FD06E701420287009E000BF28 +:103E100084F8A061D4F8A201C5F80200B4F8A601A4 +:103E2000E88094F8A0010028F2D101208BE7FE4A37 +:103E30009060D1707047002180F8431080F84410E2 +:103E400080F8471090F8B61009B1022100E0032174 +:103E5000FEF7E5BE2DE9F041F34C0546E06809B1F7 +:103E6000002104E0B0F8BE10B0F8AE201144A0F874 +:103E7000BE1090F8461139B990F846200123194632 +:103E8000383001F086FD30B1E06830F8601FB0F8DE +:103E90004E2011440180E06890F8663033B1B0F8EC +:103EA0006210B0F8AE201144A0F8621090F96A7068 +:103EB000002F06DDB0F86810B0F8AE201144A0F86D +:103EC000681001213D2615B180F8536013E0227877 +:103ED000022A0AD0012A11D062782AB380F852103F +:103EE00012F0140F0DD01E2113E090F8A420062A22 +:103EF0003CD016223AE080F8521044E090F8482175 +:103F000034E0110702D580F853603CE0910603D5F8 +:103F1000232180F8531036E0900700D1FFDFE168DD +:103F20002A2081F853002AE02BB1B0F86220B0F8C3 +:103F300064309A4210D2002F05DDB0F86820B0F846 +:103F400064309A4208D2B0F86030B0F85E209342F4 +:103F500004D390F846310BB1222207E090F84730A5 +:103F60003BB1B0F85C30934209D3082280F853206B +:103F7000C1E7B0F85C20062A01D33E22F6E7E068EC +:103F800090F8521019B1E068BDE8F04153E7BDE880 +:103F9000F0410021FEF743BE2DE9F047A24C8146D7 +:103FA0000D46E0680088F8F787FE060000D1FFDFC5 +:103FB00060782843607020794FF000058006E06843 +:103FC00004D5A0F85C5080F8BC5003E030F85C1FCA +:103FD000491C0180FFF7F5FD012740B3A0880005CB +:103FE00006D5E06890F8491011B1A0F854501EE0D1 +:103FF000E068B0F85410491C89B2A0F85410B0F829 +:1040000056208A4201D3531A00E00023B4F806C0B8 +:104010000CF1050C634501D880F85A70914206D323 +:10402000A0F8545080F89871E078F4F75DFD20799D +:104030004FF0020810F0600F0ED0E06890F84710C3 +:1040400011B1032908D102E080F8477001E080F83F +:1040500047800121FEF7E3FDE06890F84710012951 +:1040600004D1A188C90501D580F84780B9F1000FB6 +:1040700078D1A188890502D5A0F8D05003E030F8A6 +:10408000D01F491C018000F085FBFFF7A4FC00F065 +:1040900058FD0028E06802D0A0F8B05003E030F8E6 +:1040A000B01F491C018000F04FFD38B1E16891F864 +:1040B000BC00022807D8401C81F8BC00E06890F8DA +:1040C000BC00022804D9E06820F8B05F4580057381 +:1040D000E0680123002190F84420383001F059FCB9 +:1040E00020B9E06890F844000C2859D1E068012319 +:1040F000002190F84320383001F04BFC98B3E06881 +:104100000123002190F84620383001F042FC50B3E2 +:10411000E06890F84710022942D190F8BC0010BB2B +:104120003046F8F754F8F0B1E16891F8A300FF28A1 +:1041300036D1B1F8AA00012832D981F8B570B1F8AA +:104140005E00B1F85C20831E9A4201DB012002E090 +:10415000801A401E80B2B1F8B020E3889A4203D39F +:10416000012204E027E01BE09A1A521C92B290420E +:1041700000D91046012801D181F8B55091F84021AD +:1041800092B1B1F8B220B1F842118A4201D30121B3 +:1041900002E0891A491C89B2884205D9084603E021 +:1041A000E168012081F8B550E1680A8F1044A1F858 +:1041B000AC00FFF717FDA088C0F340214846FFF789 +:1041C00049FEE06880F8B650BDE8F047FDF7C5B895 +:1041D0001549024648788B7818430DD10846C068C7 +:1041E00042B10979090703D590F84600082803D0A1 +:1041F00001207047FEF71CBC0020704770B50A4CC8 +:1042000005460E46A0882843A080A80703D5E807E6 +:1042100000D0FFDF2661EA074FF000014FF00100F8 +:104220001DD06661F27801E0E4000020062A02D089 +:104230000B2A14D10AE0E26892F84430172B0ED111 +:104240000023C2E91E3382F8480008E0E26892F8D1 +:104250004430112B03D182F8481082F86C00AA0771 +:1042600018D52269D278052A02D00B2A12D10AE089 +:10427000E16891F84420152A0CD10022E1E92022BE +:1042800001F8370C06E0E06890F84420102A01D1CC +:1042900080F84910280601D50820A07012E42DE905 +:1042A000F84F4FF00108414661F3070292468146FC +:1042B0000025FE4CA5806570A5702570E06080F833 +:1042C000B6800088F8F7F8FC070000D1FFDFE0684F +:1042D0000088FDF707F8E0680088FDF72CF8E06833 +:1042E000B0F8AA1071B190F8A310FF290FD190F87F +:1042F000461189B190F8462001231946383001F063 +:1043000048FB78B1E06890F8A300FF2804D0E0688B +:1043100090F8A300FFF7D7FBE06890F8B71089B1D9 +:10432000E58018E0E068A0F8605090F8471180F848 +:10433000A41000210220FFF7EBFAE06880F8B550E6 +:104340000220E7E790F86C1119B9018C828891423C +:1043500000D88188E180B0F8AE10491E8EB2B0F866 +:10436000B0103144A0F8B01090F8B41021B1A0F80A +:10437000B25080F8B45004E0B0F8B2103144A0F864 +:10438000B21030F85C1F31440180FFF71AFC20B1F5 +:10439000E06830F8541F31440180E068B0F8AA109A +:1043A000012902D8491CA0F8AA100EB180F8BC500F +:1043B00090F8B510A1B1B0F8B000E18888420FD2F2 +:1043C0003846F7F704FF58B1E06890F8401139B16A +:1043D000B0F8B210B0F84201814201D300F0B7FB4F +:1043E000E06880F8B55090F844100B2901D00C29F2 +:1043F00015D1028FB0F85C31D21A12B2002A0EDB4E +:10440000D0F85E11816090F862110173022101F011 +:10441000C4F9E06880F8445080F8768022E02129D1 +:104420000FD1018FB0F85C21891A09B2002908DB8D +:1044300090F86801FFF757FAE06800F8445FC57527 +:1044400010E090F8431021290CD1018FB0F85C01E5 +:10445000081A00B2002805DB0120FFF744FAE068E3 +:1044600080F84350E0680146B0F8AE20383001F0E3 +:104470000EFAE06890F8401109B1A0F8B2508C48EB +:1044800000908C4B8C4A4946504600F0D6FAE068C2 +:104490000123052190F84420383001F07AFA0028F1 +:1044A00003D0BDE8F84F00F05ABABDE8F88F00F02D +:1044B00019BB10B50446B0F862214388B0F8641106 +:1044C000B0F866019A4205D1A388994202D1E388E7 +:1044D00098420FD02388A4F87031A4F87221A4F870 +:1044E0007411A4F87601012084F86C016F48C0783B +:1044F000F4F7FAFA0121204601F04FF9002004F800 +:10450000440F0320E07010BD401A00B247F6FE7160 +:10451000884201DC002801DC012070470020704740 +:1045200010B5012808D0022808D0042808D008288F +:1045300006D0FFDF204610BD0124FBE70224F9E787 +:104540000324F7E72DE9F0478946044601F0EFFC24 +:104550008046204601F0EDFC544D0446E86890F892 +:10456000681121B190F86A7190F86B6101E0002741 +:104570003E46204601F09BFAA0B1EA6892F831105D +:1045800081420FD03C420AD0B9F1000F0AD1012874 +:1045900008D1022906D192F83000204202D1002031 +:1045A000BDE8F087404601F082FA50B1404601F084 +:1045B0007EFAE96891F83210884202D018EA0600C3 +:1045C000EED00120ECE739480021C06820F8681FD0 +:1045D0008178491C81707047344800B5C16811F872 +:1045E0006A0F401E40B20870002800DAFFDF00BDED +:1045F00010B52E4CE06890F85A11042916D190F8A5 +:10460000432001230021383001F0C3F900B9FFDF56 +:10461000E06890F86E10890703D4062180F84310F3 +:1046200004E0002180F8661080F85A11E06890F8E4 +:104630004500800707D5FFF7CFFFE06810F8451F5A +:1046400021F00201017010BD70B5184D2946E868CF +:10465000496990F8432009790E2A01D1122903D023 +:1046600000241D2A04D005E0BDE87040FEF724BEFA +:10467000162915D0172921D190F844101F291DD1D2 +:1046800080F84440FFF7A8FFE86880F85B4090F8A6 +:104690006801002812D00020BDE87040FEF7EBBD95 +:1046A00080F8434080F866401A20F5E7E4000020D7 +:1046B000993F0100D1410100FD410100EEE510B537 +:1046C0009E4CE06810F8741F41F0040101706069AD +:1046D00001F04DFC162806D1E06890F843001D2833 +:1046E00002D0222805D010BD606901F044FCFEF71D +:1046F000C2FDE168002081F8430081F8660010BD2A +:1047000010B58E4C01230021E06890F84420383029 +:1047100001F03FF930B1FFF756FFE168102081F852 +:10472000440010BDE0680123052190F84420383092 +:1047300001F02FF908B1082000E00120607010BDE1 +:1047400070B57E4C01230021E06890F84420383099 +:1047500001F01FF9012580B1606901F0B3FBE16848 +:10476000A1F85C01098FFFF7CFFE40B1E068282176 +:1047700080F8531080F8525090E565708EE5E1683E +:10478000606901F5AF7101F098FBE1680B2081F8D9 +:10479000440083E510B5FFF75CF8FEF77DFF674C3A +:1047A0002079400708D5607830B9E06890F8460075 +:1047B000072801D101202070FEF79DFC2079C0065A +:1047C00009D5607838B9E06890F844100B2902D117 +:1047D0000C2180F84410A07800070ED5E068012372 +:1047E000052190F84420383001F0D3F830B108208A +:1047F0006070E168002081F8780110BDBDE81040CC +:10480000002000F0CEBA10B528BB4C4CE16891F8FE +:104810004500C20702D00121092018E082070AD50D +:1048200001210C20FFF774F8E06810F86E1F41F0CA +:10483000010101700DE0420702D50121132006E0BD +:10484000000708D511F8A10FC87001210720FFF754 +:104850005FF8012010BD002010BD10B5374CE16895 +:1048600091F8442040B3102A06D0142A07D0152A04 +:1048700019D01B2A2BD119E001210B2018E0FBF7DE +:1048800063FA0C2816D3E0680821C830FBF760FAF9 +:1048900028B1E06804219C30FBF75AFA00B9FFDF29 +:1048A0000121042004E000F017F803E001210620B4 +:1048B000FFF72EF8012010BD1E2A08D191F85B00E9 +:1048C00038B991F8680110B191F8690108B1002078 +:1048D00010BD01211720EBE770B5184C0025E068EA +:1048E00090F8491101290AD0022925D190F86C10BD +:1048F000A9B1062180F8A4100121022017E090F848 +:104900007811002918D100F1880300F1C0010022BC +:1049100000F5A57000F0EAFF0121052007E090F8FE +:104920007400400701D5112000E00D200121FEF7A1 +:10493000EFFFE06880F84951B0E40000E400002097 +:10494000F6480078002800D00C20704710B50446C7 +:10495000FFF7F6FF00B1FFDFF048447210BDEF49EA +:1049600001200872704770B5EC4934314C6804F18D +:10497000380560B14FF4A4721B2114F8323F687CF3 +:1049800000F0A7FB2178BDE87040FBF732BF1F2085 +:1049900094F83110F7E72DE9F0410646DF48DF4D86 +:1049A00034304468DE48686204F138070120FFF7BC +:1049B000DAFF787C38B307F15001D94891E80E103E +:1049C00000F1480888E80E10396EC0F86110796E61 +:1049D000C0F865102230FCF79BF9D148012148301E +:1049E0000176D7E91212C0E90412A0F12602696A21 +:1049F000FBF701FE94F8320000F061FB0146012054 +:104A0000FBF707FE04E0686AFCF782F9FBF723FE78 +:104A10004EB9012294F8323096211046FCF7B2F8D4 +:104A20009620FCF78EF994F82C00012801D1FCF7B0 +:104A3000DCF902202870BDE8F0812DE9F047B74C81 +:104A40008046089F20781D461646894610B90EB14B +:104A500005B107B9FFDFE761C4E905650020C4E9D6 +:104A60000D892072E0712071E0706071AB4FA07110 +:104A7000A0703437A0817E68354636F8380BF8F7D9 +:104A80001BF9E0622888F8F705F92063FBF7CEFEF2 +:104A900005F11200FCF724F905F10E00FBF74AFFBF +:104AA0000120FCF732F9707EFBF74EFFFCF727F987 +:104AB0004FF4A4721B2115F8323F707C00F009FB03 +:104AC0002C782146FBF795FE224600210120FBF7BA +:104AD000E2FF7868D0F8B800FCF71EF9BDE8F047AF +:104AE000012058E78D4800B50078022800D0FFDF8C +:104AF00000BD8A4810B534304468FCF747F9FCF72C +:104B000038F9FCF7C4F8FCF7F1F8FBF7A4FD94F8CA +:104B10002C00012801D1FCF75EF9804CA08900F03F +:104B2000E7FAE269E179E07890470020207010BD53 +:104B30007A4810B50078022800D0FFDFBDE81040A9 +:104B4000D7E77648407970477448007970477349D1 +:104B50000120887170472DE9FC5F83466F481B2751 +:104B60003430A0F1140844686C4D264694F83D009A +:104B70004FF0000A4FF00109383458B3012862D0D1 +:104B8000022864D003286FD0FFDF296AA8460825D1 +:104B9000087820F008000870A37905EAC3031843D9 +:104BA00020F004000870E379042505EA8303184324 +:104BB00020F0100008706779D8F82C00F7F717FB81 +:104BC0000546FCF7DDFB022F55D0012F53D0032FF4 +:104BD00054D056E000F095FA01464FF4A47000F06E +:104BE00061FA1B2800D93846ADF804004046FCF7AE +:104BF000A5FB30B14FF48060296A00F07DFA0320F4 +:104C00001FE06A4601A9E86A00F04AFA286210B17A +:104C100094F8331029B14046FCF761FB84F8059005 +:104C2000B3E79DF8001031B9A0F800A080F802A009 +:104C3000012101F0DEF8BDF80410286A01F09DF9A9 +:104C400002206071A1E74046FCF749FB9DE7ADF803 +:104C500004706A4601A9E86A00F022FA2862002876 +:104C600093D1FFDF91E7FFE74046FCF767FB0028A1 +:104C70008BD1FFDF89E7A84301D002E00DB101210C +:104C800000E00021D8F820004546027842EA0111F0 +:104C90000170217C49B36179012926D004F15001CA +:104CA0001F488EC900F1480888E88E00216EC0F8C0 +:104CB0006110616EC0F865102230FCF729F81848C1 +:104CC000483080F818A0D4E91012C0E90412A0F10D +:104CD00026012A6AFBF78FFC96F8310000F0EFF905 +:104CE00001460020FBF795FC03E0FCF711F8FBF709 +:104CF000B2FCBBF1000F06D196F8313001229621AB +:104D00000020FBF73FFF85F80590296A0A88EA81B1 +:104D10008978297485F80090BDE8FC9FFC0000208C +:104D2000780A002070B5FF4C054639B9012D05D130 +:104D30002079401CC0B22071012820D8A1692846E2 +:104D40008847E0B1A179F84831B1012D04D141780B +:104D500011B90178C90612D5E17981B98DB9F14946 +:104D60000E310978CA0602D40078C00607D5A078AB +:104D700028B9A06A28B9608918B1C80601D40120F1 +:104D800070BD002070BD10B5E64CA06A00B9FFDF11 +:104D90006289D4E90910D21C02F0D4F9A06A6062D9 +:104DA00010BD2DE9F0470600DE48DE4D00F134006D +:104DB0004468686A04F13804477801D0012E03D1B1 +:104DC000296B01F0F9FE687068784FF000084FF029 +:104DD000010940B1012818D0022831D0032846D05B +:104DE000FFDFBDE8F087012E31D0FFF7CCFF394659 +:104DF0000122286BF7F76CFA27E000BF84F80780E0 +:104E000030E000BF84F807902CE0012E08D0FFF7B7 +:104E1000BAFF39460022286BF7F75AFA022EE0D083 +:104E2000D4E91201401C41F10001C4E91201E0790A +:104E3000012802D084F80790D3E784F80780D0E7F0 +:104E4000012E04D0286BF7F7C7FB022EC9D0D4E996 +:104E50001201401C41F10001C4E91201E07901286E +:104E6000D0D1CBE7687ABDE8F047F3F73DBE012E1D +:104E7000B7D0286BF7F7B0FBF4E72DE9F041014616 +:104E8000A848A84D343000274468686A01263834A1 +:104E9000027802F00302012A1AD0022A18D0032A4B +:104EA00003D0E87940F0040010E000F0BBFF18B335 +:104EB000A670A88940F40060A8810120696A00F00A +:104EC0001BF91DE0E771B6E5E671B4E5E871B2E5FE +:104ED0004078A8B1AA8942F40062AA81AA6A002A8D +:104EE000F1D01B2808D8287A20B1BDE8F0418020F5 +:104EF00000F0FEB80E709EE5E87940F01000E5E79E +:104F0000E0790128E0D1DDE770B58648854D343081 +:104F1000446828783834012800D0FFDFA0780126C3 +:104F200030B10020A0700146042000F0E5F82671A1 +:104F3000286A0078C043800706D1E07820B9E6707F +:104F40000220296A00F0D8F801210020FFF7EAFECC +:104F500010B1BDE87040CCE5BDE8704000201AE516 +:104F60002DE9F84F6F4F6F4C343700267D6882462D +:104F70008DF8006020783835022800D0FFDFA08946 +:104F800040F40070A0810020FFF7EDFC687CBAF1CE +:104F9000000F58D0FBF782FBFBF772FB4FF00109C3 +:104FA00068B9687C58B1606A417841B10078E979A4 +:104FB000C0F3C000884202D184F8039056E0606AD2 +:104FC0004178618121B1206BF7F73CF9A06200E0E4 +:104FD000A662A089B84640F02000A08126717868BA +:104FE00000F13807064690F82C00012813D1FBF792 +:104FF000F2FE3946304600F097FC60B1D8F8040064 +:105000003188A0F89411397A80F8961180F892913D +:10501000607AF3F769FD606AA9790078C0F38000CF +:10502000884205D000F0A1F8A08940F48070A081EA +:10503000606AE9790078C0F3C00088420AD1684606 +:10504000FFF71BFF06E008B1FBF755FBA08940F016 +:105050004000A08151460120FFF764FE00289DF822 +:10506000000007D010B10020FFF79BFEFFF741FDC5 +:10507000BDE8F88F10B10120FFF793FE0020FFF785 +:105080006AFD9DF800000028F2D00220FFF789FE9B +:10509000EEE7244A3432526892F83120FDF703BE1D +:1050A000F6F7E0BF022905D06FF00D0101EBD0004B +:1050B00080B270476FF00E0101EB9000F8E700B589 +:1050C000012802D0022802D0FFDF002000BD01200D +:1050D00000BD70B50C46054619461046FFF7E2FFC5 +:1050E000844200D22046002D01D0001D80B270BD48 +:1050F0000C4A0021526910470A4A012393705269F1 +:105100001047084810B53430446804F13800C17ABB +:10511000212910D0007B21280DD01C290ED01D295B +:105120000CD003E0FC000020780A00201F280FD0DC +:1051300094F8310010BD94F85E1106E01F2807D0E6 +:1051400094F86A0100F04FF8014694F8310008E045 +:1051500094F86A0114F8301F084000F044F8014642 +:105160006078BDE8104000F048B870B52E4844683B +:1051700094F83D003834002832D0022810D12A4D4E +:10518000343DE86AF6F79AFF00B9FFDFD4E9100171 +:10519000401C41F10001C4E91001687AF3F7A4FC56 +:1051A00000256571207920B1257100211020FFF7BD +:1051B000A3FFE07878B1E570FCF7CFF800B9FFDF26 +:1051C00000210820FFF798FFD4E91001401C41F1AD +:1051D0000001C4E91001A079012802D00120A071CA +:1051E00070BDA57170BDC10701D001207047800757 +:1051F00001D5022070470020704700B500290CD06F +:1052000008280BD0042809D0082907D0042905D084 +:10521000012806D0012904D0022000BDFFDF0820AC +:1052200000BD012000BD0000300100202DE9F0414B +:105230000F4606460024F64D0FE000BF05EBC40004 +:1052400090F84311B14206D10622394600F5A2700A +:1052500001F04CFF38B1641CE4B22878A042EDD8CC +:105260001020BDE8F0812046FBE770B50546E84810 +:105270000478621C027000EBC4060868C6F844019A +:105280008888A6F84801102C00D3FFDF86F8435128 +:10529000204670BD70B5054600F0F4F910281CD109 +:1052A000DB4C2078401EC0B22070A84215D004EB21 +:1052B000C00204EBC50102F58070D2F84321C1F8A9 +:1052C0004321D0F84700C1F84701207800F0DAF90F +:1052D000102802D0204480F8035170BD2DE9F0471A +:1052E000CB4C0646A719A078401EC5B2A57097F80A +:1052F0000381AE422AD004EB051A04EB06190AF129 +:10530000030109F10300102201F01CFF0AF18301DF +:1053100009F18300102201F015FF601905EB450229 +:1053200090F8031187F8031106EB460104EB4202E3 +:1053300004EB4101D2F80B31C1F80B31B2F80F2167 +:10534000A1F80F2190F83B0187F83B0104EBC8005E +:1053500090F84A01C00703D14046BDE8F04799E7FD +:10536000BDE8F08710B540F2C311A94801F069FF0C +:10537000FF220821A74801F05CFFA64800210A3857 +:1053800041704FF46171418010BD70B50D46064605 +:10539000FFF74CFF9E4C102807D004EBC00191F89A +:1053A0004A11C90701D0012070BD617808290ED2C9 +:1053B000102803D129463046FFF757FF617804EBE8 +:1053C000C000491C6170012180F84A11EBE7002000 +:1053D00070BD70B58E4D2878401E44B20BE000BF02 +:1053E00005EBC40090F84A01C00702D0E0B200F01B +:1053F0005AF9641E64B2002CF2DA70BD2DE9F04750 +:10540000984691460C460746FFF710FF05461028C0 +:1054100005D000F037F9102801D01220A0E77C4E0B +:10542000B07808281ED2102D04D121463846FFF747 +:105430001CFF0546B4781022601CB07006EB041700 +:10544000F81C494600F045FA07F183001022414656 +:1054500000F03FFA3019002180F8035180F83B1129 +:1054600008467DE707207BE7694810B58078401E35 +:1054700044B204E0E0B2FFF731FF641E64B2002CD6 +:10548000F8DA10BD63490A394870704761480A3834 +:105490004078704740B14AF2B811884204D85D495B +:1054A0000A394880012070470020704759480A385F +:1054B0004088704710B5FFF7B9FE102803D000F000 +:1054C000E1F8102800D1082010BD51498A788242A5 +:1054D00003D901EB001083307047002070474C491E +:1054E0008A78824203D901EB0010C01C704700206B +:1054F0007047474B10B59C7884420FD9184490F8F8 +:10550000030103EBC00090F843310B70D0F8441155 +:105510001160B0F848019080012010BD002010BD3E +:105520003B4A114491F803213A490A390A7002684A +:105530004A6080880881704710B5FBF720F818B1E1 +:10554000BDE81040FBF72BB8FF2010BD30498A782A +:10555000824209D9084490F8030101EBC00090F899 +:105560004A0100F001007047002070472DE9F04724 +:1055700000252F46264E2AE006EBC70404F5A2714B +:10558000884694F84301FFF795FF8146FFF7A7FF90 +:1055900094F84A11C90718D060B1B9F1080F05D2C3 +:1055A00006EB090191F83B11012903D0102100F00D +:1055B00081F950B11749284601F805906D1C94F8FF +:1055C00043214146EDB2FBF785F97F1CFFB23078ED +:1055D000B842D1D8C4E602460E4810B50A38407821 +:1055E00040B10B48817829B1C01CD21CFAF773FF77 +:1055F000012010BD002010BD054A01EB410102EB66 +:1056000041010268C1F80B218088A1F80F017047A1 +:10561000E80A00204201002001461022274800F03D +:1056200058B92648704726498A78824203D90844E7 +:1056300090F83B0108B100207047012070472DE928 +:10564000F0410E46074615460621304600F032F975 +:105650001B4C58B1002004E02118401C81F83B513C +:10566000C0B2A1788142F7D80120FAE53146384628 +:10567000FFF720FF082803D0204480F83B51F3E7D0 +:105680000020EEE50E4910B5034600208A7806E0BA +:105690000C1894F803419C4204D0401CC0B28242D2 +:1056A000F6D8102010BD06494A78521E4A7001EB08 +:1056B000C001002281F84A21ECE50000AB0C00207B +:1056C000E80A002000F00101400800F00102114446 +:1056D000400800F001021144400800F001021144AA +:1056E000400800F001021144400800F0010211449A +:1056F000400800F00102114401EB5000704710B562 +:1057000000248484048DDB004C43B3FBF2F394FB50 +:10571000F2F45B1C04859BB203FB02F4C384B4F572 +:10572000C84F01DD5B1EC3844FF4FA43B3FBF2F3B1 +:105730005B1C8385038C02EBC3035B1EB3FBF2F39C +:10574000C383838B4B43B3FBF2F1818310BD70B5F0 +:105750000546087B0E4600F01F0008730020E87520 +:1057600004463019007AFFF7ADFF2919641C8874CC +:10577000E97DE4B20844E875052CF2D3C0B22528CF +:1057800000D9FFDF70BD00238383028401EBC202D6 +:10579000521EB2FBF1F1C183704770B5002504467B +:1057A00000F13806032909D0F1B3012964D0022998 +:1057B0004BD101463046BDE87040C8E77021304605 +:1057C00001F061FDB571F571F5723573B573F5735F +:1057D000757135767576012086F83C00412186F892 +:1057E0003D10FF2186F86B1084F82C50258484F836 +:1057F000310084F8320060734FF448606080A4F890 +:10580000A850A4F8AA50A4F8AC50A4F8AE50A4F83C +:10581000B050A4F8B25084F8B55084F8B750A4F84A +:10582000BE5084F8BC5000E010E0A4F8D050A4F8BA +:10583000D25084F8685184F8695184F8405184F852 +:10584000465184F8495184F85A5170BDA4F8BE50AD +:1058500084F8B6506188FE480A460844B0FBF1F06F +:10586000A4F856004BF68030A4F85800E388304680 +:10587000FFF745FF21469DE7A4F8BE504188B4F8E4 +:105880006631B4F862213046BDE8704037E7C37D29 +:105890000BB1252B01D9122070472AB14B7B2BB1BC +:1058A000012B05D01F2070470020704700F0A9B9D8 +:1058B00000F04FB910B500231A4603E0845C23437F +:1058C000521CD2B28A42F9D30BB1002010BD012084 +:1058D00010BD30B5134606E0CC18D51A14F8014CAB +:1058E0005B1E4455DBB2002BF6D130BD70B50E46C1 +:1058F0008CB0144601461D4610226846FFF7E9FFAA +:105900001022314604A8FFF7E4FF684600F0FCFBD4 +:1059100008A94FF0100228461CB1FFF7DAFF0CB0BF +:1059200070BD01F00FFCFAE738B505460C46684635 +:10593000FBF766FA00281ED09DF90000207294F94A +:1059400009100022411A00D5494295F82D308B42AA +:1059500010DCFF2B0ED0A17A491CC9B2A17295F8B8 +:105960002E30994202D8617A7F2903D160720020DB +:10597000A0720122104638BD0C2806D00B2804D096 +:105980000D2802D01C38062801D8012070470020BD +:10599000704710B5A2F10F030C292ED2DFE801F0F9 +:1059A00006080D1215181C2D242B2D273AB324E0C0 +:1059B000072A24D0082A22D01FE00C2A1FD00B2A45 +:1059C0001DD01AE00D2A1AD017E00C2B17D914E0BD +:1059D000103A0B2A13D910E0032B10D990F8340099 +:1059E00058B11B2A0BD908E0062A08D005E01C3A5A +:1059F000062A04D901E00E2A01D0002010BD0120A2 +:105A000010BD2DE9F0410C46054640F2337786681B +:105A100006E000BFF9F73CF93946F8F742FEA86006 +:105A20002846F9F702FB0028F4D094B13046A96863 +:105A3000F9F73CFE00280CDD2044401EB0FBF4F7D3 +:105A400007FB04F13046F8F72CFEA8603846BDE8A5 +:105A5000F0810020FBE770B5044690420AD2101B8B +:105A6000642800D2642025188D4204D8F9F751FE2D +:105A700008B1284670BD204670BD2DE9F0410E46A4 +:105A80001B27384691F8311000F05AF84FF4A474EF +:105A9000A04200D920460546384696F8321000F05C +:105AA0004FF8A04200D9204628449830CFE7C107DC +:105AB00001D001207047810701D5022070474007BF +:105AC00001D508207047002070472DE9F0410546B8 +:105AD000164688460124084600F029FA0746404643 +:105AE00000F027FA0346FFF7E2FF02463846FFF7C9 +:105AF000DEFF52EA000100D10024990700D1002204 +:105B0000B90700D1002095F83110914200D1002250 +:105B1000327095F83210814200D1002070706AB95D +:105B200060B9404600F007FA298F401A00B247F6E4 +:105B3000FE71884201DC002800DC0024204686E754 +:105B4000022903D0C000703080B2704780003C3022 +:105B5000FAE7F0B50C7C8B7BCD7B5C404B7C0288FC +:105B60006B4044EA0323C67D5A400024D5B2120A92 +:105B700095FAA5F592FAA2F22D0E120E45EA02222E +:105B800002EB0212641C1A44E4B292B2032CEDD36D +:105B90005A402523B2FBF3F403FB142301EBD30596 +:105BA00003762F7A03F00704012505FA04F427424F +:105BB00001D043761BE05643320C521CD2B2002374 +:105BC000C418A47C944214D30024CE1896F808601C +:105BD00005FA04F73E4201D0521ED2B222B1641C33 +:105BE000E4B2082CF4D306E004EBC30141760020B4 +:105BF000F0BD121BD2B25B1CDBB2052BE0D31F2021 +:105C0000F0BDF0B5037E0C7E012504FB0232252396 +:105C1000B2FBF3F403FB142201EBD204027602F090 +:105C20000703247A05FA03F31C4201D0427620E0F0 +:105C3000C37DB2FBF3F403FB1422521CD2B2002347 +:105C4000C418A47C944216D30024CE18367A01E0FE +:105C5000FFDB050005FA04F73E4201D0521ED2B226 +:105C600022B1641CE4B2082CF1D306E004EBC301BA +:105C700041760020F0BD121BD2B25B1CDBB2052BBB +:105C8000DED31F20F0BD0000282101F0DABA30B5C4 +:105C90000546007801F00F0220F00F001043287035 +:105CA00007290BD2DFE801F004060406040804000B +:105CB000062405E00C2403E0222401E00024FFDF99 +:105CC000687820F03F002043687030BD007800F015 +:105CD0000F0070470A6840F8032F89888180704759 +:105CE0000A6840F8092F898881807047027840232C +:105CF00022F0400203EA81110A43027070470278E1 +:105D000022F0800242EAC1120270704770B5154657 +:105D10000E4604461F2A00D9FFDF2A46314604F109 +:105D2000090001F00FFA6078AD1D20F03F0005F08A +:105D30003F010843607070BD70B515460E460446BD +:105D40001F2A00D9FFDF2A46314604F1090001F07D +:105D5000F9F96078AD1D20F03F0005F03F010843E0 +:105D6000607070BD30B5017801F00F01032922D0B9 +:105D7000052925D14578B0F81910B0F81B40B0F8C6 +:105D80001730827D05F03F05222D19D1062917D342 +:105D90004FF44865A94213D8B4F5FA7F10D27AB10E +:105DA000082A0DD88A420BD28B4209D8B0F81D00C0 +:105DB000A84207D904E0407800F03F000C2801D049 +:105DC000002030BD012030BD00B5027801F0030392 +:105DD00022F003021A43027000224270012904D00B +:105DE000022902D0032901D0FFDF00BD012141704B +:105DF00000BD00B5027801F0030322F003021A434C +:105E0000027000224270012904D0022902D0032925 +:105E100001D0FFDF00BD0121417000BD007800F01E +:105E200003007047417889B1C0780E2805D00F284B +:105E300003D0102801D0192802D31B2904D905E06A +:105E4000524A105C884201D10120704700207047FF +:105E500030B50546C170192902D24C48445C01E0B6 +:105E60000024FFDF6C7030BDB0F807007047B0F859 +:105E700009007047B0F80B00704770B5B0F8072004 +:105E8000B0F80940B0F805300179951F40F67A4620 +:105E9000B54210D8B4F5FA7F0DD261B108290AD8FD +:105EA000914208D2934206D8B0F80B00B0F5486F83 +:105EB00001D8012070BD002070BD42680A60007AE0 +:105EC00008717047B0F80900704700797047426860 +:105ED0000A6080684860704780890880704750F881 +:105EE0000E2F0A60406848607047D0F816000860BE +:105EF00070470A6842604968816070470968C160FC +:105F000070470079704742680A608068486070474F +:105F10000A6842604968816070470179490704D086 +:105F20004079400701D00120704700207047007978 +:105F3000704740797047C08870470CB514A2D2E909 +:105F40000012CDE900120179407901F0070269469B +:105F50001DF80220012A04D800F00700085C01287F +:105F600001D900200CBD01200CBD017170470079E2 +:105F70007047417170474079704730B50C4605460F +:105F80001B2900D9FFDF6C7030BD00009477010041 +:105F9000000101020102020370B50C46A0F12001CC +:105FA0002A2901D301200CE03E280CD020CC084E39 +:105FB00094E80E0006EB8000241F50F8806C284601 +:105FC000B047206070BD2046EBF7EEF8F9E700001F +:105FD000B077010010B5524800F05CFA00B1FFDF65 +:105FE0004F48401C00F056FA002800D0FFDF10BDDB +:105FF0002DE9F14F4B4ED6F800B00127484800F08C +:1060000051FADFF81C8128B95FF0000708F10100A0 +:1060100000F05EFA444C00254FF003090120606057 +:10602000C4F80051C4F80451009931602060DFF8D1 +:10603000FCA018E0DAF80000C00614D50E2000F02D +:1060400064F8EFF3108010F0010072B600D0012068 +:10605000C4F80493D4F8001119B9D4F8041101B9A3 +:1060600020BF00B962B6D4F8000118B9D4F8040111 +:106070000028DFD0D4F804010028CFD137B1C6F80A +:1060800000B008F1010000F00DFA11E008F1010084 +:1060900000F008FA0028B9D1C4F80893C4F80451F4 +:1060A000C4F800510E2000F030F81D4800F010FA3E +:1060B0000020BDE8F88F2DE9F0438DB00D4606466F +:1060C00000240DF110090DF1200817E004EB44073E +:1060D000102255F82710684601F034F805EB8707C1 +:1060E00010224846796801F02DF86846FFF780FFD6 +:1060F00010224146B86801F025F8641CB442E5DB83 +:106100000DB00020BDE8F08372E700F01F0201210E +:1061100091404009800000F1E020C0F880127047F3 +:106120004A01002004E5004000E0004010ED00E0DE +:10613000CD4900200870704770B5CC4D01232B600D +:10614000CB4B1C68002CFCD0002407E00E680660D6 +:106150001E68002EFCD0001D091D641C9442F5D35E +:106160000020286018680028FCD070BD70B5BE4EB5 +:106170000446C04D3078022800D0FFDFAC4200D387 +:10618000FFDF7169BC48012903D847F230529442BD +:1061900001DD03224271491C7161291BC160B649AE +:1061A0007078F8F7BDFF002800D1FFDF70BD70B533 +:1061B000AD4C0D466178884200D0FFDFAD4E082D12 +:1061C0004BD2DFE805F04A041E2D4A4A4A382078AF +:1061D000022800D0FFDF03202070A078012801D022 +:1061E00020B108E0A06800F01FFD04E004F1080001 +:1061F00007C8FFF7A1FF05202070BDE87040F8F741 +:1062000053BCF8F745FD01466068F9F74FFAB04214 +:1062100002D2616902290BD30320F9F7FAFC12E0DC +:10622000F8F736FD01466068F9F740FAB042F3D25C +:10623000BDE870409AE7207802280AD0052806D0E9 +:10624000FFDF04202070BDE8704000F002B902209A +:1062500000E00320F9F7DDFCF3E7FFDF70BD70B568 +:106260000546F8F715FD804C60602078012800D0C5 +:10627000FFDF8149012008700020087104208D6033 +:1062800048717C48C860022020706078F8F748FFA9 +:10629000002800D1FFDF70BD10B5734C207808B125 +:1062A000112010BD7548F8F77AFC6070202804D0E2 +:1062B000012020700020606110BD032010BD020B82 +:1062C0000121B0F5003F02D291406D4806E0B0F5E3 +:1062D000802F08D2203A6A489140001D006808408B +:1062E00000D001207047002070472DE9F04114468E +:1062F00000EB84070E4605463F1F00F0A8FC4FF058 +:1063000080510A69504306EB8402121FB24201D247 +:10631000012200E000221CB10969B4EB910F02D9FF +:106320000920BDE8F08157498D4216D3AF4214D3FE +:10633000854205D2874203D245EA0600800701D094 +:106340001020EEE78E4208D33AB92846FFF7B7FF90 +:1063500018B93846FFF7B3FF08B10F20E1E74A4804 +:106360004A490068884205D0224631462846FFF750 +:10637000E3FE10E0FFF790FF0028D2D13A48002159 +:106380008560C0E9036481704FF4A97104FB01F0DA +:106390001830FFF764FF0020C3E770B54FF0805559 +:1063A000044628693749B1FBF0F084420AD300F073 +:1063B0004EFCA04201D8102070BD28696043FFF751 +:1063C0007EFF08B10F2070BD2F4830490068884219 +:1063D00004D02869604300F027FC0CE0FFF75CFF65 +:1063E0000028F0D129692048614381600121817032 +:1063F0002748FFF734FF002070BD2249090BB1EB9D +:10640000401F07D9404201EB4011202903D34FF030 +:10641000FF307047002101208840401E704770B552 +:1064200005460C4652EA030001D0062070BD00204C +:10643000FFF7E3FF284204D10120FFF7DEFF2042EF +:1064400001D00F2070BD21462846BDE8704000F005 +:1064500041BE10B5044C6078F8F7FBFB00B9FFDFD4 +:106460000020207010BD00004C01002004E5014018 +:1064700000E40140105C0C00BC0C0020AF61010086 +:106480000006004000800100A4000020BEBAFECA41 +:106490007C5E010000210170084670470146002023 +:1064A00008707047EFF3108101F0010172B60278B5 +:1064B000012A01D0012200E000220123037001B96A +:1064C00062B60AB1002070474FF400507047E9E708 +:1064D000EFF3108111F0010F72B64FF0000202705D +:1064E00000D162B600207047F2E700004C4909680D +:1064F0000160002070474A49086000207047012170 +:106500008A0720B1012804D042F204007047916745 +:1065100000E0D1670020704742490120086042F244 +:106520000600704708B504233E4A1907103230B1FF +:10653000C1F80433106840F0010010600BE01068EF +:1065400020F001001060C1F808330020C1F80801F4 +:10655000354800680090002008BD011F0B2909D8AC +:10656000304910310A6822F01E0242EA40000860F9 +:106570000020704742F205007047000100F18040A2 +:10658000C0F8041900207047000100F18040C0F8F5 +:10659000081900207047000100F18040D0F8000980 +:1065A000086000207047012801D9072070471F4A62 +:1065B00052F8200002680A43026000207047012858 +:1065C00001D907207047194A52F8200002688A430F +:1065D000026000207047012801D907207047134A44 +:1065E00052F820000068086000207047020010493F +:1065F0004FF0000003D0012A01D0072070470A6045 +:1066000070474FF080410020C1F808014FF0E020B2 +:10661000802180F800140121C0F8001170470000AB +:1066200000040040000500400801004058780100C7 +:10663000780500406249634B0A6863499A420968D9 +:1066400001D1C1F310010160002070475C495D4B2E +:106650000A685D49091D9A4201D1C0F31000086023 +:10666000002070475649574B0A68574908319A42EB +:1066700001D1C0F3100008600020704730B5504BC6 +:10668000504D1C6842F20803AC4202D0142802D2DA +:1066900003E0112801D3184630BDC3004B4818440D +:1066A000C0F81015C0F81425002030BD4449454BF2 +:1066B0000A6842F209019A4202D0062802D203E097 +:1066C000042801D308467047404A012142F830109F +:1066D000002070473A493B4B0A6842F209019A424E +:1066E00002D0062802D203E0042801D308467047EE +:1066F000364A012102EBC00041600020704770B5AE +:106700002F4A304E314C156842F2090304EB8002E7 +:10671000B54204D0062804D2C2F8001807E00428C5 +:1067200001D3184670BDC1F31000C2F80008002064 +:1067300070BD70B5224A234E244C156842F20903FD +:1067400004EB8002B54204D0062804D2D2F8000837 +:1067500007E0042801D3184670BDD2F80008C0F342 +:1067600010000860002070BD174910B508311848A6 +:1067700008601120154A002102EBC003C3F8101570 +:10678000C3F81415401C1428F6D3002006E0042892 +:1067900004D302EB8003C3F8001807E002EB800388 +:1067A000D3F80048C4F31004C3F80048401C06287E +:1067B000EDD310BD04490648083108607047000059 +:1067C000A4000020BEBAFECA00F5014000F001405E +:1067D0000000FEFF774B1B6803B19847BFF34F8F54 +:1067E00075480168754A01F4E06111430160BFF327 +:1067F0004F8FFEE710B5EFF3108010F0010F72B667 +:1068000001D0012400E0002400F0CAF850B1EAF7FA +:1068100067FDF8F70AF8F9F79FF9ECF7E2FB68492A +:106820000020086004B962B6002010BD70B50C46A7 +:106830000646EFF3108010F0010F72B601D001256B +:1068400000E0002500F0ACF818B105B962B60820E8 +:1068500070BDEAF7BFFCEAF747FD02460020430996 +:106860009B0003F1E02300F01F01D3F80031CB407F +:10687000D9071BD0202803D222FA00F1C90722D160 +:1068800041B2002906DA01F00F0101F1E02191F88F +:10689000141D03E001F1E02191F8001449090829D1 +:1068A00011D281B101290ED004290CD0401C6428DA +:1068B000D5D3ECF795FB4249424808602046F9F7EA +:1068C0008BFD60B904E005B962B641F2010070BD0C +:1068D000384804602EB13046F9F7CBFD18B11024CA +:1068E00029E0394E16E03078022802D94FF480545E +:1068F00021E007240028707801D0E0B908E0D0B189 +:10690000202818D8B078212815D8012813D001E004 +:10691000B07880B92D49802081F8140DEAF7E4FCA5 +:106920003146F9F7FFF8F7F73FFF00F0C3F93046BB +:10693000EAF7A8FC044605B962B61CB1FFF75AFF96 +:10694000204670BD002070BD10B5044600F028F848 +:1069500000B101202070002010BD1D4908600020FA +:10696000704710B50C46102808D011280BD01228FB +:106970000CD013280ED00120086010BDD4E900010E +:10698000FFF754FF0AE0FFF735FF07E02068FFF745 +:10699000DBFF03E00E49206808600020206010BD86 +:1069A000074808490068884201D10120704700204B +:1069B00070470000640100200CED00E00400FA05BF +:1069C000A4000020BEBAFECA607801000BE000E01F +:1069D0000400002000B5744910F1080F19D00CDC38 +:1069E00010F1280F1DD010F1140F18D010F1100F56 +:1069F00013D010F10C0F08D10DE010F1040F06D0E8 +:106A000080B103280ED004280CD0FFDF00BDFC208D +:106A100008E0F82006E0F42004E0F02002E0EC209A +:106A200000E0D820086000BD5F4900B5091D0128BD +:106A300003D0022803D0FFDF00BD032000E00420C4 +:106A4000086000BD584800B5001D016801F00F0145 +:106A5000032905D0006800F00F00042802D0FFDFF2 +:106A6000012000BD022000BD504930B1012803D1F2 +:106A7000086840F00100086070470868FBE72DE9EE +:106A8000F04105461F464FF4C8604FF47A7601295D +:106A900012D0022A17D046490C181846FAF7A6FB5E +:106AA00004443846FAF7BCFB204400F27120B0FBE6 +:106AB000F6F0281ABDE8F081022A00D1304649F6E6 +:106AC00008514418E9E73B493046E5E770B51546FB +:106AD0000646012914D0022B15D0354CFA34104645 +:106AE000FAF791FB4FF47A71012D0FD04A10A21AD8 +:106AF000104400F28920B0FBF1F0301A801E70BD06 +:106B000049F6CA64EBE72B4C643CE7E70A46EEE73C +:106B10002DE9F041054614464FF4C8604FF47A76EB +:106B2000012911D0022B16D021490F181046FAF76F +:106B30006AFB012C12D04FF4FA71791A08446438B8 +:106B4000B0FBF6F0281AB5E7022B00D1304649F623 +:106B500008514718EAE717493046E6E73146ECE7BF +:106B60002DE9F04105460C4616461046FAF73EFB65 +:106B700005EB4501C1EBC51100EBC1004FF47A757F +:106B8000012C0FD0691047182046FAF73CFB381A41 +:106B900000F60F60B0FBF5F43046FAF71DFB204419 +:106BA000401D87E72946EEE70C15004050160040CF +:106BB000A2240200683602002DE9FE430C468046FE +:106BC000FFF72CF9074698F80160204601A96A46AC +:106BD000F5F709FD05000DD0012F02D00320BDE817 +:106BE000FE83204602AA0199F5F71FFC0298B0F82F +:106BF00003000AE0022F14D1042E12D3B8F80300C8 +:106C0000BDF80020011D914204D8001D80B2A919D1 +:106C1000814202D14FF00000E1E702D24FF00100C3 +:106C2000DDE74FF00200DAE70B4A022111600B4961 +:106C30000B68002BFCD0084B1B1D1860086800284F +:106C4000FCD00020106008680028FCD070474FF08E +:106C5000805040697047000004E5014000E40140B5 +:106C600002000B464FF00000014620D0012A04D05C +:106C7000022A04D0032A0DD103E0012002E0022001 +:106C800015E00320072B05D2DFE803F00406080A0D +:106C90000C0E100007207047012108E0022106E0D9 +:106CA000032104E0042102E0052100E00621F7F7BA +:106CB00092BF0000F64805218170002101704170EB +:106CC0007047F4490A78012A05D0CA681044C860A0 +:106CD0004038F8F7B8BC8A6810448860F8E70028A4 +:106CE00019D00378EC49ED4A13B1012B0ED011E015 +:106CF0000379012B00D06BB943790BB1012B09D17A +:106D00008368643B8B4205D2C0680EE00379012B97 +:106D100002D00BB10020704743790BB1012BF9D1A0 +:106D2000C368643B8B42F5D280689042F2D8012060 +:106D30007047D84910B501220A700279A2B1002229 +:106D40000A71427992B104224A718268D04C52325F +:106D50008A60C0681434C8606060F7F799FFCC4956 +:106D600020600220887010BD0322E9E70322EBE7D0 +:106D700070B5044609B1012000E00320C54D002193 +:106D80002970217901B100202871607968B104204F +:106D9000BF4E6871A168F068F7F783FCA860E068EF +:106DA0005230E8600320B07070BD0320F0E72DE999 +:106DB000F04105460226F8F772FB006800B1FFDFDC +:106DC000B34C01273DB12878B0B1012805D0022885 +:106DD00010D0032813D027710CE06868C82807D3A7 +:106DE000F8F797FC20B16868FFF76BFF012603E016 +:106DF000002601E000F056F93046BDE8F081207829 +:106E00000028F7D16868FFF76AFF0028E3D06868B8 +:106E1000017879B1A078042800D0FFDF01216868EB +:106E2000FFF7A6FF9B49E078F8F77AF90028E1D14F +:106E3000FFDFDFE7FFF77DFF6770DBE72DE9F04756 +:106E4000934C8846E178884200D0FFDFDFF840921B +:106E5000002501278F4E09F11409B8F1080F75D2EA +:106E6000DFE808F0040C28527A808D95A07803287A +:106E700002D0022800D0FFDFBDE8F087A078032809 +:106E800002D0022800D0FFDF0420A07025712078F6 +:106E9000002878D1FFF715FF3078012806D0B068B8 +:106EA000E06000F01EF92061002060E0E078F8F773 +:106EB00034F8F5E7A078032802D0022800D0FFDFDD +:106EC000207800286DD1A078032816D0F7F7E0FECF +:106ED00001464F46D9F80000F8F7E8FB00280EDB22 +:106EE000796881420BDB081AF0606A49E078F8F7AC +:106EF00017F90028C0D1FFDFBEE7042028E00420F6 +:106F0000F8F787FEA570B7E7A078032802D002281B +:106F100000D0FFDF207888BBA078032817D0F7F7D0 +:106F2000B7FE01464F46D9F80000F8F7BFFB00282E +:106F3000E5DB79688142E2DB081AF0605549E078C8 +:106F4000F8F7EEF8002897D1FFDF95E740E005203D +:106F5000F8F75FFEA7708FE7A078042800D0FFDF66 +:106F6000022004E0A078042800D0FFDF0120A168FF +:106F70008847FFF71CFF054630E004E011E0A078E9 +:106F8000042800D0FFDFBDE8F04700F08BB8A07800 +:106F9000042804D0617809B1022800D0FFDF2078EE +:106FA00018B1BDE8F04700F086B8207920B106207E +:106FB000F8F72FFE2571CDE7607838B13549E078D4 +:106FC000F8F7AEF800B9FFDF657055E70720BFE7B7 +:106FD000FFDF51E73DB1012D03D0FFDF022DF9D1D5 +:106FE0004AE70420C3E70320C1E770B5050005D0D8 +:106FF000274CA078052803D0112070BD102070BD4B +:107000002748F7F7CCFDE070202803D00020A560CA +:10701000A07070BD032070BD1D4810B5017809B186 +:10702000112010BD8178052906D0012906D029B18B +:1070300001210170002010BD0F2010BD00F03BF8B1 +:10704000F8E770B5124C0546A07808B1012809D1BF +:1070500055B12846FFF743FE40B1287840B1A078EB +:10706000012809D00F2070BD102070BD072070BD11 +:107070002846FFF75EFE03E000212846FFF778FE72 +:107080000449E078F8F74CF800B9FFDF002070BD44 +:1070900068010020CC0C00203D860100FF1FA107E5 +:1070A0003D6E01000A4810B5006900F019F8BDE80E +:1070B0001040F7F7F9BC064810B5C078F7F7C9FDDE +:1070C00000B9FFDF0820F8F7A4FDBDE81040F1E5A6 +:1070D00068010020044A1060101D01600020704704 +:1070E00070470020704700000006004040EA01039E +:1070F00010B59B070FD1042A0DD310C808C9121F61 +:107100009C42F8D020BA19BA884201D9012010BD9A +:107110004FF0FF3010BD1AB1D30703D0521C07E067 +:10712000002010BD10F8013B11F8014B1B1B07D1CB +:1071300010F8013B11F8014B1B1B01D1921EF1D13C +:10714000184610BD032A40F2308010F0030C00F006 +:10715000158011F8013BBCF1020F624498BF11F891 +:1071600001CB00F8013B38BF11F8013BA2F104024A +:1071700098BF00F801CB38BF00F8013B11F00303C2 +:1071800000F02580083AC0F0088051F8043B083A26 +:1071900051F804CBA0E80810F5E7121D5CBF51F8C8 +:1071A000043B40F8043BAFF30080D20724BF11F842 +:1071B000013B11F801CB48BF11F8012B24BF00F8A7 +:1071C000013B00F801CB48BF00F8012B704710B518 +:1071D000203AC0F00B80B1E81850203AA0E81850CF +:1071E000B1E81850A0E81850BFF4F5AF5FEA027C90 +:1071F00024BFB1E81850A0E8185044BF18C918C0FF +:10720000BDE810405FEA827C24BF51F8043B40F89F +:10721000043B08BF7047D20728BF31F8023B48BF84 +:1072200011F8012B28BF20F8023B48BF00F8012BC2 +:10723000704702F0FF0343EA032242EA024200F0F1 +:1072400002B84FF000020429C0F0128010F0030CC5 +:1072500000F01B80CCF1040CBCF1020F18BF00F849 +:10726000012BA8BF20F8022BA1EB0C0100F00DB8F8 +:107270005FEAC17C24BF00F8012B00F8012B48BF56 +:1072800000F8012B70474FF0000200B513469446FA +:107290009646203922BFA0E80C50A0E80C50B1F16E +:1072A0002001BFF4F7AF090728BFA0E80C5048BF82 +:1072B0000CC05DF804EB890028BF40F8042B08BF20 +:1072C000704748BF20F8022B11F0804F18BF00F81C +:1072D000012B7047FEDF04207146084219D1069940 +:1072E000124A914215DC069902394878DF2810D1FC +:1072F0000878FE2807D0FF280BD14FF001004FF08F +:1073000000020B4B184741F201000099019A084B0B +:107310001847084B002B02D01B68DB6818474FF05A +:10732000FF3071464FF00002014B1847008001000A +:10733000D567010004000020184819497047FFF77D +:10734000FBFFE9F72BFF00BD4FF48050154909689A +:10735000884203D1144A13605B68184700BD0000DF +:1073600020BFFDE74FF480500E490968884210D1D4 +:107370000E4B18684FF0FF318842F1D080F3088837 +:107380004FF02021884204DD0948026803210A43A6 +:1073900002600848804708488047FFDFE00C002073 +:1073A000E00C00200000002004000020008001000C +:1073B00014090040B1040100497301000420714622 +:1073C000084202D0EFF3098101E0EFF308818869F8 +:1073D00002380078102813DB20280FDB2B280BDB6A +:1073E0000A4A12680A4B9A4203D1602804DB094A10 +:1073F0001047022008607047074A1047074A1047A5 +:10740000074A12682C32126810470000A4000020BE +:10741000BEBAFECAED120000995F01006369010067 +:10742000040000200D4B0E4908470E4B0C4908473D +:107430000D4B0B4908470D4B094908470C4B0849B0 +:1074400008470C4B064908470B4B054908470B4BAF +:10745000034908470A4B024908470000FD8800001D +:10746000798B0000C92E0000832D0000172D00002D +:107470004F2F0000F3120000D52A00001D8B0000E2 +:10748000A9110000797F000081810000E1820000E5 +:10749000058300003F8300007D830000AF83000070 +:1074A000DF83000031840000A78000006F1200001D +:1074B0006F120000BF1D0000FD1D00001D1E00001A +:1074C000A91E0000C51F000083200000B32000009B +:1074D000552100003F1B0000EB2300006F2400003B +:1074E0008F2400006B2800008F280000BF270000B9 +:1074F00013280000C128000055290000273D000086 +:10750000013E00003541000033420000A942000066 +:107510001343000077430000731200006B44000027 +:10752000D54400009D240000A32400007312000035 +:10753000731200007312000073120000AD240000EB +:10754000ED240000731200006F1200006F120000A3 +:107550006F120000E15200006753000083530000E7 +:107560009F5300002D550000C9530000D353000065 +:107570001554000037540000135500005555000005 +:107580006F120000C76D0000E76D0000E96D00009C +:107590002D6E00005B6E0000496F0000D76F000089 +:1075A000EB6F00003970000029710000CF720000FD +:1075B000F9730000D55D0000117400006F12000027 +:1075C0006F120000731200007312000073120000AB +:1075D0007312000073120000100110013A02000043 +:1075E0001A02000405060000BD7A0000AB7A000014 +:1075F000FFFFFFFF0000FFFFEDB000002F190000AC +:10760000814E00001F5E0000937800000000000023 +:10761000736B0000536B0000C16B000063520000ED +:107620002552000045520000A3AF000031B0000019 +:1076300039370000E16B000000000000116C000011 +:10764000B152000000000000000000000000000037 +:1076500000000000B93700004D3500004D35000036 +:107660009B1D000051B00000A3600000934D00007E +:10767000953C01007B3500007B350000BD1D0000FE +:107680007DB0000027610000054E0000A93C01000C +:1076900070017001400034005C002400A80100006B +:1076A0000300656C74620000000000000000000030 +:1076B0000000000000008700000000000000000043 +:1076C000000000000000BE83605ADB0B376038A565 +:1076D000F5AA9183886C000001000000F9D1000038 +:1076E000C1E00000000000010206030405000000E4 +:1076F0000700000000000000060000000A00000073 +:107700003200000073000000B4000000752C01007E +:1077100000000000631C0100314B0100000000006C +:1077200000000000E51C0100614F010000000000A6 +:1077300000000000D91B0100094F010000000000FB +:107740000000000023200100935001000000000011 +:1077500000000000555555D6BE898E000000A606D3 +:10776000340DC21300004A03EE059208000096048F +:107770001409920DF401FA00960064004B003200E7 +:107780001E0014000A000500020001000041000074 +:10779000000000000C0802170D0101020909010197 +:1077A0000602091818030101090903030500000076 +:1077B000356601004D660100656601007D660100C9 +:1077C000AD660100D5660100FF6601003367010068 +:1077D0009B630100EB6201001F64010095640100DE +:1077E000A5640100D16401005BFD000063FD0000A1 +:1077F00075FD0000FF64010019650100ED640100E2 +:10780000F7640100256501005B6501007B650100EF +:107810008965010097650100A7650100BF6501004A +:10782000D7650100ED65010000000000FB86000047 +:107830005187000067870000616C0100F15F010063 +:10784000B7600100EB6F0100197001004370010087 +:10785000B5FB000085FF00001C050040200500402E +:107860000010020084780100080000207C01000064 +:1078700044110000B0780100840100205C0B00007E +:107880008011000001190545600D0020360100013E +:1078900000703720FB349B5F80041B8000100D9923 +:1078A000E3070020A007002026080020024C10005B +:00000001FF diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf51822_5.0.0_release-notes.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf51822_5.0.0_release-notes.pdf new file mode 100644 index 0000000000..0cff6f8c31 Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf51822_5.0.0_release-notes.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_licence-agreement.txt new file mode 100644 index 0000000000..00c2e54c47 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 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 form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_migration-document.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_migration-document.pdf new file mode 100644 index 0000000000..afd9ec7f41 Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/doc/s132_nrf52_5.0.0_migration-document.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_err.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_err.h new file mode 100644 index 0000000000..1b0b9d4435 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_err.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x004) /**< Invalid role. */ +/** @} */ + + +/** @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_.h or ble_error_.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 + + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gap.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gap.h new file mode 100644 index 0000000000..13f7721c58 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gap.h @@ -0,0 +1,2170 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_GAP Generic Access Profile (GAP) + @{ + @brief Definitions and prototypes for the GAP interface. + */ + +#ifndef BLE_GAP_H__ +#define BLE_GAP_H__ + + +#include "ble_types.h" +#include "ble_ranges.h" +#include "nrf_svc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup BLE_GAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GAP API SVC numbers. + */ +enum BLE_GAP_SVCS +{ + SD_BLE_GAP_ADDR_SET = BLE_GAP_SVC_BASE, /**< Set own Bluetooth Address. */ + SD_BLE_GAP_ADDR_GET, /**< Get own Bluetooth Address. */ + SD_BLE_GAP_WHITELIST_SET, /**< Set active whitelist. */ + SD_BLE_GAP_DEVICE_IDENTITIES_SET, /**< Set device identity list. */ + SD_BLE_GAP_PRIVACY_SET, /**< Set Privacy settings*/ + SD_BLE_GAP_PRIVACY_GET, /**< Get Privacy settings*/ + SD_BLE_GAP_ADV_DATA_SET, /**< Set Advertising Data. */ + SD_BLE_GAP_ADV_START, /**< Start Advertising. */ + SD_BLE_GAP_ADV_STOP, /**< Stop Advertising. */ + SD_BLE_GAP_CONN_PARAM_UPDATE, /**< Connection Parameter Update. */ + SD_BLE_GAP_DISCONNECT, /**< Disconnect. */ + SD_BLE_GAP_TX_POWER_SET, /**< Set TX Power. */ + SD_BLE_GAP_APPEARANCE_SET, /**< Set Appearance. */ + SD_BLE_GAP_APPEARANCE_GET, /**< Get Appearance. */ + SD_BLE_GAP_PPCP_SET, /**< Set PPCP. */ + SD_BLE_GAP_PPCP_GET, /**< Get PPCP. */ + SD_BLE_GAP_DEVICE_NAME_SET, /**< Set Device Name. */ + SD_BLE_GAP_DEVICE_NAME_GET, /**< Get Device Name. */ + SD_BLE_GAP_AUTHENTICATE, /**< Initiate Pairing/Bonding. */ + SD_BLE_GAP_SEC_PARAMS_REPLY, /**< Reply with Security Parameters. */ + SD_BLE_GAP_AUTH_KEY_REPLY, /**< Reply with an authentication key. */ + SD_BLE_GAP_LESC_DHKEY_REPLY, /**< Reply with an LE Secure Connections DHKey. */ + SD_BLE_GAP_KEYPRESS_NOTIFY, /**< Notify of a keypress during an authentication procedure. */ + SD_BLE_GAP_LESC_OOB_DATA_GET, /**< Get the local LE Secure Connections OOB data. */ + SD_BLE_GAP_LESC_OOB_DATA_SET, /**< Set the remote LE Secure Connections OOB data. */ + SD_BLE_GAP_ENCRYPT, /**< Initiate encryption procedure. */ + SD_BLE_GAP_SEC_INFO_REPLY, /**< Reply with Security Information. */ + SD_BLE_GAP_CONN_SEC_GET, /**< Obtain connection security level. */ + SD_BLE_GAP_RSSI_START, /**< Start reporting of changes in RSSI. */ + SD_BLE_GAP_RSSI_STOP, /**< Stop reporting of changes in RSSI. */ + SD_BLE_GAP_SCAN_START, /**< Start Scanning. */ + SD_BLE_GAP_SCAN_STOP, /**< Stop Scanning. */ + SD_BLE_GAP_CONNECT, /**< Connect. */ + SD_BLE_GAP_CONNECT_CANCEL, /**< Cancel ongoing connection procedure. */ + SD_BLE_GAP_RSSI_GET, /**< Get the last RSSI sample. */ + SD_BLE_GAP_PHY_UPDATE, /**< Initiate or respond to a PHY Update Procedure. */ + SD_BLE_GAP_DATA_LENGTH_UPDATE, /**< Initiate or respond to a Data Length Update Procedure. */ +}; + +/**@brief GAP Event IDs. + * IDs that uniquely identify an event coming from the stack to the application. + */ +enum BLE_GAP_EVTS +{ + BLE_GAP_EVT_CONNECTED = BLE_GAP_EVT_BASE, /**< Connection established. \n See @ref ble_gap_evt_connected_t. */ + BLE_GAP_EVT_DISCONNECTED, /**< Disconnected from peer. \n See @ref ble_gap_evt_disconnected_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE, /**< Connection Parameters updated. \n See @ref ble_gap_evt_conn_param_update_t. */ + BLE_GAP_EVT_SEC_PARAMS_REQUEST, /**< Request to provide security parameters. \n Reply with @ref sd_ble_gap_sec_params_reply. \n See @ref ble_gap_evt_sec_params_request_t. */ + BLE_GAP_EVT_SEC_INFO_REQUEST, /**< Request to provide security information. \n Reply with @ref sd_ble_gap_sec_info_reply. \n See @ref ble_gap_evt_sec_info_request_t. */ + BLE_GAP_EVT_PASSKEY_DISPLAY, /**< Request to display a passkey to the user. \n In LESC Numeric Comparison, reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_passkey_display_t. */ + BLE_GAP_EVT_KEY_PRESSED, /**< Notification of a keypress on the remote device.\n See @ref ble_gap_evt_key_pressed_t */ + BLE_GAP_EVT_AUTH_KEY_REQUEST, /**< Request to provide an authentication key. \n Reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_auth_key_request_t. */ + BLE_GAP_EVT_LESC_DHKEY_REQUEST, /**< Request to calculate an LE Secure Connections DHKey. \n Reply with @ref sd_ble_gap_lesc_dhkey_reply. \n See @ref ble_gap_evt_lesc_dhkey_request_t */ + BLE_GAP_EVT_AUTH_STATUS, /**< Authentication procedure completed with status. \n See @ref ble_gap_evt_auth_status_t. */ + BLE_GAP_EVT_CONN_SEC_UPDATE, /**< Connection security updated. \n See @ref ble_gap_evt_conn_sec_update_t. */ + BLE_GAP_EVT_TIMEOUT, /**< Timeout expired. \n See @ref ble_gap_evt_timeout_t. */ + BLE_GAP_EVT_RSSI_CHANGED, /**< RSSI report. \n See @ref ble_gap_evt_rssi_changed_t. */ + BLE_GAP_EVT_ADV_REPORT, /**< Advertising report. \n See @ref ble_gap_evt_adv_report_t. */ + BLE_GAP_EVT_SEC_REQUEST, /**< Security Request. \n See @ref ble_gap_evt_sec_request_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, /**< Connection Parameter Update Request. \n Reply with @ref sd_ble_gap_conn_param_update. \n See @ref ble_gap_evt_conn_param_update_request_t. */ + BLE_GAP_EVT_SCAN_REQ_REPORT, /**< Scan request report. \n See @ref ble_gap_evt_scan_req_report_t. */ + BLE_GAP_EVT_PHY_UPDATE_REQUEST, /**< PHY Update Request. \n Reply with @ref sd_ble_gap_phy_update. \n See @ref ble_gap_evt_phy_update_request_t. */ + BLE_GAP_EVT_PHY_UPDATE, /**< PHY Update Procedure is complete. \n See @ref ble_gap_evt_phy_update_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST, /**< Data Length Update Request. \n Reply with @ref sd_ble_gap_data_length_update.\n See @ref ble_gap_evt_data_length_update_request_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE, /**< LL Data Channel PDU payload length updated. \n See @ref ble_gap_evt_data_length_update_t. */ +}; + +/**@brief GAP Option IDs. + * IDs that uniquely identify a GAP option. + */ +enum BLE_GAP_OPTS +{ + BLE_GAP_OPT_CH_MAP = BLE_GAP_OPT_BASE, /**< Channel Map. @ref ble_gap_opt_ch_map_t */ + BLE_GAP_OPT_LOCAL_CONN_LATENCY, /**< Local connection latency. @ref ble_gap_opt_local_conn_latency_t */ + BLE_GAP_OPT_PASSKEY, /**< Set passkey. @ref ble_gap_opt_passkey_t */ + BLE_GAP_OPT_SCAN_REQ_REPORT, /**< Scan request report. @ref ble_gap_opt_scan_req_report_t */ + BLE_GAP_OPT_COMPAT_MODE_1, /**< Compatibility mode. @ref ble_gap_opt_compat_mode_1_t */ + BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, /**< Set Authenticated payload timeout. @ref ble_gap_opt_auth_payload_timeout_t */ + BLE_GAP_OPT_SLAVE_LATENCY_DISABLE, /**< Disable slave latency. @ref ble_gap_opt_slave_latency_disable_t */ +}; + +/**@brief GAP Configuration IDs. + * + * IDs that uniquely identify a GAP configuration. + */ +enum BLE_GAP_CFGS +{ + BLE_GAP_CFG_ROLE_COUNT = BLE_GAP_CFG_BASE, /**< Role count configuration. */ + BLE_GAP_CFG_DEVICE_NAME, /**< Device name configuration. */ +}; + +/** @} */ + +/**@addtogroup BLE_GAP_DEFINES Defines + * @{ */ + +/**@defgroup BLE_ERRORS_GAP SVC return values specific to GAP + * @{ */ +#define BLE_ERROR_GAP_UUID_LIST_MISMATCH (NRF_GAP_ERR_BASE + 0x000) /**< UUID list does not contain an integral number of UUIDs. */ +#define BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST (NRF_GAP_ERR_BASE + 0x001) /**< Use of Whitelist not permitted with discoverable advertising. */ +#define BLE_ERROR_GAP_INVALID_BLE_ADDR (NRF_GAP_ERR_BASE + 0x002) /**< The upper two bits of the address do not correspond to the specified address type. */ +#define BLE_ERROR_GAP_WHITELIST_IN_USE (NRF_GAP_ERR_BASE + 0x003) /**< Attempt to modify the whitelist while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE (NRF_GAP_ERR_BASE + 0x004) /**< Attempt to modify the device identity list while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE (NRF_GAP_ERR_BASE + 0x005) /**< The device identity list contains entries with duplicate identity addresses. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLES GAP Roles + * @note Not explicitly used in peripheral API, but will be relevant for central API. + * @{ */ +#define BLE_GAP_ROLE_INVALID 0x0 /**< Invalid Role. */ +#define BLE_GAP_ROLE_PERIPH 0x1 /**< Peripheral Role. */ +#define BLE_GAP_ROLE_CENTRAL 0x2 /**< Central Role. */ +/**@} */ + + +/**@defgroup BLE_GAP_TIMEOUT_SOURCES GAP Timeout sources + * @{ */ +#define BLE_GAP_TIMEOUT_SRC_ADVERTISING 0x00 /**< Advertising timeout. */ +#define BLE_GAP_TIMEOUT_SRC_SCAN 0x01 /**< Scanning timeout. */ +#define BLE_GAP_TIMEOUT_SRC_CONN 0x02 /**< Connection timeout. */ +#define BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD 0x03 /**< Authenticated payload timeout. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADDR_TYPES GAP Address types + * @{ */ +#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00 /**< Public address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01 /**< Random static address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02 /**< Random private resolvable address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03 /**< Random private non-resolvable address. */ +/**@} */ + + +/**@brief The default interval in seconds at which a private address is refreshed. */ +#define BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S (900) /* 15 minutes. */ +/**@brief The maximum interval in seconds at which a private address can be refreshed. */ +#define BLE_GAP_MAX_PRIVATE_ADDR_CYCLE_INTERVAL_S (41400) /* 11 hours 30 minutes. */ + + +/** @brief BLE address length. */ +#define BLE_GAP_ADDR_LEN (6) + + +/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes + * @{ */ +#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ +#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ +#define BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY 0x02 /**< Device will send and accept only private addresses for its own address, + and will not accept a peer using identity address as sender address when + the peer IRK is exchanged, non-zero and added to the identity list. */ +/**@} */ + + +/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format + * @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm + * @{ */ +#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */ +#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */ +#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */ +#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */ +#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */ +#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */ +#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */ +#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */ +#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */ +#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */ +#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */ +#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */ +#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ +#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ +#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FLAGS GAP Advertisement Flags + * @{ */ +#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_INTERVALS GAP Advertising interval max and min + * @{ */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 /**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 /**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ + /**@} */ + + +/**@defgroup BLE_GAP_SCAN_INTERVALS GAP Scan interval max and min + * @{ */ +#define BLE_GAP_SCAN_INTERVAL_MIN 0x0004 /**< Minimum Scan interval in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_INTERVAL_MAX 0x4000 /**< Maximum Scan interval in 625 us units, i.e. 10.24 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_WINDOW GAP Scan window max and min + * @{ */ +#define BLE_GAP_SCAN_WINDOW_MIN 0x0004 /**< Minimum Scan window in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_WINDOW_MAX 0x4000 /**< Maximum Scan window in 625 us units, i.e. 10.24 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_TIMEOUT GAP Scan timeout max and min + * @{ */ +#define BLE_GAP_SCAN_TIMEOUT_MIN 0x0001 /**< Minimum Scan timeout in seconds. */ +#define BLE_GAP_SCAN_TIMEOUT_MAX 0xFFFF /**< Maximum Scan timeout in seconds. */ + /** @} */ + + +/**@brief Maximum size of advertising data in octets. */ +#define BLE_GAP_ADV_MAX_SIZE (31) + + +/**@defgroup BLE_GAP_ADV_TYPES GAP Advertising types + * @{ */ +#define BLE_GAP_ADV_TYPE_ADV_IND 0x00 /**< Connectable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01 /**< Connectable directed. */ +#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02 /**< Scannable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03 /**< Non connectable undirected. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FILTER_POLICIES GAP Advertising filter policies + * @{ */ +#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ +#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01 /**< Filter scan requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02 /**< Filter connect requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03 /**< Filter both scan and connect requests with whitelist. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_TIMEOUT_VALUES GAP Advertising timeout values + * @{ */ +#define BLE_GAP_ADV_TIMEOUT_LIMITED_MAX (180) /**< Maximum advertising time in limited discoverable mode (TGAP(lim_adv_timeout) = 180 s). */ +#define BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED (0) /**< Unlimited advertising in general discoverable mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_DISC_MODES GAP Discovery modes + * @{ */ +#define BLE_GAP_DISC_MODE_NOT_DISCOVERABLE 0x00 /**< Not discoverable discovery Mode. */ +#define BLE_GAP_DISC_MODE_LIMITED 0x01 /**< Limited Discovery Mode. */ +#define BLE_GAP_DISC_MODE_GENERAL 0x02 /**< General Discovery Mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_IO_CAPS GAP IO Capabilities + * @{ */ +#define BLE_GAP_IO_CAPS_DISPLAY_ONLY 0x00 /**< Display Only. */ +#define BLE_GAP_IO_CAPS_DISPLAY_YESNO 0x01 /**< Display and Yes/No entry. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_ONLY 0x02 /**< Keyboard Only. */ +#define BLE_GAP_IO_CAPS_NONE 0x03 /**< No I/O capabilities. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY 0x04 /**< Keyboard and Display. */ +/**@} */ + + +/**@defgroup BLE_GAP_AUTH_KEY_TYPES GAP Authentication Key Types + * @{ */ +#define BLE_GAP_AUTH_KEY_TYPE_NONE 0x00 /**< No key (may be used to reject). */ +#define BLE_GAP_AUTH_KEY_TYPE_PASSKEY 0x01 /**< 6-digit Passkey. */ +#define BLE_GAP_AUTH_KEY_TYPE_OOB 0x02 /**< Out Of Band data. */ +/**@} */ + + +/**@defgroup BLE_GAP_KP_NOT_TYPES GAP Keypress Notification Types + * @{ */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_START 0x00 /**< Passkey entry started. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_IN 0x01 /**< Passkey digit entered. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_OUT 0x02 /**< Passkey digit erased. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_CLEAR 0x03 /**< Passkey cleared. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_END 0x04 /**< Passkey entry completed. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS GAP Security status + * @{ */ +#define BLE_GAP_SEC_STATUS_SUCCESS 0x00 /**< Procedure completed with success. */ +#define BLE_GAP_SEC_STATUS_TIMEOUT 0x01 /**< Procedure timed out. */ +#define BLE_GAP_SEC_STATUS_PDU_INVALID 0x02 /**< Invalid PDU received. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_BEGIN 0x03 /**< Reserved for Future Use range #1 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_END 0x80 /**< Reserved for Future Use range #1 end. */ +#define BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user canceled or other). */ +#define BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE 0x82 /**< Out of Band Key not available. */ +#define BLE_GAP_SEC_STATUS_AUTH_REQ 0x83 /**< Authentication requirements not met. */ +#define BLE_GAP_SEC_STATUS_CONFIRM_VALUE 0x84 /**< Confirm value failed. */ +#define BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 0x85 /**< Pairing not supported. */ +#define BLE_GAP_SEC_STATUS_ENC_KEY_SIZE 0x86 /**< Encryption key size. */ +#define BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED 0x87 /**< Unsupported SMP command. */ +#define BLE_GAP_SEC_STATUS_UNSPECIFIED 0x88 /**< Unspecified reason. */ +#define BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS 0x89 /**< Too little time elapsed since last attempt. */ +#define BLE_GAP_SEC_STATUS_INVALID_PARAMS 0x8A /**< Invalid parameters. */ +#define BLE_GAP_SEC_STATUS_DHKEY_FAILURE 0x8B /**< DHKey check failure. */ +#define BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE 0x8C /**< Numeric Comparison failure. */ +#define BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG 0x8D /**< BR/EDR pairing in progress. */ +#define BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED 0x8E /**< BR/EDR Link Key cannot be used for LE keys. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_BEGIN 0x8F /**< Reserved for Future Use range #2 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_END 0xFF /**< Reserved for Future Use range #2 end. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS_SOURCES GAP Security status sources + * @{ */ +#define BLE_GAP_SEC_STATUS_SOURCE_LOCAL 0x00 /**< Local failure. */ +#define BLE_GAP_SEC_STATUS_SOURCE_REMOTE 0x01 /**< Remote failure. */ +/**@} */ + + +/**@defgroup BLE_GAP_CP_LIMITS GAP Connection Parameters Limits + * @{ */ +#define BLE_GAP_CP_MIN_CONN_INTVL_NONE 0xFFFF /**< No new minimum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 /**< Lowest minimum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MAX 0x0C80 /**< Highest minimum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_NONE 0xFFFF /**< No new maximum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MIN 0x0006 /**< Lowest maximum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MAX 0x0C80 /**< Highest maximum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_SLAVE_LATENCY_MAX 0x01F3 /**< Highest slave latency permitted, in connection events. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE 0xFFFF /**< No new supervision timeout specified in connect parameters. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN 0x000A /**< Lowest supervision timeout permitted, in units of 10 ms, i.e. 100 ms. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 0x0C80 /**< Highest supervision timeout permitted, in units of 10 ms, i.e. 32 s. */ +/**@} */ + + +/**@defgroup BLE_GAP_DEVNAME GAP device name defines. + * @{ */ +#define BLE_GAP_DEVNAME_DEFAULT "nRF5x" /**< Default device name value. */ +#define BLE_GAP_DEVNAME_DEFAULT_LEN 31 /**< Default number of octets in device name. */ +#define BLE_GAP_DEVNAME_MAX_LEN 248 /**< Maximum number of octets in device name. */ +/**@} */ + + +/**@brief Disable RSSI events for connections */ +#define BLE_GAP_RSSI_THRESHOLD_INVALID 0xFF + +/**@defgroup BLE_GAP_PHYS GAP PHYs + * @{ */ +#define BLE_GAP_PHY_AUTO 0x00 /**< Automatic PHY selection. Refer @ref sd_ble_gap_phy_update for more information.*/ +#define BLE_GAP_PHY_1MBPS 0x01 /**< 1 Mbps PHY. */ +#define BLE_GAP_PHY_2MBPS 0x02 /**< 2 Mbps PHY. */ +#define BLE_GAP_PHY_CODED 0x04 /**< Coded PHY. */ + +/**@} */ + +/**@defgroup BLE_GAP_CONN_SEC_MODE_SET_MACROS GAP attribute security requirement setters + * + * See @ref ble_gap_conn_sec_mode_t. + * @{ */ +/**@brief Set sec_mode pointed to by ptr to have no access rights.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(ptr) do {(ptr)->sm = 0; (ptr)->lv = 0;} while(0) +/**@brief Set sec_mode pointed to by ptr to require no protection, open link.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_OPEN(ptr) do {(ptr)->sm = 1; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption, but no MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 2;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 3;} while(0) +/**@brief Set sec_mode pointed to by ptr to require LESC encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 4;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption, no MITM protection needed.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption with MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 2;} while(0) +/**@} */ + + +/**@brief GAP Security Random Number Length. */ +#define BLE_GAP_SEC_RAND_LEN 8 + + +/**@brief GAP Security Key Length. */ +#define BLE_GAP_SEC_KEY_LEN 16 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key Length. */ +#define BLE_GAP_LESC_P256_PK_LEN 64 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman DHKey Length. */ +#define BLE_GAP_LESC_DHKEY_LEN 32 + + +/**@brief GAP Passkey Length. */ +#define BLE_GAP_PASSKEY_LEN 6 + + +/**@brief Maximum amount of addresses in the whitelist. */ +#define BLE_GAP_WHITELIST_ADDR_MAX_COUNT (8) + + +/**@brief Maximum amount of identities in the device identities list. */ +#define BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT (8) + + +/**@brief Default connection count for a configuration. */ +#define BLE_GAP_CONN_COUNT_DEFAULT (1) + + +/**@defgroup BLE_GAP_EVENT_LENGTH GAP event length defines. + * @{ */ +#define BLE_GAP_EVENT_LENGTH_MIN (2) /**< Minimum event length, in 1.25 ms units. */ +#define BLE_GAP_EVENT_LENGTH_DEFAULT (3) /**< Default event length, in 1.25 ms units. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLE_COUNT GAP concurrent connection count defines. + * @{ */ +#define BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT (1) /**< Default maximum number of connections concurrently acting as peripherals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT (3) /**< Default maximum number of connections concurrently acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT (1) /**< Default number of SMP instances shared between all connections acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_COMBINED_MAX (20) /**< Maximum supported number of concurrent connections in the peripheral and central roles combined. */ +/**@} */ + + +/**@brief Automatic data length parameter. */ +#define BLE_GAP_DATA_LENGTH_AUTO 0 + +/**@defgroup BLE_GAP_AUTH_PAYLOAD_TIMEOUT Authenticated payload timeout defines. + * @{ */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX (48000) /**< Maximum authenticated payload timeout in 10 ms units, i.e. 8 minutes. */ +#define BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MIN (1) /**< Minimum authenticated payload timeout in 10 ms units, i.e. 10 ms. */ +/**@} */ + +/**@defgroup GAP_SEC_MODES GAP Security Modes + * @{ */ +#define BLE_GAP_SEC_MODE 0x00 /**< No key (may be used to reject). */ +/**@} */ +/** @} */ + + +/**@addtogroup BLE_GAP_STRUCTURES Structures + * @{ */ + +/**@brief Bluetooth Low Energy address. */ +typedef struct +{ + uint8_t addr_id_peer : 1; /**< Only valid for peer addresses. + Reference to peer in device identities list (as set with @ref sd_ble_gap_device_identities_set) when peer is using privacy. */ + uint8_t addr_type : 7; /**< See @ref BLE_GAP_ADDR_TYPES. */ + uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format. */ +} ble_gap_addr_t; + + +/**@brief GAP connection parameters. + * + * @note When ble_conn_params_t is received in an event, both min_conn_interval and + * max_conn_interval will be equal to the connection interval set by the central. + * + * @note If both conn_sup_timeout and max_conn_interval are specified, then the following constraint applies: + * conn_sup_timeout * 4 > (1 + slave_latency) * max_conn_interval + * that corresponds to the following Bluetooth Spec requirement: + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, where Conn_Interval_Max is given in milliseconds. + */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/ +} ble_gap_conn_params_t; + + +/**@brief GAP connection security modes. + * + * Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\n + * Security Mode 1 Level 1: No security is needed (aka open link).\n + * Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\n + * Security Mode 1 Level 3: MITM protected encrypted link required.\n + * Security Mode 1 Level 4: LESC MITM protected encrypted link using a 128-bit strength encryption key required.\n + * Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\n + * Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\n + */ +typedef struct +{ + uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */ + uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */ + +} ble_gap_conn_sec_mode_t; + + +/**@brief GAP connection security status.*/ +typedef struct +{ + ble_gap_conn_sec_mode_t sec_mode; /**< Currently active security mode for this connection.*/ + uint8_t encr_key_size; /**< Length of currently active encryption key, 7 to 16 octets (only applicable for bonding procedures). */ +} ble_gap_conn_sec_t; + +/**@brief Identity Resolving Key. */ +typedef struct +{ + uint8_t irk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing IRK. */ +} ble_gap_irk_t; + + +/**@brief Channel mask for RF channels used in advertising. */ +typedef struct +{ + uint8_t ch_37_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 37 */ + uint8_t ch_38_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 38 */ + uint8_t ch_39_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 39 */ +} ble_gap_adv_ch_mask_t; + + +/**@brief GAP advertising parameters. */ +typedef struct +{ + uint8_t type; /**< See @ref BLE_GAP_ADV_TYPES. */ + ble_gap_addr_t const *p_peer_addr; /**< Address of a known peer. + - When privacy is enabled and the local device use @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE addresses, the device identity list is searched for a matching + entry. If the local IRK for that device identity is set, the local IRK for that device will be used to generate the advertiser address field in the advertise packet. + - If type is @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this must be set to the targeted initiator. If the initiator is in the device identity list, + the peer IRK for that device will be used to generate the initiator address field in the ADV_DIRECT_IND packet. */ + uint8_t fp; /**< Filter Policy, see @ref BLE_GAP_ADV_FILTER_POLICIES. */ + uint16_t interval; /**< Advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20 ms to 10.24 s), see @ref BLE_GAP_ADV_INTERVALS. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for high duty cycle directed advertising. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, set @ref BLE_GAP_ADV_INTERVAL_MIN <= interval <= @ref BLE_GAP_ADV_INTERVAL_MAX for low duty cycle advertising.*/ + uint16_t timeout; /**< Advertising timeout between 0x0001 and 0x3FFF in seconds, 0x0000 disables timeout. See also @ref BLE_GAP_ADV_TIMEOUT_VALUES. If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for High duty cycle directed advertising. */ + ble_gap_adv_ch_mask_t channel_mask; /**< Advertising channel mask. See @ref ble_gap_adv_ch_mask_t. */ +} ble_gap_adv_params_t; + + +/**@brief GAP scanning parameters. */ +typedef struct +{ + uint8_t active : 1; /**< If 1, perform active scanning (scan requests). */ + uint8_t use_whitelist : 1; /**< If 1, filter advertisers using current active whitelist. */ + uint8_t adv_dir_report : 1; /**< If 1, also report directed advertisements where the initiator field is set to a private resolvable address, + even if the address did not resolve to an entry in the device identity list. A report will be generated + even if the peer is not in the whitelist. */ + uint16_t interval; /**< Scan interval between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */ + uint16_t window; /**< Scan window between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */ + uint16_t timeout; /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ +} ble_gap_scan_params_t; + + +/**@brief Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of time. + * The privacy feature, when enabled, hides the local device identity and replaces it with a private address + * that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity Resolving Key (IRK). + * With this key, a device can generate a random private address that can only be recognized by peers in possession of that key, + * and devices can establish connections without revealing their real identities. + * + * Both network privacy (@ref BLE_GAP_PRIVACY_MODE_NETWORK_PRIVACY) and device privacy (@ref BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY) + * are supported. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref sd_ble_gap_sec_params_reply is called. + */ +typedef struct +{ + uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ + uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ + uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ + ble_gap_irk_t *p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. + When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. + By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ +} ble_gap_privacy_params_t; + + +/**@brief PHY preferences for TX and RX + * @note tx_phys and rx_phys are bit fields. Multiple bits can be set in them to indicate multiple preferred PHYs for each direction. + * @code + * p_gap_phys->tx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * p_gap_phys->rx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * @endcode + * + */ +typedef struct +{ + uint8_t tx_phys; /**< Preferred transmit PHYs, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phys; /**< Preferred receive PHYs, see @ref BLE_GAP_PHYS. */ +} ble_gap_phys_t; + +/** @brief Keys that can be exchanged during a bonding procedure. */ +typedef struct +{ + uint8_t enc : 1; /**< Long Term Key and Master Identification. */ + uint8_t id : 1; /**< Identity Resolving Key and Identity Address Information. */ + uint8_t sign : 1; /**< Connection Signature Resolving Key. */ + uint8_t link : 1; /**< Derive the Link Key from the LTK. */ +} ble_gap_sec_kdist_t; + + +/**@brief GAP security parameters. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Enable Man In The Middle protection. */ + uint8_t lesc : 1; /**< Enable LE Secure Connection pairing. */ + uint8_t keypress : 1; /**< Enable generation of keypress notifications. */ + uint8_t io_caps : 3; /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ + uint8_t oob : 1; /**< The OOB data flag. + - In LE legacy pairing, this flag is set if a device has out of band authentication data. + The OOB method is used if both of the devices have out of band authentication data. + - In LE Secure Connections pairing, this flag is set if a device has the peer device's out of band authentication data. + The OOB method is used if at least one device has the peer device's OOB data available. */ + uint8_t min_key_size; /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ + uint8_t max_key_size; /**< Maximum encryption key size in octets between min_key_size and 16. */ + ble_gap_sec_kdist_t kdist_own; /**< Key distribution bitmap: keys that the local device will distribute. */ + ble_gap_sec_kdist_t kdist_peer; /**< Key distribution bitmap: keys that the remote device will distribute. */ +} ble_gap_sec_params_t; + + +/**@brief GAP Encryption Information. */ +typedef struct +{ + uint8_t ltk[BLE_GAP_SEC_KEY_LEN]; /**< Long Term Key. */ + uint8_t lesc : 1; /**< Key generated using LE Secure Connections. */ + uint8_t auth : 1; /**< Authenticated Key. */ + uint8_t ltk_len : 6; /**< LTK length in octets. */ +} ble_gap_enc_info_t; + + +/**@brief GAP Master Identification. */ +typedef struct +{ + uint16_t ediv; /**< Encrypted Diversifier. */ + uint8_t rand[BLE_GAP_SEC_RAND_LEN]; /**< Random Number. */ +} ble_gap_master_id_t; + + +/**@brief GAP Signing Information. */ +typedef struct +{ + uint8_t csrk[BLE_GAP_SEC_KEY_LEN]; /**< Connection Signature Resolving Key. */ +} ble_gap_sign_info_t; + + +/**@brief GAP LE Secure Connections P-256 Public Key. */ +typedef struct +{ + uint8_t pk[BLE_GAP_LESC_P256_PK_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key. Stored in the standard SMP protocol format: {X,Y} both in little-endian. */ +} ble_gap_lesc_p256_pk_t; + + +/**@brief GAP LE Secure Connections DHKey. */ +typedef struct +{ + uint8_t key[BLE_GAP_LESC_DHKEY_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman Key. Stored in little-endian. */ +} ble_gap_lesc_dhkey_t; + + +/**@brief GAP LE Secure Connections OOB data. */ +typedef struct +{ + ble_gap_addr_t addr; /**< Bluetooth address of the device. */ + uint8_t r[BLE_GAP_SEC_KEY_LEN]; /**< Random Number. */ + uint8_t c[BLE_GAP_SEC_KEY_LEN]; /**< Confirm Value. */ +} ble_gap_lesc_oob_data_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONNECTED. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + uint8_t role; /**< BLE role for this connection, see @ref BLE_GAP_ROLES */ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_connected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_DISCONNECTED. */ +typedef struct +{ + uint8_t reason; /**< HCI error code, see @ref BLE_HCI_STATUS_CODES. */ +} ble_gap_evt_disconnected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_PHY_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_phys_t peer_preferred_phys; /**< The PHYs the peer prefers to use. */ +} ble_gap_evt_phy_update_request_t; + +/**@brief Event Structure for @ref BLE_GAP_EVT_PHY_UPDATE. */ +typedef struct +{ + uint8_t status; /**< Status of the procedure, see @ref BLE_HCI_STATUS_CODES.*/ + uint8_t tx_phy; /**< TX PHY for this connection, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phy; /**< RX PHY for this connection, see @ref BLE_GAP_PHYS. */ +} ble_gap_evt_phy_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. */ +typedef struct +{ + ble_gap_sec_params_t peer_params; /**< Initiator Security Parameters. */ +} ble_gap_evt_sec_params_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_INFO_REQUEST. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + ble_gap_master_id_t master_id; /**< Master Identification for LTK lookup. */ + uint8_t enc_info : 1; /**< If 1, Encryption Information required. */ + uint8_t id_info : 1; /**< If 1, Identity Information required. */ + uint8_t sign_info : 1; /**< If 1, Signing Information required. */ +} ble_gap_evt_sec_info_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_PASSKEY_DISPLAY. */ +typedef struct +{ + uint8_t passkey[BLE_GAP_PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ + uint8_t match_request : 1; /**< If 1 requires the application to report the match using @ref sd_ble_gap_auth_key_reply + with either @ref BLE_GAP_AUTH_KEY_TYPE_NONE if there is no match or + @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY if there is a match. */ +} ble_gap_evt_passkey_display_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_KEY_PRESSED. */ +typedef struct +{ + uint8_t kp_not; /**< Keypress notification type, see @ref BLE_GAP_KP_NOT_TYPES. */ +} ble_gap_evt_key_pressed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_KEY_REQUEST. */ +typedef struct +{ + uint8_t key_type; /**< See @ref BLE_GAP_AUTH_KEY_TYPES. */ +} ble_gap_evt_auth_key_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST. */ +typedef struct +{ + ble_gap_lesc_p256_pk_t *p_pk_peer; /**< LE Secure Connections remote P-256 Public Key. This will point to the application-supplied memory + inside the keyset during the call to @ref sd_ble_gap_sec_params_reply. */ + uint8_t oobd_req :1; /**< LESC OOB data required. A call to @ref sd_ble_gap_lesc_oob_data_set is required to complete the procedure. */ +} ble_gap_evt_lesc_dhkey_request_t; + + +/**@brief Security levels supported. + * @note See Bluetooth Specification Version 4.2 Volume 3, Part C, Chapter 10, Section 10.2.1. +*/ +typedef struct +{ + uint8_t lv1 : 1; /**< If 1: Level 1 is supported. */ + uint8_t lv2 : 1; /**< If 1: Level 2 is supported. */ + uint8_t lv3 : 1; /**< If 1: Level 3 is supported. */ + uint8_t lv4 : 1; /**< If 1: Level 4 is supported. */ +} ble_gap_sec_levels_t; + + +/**@brief Encryption Key. */ +typedef struct +{ + ble_gap_enc_info_t enc_info; /**< Encryption Information. */ + ble_gap_master_id_t master_id; /**< Master Identification. */ +} ble_gap_enc_key_t; + + +/**@brief Identity Key. */ +typedef struct +{ + ble_gap_irk_t id_info; /**< Identity Resolving Key. */ + ble_gap_addr_t id_addr_info; /**< Identity Address. */ +} ble_gap_id_key_t; + + +/**@brief Security Keys. */ +typedef struct +{ + ble_gap_enc_key_t *p_enc_key; /**< Encryption Key, or NULL. */ + ble_gap_id_key_t *p_id_key; /**< Identity Key, or NULL. */ + ble_gap_sign_info_t *p_sign_key; /**< Signing Key, or NULL. */ + ble_gap_lesc_p256_pk_t *p_pk; /**< LE Secure Connections P-256 Public Key. When in debug mode the application must use the value defined + in the Core Bluetooth Specification v4.2 Vol.3, Part H, Section 2.3.5.6.1 */ +} ble_gap_sec_keys_t; + + +/**@brief Security key set for both local and peer keys. */ +typedef struct +{ + ble_gap_sec_keys_t keys_own; /**< Keys distributed by the local device. For LE Secure Connections the encryption key will be generated locally and will always be stored if bonding. */ + ble_gap_sec_keys_t keys_peer; /**< Keys distributed by the remote device. For LE Secure Connections, p_enc_key must always be NULL. */ +} ble_gap_sec_keyset_t; + + +/**@brief Data Length Update Procedure parameters. */ +typedef struct +{ + uint16_t max_tx_octets; /**< Maximum number of payload octets that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_octets; /**< Maximum number of payload octets that a Controller supports for reception of a single Link Layer Data Channel PDU. */ + uint16_t max_tx_time_us; /**< Maximum time, in microseconds, that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_time_us; /**< Maximum time, in microseconds, that a Controller supports for reception of a single Link Layer Data Channel PDU. */ +} ble_gap_data_length_params_t; + + +/**@brief Data Length Update Procedure local limitation. */ +typedef struct +{ + uint16_t tx_payload_limited_octets; /**< If > 0, the requested TX packet length is too long by this many octets. */ + uint16_t rx_payload_limited_octets; /**< If > 0, the requested RX packet length is too long by this many octets. */ + uint16_t tx_rx_time_limited_us; /**< If > 0, the requested combination of TX and RX packet lengths is too long by this many microseconds. */ +} ble_gap_data_length_limitation_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_STATUS. */ +typedef struct +{ + uint8_t auth_status; /**< Authentication status, see @ref BLE_GAP_SEC_STATUS. */ + uint8_t error_src : 2; /**< On error, source that caused the failure, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ + uint8_t bonded : 1; /**< Procedure resulted in a bond. */ + uint8_t lesc : 1; /**< Procedure resulted in a LE Secure Connection. */ + ble_gap_sec_levels_t sm1_levels; /**< Levels supported in Security Mode 1. */ + ble_gap_sec_levels_t sm2_levels; /**< Levels supported in Security Mode 2. */ + ble_gap_sec_kdist_t kdist_own; /**< Bitmap stating which keys were exchanged (distributed) by the local device. If bonding with LE Secure Connections, the enc bit will be always set. */ + ble_gap_sec_kdist_t kdist_peer; /**< Bitmap stating which keys were exchanged (distributed) by the remote device. If bonding with LE Secure Connections, the enc bit will never be set. */ +} ble_gap_evt_auth_status_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_SEC_UPDATE. */ +typedef struct +{ + ble_gap_conn_sec_t conn_sec; /**< Connection security level. */ +} ble_gap_evt_conn_sec_update_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Source of timeout event, see @ref BLE_GAP_TIMEOUT_SOURCES. */ +} ble_gap_evt_timeout_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_RSSI_CHANGED. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ +} ble_gap_evt_rssi_changed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_ADV_REPORT. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + ble_gap_addr_t direct_addr; /**< Set when the scanner is unable to resolve the private resolvable address of the initiator + field of a directed advertisement packet and the scanner has been enabled to report this in @ref ble_gap_scan_params_t::adv_dir_report. */ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ + uint8_t scan_rsp : 1; /**< If 1, the report corresponds to a scan response and the type field may be ignored. */ + uint8_t type : 2; /**< See @ref BLE_GAP_ADV_TYPES. Only valid if the scan_rsp field is 0. */ + uint8_t dlen : 5; /**< Advertising or scan response data length. */ + uint8_t data[BLE_GAP_ADV_MAX_SIZE]; /**< Advertising or scan response data. */ +} ble_gap_evt_adv_report_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_REQUEST. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Man In The Middle protection requested. */ + uint8_t lesc : 1; /**< LE Secure Connections requested. */ + uint8_t keypress : 1; /**< Generation of keypress notifications requested. */ +} ble_gap_evt_sec_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SCAN_REQ_REPORT. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ +} ble_gap_evt_scan_req_report_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_data_length_params_t peer_params; /**< Peer data length parameters. */ +} ble_gap_evt_data_length_update_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE. */ +typedef struct +{ + ble_gap_data_length_params_t effective_params; /**< The effective data length parameters. */ +} ble_gap_evt_data_length_update_t; + + +/**@brief GAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + union /**< union alternative identified by evt_id in enclosing struct. */ + { + ble_gap_evt_connected_t connected; /**< Connected Event Parameters. */ + ble_gap_evt_disconnected_t disconnected; /**< Disconnected Event Parameters. */ + ble_gap_evt_conn_param_update_t conn_param_update; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_sec_params_request_t sec_params_request; /**< Security Parameters Request Event Parameters. */ + ble_gap_evt_sec_info_request_t sec_info_request; /**< Security Information Request Event Parameters. */ + ble_gap_evt_passkey_display_t passkey_display; /**< Passkey Display Event Parameters. */ + ble_gap_evt_key_pressed_t key_pressed; /**< Key Pressed Event Parameters. */ + ble_gap_evt_auth_key_request_t auth_key_request; /**< Authentication Key Request Event Parameters. */ + ble_gap_evt_lesc_dhkey_request_t lesc_dhkey_request; /**< LE Secure Connections DHKey calculation request. */ + ble_gap_evt_auth_status_t auth_status; /**< Authentication Status Event Parameters. */ + ble_gap_evt_conn_sec_update_t conn_sec_update; /**< Connection Security Update Event Parameters. */ + ble_gap_evt_timeout_t timeout; /**< Timeout Event Parameters. */ + ble_gap_evt_rssi_changed_t rssi_changed; /**< RSSI Event Parameters. */ + ble_gap_evt_adv_report_t adv_report; /**< Advertising Report Event Parameters. */ + ble_gap_evt_sec_request_t sec_request; /**< Security Request Event Parameters. */ + ble_gap_evt_conn_param_update_request_t conn_param_update_request; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_scan_req_report_t scan_req_report; /**< Scan Request Report Parameters. */ + ble_gap_evt_phy_update_request_t phy_update_request; /**< PHY Update Request Event Parameters. */ + ble_gap_evt_phy_update_t phy_update; /**< PHY Update Parameters. */ + ble_gap_evt_data_length_update_request_t data_length_update_request; /**< Data Length Update Request Event Parameters. */ + ble_gap_evt_data_length_update_t data_length_update; /**< Data Length Update Event Parameters. */ + } params; /**< Event Parameters. */ +} ble_gap_evt_t; + + +/** + * @brief BLE GAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The connection count for the connection configurations is zero. + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - The sum of conn_count for all connection configurations combined exceeds UINT8_MAX. + * - The event length is smaller than @ref BLE_GAP_EVENT_LENGTH_MIN. + */ +typedef struct +{ + uint8_t conn_count; /**< The number of concurrent connections the application can create with this configuration. + The default and minimum value is @ref BLE_GAP_CONN_COUNT_DEFAULT. */ + uint16_t event_length; /**< The time set aside for this connection on every connection interval in 1.25 ms units. + The default value is @ref BLE_GAP_EVENT_LENGTH_DEFAULT, the minimum value is @ref BLE_GAP_EVENT_LENGTH_MIN. + The event length and the connection interval are the primary parameters + for setting the throughput of a connection. + See the SoftDevice Specification for details on throughput. */ +} ble_gap_conn_cfg_t; + + +/** + * @brief Configuration of maximum concurrent connections in the different connected roles, set with + * @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The sum of periph_role_count and central_role_count is too + * large. The maximum supported sum of concurrent connections is + * @ref BLE_GAP_ROLE_COUNT_COMBINED_MAX. + * @retval ::NRF_ERROR_INVALID_PARAM central_sec_count is larger than central_role_count. + */ +typedef struct +{ + uint8_t periph_role_count; /**< Maximum number of connections concurrently acting as a peripheral. Default value is @ref BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT. */ + uint8_t central_role_count; /**< Maximum number of connections concurrently acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT. */ + uint8_t central_sec_count; /**< Number of SMP instances shared between all connections acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT. */ +} ble_gap_cfg_role_count_t; + + +/** + * @brief Device name and its properties, set with @ref sd_ble_cfg_set. + * + * @note If the device name is not configured, the default device name will be @ref + * BLE_GAP_DEVNAME_DEFAULT, the maximum device name length will be @ref + * BLE_GAP_DEVNAME_DEFAULT_LEN, vloc will be set to @ref BLE_GATTS_VLOC_STACK and the device name + * will have no write access. + * + * @note If @ref max_len is more than @ref BLE_GAP_DEVNAME_DEFAULT_LEN and vloc is set to @ref BLE_GATTS_VLOC_STACK, + * the attribute table size must be increased to have room for the longer device name (see + * @ref sd_ble_cfg_set and @ref ble_gatts_cfg_attr_tab_size_t). + * + * @note If vloc is @ref BLE_GATTS_VLOC_STACK : + * - p_value must point to non-volatile memory (flash) or be NULL. + * - If p_value is NULL, the device name will initially be empty. + * + * @note If vloc is @ref BLE_GATTS_VLOC_USER : + * - p_value cannot be NULL. + * - If the device name is writable, p_value must point to volatile memory (RAM). + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - Invalid device name location (vloc). + * - Invalid device name security mode. + * @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true: + * - 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_NOT_SUPPORTED Device name security mode is not supported. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vloc:2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t *p_value; /**< Pointer to where the value (device name) is stored or will be stored. */ + uint16_t current_len; /**< Current length in bytes of the memory pointed to by p_value.*/ + uint16_t max_len; /**< Maximum length in bytes of the memory pointed to by p_value.*/ +} ble_gap_cfg_device_name_t; + + +/**@brief Configuration structure for GAP configurations. */ +typedef union +{ + ble_gap_cfg_role_count_t role_count_cfg; /**< Role count configuration, cfg_id is @ref BLE_GAP_CFG_ROLE_COUNT. */ + ble_gap_cfg_device_name_t device_name_cfg; /**< Device name configuration, cfg_id is @ref BLE_GAP_CFG_DEVICE_NAME. */ +} ble_gap_cfg_t; + + +/**@brief Channel Map option. + * Used with @ref sd_ble_opt_get to get the current channel map + * or @ref sd_ble_opt_set to set a new channel map. When setting the + * channel map, it applies to all current and future connections. When getting the + * current channel map, it applies to a single connection and the connection handle + * must be supplied. + * + * @note Setting the channel map may take some time, depending on connection parameters. + * The time taken may be different for each connection and the get operation will + * return the previous channel map until the new one has taken effect. + * + * @note After setting the channel map, by spec it can not be set again until at least 1 s has passed. + * See Bluetooth Specification Version 4.1 Volume 2, Part E, Section 7.3.46. + * + * @retval ::NRF_SUCCESS Get or set successful. + * @retval ::NRF_ERROR_BUSY Channel map was set again before enough time had passed. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied for get. + * @retval ::NRF_ERROR_NOT_SUPPORTED Returned by sd_ble_opt_set in peripheral-only SoftDevices. + * + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle (only applicable for get) */ + uint8_t ch_map[5]; /**< Channel Map (37-bit). */ +} ble_gap_opt_ch_map_t; + + +/**@brief Local connection latency option. + * + * Local connection latency is a feature which enables the slave to improve + * current consumption by ignoring the slave latency set by the peer. The + * local connection latency can only be set to a multiple of the slave latency, + * and cannot be longer than half of the supervision timeout. + * + * Used with @ref sd_ble_opt_set to set the local connection latency. The + * @ref sd_ble_opt_get is not supported for this option, but the actual + * local connection latency (unless set to NULL) is set as a return parameter + * when setting the option. + * + * @note The latency set will be truncated down to the closest slave latency event + * multiple, or the nearest multiple before half of the supervision timeout. + * + * @note The local connection latency is disabled by default, and needs to be enabled for new + * connections and whenever the connection is updated. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t requested_latency; /**< Requested local connection latency. */ + uint16_t * p_actual_latency; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ +} ble_gap_opt_local_conn_latency_t; + +/**@brief Disable slave latency + * + * Used with @ref sd_ble_opt_set to temporarily disable slave latency of a peripheral connection (see @ref ble_gap_conn_params_t::slave_latency). And to re-enable it again. + * When disabled, the peripheral will ignore the slave_latency set by the central. + * + * @note Shall only be called on peripheral links. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint8_t disable : 1; /**< Set to 1 to disable slave latency. Set to 0 enable it again.*/ +} ble_gap_opt_slave_latency_disable_t; + +/**@brief Passkey Option. + * + * Structure containing the passkey to be used during pairing. This can be used with @ref + * sd_ble_opt_set to make the SoftDevice use a preprogrammed passkey for authentication + * instead of generating a random one. + * + * @note Repeated pairing attempts using the same preprogrammed passkey makes pairing vulnerable to MITM attacks. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + */ +typedef struct +{ + uint8_t const * p_passkey; /**< Pointer to 6-digit ASCII string (digit 0..9 only, no NULL termination) passkey to be used during pairing. If this is NULL, the SoftDevice will generate a random passkey if required.*/ +} ble_gap_opt_passkey_t; + + +/**@brief Scan request report option. + * + * This can be used with @ref sd_ble_opt_set to make the SoftDevice send + * @ref BLE_GAP_EVT_SCAN_REQ_REPORT events. + * + * @note Due to the limited space reserved for scan request report events, + * not all received scan requests will be reported. + * + * @note If whitelisting is used, only whitelisted requests are reported. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When advertising is ongoing while the option is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable scan request reports. */ +} ble_gap_opt_scan_req_report_t; + +/**@brief Compatibility mode 1 option. + * + * This can be used with @ref sd_ble_opt_set to enable and disable + * compatibility mode 1. Compatibility mode 1 is disabled by default. + * + * @note Compatibility mode 1 enables interoperability with devices that do not support a value of + * 0 for the WinOffset parameter in the Link Layer CONNECT_IND packet. This applies to a + * limited set of legacy peripheral devices from another vendor. Enabling this compatibility + * mode will only have an effect if the local device will act as a central device and + * initiate a connection to a peripheral device. In that case it may lead to the connection + * creation taking up to one connection interval longer to complete for all connections. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When connection creation is ongoing while mode 1 is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable compatibility mode 1.*/ +} ble_gap_opt_compat_mode_1_t; + +/**@brief Authenticated payload timeout option. + * + * This can be used with @ref sd_ble_opt_set to change the Authenticated payload timeout to a value other + * than the default of @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT_MAX. + * + * @note The authenticated payload timeout event ::BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD will be generated + * if auth_payload_timeout time has elapsed without receiving a packet with a valid MIC on an encrypted + * link. + * + * @note The LE ping procedure will be initiated before the timer expires to give the peer a chance + * to reset the timer. In addition the stack will try to prioritize running of LE ping over other + * activities to increase chances of finishing LE ping before timer expires. To avoid side-effects + * on other activities, it is recommended to use high timeout values. + * Recommended timeout > 2*(connInterval * (6 + connSlaveLatency)). + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. auth_payload_timeout was outside of allowed range. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t auth_payload_timeout; /**< Requested timeout in 10 ms unit, see @ref BLE_GAP_AUTH_PAYLOAD_TIMEOUT. */ +} ble_gap_opt_auth_payload_timeout_t; + + +/**@brief Option structure for GAP options. */ +typedef union +{ + ble_gap_opt_ch_map_t ch_map; /**< Parameters for the Channel Map option. */ + ble_gap_opt_local_conn_latency_t local_conn_latency; /**< Parameters for the Local connection latency option */ + ble_gap_opt_passkey_t passkey; /**< Parameters for the Passkey option.*/ + ble_gap_opt_scan_req_report_t scan_req_report; /**< Parameters for the scan request report option.*/ + ble_gap_opt_compat_mode_1_t compat_mode_1; /**< Parameters for the compatibility mode 1 option.*/ + ble_gap_opt_auth_payload_timeout_t auth_payload_timeout; /**< Parameters for the authenticated payload timeout option.*/ + ble_gap_opt_slave_latency_disable_t slave_latency_disable; /**< Parameters for the Disable slave latency option */ +} ble_gap_opt_t; +/**@} */ + + +/**@addtogroup BLE_GAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set the local Bluetooth identity address. + * + * The local Bluetooth identity address is the address that identifies this device to other peers. + * The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @note The identity address cannot be changed while advertising, scanning or creating a connection. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the ability to + * reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC upon being + * enabled. The address is a random number populated during the IC manufacturing process and remains unchanged + * for the lifetime of each IC. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @param[in] p_addr Pointer to address structure. + * + * @retval ::NRF_SUCCESS Address successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, + * scanning or creating a connection. + */ +SVCALL(SD_BLE_GAP_ADDR_SET, uint32_t, sd_ble_gap_addr_set(ble_gap_addr_t const *p_addr)); + + +/**@brief Get local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval ::NRF_SUCCESS Address successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + */ +SVCALL(SD_BLE_GAP_ADDR_GET, uint32_t, sd_ble_gap_addr_get(ble_gap_addr_t *p_addr)); + + +/**@brief Set the active whitelist in the SoftDevice. + * + * @note Only one whitelist can be used at a time and the whitelist is shared between the BLE roles. + * The whitelist cannot be set if a BLE role is using the whitelist. + * + * @note If an address is resolved using the information in the device identity list, then the whitelist + * filter policy applies to the peer identity address and not the resolvable address sent on air. + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @endmscs + * + * @param[in] pp_wl_addrs Pointer to a whitelist of peer addresses, if NULL the whitelist will be cleared. + * @param[in] len Length of the whitelist, maximum @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * + * @retval ::NRF_SUCCESS The whitelist is successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The whitelist (or one of its entries) provided is invalid. + * @retval ::BLE_ERROR_GAP_WHITELIST_IN_USE The whitelist is in use by a BLE role and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given whitelist size is invalid (zero or too large); this can only return when + * pp_wl_addrs is not NULL. + */ +SVCALL(SD_BLE_GAP_WHITELIST_SET, uint32_t, sd_ble_gap_whitelist_set(ble_gap_addr_t const * const * pp_wl_addrs, uint8_t len)); + + +/**@brief Set device identity list. + * + * @note Only one device identity list can be used at a time and the list is shared between the BLE roles. + * The device identity list cannot be set if a BLE role is using the list. + * + * @param[in] pp_id_keys Pointer to an array of peer identity addresses and peer IRKs, if NULL the device identity list will be cleared. + * @param[in] pp_local_irks Pointer to an array of local IRKs. Each entry in the array maps to the entry in pp_id_keys at the same index. + * To fill in the list with the currently set device IRK for all peers, set to NULL. + * @param[in] len Length of the device identity list, maximum @ref BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The device identity list successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The device identity list (or one of its entries) provided is invalid. + * This code may be returned if the local IRK list also has an invalid entry. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE The device identity list is in use and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE The device identity list contains multiple entries with the same identity address. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given device identity list size invalid (zero or too large); this can + * only return when pp_id_keys is not NULL. + */ +SVCALL(SD_BLE_GAP_DEVICE_IDENTITIES_SET, uint32_t, sd_ble_gap_device_identities_set(ble_gap_id_key_t const * const * pp_id_keys, ble_gap_irk_t const * const * pp_local_irks, uint8_t len)); + + +/**@brief Set privacy settings. + * + * @note Privacy settings cannot be changed while advertising, scanning or creating a connection. + * + * @param[in] p_privacy_params Privacy settings. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer to privacy settings is NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + * @retval ::NRF_ERROR_INVALID_PARAM Out of range parameters are provided. + * @retval ::NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while advertising, scanning + * or creating a connection. + */ +SVCALL(SD_BLE_GAP_PRIVACY_SET, uint32_t, sd_ble_gap_privacy_set(ble_gap_privacy_params_t const *p_privacy_params)); + + +/**@brief Get privacy settings. + * + * @note ::ble_gap_privacy_params_t::p_device_irk must be initialized to NULL or a valid address before this function is called. + * If it is initialized to a valid address, the address pointed to will contain the current device IRK on return. + * + * @param[in,out] p_privacy_params Privacy settings. + * + * @retval ::NRF_SUCCESS Privacy settings read. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer given for returning the privacy settings may be NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + */ +SVCALL(SD_BLE_GAP_PRIVACY_GET, uint32_t, sd_ble_gap_privacy_get(ble_gap_privacy_params_t *p_privacy_params)); + + +/**@brief Set, clear or update advertising and scan response data. + * + * @note The format of the advertising data will be checked by this call to ensure interoperability. + * Limitations imposed by this API call to the data provided include having a flags data type in the scan response data and + * duplicating the local name in the advertising data and scan response data. + * + * @note To clear the advertising data and set it to a 0-length packet, simply provide a valid pointer (p_data/p_sr_data) with its corresponding + * length (dlen/srdlen) set to 0. + * + * @note The call will fail if p_data and p_sr_data are both NULL since this would have no effect. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_data Raw data to be placed in advertising packet. If NULL, no changes are made to the current advertising packet data. + * @param[in] dlen Data length for p_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_data is NULL, can be 0 if p_data is not NULL. + * @param[in] p_sr_data Raw data to be placed in scan response packet. If NULL, no changes are made to the current scan response packet data. + * @param[in] srdlen Data length for p_sr_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_sr_data is NULL, can be 0 if p_data is not NULL. + * + * @retval ::NRF_SUCCESS Advertising data successfully updated or cleared. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, both p_data and p_sr_data cannot be NULL. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_FLAGS Invalid combination of advertising flags supplied. + * @retval ::NRF_ERROR_INVALID_DATA Invalid data type(s) supplied, check the advertising data format specification. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid data length(s) supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported data type. + * @retval ::BLE_ERROR_GAP_UUID_LIST_MISMATCH Invalid UUID list supplied. + */ +SVCALL(SD_BLE_GAP_ADV_DATA_SET, uint32_t, sd_ble_gap_adv_data_set(uint8_t const *p_data, uint8_t dlen, uint8_t const *p_sr_data, uint8_t srdlen)); + + +/**@brief Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @note Only one advertiser may be active at any time. + * + * @events + * @event{@ref BLE_GAP_EVT_CONNECTED, Generated after connection has been established through connectable advertising.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Advertisement has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_adv_params Pointer to advertising parameters structure. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or @ref + * BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. If + * @ref ble_gap_adv_params_t::type is @ref BLE_GAP_ADV_TYPE_ADV_NONCONN_IND, + * this is ignored. + * + * @retval ::NRF_SUCCESS The BLE stack has started advertising. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections has been reached; connectable advertiser cannot be started. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check the accepted ranges and limits. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Bluetooth address supplied. + * @retval ::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST Discoverable mode and whitelist incompatible. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Observer) and try again + */ +SVCALL(SD_BLE_GAP_ADV_START, uint32_t, sd_ble_gap_adv_start(ble_gap_adv_params_t const *p_adv_params, uint8_t conn_cfg_tag)); + + +/**@brief Stop advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The BLE stack has stopped advertising. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (most probably not in advertising state). + */ +SVCALL(SD_BLE_GAP_ADV_STOP, uint32_t, sd_ble_gap_adv_stop(void)); + + + +/**@brief Update connection parameters. + * + * @details In the central role this will initiate a Link Layer connection parameter update procedure, + * otherwise in the peripheral role, this will send the corresponding L2CAP request and wait for + * the central to perform the procedure. In both cases, and regardless of success or failure, the application + * will be informed of the result with a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE event. + * + * @details This function can be used as a central both to reply to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST or to start the procedure unrequested. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_PARAM_UPDATE, Result of the connection parameter update procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CPU_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CPU_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CPU_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_conn_params Pointer to desired connection parameters. If NULL is provided on a peripheral role, + * the parameters in the PPCP characteristic of the GAP service will be used instead. + * If NULL is provided on a central role and in response to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request will be rejected + * + * @retval ::NRF_SUCCESS The Connection Update procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY Procedure already in progress, wait for pending procedures to complete and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GAP_CONN_PARAM_UPDATE, uint32_t, sd_ble_gap_conn_param_update(uint16_t conn_handle, ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Disconnect (GAP Link Termination). + * + * @details This call initiates the disconnection procedure, and its completion will be communicated to the application + * with a @ref BLE_GAP_EVT_DISCONNECTED event. + * + * @events + * @event{@ref BLE_GAP_EVT_DISCONNECTED, Generated when disconnection procedure is complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CONN_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] hci_status_code HCI status code, see @ref BLE_HCI_STATUS_CODES (accepted values are @ref BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION and @ref BLE_HCI_CONN_INTERVAL_UNACCEPTABLE). + * + * @retval ::NRF_SUCCESS The disconnection procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (disconnection is already in progress). + */ +SVCALL(SD_BLE_GAP_DISCONNECT, uint32_t, sd_ble_gap_disconnect(uint16_t conn_handle, uint8_t hci_status_code)); + + +/**@brief Set the radio's transmit power. + * + * @param[in] tx_power Radio transmit power in dBm (accepted values are -40, -20, -16, -12, -8, -4, 0, 3, and 4 dBm). + * + * @retval ::NRF_SUCCESS Successfully changed the transmit power. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_TX_POWER_SET, uint32_t, sd_ble_gap_tx_power_set(int8_t tx_power)); + + +/**@brief Set GAP Appearance value. + * + * @param[in] appearance Appearance (16-bit), see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_SET, uint32_t, sd_ble_gap_appearance_set(uint16_t appearance)); + + +/**@brief Get GAP Appearance value. + * + * @param[out] p_appearance Pointer to appearance (16-bit) to be filled in, see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_GET, uint32_t, sd_ble_gap_appearance_get(uint16_t *p_appearance)); + + +/**@brief Set GAP Peripheral Preferred Connection Parameters. + * + * @param[in] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure with the desired parameters. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_SET, uint32_t, sd_ble_gap_ppcp_set(ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Get GAP Peripheral Preferred Connection Parameters. + * + * @param[out] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure where the parameters will be stored. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_GET, uint32_t, sd_ble_gap_ppcp_get(ble_gap_conn_params_t *p_conn_params)); + + +/**@brief Set GAP device name. + * + * @note If the device name is located in application flash memory (see @ref ble_gap_cfg_device_name_t), + * it cannot be changed. Then @ref NRF_ERROR_FORBIDDEN will be returned. + * + * @param[in] p_write_perm Write permissions for the Device Name characteristic, see @ref ble_gap_conn_sec_mode_t. + * @param[in] p_dev_name Pointer to a UTF-8 encoded, non NULL-terminated string. + * @param[in] len Length of the UTF-8, non NULL-terminated string pointed to by p_dev_name in octets (must be smaller or equal than @ref BLE_GAP_DEVNAME_MAX_LEN). + * + * @retval ::NRF_SUCCESS GAP device name and permissions set successfully. + * @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_FORBIDDEN Device name is not writable. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len)); + + +/**@brief Get GAP device name. + * + * @note If the device name is longer than the size of the supplied buffer, + * p_len will return the complete device name length, + * and not the number of bytes actually returned in p_dev_name. + * The application may use this information to allocate a suitable buffer size. + * + * @param[out] p_dev_name Pointer to an empty buffer where the UTF-8 non NULL-terminated string will be placed. Set to NULL to obtain the complete device name length. + * @param[in,out] p_len Length of the buffer pointed by p_dev_name, complete device name length on output. + * + * @retval ::NRF_SUCCESS GAP device name retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_GET, uint32_t, sd_ble_gap_device_name_get(uint8_t *p_dev_name, uint16_t *p_len)); + + +/**@brief Initiate the GAP Authentication procedure. + * + * @details In the central role, this function will send an SMP Pairing Request (or an SMP Pairing Failed if rejected), + * otherwise in the peripheral role, an SMP Security Request will be sent. + * + * @events + * @event{Depending on the security parameters set and the packet exchanges with the peer\, the following events may be generated:} + * @event{@ref BLE_GAP_EVT_SEC_PARAMS_REQUEST} + * @event{@ref BLE_GAP_EVT_SEC_INFO_REQUEST} + * @event{@ref BLE_GAP_EVT_PASSKEY_DISPLAY} + * @event{@ref BLE_GAP_EVT_KEY_PRESSED} + * @event{@ref BLE_GAP_EVT_AUTH_KEY_REQUEST} + * @event{@ref BLE_GAP_EVT_LESC_DHKEY_REQUEST} + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE} + * @event{@ref BLE_GAP_EVT_AUTH_STATUS} + * @event{@ref BLE_GAP_EVT_TIMEOUT} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_sec_params Pointer to the @ref ble_gap_sec_params_t structure with the security parameters to be used during the pairing or bonding procedure. + * In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. + * In the central role, this pointer may be NULL to reject a Security Request. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_NO_MEM The maximum number of authentication procedures that can run in parallel for the given role is reached. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + * @retval ::NRF_ERROR_TIMEOUT A SMP timeout has occurred, and further SMP operations on this link is prohibited. + */ +SVCALL(SD_BLE_GAP_AUTHENTICATE, uint32_t, sd_ble_gap_authenticate(uint16_t conn_handle, ble_gap_sec_params_t const *p_sec_params)); + + +/**@brief Reply with GAP security parameters. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_CONFIRM_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_KS_TOO_SMALL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_APP_ERROR_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_REMOTE_PAIRING_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_TIMEOUT_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] sec_status Security status, see @ref BLE_GAP_SEC_STATUS. + * @param[in] p_sec_params Pointer to a @ref ble_gap_sec_params_t security parameters structure. In the central role this must be set to NULL, as the parameters have + * already been provided during a previous call to @ref sd_ble_gap_authenticate. + * @param[in,out] p_sec_keyset Pointer to a @ref ble_gap_sec_keyset_t security keyset structure. Any keys generated and/or distributed as a result of the ongoing security procedure + * will be stored into the memory referenced by the pointers inside this structure. The keys will be stored and available to the application + * upon reception of a @ref BLE_GAP_EVT_AUTH_STATUS event. + * Note that the SoftDevice expects the application to provide memory for storing the + * peer's keys. So it must be ensured that the relevant pointers inside this structure are not NULL. The pointers to the local key + * can, however, be NULL, in which case, the local key data will not be available to the application upon reception of the + * @ref BLE_GAP_EVT_AUTH_STATUS event. + * + * @retval ::NRF_SUCCESS Successfully accepted security parameter from the application. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + */ +SVCALL(SD_BLE_GAP_SEC_PARAMS_REPLY, uint32_t, sd_ble_gap_sec_params_reply(uint16_t conn_handle, uint8_t sec_status, ble_gap_sec_params_t const *p_sec_params, ble_gap_sec_keyset_t const *p_sec_keyset)); + + +/**@brief Reply with an authentication key. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_AUTH_KEY_REQUEST or a @ref BLE_GAP_EVT_PASSKEY_DISPLAY, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] key_type See @ref BLE_GAP_AUTH_KEY_TYPES. + * @param[in] p_key If key type is @ref BLE_GAP_AUTH_KEY_TYPE_NONE, then NULL. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY, then a 6-byte ASCII string (digit 0..9 only, no NULL termination) + * or NULL when confirming LE Secure Connections Numeric Comparison. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_OOB, then a 16-byte OOB key value in little-endian format. + * + * @retval ::NRF_SUCCESS Authentication key successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_AUTH_KEY_REPLY, uint32_t, sd_ble_gap_auth_key_reply(uint16_t conn_handle, uint8_t key_type, uint8_t const *p_key)); + +/**@brief Reply with an LE Secure connections DHKey. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dhkey LE Secure Connections DHKey. + * + * @retval ::NRF_SUCCESS DHKey successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_DHKEY_REPLY, uint32_t, sd_ble_gap_lesc_dhkey_reply(uint16_t conn_handle, ble_gap_lesc_dhkey_t const *p_dhkey)); + +/**@brief Notify the peer of a local keypress. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] kp_not See @ref BLE_GAP_KP_NOT_TYPES. + * + * @retval ::NRF_SUCCESS Keypress notification successfully queued for transmission. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either not entering a passkey or keypresses have not been enabled by both peers. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy. Retry at later time. + */ +SVCALL(SD_BLE_GAP_KEYPRESS_NOTIFY, uint32_t, sd_ble_gap_keypress_notify(uint16_t conn_handle, uint8_t kp_not)); + +/**@brief Generate a set of OOB data to send to a peer out of band. + * + * @note The @ref ble_gap_addr_t included in the OOB data returned will be the currently active one (or, if a connection has already been established, + * the one used during connection setup). The application may manually overwrite it with an updated value. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. Can be BLE_CONN_HANDLE_INVALID if a BLE connection has not been established yet. + * @param[in] p_pk_own LE Secure Connections local P-256 Public Key. + * @param[out] p_oobd_own The OOB data to be sent out of band to a peer. + * + * @retval ::NRF_SUCCESS OOB data successfully generated. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_GET, uint32_t, sd_ble_gap_lesc_oob_data_get(uint16_t conn_handle, ble_gap_lesc_p256_pk_t const *p_pk_own, ble_gap_lesc_oob_data_t *p_oobd_own)); + +/**@brief Provide the OOB data sent/received out of band. + * + * @note An authentication procedure with OOB selected as an algorithm must be in progress when calling this function. + * @note A @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST event with the oobd_req set to 1 must have been received prior to calling this function. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_oobd_own The OOB data sent out of band to a peer or NULL if the peer has not received OOB data. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. + * @param[in] p_oobd_peer The OOB data received out of band from a peer or NULL if none received. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref sd_ble_gap_authenticate in the central role + * or @ref sd_ble_gap_sec_params_reply in the peripheral role. + * + * @retval ::NRF_SUCCESS OOB data accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_SET, uint32_t, sd_ble_gap_lesc_oob_data_set(uint16_t conn_handle, ble_gap_lesc_oob_data_t const *p_oobd_own, ble_gap_lesc_oob_data_t const *p_oobd_peer)); + +/**@brief Initiate GAP Encryption procedure. + * + * @details In the central role, this function will initiate the encryption procedure using the encryption information provided. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE, The connection security has been updated.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_master_id Pointer to a @ref ble_gap_master_id_t master identification structure. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::BLE_ERROR_INVALID_ROLE Operation is not supported in the Peripheral role. + * @retval ::NRF_ERROR_BUSY Procedure already in progress or not allowed at this time, wait for pending procedures to complete and retry. + */ +SVCALL(SD_BLE_GAP_ENCRYPT, uint32_t, sd_ble_gap_encrypt(uint16_t conn_handle, ble_gap_master_id_t const *p_master_id, ble_gap_enc_info_t const *p_enc_info)); + + +/**@brief Reply with GAP security information. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_INFO_REQUEST, calling it at other times will result in @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * @note Data signing is not yet supported, and p_sign_info must therefore be NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_ENC_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. May be NULL to signal none is available. + * @param[in] p_id_info Pointer to a @ref ble_gap_irk_t identity information structure. May be NULL to signal none is available. + * @param[in] p_sign_info Pointer to a @ref ble_gap_sign_info_t signing information structure. May be NULL to signal none is available. + * + * @retval ::NRF_SUCCESS Successfully accepted security information. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_SEC_INFO_REPLY, uint32_t, sd_ble_gap_sec_info_reply(uint16_t conn_handle, ble_gap_enc_info_t const *p_enc_info, ble_gap_irk_t const *p_id_info, ble_gap_sign_info_t const *p_sign_info)); + + +/**@brief Get the current connection security. + * + * @param[in] conn_handle Connection handle. + * @param[out] p_conn_sec Pointer to a @ref ble_gap_conn_sec_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Current connection security successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_CONN_SEC_GET, uint32_t, sd_ble_gap_conn_sec_get(uint16_t conn_handle, ble_gap_conn_sec_t *p_conn_sec)); + + +/**@brief Start reporting the received signal strength to the application. + * + * A new event is reported whenever the RSSI value changes, until @ref sd_ble_gap_rssi_stop is called. + * + * @events + * @event{@ref BLE_GAP_EVT_RSSI_CHANGED, New RSSI data available. How often the event is generated is + * dependent on the settings of the threshold_dbm + * and skip_count input parameters.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] threshold_dbm Minimum change in dBm before triggering the @ref BLE_GAP_EVT_RSSI_CHANGED event. Events are disabled if threshold_dbm equals @ref BLE_GAP_RSSI_THRESHOLD_INVALID. + * @param[in] skip_count Number of RSSI samples with a change of threshold_dbm or more before sending a new @ref BLE_GAP_EVT_RSSI_CHANGED event. + * + * @retval ::NRF_SUCCESS Successfully activated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Disconnection in progress. Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_START, uint32_t, sd_ble_gap_rssi_start(uint16_t conn_handle, uint8_t threshold_dbm, uint8_t skip_count)); + + +/**@brief Stop reporting the received signal strength. + * + * @note An RSSI change detected before the call but not yet received by the application + * may be reported after @ref sd_ble_gap_rssi_stop has been called. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * + * @retval ::NRF_SUCCESS Successfully deactivated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_STOP, uint32_t, sd_ble_gap_rssi_stop(uint16_t conn_handle)); + + +/**@brief Get the received signal strength for the last connection event. + * + * @ref sd_ble_gap_rssi_start must be called to start reporting RSSI before using this function. @ref NRF_ERROR_NOT_FOUND + * will be returned until RSSI was sampled for the first time after calling @ref sd_ble_gap_rssi_start. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[out] p_rssi Pointer to the location where the RSSI measurement shall be stored. + * + * @retval ::NRF_SUCCESS Successfully read the RSSI. + * @retval ::NRF_ERROR_NOT_FOUND No sample is available. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is not ongoing, or disconnection in progress. + */ +SVCALL(SD_BLE_GAP_RSSI_GET, uint32_t, sd_ble_gap_rssi_get(uint16_t conn_handle, int8_t *p_rssi)); + + +/**@brief Start scanning (GAP Discovery procedure, Observer Procedure). + * + * @events + * @event{@ref BLE_GAP_EVT_ADV_REPORT, An advertising or scan response packet has been received.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Scanner has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_scan_params Pointer to scan parameters structure. + * + * @retval ::NRF_SUCCESS Successfully initiated scanning procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_SCAN_START, uint32_t, sd_ble_gap_scan_start(ble_gap_scan_params_t const *p_scan_params)); + + +/**@brief Stop scanning (GAP Discovery procedure, Observer Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully stopped scanning procedure. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (most probably not in scanning state). + */ +SVCALL(SD_BLE_GAP_SCAN_STOP, uint32_t, sd_ble_gap_scan_stop(void)); + + +/**@brief Create a connection (GAP Link Establishment). + * + * @note If a scanning procedure is currently in progress it will be automatically stopped when calling this function. + * The scanning procedure will be stopped even if the function returns an error. + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @param[in] p_peer_addr Pointer to peer address. If the use_whitelist bit is set in @ref ble_gap_scan_params_t, then this is ignored. + * @param[in] p_scan_params Pointer to scan parameters structure. + * @param[in] p_conn_params Pointer to desired connection parameters. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or @ref + * BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. + * + * @retval ::NRF_SUCCESS Successfully initiated connection procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid parameter(s) pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * - Invalid parameter(s) in p_scan_params or p_conn_params. + * - Use of whitelist requested but whitelist has not been set, see @ref sd_ble_gap_whitelist_set. + * - Peer address was not present in the device identity list, see @ref sd_ble_gap_device_identities_set. + * @retval ::NRF_ERROR_INVALID_STATE The SoftDevice is in an invalid state to perform this operation. This may be due to an + * existing locally initiated connect procedure, which must complete before initiating again. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Peer address. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections has been reached. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_CONNECT, uint32_t, sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params, uint8_t conn_cfg_tag)); + + +/**@brief Cancel a connection establishment. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully canceled an ongoing connection procedure. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + */ +SVCALL(SD_BLE_GAP_CONNECT_CANCEL, uint32_t, sd_ble_gap_connect_cancel(void)); + + +/**@brief Initiate or respond to a PHY Update Procedure + * + * @details This function is used to initiate or respond to a PHY Update Procedure. It will always generate a + * @ref BLE_GAP_EVT_PHY_UPDATE event if successfully executed. If @ref ble_gap_phys_t::tx_phys or @ref ble_gap_phys_t::rx_phys + * is @ref BLE_GAP_PHY_AUTO, then the stack will select a PHY for the respective direction based on the peer's PHY preferences + * and the local stack configuration. If the peer does not support the PHY Update Procedure, then the + * resulting @ref BLE_GAP_EVT_PHY_UPDATE event will have a status set to + * @ref BLE_HCI_UNSUPPORTED_REMOTE_FEATURE. + * If the PHY procedure was rejected by the peer due to a procedure collision, the status will be + * @ref BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION or @ref BLE_HCI_DIFFERENT_TRANSACTION_COLLISION. + * If the peer responds to the PHY Update procedure with invalid parameters, the status will be @ref BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS. + * If the PHY procedure was rejected by the peer for a different reason, the status will contain the reason as specified by the peer. + * + * @events + * @event{@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update Procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_PHY_UPDATE} + * @mmsc{@ref BLE_GAP_PERIPHERAL_PHY_UPDATE} + * @endmscs + * + * @param[in] conn_handle Connection handle to indicate the connection for which the PHY Update is requested. + * @param[in] p_gap_phys Pointer to PHY structure. + * + * @retval ::NRF_SUCCESS Successfully requested a PHY Update. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Unsupported PHYs supplied to the call. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY Procedure is already in progress or not allowed at this time. Process pending events and wait for the pending procedure to complete and retry. + * + */ +SVCALL(SD_BLE_GAP_PHY_UPDATE, uint32_t, sd_ble_gap_phy_update(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys)); + +/**@brief Initiate or respond to a Data Length Update Procedure. + * + * @note Only symmetric input parameters for the Data Length Update is supported. Only @ref + * BLE_GAP_DATA_LENGTH_AUTO for max_tx_time_us and max_rx_time_us is supported. + * + * @note If the application uses @ref BLE_GAP_DATA_LENGTH_AUTO for one or more members of + * p_dl_params, the SoftDevice will choose the highest value supported in current + * configuration and connection parameters. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dl_params Pointer to local parameters to be used in Data Length Update + * Procedure. Set any member to @ref BLE_GAP_DATA_LENGTH_AUTO to let + * the SoftDevice automatically decide the value for that member. + * Set to NULL to use automatic values for all members. + * @param[out] p_dl_limitation Pointer to limitation to be written when local device does not + * have enough resources to accommodate the requested Data Length + * Update parameters. Ignored if NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_DATA_LENGTH_UPDATE_PROCEDURE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully set Data Length Extension initiation/response parameters. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED The requested parameters are not supported by the SoftDevice. + * @retval ::NRF_ERROR_RESOURCES The requested parameters can not be accommodated. Inspect + * p_dl_limitation so see where the limitation is. + * @retval ::NRF_ERROR_BUSY Peer has already initiated a Data Length Update Procedure. Process the + * pending @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event to respond. + */ +SVCALL(SD_BLE_GAP_DATA_LENGTH_UPDATE, uint32_t, sd_ble_gap_data_length_update(uint16_t conn_handle, ble_gap_data_length_params_t const *p_dl_params, ble_gap_data_length_limitation_t *p_dl_limitation)); + + + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GAP_H__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatt.h new file mode 100644 index 0000000000..4e054cf5c3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatt.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 ATT MTU, in bytes. */ +#define BLE_GATT_ATT_MTU_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 Authorization. */ +#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 connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval NRF_ERROR_INVALID_PARAM att_mtu is smaller than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +typedef struct +{ + uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive. + The default and minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + @mscs + @mmsc{@ref BLE_GATTC_MTU_EXCHANGE} + @mmsc{@ref BLE_GATTS_MTU_EXCHANGE} + @endmscs + */ +} ble_gatt_conn_cfg_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; /**< Notification 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gattc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gattc.h new file mode 100644 index 0000000000..191f3a85ea --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gattc.h @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. */ + BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE /**< Write without Response transmission complete. \n See @ref ble_gattc_evt_write_cmd_tx_complete_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. */ +/** @} */ + +/** @defgroup BLE_GATTC_DEFAULTS GATT Client defaults + * @{ */ +#define BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Write without Response that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTC_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTC connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t write_cmd_tx_queue_size; /**< The guaranteed minimum number of Write without Response that can be queued for transmission. + The default value is @ref BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT */ +} ble_gattc_conn_cfg_t; + +/**@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 Event structure for @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of write without response transmissions completed. */ +} ble_gattc_evt_write_cmd_tx_complete_t; + +/**@brief GATTC event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + 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. */ + ble_gattc_evt_write_cmd_tx_complete_t write_cmd_tx_complete; /**< Write without Response transmission complete 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 Only one write with response procedure can be ongoing per connection at a time. + * If the application tries to write with response while another write with response procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTC_EVT_WRITE_RSP event will be issued as soon as the write response arrives from the peer. + * + * @note The number of Write without Response that can be queued is configured by @ref ble_gattc_conn_cfg_t::write_cmd_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event will be issued as soon as the transmission of the write without response is complete. + * + * @note The application can keep track of the available queue element count for writes without responses by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE, Write without response transmission complete.} + * @event{@ref BLE_GATTC_EVT_WRITE_RSP, Write response received from the peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_WITHOUT_RESP_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_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 For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry. + * @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued. + * Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry. + */ +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_ATT_MTU_DEFAULT. + * + * @events + * @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP} + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - 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__ */ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatts.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatts.h new file mode 100644 index 0000000000..5e8615c05d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_gatts.h @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. \n 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 respond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */ + BLE_GATTS_EVT_HVN_TX_COMPLETE /**< Handle Value Notification transmission complete. \n See @ref ble_gatts_evt_hvn_tx_complete_t. */ +}; + +/**@brief GATTS Configuration IDs. + * + * IDs that uniquely identify a GATTS configuration. + */ +enum BLE_GATTS_CFGS +{ + BLE_GATTS_CFG_SERVICE_CHANGED = BLE_GATTS_CFG_BASE, /**< Service changed configuration. */ + BLE_GATTS_CFG_ATTR_TAB_SIZE, /**< Attribute table size configuration. */ +}; + +/** @} */ + +/** @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_SERVICE_CHANGED Service Changed Inclusion Values + * @{ + */ +#define BLE_GATTS_SERVICE_CHANGED_DEFAULT (1) /**< Default is to include the Service Changed characteristic in the Attribute Table. */ +/** @} */ + +/** @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 (1408) /**< Default Attribute Table size. */ +/** @} */ + +/** @defgroup BLE_GATTS_DEFAULTS GATT Server defaults + * @{ + */ +#define BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Handle Value Notifications that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTS_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTS connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t hvn_tx_queue_size; /**< Minimum guaranteed number of Handle Value Notifications that can be queued for transmission. + The default value is @ref BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT */ +} ble_gatts_conn_cfg_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 const *p_uuid; /**< Pointer to the attribute UUID. */ + ble_gatts_attr_md_t const *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 const *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 const *p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */ + ble_gatts_attr_md_t const *p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *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 const *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. */ + uint8_t const *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 Service Changed Inclusion configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t service_changed : 1; /**< If 1, include the Service Changed characteristic in the Attribute Table. Default is @ref BLE_GATTS_SERVICE_CHANGED_DEFAULT. */ +} ble_gatts_cfg_service_changed_t; + +/**@brief Attribute table size configuration parameters, set with @ref sd_ble_cfg_set. + * + * @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. + */ +typedef struct +{ + uint32_t attr_tab_size; /**< Attribute table size. Default is @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, minimum is @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. */ +} ble_gatts_cfg_attr_tab_size_t; + +/**@brief Config structure for GATTS configurations. */ +typedef union +{ + ble_gatts_cfg_service_changed_t service_changed; /**< Include service changed characteristic, cfg_id is @ref BLE_GATTS_CFG_SERVICE_CHANGED. */ + ble_gatts_cfg_attr_tab_size_t attr_tab_size; /**< Attribute table size, cfg_id is @ref BLE_GATTS_CFG_ATTR_TAB_SIZE. */ +} ble_gatts_cfg_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 finalize 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 Event structure for @ref BLE_GATTS_EVT_HVN_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of notification transmissions completed. */ +} ble_gatts_evt_hvn_tx_complete_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. */ + ble_gatts_evt_hvn_tx_complete_t hvn_tx_complete; /**< Handle Value Notification transmission complete Event Parameters. */ + } 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 writable auxiliaries bits, + * readable (no security) and writable (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 whether 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. + * + * @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 NRF_ERROR_RESOURCES. + * The caller can check whether the value has been updated by looking at the contents of *(p_hvx_params->p_len). + * + * @note Only one indication procedure can be ongoing per connection at a time. + * If the application tries to indicate an attribute value while another indication procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from the peer. + * + * @note The number of Handle Value Notifications that can be queued is configured by @ref ble_gatts_conn_cfg_t::hvn_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event will be issued as soon as the transmission of the notification is complete. + * + * @note The application can keep track of the available queue element count for notifications by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTS_EVT_HVN_TX_COMPLETE, Notification transmission complete.} + * @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from the 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} + * @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 For @ref BLE_GATT_HVX_INDICATION Procedure already in progress. Wait for a @ref BLE_GATTS_EVT_HVC event and retry. + * @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 ::NRF_ERROR_RESOURCES Too many notifications queued. + * Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry. + */ +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_cfg_set and @ref ble_gatts_cfg_service_changed_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_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_BUSY The stack is busy, process pending events and retry. + * @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. + */ +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. + */ +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 persistently 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. Unconditionally 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_ATT_MTU_DEFAULT. + * + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - 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. + */ +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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_hci.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_hci.h new file mode 100644 index 0000000000..f0dde9a03a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_hci.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +*/ +#define BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE 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 Advertisement 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_l2cap.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_l2cap.h new file mode 100644 index 0000000000..3b53ded092 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_l2cap.h @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_TERMINOLOGY Terminology + * @{ + * @details + * + * L2CAP SDU + * - A data unit that the application can send/receive to/from a peer. + * + * L2CAP PDU + * - A data unit that is exchanged between local and remote L2CAP entities. + * It consists of L2CAP protocol control information and payload fields. + * The payload field can contain an L2CAP SDU or a part of an L2CAP SDU. + * + * L2CAP MTU + * - The maximum length of an L2CAP SDU. + * + * L2CAP MPS + * - The maximum length of an L2CAP PDU payload field. + * + * Credits + * - A value indicating the number of L2CAP PDUs that the receiver of the credit can send to the peer. + * @} */ + +/**@addtogroup BLE_L2CAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief L2CAP API SVC numbers. */ +enum BLE_L2CAP_SVCS +{ + SD_BLE_L2CAP_CH_SETUP = BLE_L2CAP_SVC_BASE, /**< Set up an L2CAP channel. */ + SD_BLE_L2CAP_CH_RELEASE, /**< Release an L2CAP channel. */ + SD_BLE_L2CAP_CH_RX, /**< Receive an SDU on an L2CAP channel. */ + SD_BLE_L2CAP_CH_TX, /**< Transmit an SDU on an L2CAP channel. */ + SD_BLE_L2CAP_CH_FLOW_CONTROL, /**< Advanced SDU reception flow control. */ +}; + +/**@brief L2CAP Event IDs. */ +enum BLE_L2CAP_EVTS +{ + BLE_L2CAP_EVT_CH_SETUP_REQUEST = BLE_L2CAP_EVT_BASE, /**< L2CAP Channel Setup Request event. + \n See @ref ble_l2cap_evt_ch_setup_request_t. */ + BLE_L2CAP_EVT_CH_SETUP_REFUSED, /**< L2CAP Channel Setup Refused event. + \n See @ref ble_l2cap_evt_ch_setup_refused_t. */ + BLE_L2CAP_EVT_CH_SETUP, /**< L2CAP Channel Setup Completed event. + \n See @ref ble_l2cap_evt_ch_setup_t. */ + BLE_L2CAP_EVT_CH_RELEASED, /**< L2CAP Channel Released event. + \n No additional event structure applies. */ + BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED, /**< L2CAP Channel SDU data buffer released event. + \n See @ref ble_l2cap_evt_ch_sdu_buf_released_t. */ + BLE_L2CAP_EVT_CH_CREDIT, /**< L2CAP Channel Credit received. + \n See @ref ble_l2cap_evt_ch_credit_t. */ + BLE_L2CAP_EVT_CH_RX, /**< L2CAP Channel SDU received. + \n See @ref ble_l2cap_evt_ch_rx_t. */ + BLE_L2CAP_EVT_CH_TX, /**< L2CAP Channel SDU transmitted. + \n See @ref ble_l2cap_evt_ch_tx_t. */ +}; + +/** @} */ + +/**@addtogroup BLE_L2CAP_DEFINES Defines + * @{ */ + +/**@brief Maximum number of L2CAP channels per connection. */ +#define BLE_L2CAP_CH_COUNT_MAX (64) + +/**@brief Minimum L2CAP MTU, in bytes. */ +#define BLE_L2CAP_MTU_MIN (23) + +/**@brief Minimum L2CAP MPS, in bytes. */ +#define BLE_L2CAP_MPS_MIN (23) + +/**@brief Invalid CID. */ +#define BLE_L2CAP_CID_INVALID (0x0000) + +/**@brief Default number of credits for @ref sd_ble_l2cap_ch_flow_control. */ +#define BLE_L2CAP_CREDITS_DEFAULT (1) + +/**@defgroup BLE_L2CAP_CH_SETUP_REFUSED_SRCS L2CAP channel setup refused sources + * @{ */ +#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_LOCAL (0x01) /**< Local. */ +#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_REMOTE (0x02) /**< Remote. */ + /** @} */ + + /** @defgroup BLE_L2CAP_CH_STATUS_CODES L2CAP channel status codes + * @{ */ +#define BLE_L2CAP_CH_STATUS_CODE_SUCCESS (0x0000) /**< Success. */ +#define BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED (0x0002) /**< LE_PSM not supported. */ +#define BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES (0x0004) /**< No resources available. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHENTICATION (0x0005) /**< Insufficient authentication. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHORIZATION (0x0006) /**< Insufficient authorization. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC_KEY_SIZE (0x0007) /**< Insufficient encryption key size. */ +#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC (0x0008) /**< Insufficient encryption. */ +#define BLE_L2CAP_CH_STATUS_CODE_INVALID_SCID (0x0009) /**< Invalid Source CID. */ +#define BLE_L2CAP_CH_STATUS_CODE_SCID_ALLOCATED (0x000A) /**< Source CID already allocated. */ +#define BLE_L2CAP_CH_STATUS_CODE_UNACCEPTABLE_PARAMS (0x000B) /**< Unacceptable parameters. */ +#define BLE_L2CAP_CH_STATUS_CODE_NOT_UNDERSTOOD (0x8000) /**< Command Reject received instead of LE Credit Based Connection Response. */ +#define BLE_L2CAP_CH_STATUS_CODE_TIMEOUT (0xC000) /**< Operation timed out. */ +/** @} */ + +/** @} */ + +/**@addtogroup BLE_L2CAP_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE L2CAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @note These parameters are set per connection, so all L2CAP channels created on this connection + * will have the same parameters. + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - rx_mps is smaller than @ref BLE_L2CAP_MPS_MIN. + * - tx_mps is smaller than @ref BLE_L2CAP_MPS_MIN. + * - ch_count is greater than @ref BLE_L2CAP_CH_COUNT_MAX. + * @retval ::NRF_ERROR_NO_MEM rx_mps or tx_mps is set too high. + */ +typedef struct +{ + uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall + be able to receive on L2CAP channels on connections with this + configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */ + uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall + be able to transmit on L2CAP channels on connections with this + configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */ + uint8_t rx_queue_size; /**< Number of SDU data buffers that can be queued for reception per + L2CAP channel. The minimum value is one. */ + uint8_t tx_queue_size; /**< Number of SDU data buffers that can be queued for transmission + per L2CAP channel. The minimum value is one. */ + uint8_t ch_count; /**< Number of L2CAP channels the application can create per connection + with this configuration. The default value is zero, the maximum + value is @ref BLE_L2CAP_CH_COUNT_MAX. + @note if this parameter is set to zero, all other parameters in + @ref ble_l2cap_conn_cfg_t are ignored. */ +} ble_l2cap_conn_cfg_t; + +/**@brief L2CAP channel RX parameters. */ +typedef struct +{ + uint16_t rx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP shall be able to + receive on this L2CAP channel. + - Must be equal to or greater than @ref BLE_L2CAP_MTU_MIN. */ + uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall be + able to receive on this L2CAP channel. + - Must be equal to or greater than @ref BLE_L2CAP_MPS_MIN. + - Must be equal to or less than @ref ble_l2cap_conn_cfg_t::rx_mps. */ + ble_data_t sdu_buf; /**< SDU data buffer for reception. + - If @ref ble_data_t::p_data is non-NULL, initial credits are + issued to the peer. + - If @ref ble_data_t::p_data is NULL, no initial credits are + issued to the peer. */ +} ble_l2cap_ch_rx_params_t; + +/**@brief L2CAP channel setup parameters. */ +typedef struct +{ + ble_l2cap_ch_rx_params_t rx_params; /**< L2CAP channel RX parameters. */ + uint16_t le_psm; /**< LE Protocol/Service Multiplexer. Used when requesting + setup of an L2CAP channel, ignored otherwise. */ + uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES. + Used when replying to a setup request of an L2CAP + channel, ignored otherwise. */ +} ble_l2cap_ch_setup_params_t; + +/**@brief L2CAP channel TX parameters. */ +typedef struct +{ + uint16_t tx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP is able to + transmit on this L2CAP channel. */ + uint16_t peer_mps; /**< The maximum L2CAP PDU payload size, in bytes, that the peer is + able to receive on this L2CAP channel. */ + uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP is able + to transmit on this L2CAP channel. This is effective tx_mps, + selected by the SoftDevice as + MIN( @ref ble_l2cap_ch_tx_params_t::peer_mps, @ref ble_l2cap_conn_cfg_t::tx_mps ) */ + uint16_t credits; /**< Initial credits given by the peer. */ +} ble_l2cap_ch_tx_params_t; + +/**@brief L2CAP Channel Setup Request event. */ +typedef struct +{ + ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */ + uint16_t le_psm; /**< LE Protocol/Service Multiplexer. */ +} ble_l2cap_evt_ch_setup_request_t; + +/**@brief L2CAP Channel Setup Refused event. */ +typedef struct +{ + uint8_t source; /**< Source, see @ref BLE_L2CAP_CH_SETUP_REFUSED_SRCS */ + uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES */ +} ble_l2cap_evt_ch_setup_refused_t; + +/**@brief L2CAP Channel Setup Completed event. */ +typedef struct +{ + ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */ +} ble_l2cap_evt_ch_setup_t; + +/**@brief L2CAP Channel SDU Data Duffer Released event. */ +typedef struct +{ + ble_data_t sdu_buf; /**< Returned reception or transmission SDU data buffer. The SoftDevice + returns SDU data buffers supplied by the application, which have + not yet been returned previously via a @ref BLE_L2CAP_EVT_CH_RX or + @ref BLE_L2CAP_EVT_CH_TX event. */ +} ble_l2cap_evt_ch_sdu_buf_released_t; + +/**@brief L2CAP Channel Credit received event. */ +typedef struct +{ + uint16_t credits; /**< Additional credits given by the peer. */ +} ble_l2cap_evt_ch_credit_t; + +/**@brief L2CAP Channel received SDU event. */ +typedef struct +{ + uint16_t sdu_len; /**< Total SDU length, in bytes. */ + ble_data_t sdu_buf; /**< SDU data buffer. + @note If there is not enough space in the buffer + (sdu_buf.len < sdu_len) then the rest of the SDU will be + silently discarded by the SoftDevice. */ +} ble_l2cap_evt_ch_rx_t; + +/**@brief L2CAP Channel transmitted SDU event. */ +typedef struct +{ + ble_data_t sdu_buf; /**< SDU data buffer. */ +} ble_l2cap_evt_ch_tx_t; + +/**@brief L2CAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which the event occured. */ + uint16_t local_cid; /**< Local Channel ID of the L2CAP channel, or + @ref BLE_L2CAP_CID_INVALID if not present. */ + union + { + ble_l2cap_evt_ch_setup_request_t ch_setup_request; /**< L2CAP Channel Setup Request Event Parameters. */ + ble_l2cap_evt_ch_setup_refused_t ch_setup_refused; /**< L2CAP Channel Setup Refused Event Parameters. */ + ble_l2cap_evt_ch_setup_t ch_setup; /**< L2CAP Channel Setup Completed Event Parameters. */ + ble_l2cap_evt_ch_sdu_buf_released_t ch_sdu_buf_released;/**< L2CAP Channel SDU Data Buffer Released Event Parameters. */ + ble_l2cap_evt_ch_credit_t credit; /**< L2CAP Channel Credit Received Event Parameters. */ + ble_l2cap_evt_ch_rx_t rx; /**< L2CAP Channel SDU Received Event Parameters. */ + ble_l2cap_evt_ch_tx_t tx; /**< L2CAP Channel SDU Transmitted Event Parameters. */ + } params; /**< Event Parameters. */ +} ble_l2cap_evt_t; + +/** @} */ + +/**@addtogroup BLE_L2CAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set up an L2CAP channel. + * + * @details This function is used to: + * - Request setup of an L2CAP channel: sends an LE Credit Based Connection Request packet to a peer. + * - Reply to a setup request of an L2CAP channel (if called in response to a + * @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST event): sends an LE Credit Based Connection + * Response packet to a peer. + * + * @note A call to this function will require the application to keep the SDU data buffer alive + * until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX or + * @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_SETUP, Setup successful.} + * @event{@ref BLE_L2CAP_EVT_CH_SETUP_REFUSED, Setup failed.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_SETUP_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in,out] p_local_cid Pointer to a uint16_t containing Local Channel ID of the L2CAP channel: + * - As input: @ref BLE_L2CAP_CID_INVALID when requesting setup of an L2CAP + * channel or local_cid provided in the @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST + * event when replying to a setup request of an L2CAP channel. + * - As output: local_cid for this channel. + * @param[in] p_params L2CAP channel parameters. + * + * @retval ::NRF_SUCCESS Successfully queued request or response for transmission. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @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. + * @retval ::NRF_ERROR_INVALID_LENGTH Supplied higher rx_mps than has been configured on this link. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (L2CAP channel already set up). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_RESOURCES The limit has been reached for available L2CAP channels, + * see @ref ble_l2cap_conn_cfg_t::ch_count. + */ +SVCALL(SD_BLE_L2CAP_CH_SETUP, uint32_t, sd_ble_l2cap_ch_setup(uint16_t conn_handle, uint16_t *p_local_cid, ble_l2cap_ch_setup_params_t const *p_params)); + +/**@brief Release an L2CAP channel. + * + * @details This sends a Disconnection Request packet to a peer. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_RELEASED, Release complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_RELEASE_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * + * @retval ::NRF_SUCCESS Successfully queued request for transmission. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for the L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + */ +SVCALL(SD_BLE_L2CAP_CH_RELEASE, uint32_t, sd_ble_l2cap_ch_release(uint16_t conn_handle, uint16_t local_cid)); + +/**@brief Receive an SDU on an L2CAP channel. + * + * @details This may issue additional credits to the peer using an LE Flow Control Credit packet. + * + * @note A call to this function will require the application to keep the memory pointed by + * @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX + * or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::rx_queue_size SDU data buffers + * for reception per L2CAP channel. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_RX, The SDU is received.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_RX_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * @param[in] p_sdu_buf Pointer to the SDU data buffer. + * + * @retval ::NRF_SUCCESS Buffer accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for an L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_RESOURCES Too many SDU data buffers supplied. Wait for a + * @ref BLE_L2CAP_EVT_CH_RX event and retry. + */ +SVCALL(SD_BLE_L2CAP_CH_RX, uint32_t, sd_ble_l2cap_ch_rx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf)); + +/**@brief Transmit an SDU on an L2CAP channel. + * + * @note A call to this function will require the application to keep the memory pointed by + * @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_TX + * or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event. + * + * @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::tx_queue_size SDUs for + * transmission per L2CAP channel. + * + * @note The application can keep track of the available credits for transmission by following + * the procedure below: + * - Store initial credits given by the peer in a variable. + * (Initial credits are provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.) + * - Decrement the variable, which stores the currently available credits, by + * ceiling((@ref ble_data_t::len + 2) / tx_mps) when a call to this function returns + * @ref NRF_SUCCESS. (tx_mps is provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.) + * - Increment the variable, which stores the currently available credits, by additional + * credits given by the peer in a @ref BLE_L2CAP_EVT_CH_CREDIT event. + * + * @events + * @event{@ref BLE_L2CAP_EVT_CH_TX, The SDU is transmitted.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_TX_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel. + * @param[in] p_sdu_buf Pointer to the SDU data buffer. + * + * @retval ::NRF_SUCCESS Successfully queued L2CAP SDU for transmission. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for the L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + * @retval ::NRF_ERROR_DATA_SIZE Invalid SDU length supplied, must not be more than + * @ref ble_l2cap_ch_tx_params_t::tx_mtu provided in + * @ref BLE_L2CAP_EVT_CH_SETUP event. + * @retval ::NRF_ERROR_RESOURCES Too many SDUs queued for transmission. Wait for a + * @ref BLE_L2CAP_EVT_CH_TX event and retry. + */ +SVCALL(SD_BLE_L2CAP_CH_TX, uint32_t, sd_ble_l2cap_ch_tx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf)); + +/**@brief Advanced SDU reception flow control. + * + * @details Adjust the way the SoftDevice issues credits to the peer. + * This may issue additional credits to the peer using an LE Flow Control Credit packet. + * + * @mscs + * @mmsc{@ref BLE_L2CAP_CH_FLOW_CONTROL_MSC} + * @endmscs + * + * @param[in] conn_handle Connection Handle. + * @param[in] local_cid Local Channel ID of the L2CAP channel or @ref BLE_L2CAP_CID_INVALID to set + * the value that will be used for newly created channels. + * @param[in] credits Number of credits that the SoftDevice will make sure the peer has every + * time it starts using a new reception buffer. + * - @ref BLE_L2CAP_CREDITS_DEFAULT is the default value the SoftDevice will + * use if this function is not called. + * - If set to zero, the SoftDevice will stop issuing credits for new reception + * buffers the application provides or has provided. SDU reception that is + * currently ongoing will be allowed to complete. + * @param[out] p_credits NULL or pointer to a uint16_t. If a valid pointer is provided, it will be + * written by the SoftDevice with the number of credits that is or will be + * available to the peer. If the value written by the SoftDevice is 0 when + * credits parameter was set to 0, the peer will not be able to send more + * data until more credits are provided by calling this function again with + * credits > 0. This parameter is ignored when local_cid is set to @ref + * BLE_L2CAP_CID_INVALID. + * + * @note Application should take care when setting number of credits higher than default value. In + * this case the application must make sure that the SoftDevice always has reception buffers + * available (see @ref sd_ble_l2cap_ch_rx) for that channel. If the SoftDevice does not have + * such buffers available, packets may be NACKed on the Link Layer and all Bluetooth traffic + * on the connection handle may be stalled until the SoftDevice again has an available + * reception buffer. This applies even if the application has used this call to set the + * credits back to default, or zero. + * + * @retval ::NRF_SUCCESS Flow control parameters accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is + * in progress for an L2CAP channel). + * @retval ::NRF_ERROR_NOT_FOUND CID not found. + */ +SVCALL(SD_BLE_L2CAP_CH_FLOW_CONTROL, uint32_t, sd_ble_l2cap_ch_flow_control(uint16_t conn_handle, uint16_t local_cid, uint16_t credits, uint16_t *p_credits)); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_L2CAP_H__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_ranges.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_ranges.h new file mode 100644 index 0000000000..5b9d891402 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_ranges.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__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_.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_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */ +#define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */ + +#define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */ +#define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */ + +#define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */ +#define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */ + +#define BLE_L2CAP_OPT_BASE 0xA0 /**< L2CAP BLE Option base. */ +#define BLE_L2CAP_OPT_LAST 0xBF /**< L2CAP BLE Option last. */ + + +#define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */ + +#define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */ +#define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */ + +#define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */ +#define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */ + +#define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */ +#define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */ + +#define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */ +#define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */ + +#define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */ +#define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */ + +#define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */ +#define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */ + +#define BLE_L2CAP_CFG_BASE 0xC0 /**< L2CAP BLE configuration base. */ +#define BLE_L2CAP_CFG_LAST 0xDF /**< L2CAP BLE configuration last. */ + + + + + +#ifdef __cplusplus +} +#endif +#endif /* BLE_RANGES_H__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_types.h new file mode 100644 index 0000000000..88c93180c8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/ble_types.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#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. */ +#define BLE_UUID_GAP_CHARACTERISTIC_RPA_ONLY 0x2AC9 /**< Resolvable Private Address Only 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 /**< Joystick (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; + +/**@brief Data structure. */ +typedef struct +{ + uint8_t *p_data; /**< Pointer to the data buffer provided to/from the application. */ + uint16_t len; /**< Length of the data buffer, in bytes. */ +} ble_data_t; + +/** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* BLE_TYPES_H__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf52/nrf_mbr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf52/nrf_mbr.h new file mode 100644 index 0000000000..c95bb8d4fd --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf52/nrf_mbr.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +*/ + +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + +#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, /**< Initialize 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, /**< Change the address the MBR starts after a reset @see ::sd_mbr_command_vector_table_base_set_t*/ + SD_MBR_COMMAND_RESERVED, + SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address @see ::sd_mbr_command_irq_forward_address_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 SoftDevice Specification 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 Change the address the MBR starts after a reset + * + * 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 SoftDevice Specification 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; + +/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR + * Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not + * change where the MBR starts after reset. + * + * @retval ::NRF_SUCCESS + */ +typedef struct +{ + uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/ +} sd_mbr_command_irq_forward_address_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.*/ + sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/ + } 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 return values, 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 ::sd_mbr_command_irq_forward_address_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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_ble.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_ble.h new file mode 100644 index 0000000000..470577b8aa --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_ble.h @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_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. */ + SD_BLE_CFG_SET, /**< Add a configuration to the BLE stack. */ +}; + +/** + * @brief BLE Module Independent Event IDs. + */ +enum BLE_COMMON_EVTS +{ + BLE_EVT_USER_MEM_REQUEST = BLE_EVT_BASE, /**< 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 */ +}; + +/**@brief BLE Connection Configuration IDs. + * + * IDs that uniquely identify a connection configuration. + */ +enum BLE_CONN_CFGS +{ + BLE_CONN_CFG_GAP = BLE_CONN_CFG_BASE, /**< BLE GAP specific connection configuration. */ + BLE_CONN_CFG_GATTC, /**< BLE GATTC specific connection configuration. */ + BLE_CONN_CFG_GATTS, /**< BLE GATTS specific connection configuration. */ + BLE_CONN_CFG_GATT, /**< BLE GATT specific connection configuration. */ + BLE_CONN_CFG_L2CAP, /**< BLE L2CAP specific connection configuration. */ +}; + +/**@brief BLE Common Configuration IDs. + * + * IDs that uniquely identify a common configuration. + */ +enum BLE_COMMON_CFGS +{ + BLE_COMMON_CFG_VS_UUID = BLE_CFG_BASE, /**< Vendor specific UUID configuration */ +}; + +/**@brief Common Option IDs. + * IDs that uniquely identify a common option. + */ +enum BLE_COMMON_OPTS +{ + BLE_COMMON_OPT_PA_LNA = BLE_OPT_BASE, /**< 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 The highest value used for @ref ble_gatt_conn_cfg_t::att_mtu in any connection configuration shall be used as a parameter. + * If that value has not been configured for any connections then @ref BLE_GATT_ATT_MTU_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_DEFAULT 10 /**< Default VS UUID count. */ +#define BLE_UUID_VS_COUNT_MAX 254 /**< Maximum VS UUID count. */ +/** @} */ + +/** @defgroup BLE_COMMON_CFG_DEFAULTS Configuration defaults. + * @{ + */ +#define BLE_CONN_CFG_TAG_DEFAULT 0 /**< Default configuration tag, SoftDevice default connection configuration. */ + +/** @} */ + +/** @} */ + +/** @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_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 events not associated with a specific function module. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which this event occurred. */ + union + { + 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. */ + } params; /**< Event parameter union. */ +} ble_common_evt_t; + +/**@brief BLE Event header. */ +typedef struct +{ + uint16_t evt_id; /**< Value from a BLE__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_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. */ + ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */ + } evt; /**< Event union. */ +} ble_evt_t; + + +/** + * @brief Version Information. + */ +typedef struct +{ + uint8_t version_number; /**< Link Layer Version number. See https://www.bluetooth.org/en-us/specification/assigned-numbers/link-layer for assigned values. */ + 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 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 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 connection configuration as set by @ref ble_gap_conn_cfg_t::event_length. + * 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_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 connection configuration type, wrapping the module specific configurations, set with + * @ref sd_ble_cfg_set. + * + * @note Connection configurations don't have to be set. + * In the case that no configurations has been set, or fewer connection configurations has been set than enabled connections, + * the default connection configuration will be automatically added for the remaining connections. + * When creating connections with the default configuration, @ref BLE_CONN_CFG_TAG_DEFAULT should be used in + * place of @ref ble_conn_cfg_t::conn_cfg_tag. See @ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect()" + * + * @mscs + * @mmsc{@ref BLE_CONN_CFG} + * @endmscs + + */ +typedef struct +{ + uint8_t conn_cfg_tag; /**< The application chosen tag it can use with the @ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect() + calls to select this configuration when creating a connection. + Must be different for all connection configurations added and not @ref BLE_CONN_CFG_TAG_DEFAULT. */ + union { + ble_gap_conn_cfg_t gap_conn_cfg; /**< GAP connection configuration, cfg_id is @ref BLE_CONN_CFG_GAP. */ + ble_gattc_conn_cfg_t gattc_conn_cfg; /**< GATTC connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTC. */ + ble_gatts_conn_cfg_t gatts_conn_cfg; /**< GATTS connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTS. */ + ble_gatt_conn_cfg_t gatt_conn_cfg; /**< GATT connection configuration, cfg_id is @ref BLE_CONN_CFG_GATT. */ + ble_l2cap_conn_cfg_t l2cap_conn_cfg; /**< L2CAP connection configuration, cfg_id is @ref BLE_CONN_CFG_L2CAP. */ + } params; /**< Connection configuration union. */ +} ble_conn_cfg_t; + +/** + * @brief Configuration of Vendor Specific UUIDs, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM Too many UUIDs configured. + */ +typedef struct +{ + uint8_t vs_uuid_count; /**< Number of 128-bit Vendor Specific UUID bases to allocate memory for. + Default value is @ref BLE_UUID_VS_COUNT_DEFAULT. Maximum value is + @ref BLE_UUID_VS_COUNT_MAX. */ +} ble_common_cfg_vs_uuid_t; + +/**@brief Common BLE Configuration type, wrapping the common configurations. */ +typedef union +{ + ble_common_cfg_vs_uuid_t vs_uuid_cfg; /**< Vendor specific UUID configuration, cfg_id is @ref BLE_COMMON_CFG_VS_UUID. */ +} ble_common_cfg_t; + +/**@brief BLE Configuration type, wrapping the module specific configurations. */ +typedef union +{ + ble_conn_cfg_t conn_cfg; /**< Connection specific configurations, cfg_id in @ref BLE_CONN_CFGS series. */ + ble_common_cfg_t common_cfg; /**< Global common configurations, cfg_id in @ref BLE_COMMON_CFGS series. */ + ble_gap_cfg_t gap_cfg; /**< Global GAP configurations, cfg_id in @ref BLE_GAP_CFGS series. */ + ble_gatts_cfg_t gatts_cfg; /**< Global GATTS configuration, cfg_id in @ref BLE_GATTS_CFGS series. */ +} ble_cfg_t; + +/** @} */ + +/** @addtogroup BLE_COMMON_FUNCTIONS Functions + * @{ */ + +/**@brief Enable the BLE stack + * + * @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. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note The value of *p_app_ram_base when the app has done no custom configuration of the + * SoftDevice, i.e. the app has not called @ref sd_ble_cfg_set before @ref sd_ble_enable, can + * be found in the release notes. + * + * @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 BLE related function other than @ref + * sd_ble_cfg_set 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_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. + */ +SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base)); + +/**@brief Add configurations for the BLE stack + * + * @param[in] cfg_id Config ID, see @ref BLE_CONN_CFGS, @ref BLE_COMMON_CFGS, @ref + * BLE_GAP_CFGS or @ref BLE_GATTS_CFGS. + * @param[in] p_cfg Pointer to a ble_cfg_t structure containing the configuration value. + * @param[in] app_ram_base The start address of the application RAM region (APP_RAM_BASE). + * See @ref sd_ble_enable for details about APP_RAM_BASE. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note If a configuration is set more than once, the last one set is the one that takes effect on + * @ref sd_ble_enable. + * + * @note Any part of the BLE stack that is NOT configured with @ref sd_ble_cfg_set will have default + * configuration. + * + * @note @ref sd_ble_cfg_set may be called at any time when the SoftDevice is enabled (see @ref + * sd_softdevice_enable) while the BLE part of the SoftDevice is not enabled (see @ref + * sd_ble_enable). + * + * @note Error codes for the configurations are described in the configuration structs. + * + * @mscs + * @mmsc{@ref BLE_COMMON_ENABLE} + * @endmscs + * + * @retval ::NRF_SUCCESS The configuration has been added successfully. + * @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid cfg_id supplied. + * @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by app_ram_base is not + * large enough to fit this configuration's memory requirement. + */ +SVCALL(SD_BLE_CFG_SET, uint32_t, sd_ble_cfg_set(uint32_t cfg_id, ble_cfg_t const * p_cfg, uint32_t 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 must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT. + * 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 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 indexes 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] p_block Pointer to a user memory block structure or NULL if memory is managed by the application. + * + * @mscs + * @mmsc{@ref BLE_GATTS_QUEUED_WRITE_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 ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid user memory block length supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no user memory request pending. + */ +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} + * @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__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error.h new file mode 100644 index 0000000000..6badee98e5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_sdm.h new file mode 100644 index 0000000000..530959b9d6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_sdm.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 erroneous SoftDevice flashing). + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_SDM_H__ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_soc.h new file mode 100644 index 0000000000..1e784b8db3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_error_soc.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_nvic.h new file mode 100644 index 0000000000..40537b45a2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_nvic.h @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#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. */ + +#define __NRF_NVIC_ISER_COUNT (2) /**< The number of ISER/ICER registers in the NVIC that are used. */ + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 0-31. */ +#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)SWI5_EGU5_IRQn) \ + )) + +/**@brief Interrupts used by the SoftDevice, with IRQn in the range 32-63. */ +#define __NRF_NVIC_SD_IRQS_1 ((uint32_t)0) + +/**@brief Interrupts available for to application, with IRQn in the range 0-31. */ +#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0) + +/**@brief Interrupts available for to application, with IRQn in the range 32-63. */ +#define __NRF_NVIC_APP_IRQS_1 (~__NRF_NVIC_SD_IRQS_1) + +/**@} */ + +/**@} */ + +/**@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<= (1 << __NVIC_PRIO_BITS)) + { + return 0; + } + if( priority == 0 + || priority == 1 + || priority == 4 + ) + { + return 0; + } + 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; + nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 ); + NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1; + *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]; + NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1]; + 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__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sd_def.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sd_def.h new file mode 100644 index 0000000000..0b4d221d6a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sd_def.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#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__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sdm.h new file mode 100644 index 0000000000..c41d86d46b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_sdm.h @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SoftDevice unique string size in bytes. */ +#define SD_UNIQUE_STR_SIZE 20 + +/** @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 the offset for the SoftDevice unique string relative to the SoftDevice base address. + * The SD_UNIQUE_STR is stored as an array of uint8_t. The size of array is @ref SD_UNIQUE_STR_SIZE. + */ +#define SD_UNIQUE_STR_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x18) + +/** @brief Defines a macro for retrieving 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 retrieving 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 retrieving 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 retrieving 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 retrieving the actual SoftDevice version 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) + +/** @brief Defines a macro for retrieving the address of SoftDevice unique str based on 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_UNIQUE_STR_ADDR_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_UNIQUE_STR_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \ + ? (((uint8_t *) ((baseaddr) + SD_UNIQUE_STR_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. 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 disallowed 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_ACCURACY Clock accuracy + * @{ */ + +#define NRF_CLOCK_LF_ACCURACY_250_PPM (0) /**< Default: 250 ppm */ +#define NRF_CLOCK_LF_ACCURACY_500_PPM (1) /**< 500 ppm */ +#define NRF_CLOCK_LF_ACCURACY_150_PPM (2) /**< 150 ppm */ +#define NRF_CLOCK_LF_ACCURACY_100_PPM (3) /**< 100 ppm */ +#define NRF_CLOCK_LF_ACCURACY_75_PPM (4) /**< 75 ppm */ +#define NRF_CLOCK_LF_ACCURACY_50_PPM (5) /**< 50 ppm */ +#define NRF_CLOCK_LF_ACCURACY_30_PPM (6) /**< 30 ppm */ +#define NRF_CLOCK_LF_ACCURACY_20_PPM (7) /**< 20 ppm */ +#define NRF_CLOCK_LF_ACCURACY_10_PPM (8) /**< 10 ppm */ +#define NRF_CLOCK_LF_ACCURACY_5_PPM (9) /**< 5 ppm */ +#define NRF_CLOCK_LF_ACCURACY_2_PPM (10) /**< 2 ppm */ +#define NRF_CLOCK_LF_ACCURACY_1_PPM (11) /**< 1 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 +/-500 ppm 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 accuracy; /**< External clock accuracy used in the LL to compute timing + windows, see @ref NRF_CLOCK_LF_ACCURACY.*/ +} 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_soc.h new file mode 100644 index 0000000000..d7d3c801b8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_soc.h @@ -0,0 +1,931 @@ +/* + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include +#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 Guaranteed 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) + +/**@brief The maximum processing time to handle a timeslot extension. */ +#define NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US (17) + +/**@brief The latest time before the end of a timeslot the timeslot can be extended. */ +#define NRF_RADIO_MIN_EXTENSION_MARGIN_US (79) + +#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. */ + +#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. + The default interrupt priority for this handler is set to 4 */ +#define RADIO_NOTIFICATION_IRQn (SWI1_EGU1_IRQn) /**< The radio notification IRQ number. */ +#define RADIO_NOTIFICATION_IRQHandler (SWI1_EGU1_IRQHandler) /**< The radio notification IRQ handler. + The default interrupt priority for this handler is set to 4 */ +#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_RAM_POWER_SET, + SD_POWER_RAM_POWER_CLR, + SD_POWER_RAM_POWER_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_V17 = 4UL, /**< 1.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V18, /**< 1.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V19, /**< 1.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V20, /**< 2.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V22, /**< 2.2 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V24, /**< 2.4 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V26, /**< 2.6 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V27, /**< 2.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V28 /**< 2.8 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: + @ref NRF_RADIO_MAX_EXTENSION_PROCESSING_TIME_US. + This action must be started at least @ref + NRF_RADIO_MIN_EXTENSION_MARGIN_US before + the end of the timeslot. */ + 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. + @note The SoftDevice will automatically turn on and off the external crystal, + at the beginning and end of the timeslot, respectively. The crystal may also + intentionally be left running after the timeslot, in cases where it is needed + by the SoftDevice shortly after the end of the timeslot. */ + 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 activities 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 const * p_key; /**< Pointer to the Encryption key. */ + soc_ecb_cleartext_t const * 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 Writes the NRF_POWER->RAM[index].POWERSET register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERSET register to write to. + * @param[in] ram_powerset Contains the word to write to the NRF_POWER->RAM[index].POWERSET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_SET, uint32_t, sd_power_ram_power_set(uint8_t index, uint32_t ram_powerset)); + +/**@brief Writes the NRF_POWER->RAM[index].POWERCLR register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERCLR register to write to. + * @param[in] ram_powerclr Contains the word to write to the NRF_POWER->RAM[index].POWERCLR register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_CLR, uint32_t, sd_power_ram_power_clr(uint8_t index, uint32_t ram_powerclr)); + +/**@brief Get contents of NRF_POWER->RAM[index].POWER register, indicates power status of RAM[index] blocks. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWER register to read from. + * @param[out] p_ram_power Content of NRF_POWER->RAM[index].POWER register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_GET, uint32_t, sd_power_ram_power_get(uint8_t index, uint32_t * p_ram_power)); + +/**@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. + * + * @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. + * + * @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. + * + * @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 application waits for an application event by calling this function, an interrupt that + * is enabled will be taken immediately on pending since this function will wait in thread mode, + * then the execution will return in the application's main thread. + * + * In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M + * MCU's System Control Register (SCR), CMSIS_SCB. In that case, when a disabled interrupt gets + * pended, this function will return to the application's main thread. + * + * @note 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. + * + * @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, the radio + * notifications must be configured 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_ERROR_INVALID_STATE A protocol stack or other SoftDevice is running. Stop all + * running activities and retry. + * @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 50 us 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 the device's Product Specification +* 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 the number of words in one +* flash page. See the device's Product Specification for details. +* +* @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 * p_dst, uint32_t 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 the device's Product Specification +* and the command parameters). +* +* +* @param[in] page_number Page number 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. + 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. + * @param[in] block_cfg3 Value to be written to the configuration register. + * + * @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 100 ms 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 const * p_request)); + +/**@} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_SOC_H__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_svc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_svc.h new file mode 100644 index 0000000000..292c692982 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/headers/nrf_svc.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_licence-agreement.txt new file mode 100644 index 0000000000..00c2e54c47 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_licence-agreement.txt @@ -0,0 +1,35 @@ +Copyright (c) 2007 - 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 form under this license must not be reverse + engineered, decompiled, modified and/or disassembled. + +THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_softdevice.hex b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_softdevice.hex new file mode 100644 index 0000000000..a644fbaf38 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/hex/s132_nrf52_5.0.0_softdevice.hex @@ -0,0 +1,8678 @@ +:020000040000FA +:1000000000040020E90800007D050000C908000088 +:1000100087050000910500009B050000000000001E +:100020000000000000000000000000000D090000BA +:10003000A505000000000000AF050000B9050000A4 +:10004000C3050000CD050000D7050000E105000054 +:10005000EB050000F5050000FF05000009060000A3 +:10006000130600001D0600002706000031060000F0 +:100070003B060000450600004F0600005906000040 +:10008000630600006D060000770600008106000090 +:100090008B060000950600009F060000A9060000E0 +:1000A000B3060000BD060000C7060000D106000030 +:1000B000DB060000E5060000EF060000F906000080 +:1000C000030700000D0700001707000021070000CC +:1000D0002B070000350700003F070000490700001C +:1000E000530700005D07000067070000710700006C +:1000F0007B070000850700008F07000099070000BC +:10010000A30700001FB500F003F88DE80F001FBD26 +:1001100000F0E0BB1FB56FF00100009040100390AD +:10012000029001904FF010208069000B420900F00E +:100130001F045DF822300120A04083434DF8223097 +:10014000684600F045F91FBDF0B54FF6FF734FF458 +:10015000B4751A466E1E11E0A94201D3344600E080 +:100160000C46091B30F8027B641E3B441A44F9D14B +:100170009CB204EB134394B204EB12420029EBD17E +:1001800098B200EB134002EB124140EA0140F0BD8F +:10019000DE4992B00446D1E90001CDE91001FF2209 +:1001A0004021684600F03CFB94E80F008DE80F000A +:1001B000684610A902E004C841F8042D8842FAD12B +:1001C00010216846FFF7C0FF1090AA208DF8440068 +:1001D000FFF7A0FF00F0F3F84FF01024A069102201 +:1001E0006946803000F002F9A069082210A900F0E9 +:1001F000FDF800F0D8F84FF080510A6949690068AD +:100200004A43824201D8102070470020704710B541 +:10021000D0E900214FF0805002EB8103026944696C +:100220006243934209D84FF01022536903EB8103D4 +:100230000169406941438B4201D9092010BD5069D1 +:10024000401C01D0002010BD0F2010BD70B501680A +:100250000446AF4D4FF01020072952D2DFE801F0DD +:10026000330419293C1E2500D4E902656468294637 +:10027000304600F0CDF82A462146304600F0B6F868 +:10028000AA002146304600F09FFA002800D0032043 +:1002900070BD00F051FB4FF4805007E0201DFFF7C8 +:1002A000AAFF0028F4D100F047FB60682860002016 +:1002B00070BD241D94E80700920000F085FA002824 +:1002C000F6D00E2070BD8069401C12D0201DFFF7B3 +:1002D0009EFF0028F6D109E08069401C09D0201D4E +:1002E000FFF789FF0028EDD1606820B12046FFF7B5 +:1002F0004FFF042070BDFFF70DFF00F060F800F025 +:1003000052F8072070BD10B50C46182802D0012005 +:10031000086010BD2068FFF799FF206010BD4FF006 +:100320001024A069401C05D0A569A66980353079E4 +:10033000AA2808D06069401C2DD060690068401C64 +:1003400029D060692CE010212846FFF7FDFE3168B6 +:1003500081421CD1A16901F18002C03105E030B1B8 +:1003600008CA51F8040D984201D1012000E0002094 +:100370008A42F4D158B1286810B1042803D0FEE7AE +:10038000284600F057F862496868086008E000F005 +:1003900016F800F008F84FF480500168491C01D0AD +:1003A00000F0A4FAFEE7BFF34F8F5A4801685A4A9B +:1003B00001F4E06111430160BFF34F8FFEE74FF09E +:1003C00010208169491C02D0806900F0AEB87047E6 +:1003D000524A01681160121D416811604F4A8168DC +:1003E00010321160111DC068086070472DE9F0419E +:1003F00017460D460646002406E03046296800F000 +:10040000A7F8641C2D1D361DBC42F6D3BDE8F08153 +:1004100070B50C4605464FF4806608E0284600F0AB +:1004200084F8B44205D3A4F5806405F58055002C0A +:10043000F4D170BD4168044609B1012500E00025F2 +:100440004FF010267069A268920000F0BDF9C8B1A3 +:10045000204600F01AF89DB17669A56864684FF4EB +:10046000002084420AD2854208D229463046FFF74E +:10047000CFFF2A4621463046FFF7B8FFFFF79FFF20 +:10048000FFF791FFFFF746FEF8E72DE9FF414FF038 +:100490001024616980680D0B01EB800000F6FF708D +:1004A000010B0020009001900290024603906846E4 +:1004B00001230BE0560902F01F0C50F8267003FAD6 +:1004C0000CFC47EA0C0740F82670521CAA42F1D3F4 +:1004D0000AE04A0901F01F0650F8225003FA06F616 +:1004E000354340F82250491C8029F2D3A169090BF9 +:1004F0004A0901F01F0150F822408B409C4340F80C +:100500002240FFF765FFBDE8FF8100005C090000A5 +:10051000000000200CED00E00400FA050006004099 +:10052000144801680029FCD07047134A0221116069 +:1005300010490B68002BFCD00F4B1B1D186008687E +:100540000028FCD00020106008680028FCD070470C +:10055000094B10B501221A60064A1468002CFCD021 +:10056000016010680028FCD0002018601068002886 +:10057000FCD010BD00E4014004E5014008208F4993 +:1005800009680958084710208C4909680958084724 +:1005900014208A49096809580847182087490968BA +:1005A0000958084730208549096809580847382004 +:1005B00082490968095808473C2080490968095858 +:1005C000084740207D4909680958084744207B496D +:1005D00009680958084748207849096809580847B0 +:1005E0004C20764909680958084750207349096822 +:1005F0000958084754207149096809580847582084 +:100600006E490968095808475C206C49096809580F +:100610000847602069490968095808476420674904 +:100620000968095808476820644909680958084753 +:100630006C20624909680958084770205F490968B9 +:100640000958084774205D49096809580847782007 +:100650005A490968095808477C20584909680958C7 +:10066000084780205549096809580847842053499C +:1006700009680958084788205049096809580847F7 +:100680008C204E4909680958084790204B49096851 +:10069000095808479420494909680958084798208B +:1006A00046490968095808479C204449096809587F +:1006B0000847A0204149096809580847A4203F4934 +:1006C000096809580847A8203C490968095808479B +:1006D000AC203A49096809580847B02037490968E9 +:1006E00009580847B4203549096809580847B8200F +:1006F0003249096809580847BC2030490968095837 +:100700000847C0202D49096809580847C4202B49CB +:10071000096809580847C82028490968095808473E +:10072000CC202649096809580847D0202349096880 +:1007300009580847D4202149096809580847D82092 +:100740001E49096809580847DC201C4909680958EE +:100750000847E0201949096809580847E420174963 +:10076000096809580847E8201449096809580847E2 +:10077000EC201249096809580847F0200F49096818 +:1007800009580847F4200D49096809580847F82016 +:100790000A49096809580847FC20084909680958A6 +:1007A00008475FF480700549096809580847000048 +:1007B00003480449024A034B704700000000002030 +:1007C000680900006809000040EA010310B59B07B2 +:1007D0000FD1042A0DD310C808C9121F9C42F8D0AB +:1007E00020BA19BA884201D9012010BD4FF0FF305C +:1007F00010BD1AB1D30703D0521C07E0002010BD72 +:1008000010F8013B11F8014B1B1B07D110F8013BFD +:1008100011F8014B1B1B01D1921EF1D1184610BDDE +:1008200002F0FF0343EA032242EA024200F005B865 +:100830007047704770474FF000020429C0F01280E3 +:1008400010F0030C00F01B80CCF1040CBCF1020F83 +:1008500018BF00F8012BA8BF20F8022BA1EB0C0158 +:1008600000F00DB85FEAC17C24BF00F8012B00F84E +:10087000012B48BF00F8012B70474FF0000200B574 +:10088000134694469646203922BFA0E80C50A0E8B3 +:100890000C50B1F12001BFF4F7AF090728BFA0E861 +:1008A0000C5048BF0CC05DF804EB890028BF40F82D +:1008B000042B08BF704748BF20F8022B11F0804F6F +:1008C00018BF00F8012B7047014B1B68DB68184705 +:1008D0000000002009480A497047FFF7FBFFFFF7B7 +:1008E00011FC00BD20BFFDE7064B1847064A10600B +:1008F000016881F30888406800470000680900002B +:10090000680900001F030000000000201EF0040F13 +:100910000CBFEFF30881EFF3098188690238007892 +:10092000182803D100E00000074A1047074A126860 +:100930002C3212681047000000B5054B1B68054AB1 +:100940009B58984700BD00000703000000000020EE +:100950005809000004000000001000000000000022 +:0809600000FFFFFF0090D0032F +:10100000E8120020111D0200152F0000831C0200B1 +:10101000152F0000152F0000152F00000000000004 +:10102000000000000000000000000000691D020038 +:10103000152F000000000000152F0000152F0000E4 +:10104000D11D0200D71D0200152F0000152F000032 +:10105000152F0000152F0000152F0000152F000080 +:10106000DD1D0200152F0000152F0000E31D0200FA +:10107000152F0000E91D0200EF1D0200F51D020002 +:10108000152F0000152F0000152F0000152F000050 +:10109000152F0000152F0000152F0000152F000040 +:1010A000152F0000FB1D0200152F0000152F00005A +:1010B000152F0000152F0000152F0000152F000020 +:1010C000011E0200152F0000152F0000152F000033 +:1010D000152F0000152F0000152F0000152F000000 +:1010E000152F0000152F0000152F0000152F0000F0 +:1010F000152F0000152F0000152F0000152F0000E0 +:10110000152F0000152F000000F002F820F0EDFD73 +:101110000AA090E8000C82448344AAF10107DA4552 +:1011200001D120F0E2FDAFF2090EBAE80F0013F092 +:10113000010F18BFFB1A43F0010318471C130200EC +:101140003C1302000A444FF0000C10F8013B13F06E +:10115000070408BF10F8014B1D1108BF10F8015B10 +:10116000641E05D010F8016B641E01F8016BF9D103 +:1011700013F0080F1EBF10F8014BAD1C0C1B09D15A +:101180006D1E58BF01F801CBFAD505E014F8016BCC +:1011900001F8016B6D1EF9D59142D6D3704700005E +:1011A0000023002400250026103A28BF78C1FBD870 +:1011B000520728BF30C148BF0B6070471FB500F011 +:1011C0003DF88DE80F001FBD1EF0040F0CBFEFF3BC +:1011D0000880EFF30980014A104700006F2E0000DD +:1011E0008269034981614FF001001044704700009B +:1011F000F511000001B41EB400B512F0AFFD01B44A +:101200000198864601BC01B01EBD0000F0B4404606 +:10121000494652465B460FB402A0013001B506486C +:10122000004700BF01BC86460FBC804689469246F7 +:101230009B46F0BC704700000911000020F052BD31 +:1012400070B51A4C054609202070A01C00F05FF80C +:101250005920A08029462046BDE8704007F0F1BF24 +:1012600007F0FABF70B50C461149097829B1A0F111 +:101270006001552908D3012013E0602804D06928B3 +:1012800002D043F201000CE020CC0A4E94E80E009C +:1012900006EB8000A0F58050241FD0F8806E284611 +:1012A000B047206070BD012070470000080000209A +:1012B0001C0000204C1E020010B504460021012035 +:1012C00000F03BF800210B2000F037F80421192032 +:1012D00000F033F804210D2000F02FF804210E2037 +:1012E00000F02BF804210F2000F027F80421C84358 +:1012F00000F023F80621162000F01FF80621152023 +:1013000000F01BF82046FFF79BFF002010BD9D2139 +:1013100001807047FFF7A4BF10487047104A10B50E +:1013200014680F4B0F4A08331A60FFF79BFF0C48F5 +:10133000001D046010BD704770474907090E002862 +:1013400006DA00F00F0000F1E02080F8141D70476D +:1013500000F1E02080F800147047000003F900421B +:101360001005024001000001FE48002101604160BB +:10137000018170472DE9F743044692B091464068D9 +:1013800012F0B2FF40B1606812F0B7FF20B9607888 +:1013900000F00300022801D0012000E00020F14EFF +:1013A0004D463072484612F05BFF18B1102015B060 +:1013B000BDE8F0832946012001F029FF0028F6D17D +:1013C00001258DF842504FF4C050ADF84000002286 +:1013D00010A9284606F0FAFB0028E8D18DF8425003 +:1013E0004FF428504FF00008ADF8400047461C214C +:1013F0006846CDF81C8020F018FC9DF81C0008AA57 +:1014000020F00F00401C20F0F00010308DF81C0080 +:1014100020788DF81D0061789DF81E0061F3420070 +:1014200040F001008DF81E009DF800000AA940F070 +:1014300002008DF800002089ADF83000ADF8327060 +:10144000608907AFADF834000B97606810AC0E9060 +:101450000A94684606F0AFF90028A8D1BDF820002C +:1014600030808DF8425042F60120ADF840009DF8E2 +:101470001E0008AA20F00600801C20F001008DF854 +:101480001E000220ADF83000ADF8340013A80E9015 +:101490000AA9684606F08FF9002888D1BDF8200017 +:1014A0007080311D484600F033F9002887D18DF84F +:1014B000425042F6A620ADF840001C216846CDF807 +:1014C0001C8020F0B2FB9DF81C00ADF8345020F0D9 +:1014D0000F00401C20F0F00010308DF81C009DF82B +:1014E0001D0008AA20F0FF008DF81D009DF81E00C9 +:1014F0000AA920F0060040F00100801C8DF81E00B3 +:101500009DF800008DF8445040F002008DF8000076 +:10151000CDE90A4711A80E90ADF83050684606F0A4 +:101520004AF9002899D1BDF82000F08000203EE75C +:101530003EB504460820ADF80000204612F090FEAB +:1015400008B110203EBD2146012001F060FE0028B8 +:10155000F8D12088ADF804006088ADF80600A088B6 +:10156000ADF80800E088ADF80A007E4801AB6A4695 +:101570008088002106F024FDBDF800100829E1D084 +:1015800003203EBD1FB50446002002900820ADF8A0 +:101590000800CDF80CD0204612F062FE10B11020E9 +:1015A00004B010BD6F4802AA81884FF6FF7006F0A4 +:1015B0004EFF0028F4D1BDF80810082901D00320FF +:1015C000EEE7BDF800102180BDF802106180BDF883 +:1015D0000410A180BDF80610E180E1E701B582B0FA +:1015E0000220ADF800005F4802AB6A464088002147 +:1015F00006F0E6FCBDF80010022900D003200EBD65 +:101600001CB5002100910221ADF80010019012F0EC +:101610004DFE08B110201CBD52486A4641884FF665 +:10162000FF7006F014FFBDF800100229F3D003206C +:101630001CBDFEB54B4C06461546207A0F46C0072A +:1016400005D0084612F00CFE18B11020FEBD0F2088 +:10165000FEBDF82D01D90C20FEBD304612F000FE73 +:1016600018BB208801A905F0ECFD0028F4D13078E2 +:101670008DF80500208801A906F081FC0028EBD137 +:1016800000909DF800009DF8051040F002008DF8D4 +:101690000000090703D040F008008DF80000208802 +:1016A000694606F009FC0028D6D1ADF8085020881C +:1016B0003B4602AA002106F083FCBDF80810A942AF +:1016C000CAD00320FEBD7CB50546002000900190E5 +:1016D0000888ADF800000C462846019512F004FE7B +:1016E00018B9204612F0E2FD08B110207CBD15B1FA +:1016F000BDF8000050B11B486A4601884FF6FF70E4 +:1017000006F0A5FEBDF8001021807CBD0C207CBD3C +:1017100030B593B0044600200D460090142101A876 +:1017200020F083FA1C2108A820F07FFA9DF8000021 +:10173000CDF808D020F00F00401C20F0F000103051 +:101740008DF800009DF8010020F0FF008DF80100E9 +:101750009DF8200040F002008DF8200001208DF857 +:10176000460001E0E201002042F60420ADF844000A +:1017700011A801902088ADF83C006088ADF83E00CB +:10178000A088ADF84000E088ADF842009DF8020066 +:1017900006AA20F00600801C20F001008DF802004F +:1017A0000820ADF80C00ADF810000FA8059001A9B5 +:1017B00008A806F000F8002803D1BDF8180028801A +:1017C000002013B030BD0000F0B5007B059F1E4621 +:1017D00014460D46012800D0FFDF0C2030803A204F +:1017E0003880002C08D0287A052806D0287B0128CC +:1017F00000D0FFDF17206081F0BDA889FBE72DE94D +:10180000F04786B0144691F80C900E9A0D46B9F147 +:10181000010F0BD01021007B2E8A8846052807D0A7 +:10182000062833D0FFDF06B0BDE8F0870221F2E7DB +:10183000E8890C2100EB400001EB400018803320C8 +:101840001080002CEFD0E889608100271AE0009614 +:10185000688808F1020301AA696900F07AFF06EBC3 +:101860000800801C07EB470186B204EB4102BDF87B +:10187000040090810DF1060140460E3210F04CFD3F +:101880007F1CBFB26089B842E1D8CCE73420108019 +:10189000E889B9F1010F11D0122148430E301880A8 +:1018A000002CC0D0E88960814846B9F1010F00D012 +:1018B0000220207300270DF1040A1FE00621ECE747 +:1018C0000096688808F1020301AA696900F041FFE7 +:1018D00006EB0800801C86B2B9F1010F12D007EBAD +:1018E000C70004EB4000BDF80410C18110220AF1CA +:1018F0000201103020F000F97F1CBFB26089B842AD +:10190000DED890E707EB470104EB4102BDF8040085 +:10191000D0810AF102014046103210F0FDFCEBE7E5 +:101920002DE9F0470E4688B090F80CC096F80C8070 +:10193000378AF5890C20109902F10C044FF0000A47 +:10194000BCF1030F08D0BCF1040F3ED0BCF1070F6F +:101950007DD0FFDF08B067E705EB850C00EB4C009E +:10196000188031200880002AF4D0A8F1060000F089 +:10197000FF09558125E0182101A820F056F90097AC +:101980007088434601AA716900F0E3FEBDF80400C7 +:101990002080BDF80600E080BDF808002081A21C70 +:1019A0000DF10A01484610F0B7FCB9F1000F00D064 +:1019B00018B184F804A0A4F802A007EB080087B2CD +:1019C0000A346D1EADB2D6D2C4E705EB850C00EB30 +:1019D0004C00188032200880002ABBD0A8F10500F6 +:1019E00000F0FF09558137E000977088434601AA4F +:1019F000716900F0AEFE9DF80600BDF80410E180AC +:101A00002179420860F3000162F34101820862F328 +:101A10008201C20862F3C301020962F304114209A0 +:101A200062F34511820962F386112171C009607168 +:101A3000BDF80700208122460DF10901484610F04B +:101A40006BFC18B184F802A0A4F800A000E007E045 +:101A500007EB080087B20A346D1EADB2C4D279E735 +:101A6000A8F1020084B205FB08F000F10E0CA3F807 +:101A700000C035230B80002AA6D0558194810097A1 +:101A800083B270880E32716900F063FE62E72DE95F +:101A9000F84F1E460A9D0C4681462AB1607A00F531 +:101AA0008070D080E089108199F80C000C274FF0ED +:101AB00000084FF00E0A0D2873D2DFE800F09E07F1 +:101AC0000E1C28303846556A737373002146484609 +:101AD0000095FFF779FEBDE8F88F207B9146082836 +:101AE00002D0032800D0FFDF378030200AE000BF9B +:101AF000A9F80A80EFE7207B9146042800D0FFDF99 +:101B0000378031202880B9F1000FF1D1E3E7207B45 +:101B10009146042800D0FFDF37803220F2E7207B97 +:101B20009146022800D0FFDF37803320EAE7207B90 +:101B30001746022800D0FFDF3420A6F800A0288036 +:101B4000002FC8D0A7F80A80C5E7207B17460428D5 +:101B500000D0FFDF3520A6F800A02880002FBAD0E3 +:101B60004046A7F80A8012E0207B1746052802D0DD +:101B7000062800D0FFDF1020308036202880002F7C +:101B8000A9D0E0897881A7F80E80B9F80E00B88155 +:101B9000A1E7207B9146072800D0FFDF3780372060 +:101BA000B0E72AE04FF0120018804FF0380017001D +:101BB000288090D0E0897881A7F80E80A7F810805F +:101BC00099F80C000A2805D00B2809D00C280DD054 +:101BD000FFDF80E7207B0C2800D0FFDF01200AE038 +:101BE000207B0D2800D0FFDF042004E0207B0E289E +:101BF00000D0FFDF052038736DE7FFDF6BE770B5BE +:101C00000C46054601F076FA20B10078222804D26D +:101C1000082070BD43F2020070BD052128460EF079 +:101C20001DFF206008B1002070BD032070BD2DE9AC +:101C3000FF4784B00027824602970798904689465E +:101C400012300AF0E2F8401D20F00306079828B988 +:101C500007A95046FFF7D3FF002853D1B9F1000F71 +:101C600005D00798017B19BB052504681BE098F88F +:101C70000000092803D00F2812D0FFDF45E00799A4 +:101C800003254868B0B3497B42887143914238D9F3 +:101C90008AB2B3B2011D0EF03AFD0446078002E09D +:101CA000079C042508340CB1208810B1032D28D0DE +:101CB0002BE00798012112300AF0DFF8ADF80C0094 +:101CC000024602AB2946504608F0B1F9070001D19F +:101CD000A01C029007983A461230C8F80400A8F8F1 +:101CE00002A003A94046029B0AF0D4F8C0B107281D +:101CF00014D200E005E0DFE800F0060811110F0A39 +:101D00000C00132026E6002024E6112022E60820FD +:101D100020E643F203001DE607201BE6032019E638 +:101D2000BDF80C002346CDE900702A4650460799BD +:101D300000F035FD57B9032D08D10798B3B2417BA8 +:101D4000406871438AB2011D0EF0F5FCB9F1000F35 +:101D5000D9D0079981F80C90D5E72DE9FE4F91462F +:101D60001A881C468A468046FAB102AB494608F0FA +:101D70005EF9050019D04046A61C27880EF08AFFA0 +:101D80003246072629463B4600960EF049FB20883E +:101D90002346CDE900504A465146404600F0FFFC3C +:101DA000002020800120BDE8FE8F0020FBE710B559 +:101DB00086B01C46AAB104238DF800301388ADF814 +:101DC00008305288ADF80A208A788DF80E200988EC +:101DD000ADF80C1000236A462146FFF728FF06B035 +:101DE00010BD1020FBE770B50D4605210EF036FE44 +:101DF000040000D1FFDF294604F11200BDE8704065 +:101E00000AF024B82DE9F8430D468046002607F075 +:101E1000CCFA0446287812287BD2DFE800F07A5406 +:101E2000543C355632321332323209323232323287 +:101E30002879001FC0B2022801D0102810D114BB8D +:101E4000FFDF35E004B9FFDF052140460EF006FE56 +:101E5000007B032806D004280BD0072828D0FFDFFA +:101E6000072657E02879801FC0B2022820D050B141 +:101E7000F6E72879401FC0B2022819D0102817D0E1 +:101E8000EEE704B9FFDF13E004B9FFDF287901288A +:101E90000ED1172139E0052140460EF0DFFD070085 +:101EA00000D1FFDF07F11201404609F0A6FF2CB177 +:101EB0002A462146404600F05CFC2BE013214046B8 +:101EC00002F0AAFC26E0FFDF24E004B9FFDF0521D1 +:101ED00040460EF0C3FD060000D1FFDF694606F163 +:101EE000120009F094FF060000D0FFDFA98817292F +:101EF00001D2172200E00A46BDF80000824202D952 +:101F0000014602E005E01729C3D3404600F057FC24 +:101F1000CEE7FFDF3046BDE8F883401D20F0030226 +:101F200019B102FB01F0001D00E0002010447047D1 +:101F300013B5009850B100244FEA0D000EF091FB4C +:101F4000002C02D1F84A009911601CBD0124002028 +:101F5000F4E72DE9F0470C461546242120461FF0F2 +:101F600064FE05B9FFDFA87860732888DFF8B8A39E +:101F7000401D20F00301AF788946DAF800000EF02A +:101F80008EFB060000D1FFDF4FF000082660A6F8A8 +:101F9000008077B109FB07F1091D0AD0DAF80000CB +:101FA0000EF07DFB060000D1FFDF6660C6F8008002 +:101FB00001E0C4F80480298804F11200BDE8F0476C +:101FC00009F00DBF2DE9F047804601F112000D46E2 +:101FD000814609F01AFF401DD34F20F003026E7BAB +:101FE0001446296838680EF085FB3EB104FB06F202 +:101FF000121D03D0696838680EF07CFB05200EF0D6 +:10200000D7FC044605200EF0DBFC201A012802D183 +:1020100038680EF039FB49464046BDE8F04709F004 +:10202000F3BE70B5054605210EF018FD040000D181 +:10203000FFDF04F112012846BDE8704009F0DDBE63 +:102040002DE9F04F91B04FF0000BADF834B0ADF882 +:1020500004B047880C4605469246052138460EF0E6 +:10206000FDFC060000D1FFDF24B1A780A4F806B074 +:10207000A4F808B0297809220B20B2EB111F297AA5 +:102080007DD104F110023827C91E4FF00C094FF022 +:10209000010803920F2973D2DFE801F0F4F3F28113 +:1020A00008D48A8FA13DDDF5F0B8B800307B022856 +:1020B00000D0FFDFA88909EBC001ADF80410302182 +:1020C000ADF83410002C25D06081B5F80E900027B3 +:1020D0001DE004EBC708317C88F80E10F189A8F8E0 +:1020E0000C10CDF800906888042304AA296900F038 +:1020F00030FBBDF81010A8F8101009F10400BDF86D +:1021000012107F1C1FFA80F9A8F81210BFB2608964 +:10211000B842DED80FE1307B022800D0FFDFE9892A +:1021200009EBC100ADF804003020ADF83400287B85 +:102130000A90001FC0B20F90002CEBD06181B5F85F +:102140001090002727E000BFCDF8009068886969EB +:1021500003AA0A9B00F0FDFA0A9904EBC70809EBF1 +:1021600001001FFA80F908F10C0204A90F9810F081 +:10217000D3F818B188F80EB0A8F80CB001E0D7E099 +:10218000D4E0BDF80C10A8F81010BDF80E107F1C9C +:10219000A8F81210BFB26089B842D5D8CBE00DA81C +:1021A000009001AB224629463046FFF728FBC2E0EB +:1021B000307B082805D0FFDF03E0307B082800D003 +:1021C000FFDFE8891030ADF804003620ADF83400A8 +:1021D000002C3FD0A9896181F189A18127E0307B62 +:1021E000092800D0FFDFA88900F10C01ADF8041028 +:1021F0003721ADF83410002C2CD06081E889009094 +:10220000AB89688804F10C02296956E0E889392114 +:10221000103080B2ADF80400ADF83410002C74D04A +:10222000A9896181287A10280AD002212173E989BD +:10223000E181288A0090EB8968886969039A3CE00B +:102240000121F3E70DA8009001AB22462946304654 +:10225000FFF766FB6FE0307B0A2800D0FFDF12201B +:10226000ADF80400ADF834704CB3A9896181A4F8CD +:1022700010B0A4F80EB084F80C805CE020E002E01E +:1022800031E039E042E0307B0B2800D0FFDF288AC4 +:10229000ADF834701230ADF8040084B1042121731C +:1022A000A9896181E989E181298A2182688A00906E +:1022B0002B8A688804F11202696900F04AFA3AE050 +:1022C000307B0C2800D0FFDF1220ADF80400ADF801 +:1022D00034703CB305212173A4F80AB0A4F80EB001 +:1022E000A4F810B027E00DA8009001AB22462946C3 +:1022F0003046FFF769FA1EE00DA8009001AB2246B8 +:1023000029463046FFF7C3FB15E036E03B21ADF828 +:102310000400ADF8341084B3A4F80680A4F808B023 +:1023200084F80AB007E0000010000020FFDF02E0A0 +:10233000012919D0FFDFBDF80400AAF800007CB124 +:10234000BDF834002080BDF804006080BDF8340082 +:10235000392805D03B2803D03C2801D086F80CB0A2 +:1023600011B00020BDE8F08F3C21ADF80400ADF8BD +:10237000341014B1697AA172DDE7FFE7AAF8000012 +:10238000EEE72DE9F84356880F46804615460521AD +:1023900030460EF063FB040000D1FFDF12340094DE +:1023A0003B46414630466A6809F02EFFB3E570B5FA +:1023B0000D4605210EF052FB040000D1FFDF294637 +:1023C00004F11200BDE8704009F02CBD70B50D4657 +:1023D00005210EF043FB040000D1FFDF294604F184 +:1023E0001200BDE8704009F050BD70B505460521EA +:1023F0000EF034FB040000D1FFDF04F10803214696 +:102400002846BDE870400422A7E470B505460521C2 +:102410000EF024FB040000D1FFDF2146284623688C +:10242000BDE87040052298E470B5064605210EF01F +:1024300015FB040000D1FFDF04F1120009F0E5FCF8 +:10244000401D20F0030511E0011D00880322431800 +:1024500021463046FFF781FC00280BD0607BABB2F1 +:10246000684382B26068011D0EF09BF96068418884 +:102470000029E9D170BD70B50E46054606F095FFFE +:10248000040000D1FFDF0120207266726580207891 +:1024900020F00F00C01C20F0F00030302070BDE8AC +:1024A000704006F085BF2DE9F0438BB00D46144611 +:1024B000814606A9FFF7A3FB002814D14FF6FF764B +:1024C00001274FF420588CB103208DF80000102014 +:1024D000ADF8100007A8059007AA204604A90FF040 +:1024E0003AFF78B107200BB0BDE8F0830820ADF8C3 +:1024F00008508DF80E708DF80000ADF80A60ADF848 +:102500000C800CE00698A17801742188C1818DF8B7 +:102510000E70ADF80850ADF80C80ADF80A606A4650 +:1025200002214846069BFFF782FBDCE708B5012243 +:102530008DF8022042F60202ADF800200A4603237D +:102540006946FFF734FC08BD08B501228DF802206A +:1025500042F60302ADF800200A4604236946FFF75D +:1025600026FC08BD00B587B079B102228DF80020A5 +:102570000A88ADF808204988ADF80A1000236A4699 +:102580000521FFF754FB07B000BD1020FBE709B1A0 +:1025900007230CE40720704770B588B00D46144639 +:1025A000064606A9FFF72BFB00280ED17CB10620BA +:1025B000ADF808508DF80000ADF80A40069B6A4659 +:1025C0000821DC813046FFF732FB08B070BD0520E2 +:1025D0008DF80000ADF80850F0E700B587B059B1AC +:1025E00007238DF80030ADF80820039100236A46D8 +:1025F0000921FFF71CFBC6E71020C4E770B588B0BF +:102600000C460646002506A9FFF7F9FA0028DCD19A +:1026100006980121123009F030FC9CB1217806297E +:1026200021D2DFE801F0200505160318801E80B2D4 +:10263000C01EE28880B20AB1A3681BB1824203D9EE +:102640000C20C2E71020C0E7042904D0A08850B9AC +:1026500001E00620B9E7012913D0022905D0042999 +:102660001CD005292AD00720AFE709208DF80000EB +:102670006088ADF80800E088ADF80A00A068039013 +:1026800023E00C208DF800006088ADF80800E08899 +:10269000ADF80A00A0680A25039016E00D208DF819 +:1026A00000006088ADF80800A088ADF80A00E08856 +:1026B000ADF80C00A0680B25049006E00E208DF804 +:1026C000000060788DF808000C256A4629463046DF +:1026D000069BFFF7ACFA78E700B587B00F228DF8BC +:1026E0000020ADF8081000236A461946FFF79FFA4C +:1026F00049E700B587B071B102228DF800200A8841 +:10270000ADF808204988ADF80A1000236A46062172 +:10271000FFF78DFA37E7102035E770B586B006462B +:1027200001200D46ADF808108DF800000146002389 +:102730006A463046FFF77BFA040008D12946304646 +:1027400005F058FC0021304605F072FC204606B02A +:1027500070BDF8B51C4615460E46069F0EF088FA69 +:102760002346FF1DBCB231462A4600940DF01FFEE1 +:10277000F8BD10B548800878144620F00F00C01C42 +:1027800020F0F00090300B4608701822214603F12B +:1027900008001FF0F6F9BDE8104006F009BE30B49D +:1027A0001146DDE902423CB1032903D0002330BCCD +:1027B00008F0D3BA0123FAE71A8030BC704770B52D +:1027C0000C460546FFF70FFB2146284605F021FC85 +:1027D0002846BDE87040012105F02ABC4FF0E022F8 +:1027E0004FF400410020C2F88011204908702049B0 +:1027F00090020860704730B51C4D04462878A0420E +:1028000018BF002C02D0002818BFFFDF2878A04294 +:1028100008BF30BD2C701749154A0020ECB1164D89 +:10282000DFF858C0131F012C0DD0022C1CBFFFDF96 +:1028300030BD086003200860CCF800504FF4000061 +:102840001060186030BD086002200860CCF80050AD +:102850004FF040701060186030BD086008604FF0A5 +:102860006070106030BD00B5FFDF00BD18000020B3 +:1028700008F5014000F500402403002014F5004055 +:1028800070B50B2000F0B5F9082000F0B2F9002176 +:102890000B2000F0C4F90021082000F0C0F9EC4C36 +:1028A00001256560A5600020C4F84001C4F844011A +:1028B000C4F848010B2000F0A7F9082000F0A4F9A3 +:1028C0000B2000F08BF9256070BD10B50B2000F0D7 +:1028D00090F9082000F08DF9DD4801214160816008 +:1028E000DC490A68002AFCD10021C0F84011C0F878 +:1028F0004411C0F848110B2000F086F9BDE81040E3 +:10290000082000F081B910B50B2000F07DF9BDE87A +:102910001040082000F078B900B530B1012806D089 +:10292000022806D0FFDF002000BDCB4800BDCB4809 +:1029300000BDCA48001D00BD70B5C9494FF0004038 +:102940000860C84DC00BC5F80803C74800240460E0 +:10295000C5F840410820C43500F04BF9C5F83C41AA +:10296000C248047070BD08B5B94A002128B10128D9 +:1029700011D002281CD0FFDF08BD4FF48030C2F810 +:102980000803C2F84803B3483C300160C2F8401164 +:10299000BDE80840D0E74FF40030C2F80803C2F8A1 +:1029A0004803AC4840300160C2F84411AB480CE029 +:1029B0004FF48020C2F80803C2F84803A548443009 +:1029C0000160C2F84811A548001D0068009008BDCC +:1029D00070B516460D460446022800D9FFDF0022D6 +:1029E0009B48012304F110018B4000EB8401C1F8E6 +:1029F000405526B1C1F84021C0F8043303E0C0F8C7 +:102A00000833C1F84021C0F8443370BD2DE9F041CE +:102A10001C46154630B1012834D0022839D0FFDFDA +:102A2000BDE8F081891E002221F07F411046FFF7AA +:102A3000CFFF012C24D000208C4E8A4F01247070CF +:102A40003C61894900203C3908600220091D08606A +:102A5000854904203039086083483D350560C7F852 +:102A60000042082000F0D0F82004C7F80403082032 +:102A700000F0B4F87A49E007091F08603470CFE726 +:102A80000120D9E7012B02D00022012005E001221C +:102A9000FBE7012B04D000220220BDE8F04197E7BC +:102AA0000122F9E76B480068704770B500F0C7F87D +:102AB000674C0546D4F840010026012809D1D4F816 +:102AC0000803C00305D54FF48030C4F80803C4F8E8 +:102AD0004061D4F8440101280CD1D4F808038003E4 +:102AE00008D54FF40030C4F80803C4F8446101204D +:102AF00010F0F6FBD4F8480101280CD1D4F80803F3 +:102B0000400308D54FF48020C4F80803C4F8486196 +:102B1000022010F0E5FB5648056070BD70B500F06E +:102B20008EF8524D0446287858B1FFF705FF6878B3 +:102B300020B1002085F8010010F0D2FB4C48046061 +:102B400070BD0320F8E74FF0E0214FF40010C1F80A +:102B500000027047152000F057B842490120086173 +:102B6000082000F051B83F494FF47C10C1F8080329 +:102B70000020024601EB8003C3F84025C3F8402142 +:102B8000401CC0B20628F5D37047410A43F60952EB +:102B90005143C0F3080010FB02F000F5807001EB18 +:102BA0005020704710B5430B48F2376463431B0C49 +:102BB0005C020C602F4C03FB04002F4B4CF2F724FB +:102BC00043435B0D13FB04F404EB402000F58070DD +:102BD0004012107008681844086010BD00F01F0211 +:102BE000012191404009800000F1E020C0F800116F +:102BF000704700F01F02012191404009800000F160 +:102C0000E020C0F88011704700F01F0201219140C0 +:102C10004009800000F1E020C0F8801270474907A9 +:102C2000090E002806DA00F00F0000F1E02080F81D +:102C3000141D704700F1E02080F8001470470C4824 +:102C4000001F00680A4A0D49121D116070470000FC +:102C500000B0004004B500404081004044B1004055 +:102C600008F501400080004040850040340000200D +:102C700014050240F7C2FFFF6F0C010001000001C4 +:102C80000A4810B50468094909480831086010F07D +:102C9000BBFB0648001D046010BD0649002008600B +:102CA0004FF0E0210220C1F8800270471005024079 +:102CB00001000001FC1F004010B50D2000F06FF86E +:102CC000C4B26FF0040000F06AF8C0B2844200D0D1 +:102CD000FFDF3A490120086010BD70B50D2000F0FB +:102CE00048F8374C0020C4F800010125C4F804530B +:102CF0000D2000F049F825604FF0E0216014C1F884 +:102D0000000170BD10B50D2000F033F82C480121F2 +:102D100041600021C0F80011BDE810400D2000F016 +:102D200033B8284810B50468264927480831086098 +:102D30002349D1F80001012804D0FFDF2148001DFC +:102D4000046010BD1D48001D00680022C0B2C1F81B +:102D5000002110F074FFF1E710B51948D0F8001108 +:102D60000029FBD0FFF7DDFFBDE810400D2000F08B +:102D70000BB800F01F02012191404009800000F1D2 +:102D8000E020C0F88011704700F01F02012191403F +:102D90004009800000F1E020C0F880127047002850 +:102DA00006DA00F00F0000F1E02090F8140D03E0C7 +:102DB00000F1E02090F800044009704704D500407D +:102DC00000D00040100502400100000110B5202095 +:102DD00000F075F8202000F07DF84449202081F8AB +:102DE0000004434900060860091D42480860FEF7D8 +:102DF00093FA3F49C83108603F48D0F8041341F0C6 +:102E00000101C0F80413D0F8041341F08071C0F838 +:102E10000413364901201C39C1F8000110BD10B55A +:102E2000202000F04CF8324800210160001D0160B4 +:102E30002F4A481EE83A10602F4AC2F808032C4B6C +:102E4000C8331960C2F80001C2F860012B4908605C +:102E5000BDE81040202000F03DB825492848EC3955 +:102E60000860704722492648E8390860704770B505 +:102E70001F4A8069E83A224911601F49D1F8006170 +:102E80000023204D1D4A5C1E1EB1A84206D300211E +:102E90000FE0D1F8606186B1A84209D2C1F80031D3 +:102EA000C1F860311460BDE87040202000F012B815 +:102EB0001168BDE870401EF0E3BEFFDF70BD00F09A +:102EC0001F02012191404009800000F1E020C0F87C +:102ED0008011704700F01F020121914040098000DD +:102EE00000F1E020C0F880127047000020E000E010 +:102EF000000602406413002000000240000402406B +:102F000001000001003002000F4A12680D498A4298 +:102F10000CD118470C4A12680A4B9A4206D101B5E7 +:102F200010F00EFFFFF799FFBDE80140074909685F +:102F30000958084706480749054A064B70470000EC +:102F400000000000BEBAFECAB0000020040000204D +:102F5000E8120020E812002070B50C46054609F082 +:102F6000F0FA21462846BDE870400AF0E2BB10B5F1 +:102F700011F054FBFFF732FC11F0F0F9BDE81040FE +:102F800011F0A2BA01208107086070470120810773 +:102F90004860704712480068C00700D001207047A1 +:102FA0000F48001F0068C00700D0012070470C4880 +:102FB00008300068C00700D0012070470848103072 +:102FC0000068704706490C310A68D20306D50968C3 +:102FD00001F00301814201D10120704700207047B8 +:102FE0000C0400407047704770477047704702F00C +:102FF000FF0343EA032242EA02421EF0F6BD704795 +:103000002CFFFFFFDBE5B151003002009D00FFFF08 +:1030100084000000404B4C0066D342DA82CFB49D5E +:10302000E40AD77E68976592800939FF30B5FF4D75 +:10303000044610280AD0112C06D02846122CC1783C +:1030400006D0132C08D0FFDFEC7030BDFFDFFBE7AC +:103050001129F9D0FFDFF7E71129F5D0FFDFF3E7FA +:1030600070B50FF0E3FA044610F0A0FC201AC4B2C9 +:1030700006200DF09DFC054606200DF0A1FC2E1A41 +:1030800007200DF095FC054607200DF099FCE74957 +:10309000281A3218C87812280DD000231A44132891 +:1030A0000BD0002002440878022808D000201044E9 +:1030B000201AC0B270BD0123F0E70120F2E7012021 +:1030C000F5E7DA4800B58079D849420897B051F859 +:1030D000070F89880CD017228DF80020CDF8020048 +:1030E000ADF806100BA968460AF0B4FF17B000BD92 +:1030F0004422F1E702210DF0B1BC2DE9F04196B078 +:103100001D4690460E460746FFF7F4FF04000BD01D +:103110002078222804D3A07FC0F34010A84206D113 +:10312000082016B0BDE8F08143F20200F9E749201B +:103130008DF80000ADF802703DB101208DF804005B +:103140008DF805608DF8068002E000208DF80400FF +:103150000BA968460AF07EFFA07F65F34510A077B3 +:103160000020DEE730B50446A1F120000D460A2814 +:103170004AD2DFE800F005070C1C2328353A3F440B +:10318000FFDF42E0207820283FD1FFDF3DE0A74865 +:103190000178032939D0C078132836D02078242824 +:1031A00033D0252831D023282FD0FFDF2DE0207801 +:1031B00022282AD0232828D8FFDF26E020782228BA +:1031C00023D0FFDF21E0207822281ED024281CD025 +:1031D00026281AD0272818D0292816D0FFDF14E077 +:1031E0002078252811D0FFDF0FE0207825280CD08B +:1031F000FFDF0AE02078252807D0FFDF05E02078F0 +:10320000282802D0FFDF00E0FFDF257030BD30B599 +:103210000B8840F67B444FF6FF72022801D09342A0 +:1032200004D09D1FA54224D2022802D04D88954289 +:1032300003D04D88AD1FA5421BD24C88A34218D89D +:103240008B88B3F5FA7F14D2022802D0C888904246 +:1032500005D0C88840F677450A38A84209D2C88800 +:10326000904208D0944206D05B1C6343B3EB800FBE +:1032700001DB072030BD002030BD70B514460D467F +:10328000064610F0EDFF60B90DB1A54201D90C2042 +:1032900070BD002409E000BF56F8240010F0E0FFE4 +:1032A00008B1102070BD641CE4B2AC42F4D300201D +:1032B00070BDF0B50024059D10B1A94203D850E0BF +:1032C00009B90020F0BD0920F0BD055DD5B1071991 +:1032D00097F801C0BCF1150F2DD03BDCBCF1150FE8 +:1032E00038D2DFE80CF037122020262628282F2F8E +:1032F000373737373737373737372000025D22BB4C +:10330000641CE4B28C42F9D3DBE7022DDBD1BD783B +:103310001D70072D01D26D0701D40A20F0BD15786C +:1033200045F0010515E0EF43FF0707E0012D07D049 +:1033300010E00620F0BD2F07A7F18057002FF5D031 +:103340003046F0BD1578AF0701D50B20F0BD45F034 +:1033500002051570055D641C2C44E4B28C4202D950 +:10336000B1E74FF448568C42AFD3AAE710B50278C4 +:10337000540809D0012243F20223012C07D0022C69 +:103380000DD0032C13D10FE00020087005E08079E8 +:103390000324B4EB901F0AD10A70002010BD80797D +:1033A000B2EB901F03D1F7E780798009F4D018467B +:1033B00010BD1E4A117C39B1517C022908D0032965 +:1033C00008D043F2022070470146901D01F0FCBC7A +:1033D000032100E0012101700020704738B50C4640 +:1033E0000546694601F0F0FC00280DD19DF800105B +:1033F000207861F34700207055F8010FC4F80100F0 +:10340000A888A4F80500002038BD38B51378E8B1C5 +:1034100002281BD006A46D46246800944C7905EB65 +:103420009414247864F34703137003E0CC01002064 +:103430000302FF0103280ED003F0FE00107008689D +:10344000C2F801008888A2F8050038BD23F0FE0309 +:1034500013700228E9D1D8B240F00100EEE730B590 +:103460000C46097897B0222902D2082017B030BD47 +:1034700028218DF80010ADF80200132A03D03B2A52 +:1034800001D00720F2E78DF804200BA968460AF066 +:10349000E1FD050003D121212046FFF763FE284608 +:1034A000E4E700B597B023218DF80010ADF80200D5 +:1034B0001088ADF804005088ADF80600D088ADF84B +:1034C0000A009088ADF808000020ADF80C00ADF8B7 +:1034D0000E000BA968460AF0BDFD07E600B597B0DF +:1034E0002C22FA4968461EF04CFB0020CDF8030060 +:1034F000ADF80700F648007C022801D0012000E06A +:1035000000208DF809000BA968460AF0A3FD0028E9 +:1035100000D0FFDFEAE52DE9FF470220EC4E8DF8F1 +:1035200004000027B08AADF80600B84643F202094D +:103530004DE001A80DF0FBF9050006D0B08AA8B354 +:10354000A6F81480ADF806803FE0039CA07F010739 +:103550002DD504F124000090A28EBDF8080021466C +:1035600004F1360301F00DFE050005D04D452BD0CA +:10357000112D3DD0FFDF3BE0A07F20F00800A077B9 +:10358000E07F810861F30000C10861F34100E0774A +:1035900094F8210000F01F0084F8200020782828EB +:1035A00027D129212046FFF7DDFD22E015E0400765 +:1035B0000BD5BDF80800214604F10E02FFF771FF9C +:1035C00005000DD04D4510D100257F1CFFB2022013 +:1035D0000DF0EEF9401CB842ABD8052D12D008E032 +:1035E000A07F20F00400A07703E0112D00D0FFDFC2 +:1035F0000025BDF80600B082052D05D0284604B090 +:10360000BDE8F087A6F814800020F8E770B50646FC +:10361000FFF770FD054605F0C8FE040000D1FFDF8E +:103620006680207820F00F00801C20F0F000203011 +:1036300020700620207295F83E006072BDE8704050 +:1036400005F0B6BE2DE9F04786B0040000D1FFDFDB +:1036500020789F4E20F00F00801C20F0F00070308A +:10366000207060680178091F182931D2DFE801F065 +:10367000FD30303053FC300CFCFC40FD3030FD762A +:10368000FDFD3030FDFDFBFA86883046FFF732FD48 +:103690000546304607F05FFAE0B16068807985F84A +:1036A0003E0021212846FFF75DFD3046FEF7B9FCBC +:1036B000304603F0C3FF3146022010F085FDA87F9D +:1036C00020F01000A877FFF726FF002800D0FFDFCA +:1036D00006B095E7207820F0F0002030207006201A +:1036E0002072668060688079607205F061FED8E7BC +:1036F00085882846FFF7FEFC00B9FFDF6068807808 +:10370000012800D0FFDF6068817906B02846BDE857 +:10371000F04707F0FDBD86883046FFF7EBFC05005B +:1037200000D1FFDF05F044FE60683146C088288183 +:1037300060680089688160684089A881022010F073 +:1037400043FD0020A875A87F00F003000228BFD128 +:10375000FFF7E1FE0028BBD0FFDFB9E780783C2807 +:1037600003D0002502280AD000E00125002720B15F +:103770003C2802D0022800D0FFDF17B1B8E00127B3 +:10378000F5E705F015FE1DB1B07801F0DCFAA1E017 +:103790006568B5F804A0A879AD1C012806D0307979 +:1037A000814605F097FB070003D101E0B078F7E709 +:1037B000FFDF0022022150460DF047F9040000D13E +:1037C000FFDF22212046FFF7CDFC2879012800D019 +:1037D0000220A17F804668F30101A177288B208118 +:1037E000688B6081A88BA08184F822908DF8088076 +:1037F000B8680090F86801906A46032150460DF0C1 +:1038000024F900B9FFDFB888ADF81000B8788DF85A +:10381000120004AA052150460DF017F900B9FFDF88 +:10382000B888ADF80C00F8788DF80E0003AA0421D2 +:1038300050460DF00AF900B9FFDF062105F112002C +:1038400001F0EDFA28B36879800700D5FFDF6979C8 +:10385000E07D61F34700E075D5F80600A061688956 +:10386000A08303E05EE057E050E062E0062105F14E +:103870000C0001F0D4FAB0B1B0794108607861F37E +:1038800047006070D6F80700C4F80200B6F80B00D5 +:1038900012E0E07D20F0FE00801CE075D5F81200FB +:1038A000A061E88ADCE7607820F0FE00801C607090 +:1038B000E868C4F80200288AE080B8F1010F09D056 +:1038C000B8F1020F14D0FFDF02E70000CC1F0200A6 +:1038D000CC0100203078032800D0FFDF002108460B +:1038E00010F072FC06B00120BDE8F04701F0FAB913 +:1038F000F078132800D0FFDF0021062010F064FCD0 +:1039000006B01120BDE8F047FFF790BB06B0204697 +:10391000BDE8F04701F0E6BE05F04AFDB07C40F09E +:10392000020004E005F044FDB07C40F00400B074F7 +:10393000CEE606B0BDE8F04705F03ABD2DE9F04708 +:1039400005460078914600270209FF480C463E468E +:10395000012A6DD000234FF6FF71022A69D0072A91 +:1039600009D00A2A71D0FFDFA9F800600CB12780C6 +:103970006680002044E6D5F804C09CF80060142E50 +:103980007DD010DC04F1080204F118080F2E21D0BC +:1039900004DC042E5AD0082E57D10DE0122E6FD021 +:1039A000132EF9D11FE0153E072E4ED2DFE806F0A8 +:1039B000C14D4D099FEAB00012271026BCF8040043 +:1039C00014E11C27092694B3BCF80200A0806868A3 +:1039D00000795AE11B2709264CB30320207268683E +:1039E0004088A080C0E79CF802003C2827D0102720 +:1039F00018260CF1020CD4B1BCF80200A080BCF86F +:103A000018006082BCF818002082BCF81A00A0825E +:103A1000BCF81C00E0829CF805000CF10601FFF7E1 +:103A2000F4FC9CF8040028B10120E0739CE703E05B +:103A3000BFE0DFE00220F8E7A9F8006099E71B2764 +:103A40000926002CF8D023728EE720E11D273726A7 +:103A5000002CF1D0A18069680879491DFFF7D5FCD9 +:103A6000686890F82B00A0756868C0780428E07D2D +:103A700016D020F00100E0756968C97801E06DE0BA +:103A800011E061F34200E07569681F22C97A61F3B1 +:103A9000C700E075696840460C311EF02DF863E7F9 +:103AA00040F00100E7E71D273726002CC4D0A18095 +:103AB0006868411D0079FFF7A8FC696804F10F02EE +:103AC00001F10C00CB7A01461846FFF79EFC6868AE +:103AD000807CA0756868C178E07D61F3420020F0C9 +:103AE000F900E0751F2140461EF09FF83CE72027B3 +:103AF0001026002CA0D0A180686804F10902407A49 +:103B000020726968CB1C88781946FFF77EFC2BE78A +:103B100021270A26002C8FD0BCF80210A1806968EA +:103B200009792172696849796172817C21F0040107 +:103B300057E022270B26002C84D0BCF80400A0807C +:103B40006868807820726868807901F077F960721F +:103B50006868C07901F072F9A07205E72427102681 +:103B6000002CA3D0BCF80200A080686800792081F6 +:103B70006868007A60816868C088A0816868408948 +:103B8000E081F1E623271026002C8FD0BCF802102C +:103B9000A1806968898821816968C98861816968AB +:103BA0000989A18169684989E181817C21F002014B +:103BB00017E0297A012903D0022914D0FFDFD3E6C8 +:103BC0001F271026002C95D06988A180A989218102 +:103BD000E9896181298AA181698AE181817C21F059 +:103BE00001018174C0E6122768881026214601F081 +:103BF00003F9B9E6287A072850D2DFE800F0373D0C +:103C00003D484848040011270926002C94D0B5F8F7 +:103C100002804046FFF76EFA90F822A0A4F80480D4 +:103C2000687A2072042140460CF02AFF05214046A4 +:103C30000CF026FF002140460CF022FF01214046F7 +:103C40000CF01EFF032140460CF01AFF02214046F3 +:103C50000CF016FF062140460CF012FF07214046EB +:103C60000CF00EFF504601F06EF87DE61B2709268A +:103C7000002C8AD0A180E6E61B270926002C84D0E0 +:103C8000A180287A012800D0022020726CE64A46E2 +:103C900021462846BDE8F04701F0AFBEFFDF63E6EE +:103CA00030B5294D97B0E878132802D0082017B016 +:103CB00030BD22208DF800000BA968460AF0CAF931 +:103CC000040002D1287901F03EF80021062010F00E +:103CD0007BFA2046EBE700B51B4897B0C078122866 +:103CE00001D0082016E41E208DF8000000208DF879 +:103CF00002008DF803000BA968460AF0ABF9002812 +:103D0000F0D10021062010F05FFA1120FFF78EF9A4 +:103D10000020E7E710B50C4C96B02078012815D0AC +:103D20001B208DF8000000208DF802000BA96846CA +:103D30000AF090F900280AD10021084610F044FA50 +:103D40002078032805D007E0CC010020082016B019 +:103D500010BDA07800F0F7FF012000F0C3FF0020A5 +:103D6000F5E770B5002538B1022817D0062836D0FF +:103D7000072800D0FFDF70BDFFF7CCFF0028FAD185 +:103D800005F013FB0028F6D0017821F00F01891C03 +:103D900021F0F0012031017005723FE08EB2304613 +:103DA000FFF7A8F9040000D1FFDF20782128E2D036 +:103DB00005F0FBFA60B1017821F00F01891C21F0B8 +:103DC000F00110310170022101724680A57525E0D5 +:103DD00021463046BDE870401322FFF740BBFE4845 +:103DE000C478122C03D0132C04D0FFDF70BDFFF772 +:103DF00072FF01E0FFF754FF0028F7D105F0D5FA74 +:103E00000028F3D0017821F00F01891C21F0F00186 +:103E100020310170122C05D002210172BDE87040E2 +:103E200005F0C6BA0121F8E72DE9F04116460C006D +:103E3000804600D1FFDF307820F00F00801C20F09A +:103E4000F000103030702078012804D0022817D0FC +:103E5000FFDFBDE8F0814046FFF74CF9050000D1D7 +:103E6000FFDF0320A87505F0A3FA94E80F000836D9 +:103E700086E80F00D848817C41F001018174E8E7B1 +:103E80004046FFF737F9050000D1FFDFA1884FF664 +:103E9000FF700027814202D1E288824203D0814232 +:103EA00001D1E08840B105F083FA94E80F000836AC +:103EB00086E80F00AF75CCE7A87D0128C9D178232B +:103EC00000224146022010F0D5F80220A875C0E774 +:103ED00030B5054697B00C46084610F0C1F978BBDE +:103EE00000210120203D072D73D2DFE805F00425D5 +:103EF0004C515A6640000021072010F03BF908B1F0 +:103F00001120D4E624208DF80000D4F80200CDF86A +:103F10000200A0798DF806000BA968460AF09AF80D +:103F2000050057D1002208231146072010F0A2F8FF +:103F300007284FD0FFDF4DE0606810F0D5F908B1D9 +:103F40001020B4E64A208DF800002088ADF8020069 +:103F50006088ADF804000BA968460AF07BF80500FC +:103F600038D1606898B3BDF83010018032E04C2041 +:103F70008DF800002088ADF80200A07800F0010064 +:103F80008DF8040014E0206801F0D5FF054621E01B +:103F90004B2207E08DF802000AE000BF8DF8021006 +:103FA00006E046228DF800202278D207F6D0F1E70D +:103FB0000BA968460AF04EF8E8E738208DF80000B3 +:103FC0002088ADF802006088ADF80400F0E701E059 +:103FD000FFE7072528466AE630B5054697B00C4648 +:103FE000084610F063F908B1102060E6203D072D67 +:103FF00027D2DFE805F00424242426262400208884 +:10400000FFF778F820B10078222804D208204EE685 +:1040100043F202004BE625208DF800002088ADF821 +:1040200002000BA968460AF015F80028DDD1DDF87A +:104030003210C4F802109DF83610A17137E6062040 +:1040400035E6072033E66448801D704738B51621F1 +:1040500061481DF0C8FD012000F044FE1120FEF76C +:10406000E5FF5D4C6846E11D05F0FFF89DF8001086 +:10407000A07961F3470020F00100A07100202074B6 +:104080004FF46170E08102206074FFF71AF800B10C +:10409000FFDFFDF769F901F0E2FA38BD10B50C4613 +:1040A000402120461DF09FFDA07F20F00300A07757 +:1040B000202020700020A07584F8230010BD7047D8 +:1040C0007CB5054610F0CCF808B110207CBD424C00 +:1040D000A11DD4F806000090D4F80A0001902846EB +:1040E000FFF77CF90028F1D1FEF7EBFF0028EDD0B7 +:1040F0000099C4F80610BDF8041061819DF80610FF +:1041000021737CBD10B5044610F0D0F808B1102022 +:1041100010BD314922468879C91D4008FFF775F95D +:10412000002010BD2DE9F0479CB00D4604004FF073 +:10413000000812D00822FFF7A0F800281CD10026A2 +:1041400009E000BF54F8260004A9FFF70FF9002882 +:1041500012D1761CF6B2AE42F4D32F460A2006AD39 +:104160000DF1440A8DF8180026465146284609F0FC +:1041700071FF20B143F203201CB0BDE8F087404638 +:10418000DFF8548088F805002EB300244FF00B09A7 +:104190001DE000BF56F8240005A9FFF7E7F800B1BD +:1041A000FFDF9DF81400A87056F8240050F8011F96 +:1041B000C5F803108088A5F8070085F800905146DF +:1041C000284609F047FF00B1FFDF641CE4B2BC429F +:1041D000E0D388F8057001E0CC0100200020CBE797 +:1041E0002DE9F0479EB01546894604001DD00F46C4 +:1041F00008222946FFF741F8002810D1002612E0D6 +:1042000054F8260005A9103000F0DEFD002806D184 +:104210003FB157F8260010F023F810B110201EB05F +:10422000ABE7761CF6B2AE42EAD30026A5F1010850 +:104230001CE000BF06F1010A0AF0FF0712E000BF10 +:1042400054F82600017C4A0854F827100B7CB2EB86 +:10425000530F05D10622113011311DF021FC78B128 +:104260007F1CFFB2AF42EBD30AF0FF064645E1DB0D +:10427000C8462E4607AD0DF1480924B1012003E0E0 +:1042800043F20520CBE700208DF81E0031208DF889 +:104290001C004946284609F0DDFE38B934208DF867 +:1042A0001C004946284609F0D5FE10B143F204200F +:1042B000B5E77CB300272BE054F82700A91C103089 +:1042C00000F082FD00B1FFDF54F82700102250F803 +:1042D000111FC5F803108088A5F8070054F82710AF +:1042E00005F109001DF008FCB8F1000F16D058F8D0 +:1042F0002710102205F119001DF0FEFB3220287056 +:104300004946284609F0A6FE00B1FFDF7F1CFFB238 +:10431000B742D1D3FFF7E2F8002080E705F119009A +:1043200001F0FDFDEAE770B596B004460FF098FF86 +:1043300018B960680FF0E1FF10B1102016B070BD21 +:1043400060884AF2B811884207D82078FE4D6E4640 +:1043500028B1012806D0022804D00720EEE7FEF796 +:10436000B0FE1AE06078022804D0032802D043F29D +:104370000220E3E7687417208DF80000697C0020B4 +:10438000CDF80200ADF80600022934D003292FD061 +:10439000FFDF0BA9684609F05DFE0028CED16068FA +:1043A00001F0B0FD207870B101208DF80200F01C02 +:1043B00001F0B5FD4E208DF800000BA9684609F00C +:1043C00049FE00B1FFDF20782874FFF787F8608886 +:1043D00098B1E88180B2ADF8020030208DF800007D +:1043E0000BA9684609F036FE00B1FFDF0020A5E703 +:1043F0008DF80700CDE74020FAE74FF46170E8E759 +:1044000010B504460FF052FF20B9606838B10FF0C4 +:104410006BFF08B1102010BD606801F080FDCA4834 +:10442000C1896180417C6170007C2070002010BDDA +:104430002DE9F0419CB0054600208DF864008DF810 +:1044400060008DF830008DF868001E4614468846DE +:1044500028460FF052FF18B920460FF04EFF10B15A +:1044600010201CB0F5E455EA040018D01F270CAB4F +:1044700019AA414628460097FEF71BFF0028F0D1F5 +:104480001AAB18AA314620460097FEF712FF002803 +:10449000E7D19DF86000C00703D00A20E1E70720BC +:1044A000DFE701AF7DB11A208DF804008DF806809A +:1044B00042462946F81C1DF01FFB0DA901A809F072 +:1044C000C9FD0028CDD17CB120208DF804008DF8E5 +:1044D000066032462146F81C1DF00EFB0DA901A80E +:1044E00009F0B8FD0028BCD197499DF8300048700C +:1044F0000020B6E72DE9F0479CB08A464FF000084F +:1045000092A104468DF83480D1E90001CDE919016A +:1045100020460FF0A5FE90B92078012803D16068ED +:104520000FF09EFE58B9884D4FF00109287C40B12C +:10453000687C022805D160680FF0DFFE08B110200A +:104540001AE62878012801D0082015E607200CF08B +:1045500037FA18B9207878B101280DD0FEF780FD20 +:1045600060B1608943F6E172A0F1200191422178A7 +:104570000CD3012904D0B6E01220FDE51320FBE5A1 +:1045800000287DD1A18900297AD109E0012907D02D +:104590006978C90704D0A189002971D0B4296FD8DE +:1045A000217831B1012908D0022904D0032967D12B +:1045B0000AE0002609E0022607E008B9A08908B150 +:1045C000042609E0012607E00326287C50B1687C18 +:1045D000022807D1606828B10DA96068FEF7C6FE01 +:1045E0000028ADD1207A30B1012806D0022806D0AB +:1045F000032878D105E0002704E0012702E0022724 +:1046000000E003270EB1022E0ED16FB16879B8B366 +:104610006878800702D043F20120ADE5022E03D175 +:10462000022F60D0032F5ED0207808B1012806D178 +:10463000504600F06BFB002887D185F802A01820B7 +:104640008DF838006089ADF83A006089ADF83C001B +:104650008DF83E600DF13F00FEF7ABFE00B1FFDFCD +:104660009DF834008DF840002078012806D0287C81 +:1046700068B1687C02280AD1606840B1606800E0D7 +:1046800031E050F8011FCDF84110808802E040462B +:10469000CDF84180ADF845008DF84870A07BC0F39F +:1046A0004002014662F35F01C0F3800041EA8000EE +:1046B00019A9085C8DF84700A8B169460EA809F051 +:1046C000C9FC0028A9D11B208DF838008DF83A903C +:1046D00069460EA809F0BEFC00289ED19DF8010095 +:1046E0001B281CD101E0072046E5052E0CD2DFE88F +:1046F00006F0030308080300A87800F017FB032066 +:1047000000E0022000F0EEFA012E0AD0A08940B1AC +:1047100000228300114610460FF0ACFC08B10320C4 +:104720002AE5002028E52DE9FC4107460D46032631 +:1047300008460FF0E2FD00286CD13846FEF7DAFC9F +:1047400004000CD0207805E0CC0100200706050409 +:1047500003020100222805D20820BDE8FC8143F2B3 +:104760000200FAE7A07F00F0030C2DB12946604655 +:10477000FEF74DFD0600F0D1BCF1010F05D0BCF1F4 +:10478000020F18D0FFDF3046E7E7A07D2946022858 +:1047900001D011B107E01120DFE76846FCF7F2FE17 +:1047A0000028DAD16946384606F075FD0600EAD1E0 +:1047B0000120A075E7E7A07D032803D1FE48807C97 +:1047C000C00701D035B30EE025B1A07F40071FD44C +:1047D000002100E00121384606F07DFD0600D2D11F +:1047E000A075002DCFD02A4621463846FEF759FE47 +:1047F00006461128C7D1A07F4107C4D4296844F8D0 +:104800000E1F6968616040F0040020740026BAE75A +:104810001126B8E71020A0E770B50C460546FEF754 +:1048200069FC010005D022462846BDE87040FEF72D +:1048300016BE43F2020070BD00B597B043218DF85B +:1048400000108DF802000BA9684609F003FC17B0B0 +:1048500000BD0123FEF751BC00231A461946FEF79E +:104860004CBC30B597B004460FF0FAFC10B11020E4 +:1048700017B030BD204600F095FA0028F8D1CE4D93 +:10488000E878112801D00820F2E7FEF7E9FBE0B351 +:104890002078800701D56879C0B31D208DF800000D +:1048A0002078022200F001008DF802006088ADF847 +:1048B0000400A088ADF806002078C0F3400102EAA9 +:1048C000500001438DF8091002A8FEF772FD00B1F7 +:1048D000FFDF0BA9684609F0BDFB0028C8D11E20E8 +:1048E0008DF8000001208DF8020000208DF80300F3 +:1048F0000BA9684609F0AEFB0028B9D1E08800F0AA +:104900006DFA0400B4D1122001E004E005E0FEF7E6 +:104910008DFB2046ACE71320AAE70720A8E72DE986 +:10492000F043A54E074697B0F078994615460C46D9 +:10493000122803D1FFF7CFF9002816D120460FF037 +:104940008FFCE8BB28460FF08BFCC8BB204600F06C +:1049500029FA002809D129460220FEF758FC002830 +:1049600003D1F078112803D0082017B0BDE8F083F8 +:1049700006200CF025F850B12078800701D5707919 +:1049800038B1FEF76DFB022805D21320EDE71220A7 +:10499000EBE70720E9E721208DF800006088ADF8FB +:1049A0000200A088ADF8040020784FF00008C0F3A2 +:1049B00040008DF80600207880071FD4384600E0BC +:1049C00002E00FF04DFC08B11020CEE73878400827 +:1049D00008D0012809D0022807D0032805D043F2C7 +:1049E0000220C2E78DF8078002E001208DF8070061 +:1049F00057F8010F0290B888ADF80C000DF10E00C9 +:104A0000FEF7D7FC08B10320AFE72888ADF8100007 +:104A10006888ADF81200A888ADF81400E888ADF8F1 +:104A20001600ADF81880ADF81A80484600F06EF90F +:104A300000289AD186F804900BA9684609F00AFB71 +:104A4000002892D1307900F071F9E08800F0C6F9C1 +:104A500004008AD11320FEF7E9FA204685E730B535 +:104A6000054697B00C4608460FF020FC08B1102010 +:104A7000FEE62846FEF73EFB38B10178222902D334 +:104A8000807F800604D40820F2E643F20200EFE6BD +:104A900013208DF80000ADF802500BA9684609F00C +:104AA000D9FA0028E4D19DF932107F2901D0217074 +:104AB000DEE60520DCE630B5054697B00C46084634 +:104AC0000FF0CEFB08B11020D2E62846FEF712FB0D +:104AD00020B10078222804D20820C9E643F202005F +:104AE000C6E63548807C400701D51120C0E6207815 +:104AF000800802D16078800801D00720B8E65620EF +:104B00008DF80000ADF8025020788DF80400607830 +:104B10008DF805000BA9684609F09CFAA8E62DE976 +:104B2000F041B0B014460D460646FEF7E3FA070022 +:104B300006D03878222806D2082030B0BDE8F081AF +:104B400043F20200F9E728460FF0D7FB30B94FF0E7 +:104B500000084CB120460FF0C7FB08B11020ECE76D +:104B6000C4F80080A4F804801348807C800701D535 +:104B70001120E2E797F8220004F0ACF98088011DCB +:104B8000FB2901D2001D00E0FB20C0B26A46294685 +:104B900000F0E3F82C22094904A81CF0F2FFBDF84C +:104BA0000200ADF81400BDF80600ADF81600ADF82F +:104BB0001260BDF8000003E0CC010020A01F02003D +:104BC000ADF81800BDF80400ADF81A001AA904A841 +:104BD00009F040FA00B1FFDFBDF86C00ADF8080045 +:104BE000BDF86E00ADF80A00BDF87000BDF8721097 +:104BF000BDF800200844ADF80C0007201B2A9CD308 +:104C0000BDF802101B2998D3FB2A96D8FB2994D80B +:104C100006278A4210D10121104600F05AF8BDF84B +:104C20000410884208D1BDF80200012100F051F8BB +:104C3000BDF80610884201D038467EE7BDF808006E +:104C400028B9BDF80A1011B9BDF80C1029B35DB12F +:104C5000298849B1698839B124B102982060BDF82A +:104C60000C00A080132068E7BDF80010BDF80A20F2 +:104C7000081A80B2ADF80000BDF80210891AADF82C +:104C80000210012100F025F8ADF80400BDF8020083 +:104C9000012100F01EF8ADF806002C226B490FA888 +:104CA0001CF06FFFADF83E60BDF80200ADF84000AB +:104CB000BDF80600ADF84200BDF80000ADF84400B4 +:104CC000BDF80400ADF8460025A90FA809F0C2F907 +:104CD00033E7022903D0C000703080B270478000F3 +:104CE0003C30FAE730B55A4D040008D0012C04D00E +:104CF000022C06D0032C04D0FFDF2C7030BDFFDF68 +:104D0000FBE728780128F8D0FFDFF6E710B5044666 +:104D100004F0E0F830B1407830B1204604F0EEFB0A +:104D2000002010BD072010BD122010BD10B504F0EA +:104D3000D1F8040000D1FFDF607800B9FFDF6078B0 +:104D4000401E607010BD10B504F0C4F8040000D11E +:104D5000FFDF6078401C607010BD10B5144631B1A3 +:104D60000A68226049686160218839B107E02080C3 +:104D700060800121FFF7ADFFA0800DE020806188F9 +:104D800001B96080A08820B920880121FFF7A1FF28 +:104D9000A080E088002804D160880121FFF799FFF6 +:104DA000E08010BD418843F6FD730A1F9A4209D284 +:104DB0008088042806D3B0F5804F03D8884201D8F4 +:104DC00000207047072070470278520804D0012A5B +:104DD00002D043F202207047FEF7C8BA10B548B1BE +:104DE00083000022114606200FF044F9062801D066 +:104DF000032010BD002010BD70B50C0006460DD07C +:104E0000FEF778F9050000D1FFDFA6802889208110 +:104E1000288960816889A081A889E08170BD10B56A +:104E200000231A4603E0845C2343521CD2B28A4218 +:104E3000F9D30BB1002010BD012010BD00B5012831 +:104E400003D0022801D0FFDF002000BDF81F0200C0 +:104E5000CC01002010B504460FF002FA08B1102072 +:104E600010BD2078C0F30210042807D86078072806 +:104E700004D3A178102901D8814201D2072010BDA6 +:104E8000E078410706D421794A0703D4000701D40A +:104E9000080701D5062010BD002010BD10B51378FD +:104EA0005C08C37F64F30003C3771478A40864F339 +:104EB0004103C3771078C309487863F34100487011 +:104EC00013781C090B7864F347130B701378DB0815 +:104ED00063F3000048705078487110BD10B5C47875 +:104EE0000B7864F300030B70C478640864F3410327 +:104EF0000B70C478A40864F382030B70C478E408D0 +:104F000064F3C3030B700379117863F3000111702C +:104F100003795B0863F34101117003799B0863F324 +:104F2000820111700079C00860F3C301117010BDD7 +:104F300070B514460D46064604F037FA80B1017884 +:104F4000182221F00F01891C21F0F001A03100F896 +:104F5000081B21461CF015FEBDE8704004F028BA7D +:104F600029463046BDE870401322FEF778BA10B5E6 +:104F7000FE4C94F8300000280CD104F120014FF6CB +:104F8000FF72A1F110000DF04DF900B1FFDF01201B +:104F900084F8300010BD2DE9F047064608A8894680 +:104FA00090E830041F469046142128461CF03DFE30 +:104FB0000021CAF80010B8F1000F03D0B9F1000FBA +:104FC00003D114E03878C00711D020680FF06EF9D3 +:104FD000F0BBB8F1000F07D12068123028602068BC +:104FE000143068602068A8602168CAF8001038781A +:104FF000800728D560680FF077F948BBB9F1000F3A +:105000002DD0FFF720F80168C6F8C8118188A6F8EE +:10501000CC11807986F8CE01FFF7A9FFDFF84C8329 +:1050200008F12008C5F80C80626862B196F8C801E2 +:1050300006F2C91140081032FEF7E7F91022414686 +:1050400060681CF059FD3878400712D5A06800E070 +:1050500002E00FF02BF950B11020BDE8F087606836 +:105060000028F9D0E8606068C6F8C401EBE7A068E2 +:1050700028610020F1E730B5054608780C4620F09D +:105080000F00401C20F0F0011031217000206070F2 +:1050900095F8230030B104280FD0052811D0062838 +:1050A00014D0FFDF20780121B1EB101F04D295F856 +:1050B000200000F01F00607030BD21F0F0002030B3 +:1050C00002E021F0F00030302070EBE721F0F0003A +:1050D0004030F9E710B510B190F8BD4044B1A34895 +:1050E00090F83540002064B108601060186010BD71 +:1050F00000F1BC040C6000F1E40100F58670116061 +:10510000F4E79A4C34340C60EFE700B58BB007231A +:10511000CDE902128DF801300191944900236431E8 +:105120000591099301468DF8103068460DF052F84C +:10513000002800D0FFDF0BB000BD70B590B0154661 +:105140000C4602220646ADF80820092103AB04F004 +:105150006EFF0490002812D00C208DF8010004206E +:105160008DF8040004F59A74099605948DF818508A +:105170000AA968460DF02EF800B1FFDF012010B03B +:1051800070BD30B597B00C462C251A998DF800509B +:10519000ADF80200B3B11868019058680290ADF8FC +:1051A0000C2010220DF10E001CF0A6FC0BA9684685 +:1051B00008F050FF002803D1A17F41F01001A17732 +:1051C00017B030BD00200190E8E72DE9F047064612 +:1051D000808A8CB080B20D468246FDF78BFF044674 +:1051E000624F3078283FDFF884914FF00008112893 +:1051F00073D2DFE800F072F1350936777E98A7F2B6 +:10520000EFEEEDEC5BECEC00A07F00F0030001287A +:1052100006D0002150460BF021FC050003D101E02F +:105220000121F7E7FFDF99F85C10C90702D0D9F830 +:1052300060000BE0032105F121000EF0E2FCD5F83F +:1052400021004B49B0FBF1F201FB1200C5F821002F +:105250007068A867B068E8672078252800D0FFDF6D +:10526000ECE0A07F00F00300012806D000215046AA +:105270000BF0F4FB060003D101E00121F7E7FFDFAB +:105280003078810702D52178252904D040F001002B +:1052900030700CB0E1E60220287096F820002871EA +:1052A00006F121003136C5E90206F2E7A07F00F0E1 +:1052B0000300012806D0002150460BF0CFFB04006C +:1052C00003D101E00121F7E7FFDF2078C10605D512 +:1052D0001320287041346C60DBE7BEE140F0080029 +:1052E0002070D6E72148082128380EF08AFC0320D8 +:1052F00016E02A208DF8000010220DF102007168DE +:105300001CF0FAFB10220DF11200B1681CF0F4FB46 +:10531000164968462C3908F09DFE00B1FFDF0420D5 +:1053200028706F60B5E7E07FC00600D5FFDF307CF6 +:10533000B28800F001030CB05046BDE8F0470921E7 +:1053400005F00BBD04B9FFDF716821B1102204F133 +:1053500024001CF0D1FB28212046FDF703FFA07F8D +:1053600000F00300022814D104E00000180200201D +:1053700040420F0004F12400002300901A46214609 +:105380005046FFF7FEFE112807D029212046FDF7E1 +:10539000E9FE307A84F820007BE7A07F000700D583 +:1053A000FFDF14F81E0F40F008002070A4F81680EC +:1053B000C4F81880C4F81C806178084661F3820044 +:1053C000410861F3C3006070307AE07061E727E064 +:1053D0003FE17AE051E000E037E0A07F00F0030019 +:1053E000012806D0002150460BF038FB040003D101 +:1053F00001E00121F7E7FFDF022104F189000EF04F +:1054000000FC1020287004F5E4706860B4F889107E +:10541000298204F18000FD496861C5E9029138E7FD +:10542000A07F00F00300012805D0002150460BF0BA +:1054300015FB18B901E00121F8E7FFDF0CB0324697 +:1054400021465046BDE8F04772E504B9FFDF2078F9 +:105450002128A1D93079012803D1E07F40F0100044 +:10546000E077324621465046FFF762FD0CB02046F9 +:10547000BDE8F0472321FDF775BE3279AA8005F11A +:1054800008030921504604F0D2FDE86010B1112054 +:105490002870FEE6A07F00F00300012806D000215E +:1054A00050460BF0DBFA040003D101E00121F7E7DD +:1054B000FFDF04F1660102231022081F0BF03BF905 +:1054C00080F8008031794170E3E6A07F00F00300AE +:1054D000012806D0002150460BF0C0FA050003D188 +:1054E00001E00121F7E7FFDF95F8880000F00300F5 +:1054F000012879D1A07F00F00307E07FC0F34006C8 +:1055000016B1012F04D02BE095F8A400C0072AD0D3 +:10551000D5F8C00118B395F88720017C62F38701A4 +:105520000174E27FD5F8C00162F341010174D5F83E +:10553000C00166F300010174AEB1D5F8C0011022BC +:1055400004F124018C351CF0D7FA287E40F00100CC +:105550002876287820F0010005F88C0900E016B1C3 +:10556000022F04D02CE095F88C00C00726D0D5F887 +:10557000BC1119B395F88720087C62F38700087482 +:10558000E27FD5F8BC1162F341000874D5F8BC1174 +:1055900066F3000008748EB1D5F8BC01102204F146 +:1055A00024018C351CF0A8FA287840F0010005F899 +:1055B000180B287820F0010005F8A409022F44D028 +:1055C0005FF0000000EB400005EBC00090F88C009D +:1055D000800709D595F88000D5F8C421400805F169 +:1055E00081011032FDF711FF05208DF8000095F8BC +:1055F00088006A4600F003008DF8010095F88C10D1 +:105600008DF8021095F8A4008DF80300214650464D +:1056100001F046FA2078252805D0212807D0FFDFA1 +:105620002078222803D922212046FDF79BFDA07F68 +:1056300000F0030001280AD0002150460BF020FAA8 +:1056400000283FF432AEFFDF23E60120BAE7012154 +:10565000F3E7716881F801801BE6FFDF19E670B59A +:105660006A4C0025103C04F85C5F65600CF07FFD1F +:105670006649A1F1100003F02AFE04F82C5C062014 +:10568000607262487C3020615030A0611030E0616F +:1056900070BD70B50D46FDF72DFD040000D1FFDF94 +:1056A0004FF4E87128461CF0C0FA5848543068613D +:1056B00004F124002861A07F00F00300012809D034 +:1056C0005FF0020105F59A700CF052FD002800D041 +:1056D000FFDF70BD0121F5E70A46014602F59A7029 +:1056E0000CF066BD70B5054640689CB0017809298C +:1056F00006D00C2937D00D2933D0FFDF1CB070BD88 +:1057000046883046FDF7F6FC040000D1FFDF207824 +:105710002128F3D0282821D1686802210C3001F01B +:10572000B4F9D8B168680821001D01F0AEF9A8B13C +:105730002D208DF80000ADF80260102204F1240144 +:1057400001A81CF0D9F90BA9684608F083FC00B148 +:10575000FFDF29212046FDF705FDCFE703F028FEF6 +:10576000CCE701218171686886883046FDF7C2FC6C +:10577000040000D1FFDFA07F00F00301022902D165 +:1057800020F01000A077207821280AD0686881795D +:1057900009B1807880B1A07F00F0030002285ED0BC +:1057A000FFDFA07F00F003000228A7D1FDF7B3FEC2 +:1057B0000028A3D0FFDFA1E703F0FAFDE07FC107D7 +:1057C00028D0800705D594F8200000F01F0010288D +:1057D0001ED0052084F82300207829281CD02428F6 +:1057E000DFD1314605200EF0EFFC22212046FDF7E7 +:1057F000B9FCA07F00F0030001282ED00021304624 +:105800000BF03EF90028CCD0FFDFCAE728020020C9 +:105810000620DFE70420DDE7A07F00F00300012879 +:1058200006D0002130460BF019F9050003D101E044 +:105830000121F7E7FFDF25212046FDF793FC0F202C +:105840008DF8580016A905F59A700CF0A8FC0228EE +:10585000A7D00028A5D0FFDFA3E70121CFE703F001 +:10586000A7FD9EE72DE9F0438BB099461546884683 +:105870000646FDF73FFC04004FD0207822284CD389 +:1058800023284AD0E07FC00647D4A07F00F0030061 +:10589000012806D0002130460BF0E0F8070002D0C6 +:1058A0000CE00121F7E7A07F00F00300012805D1FB +:1058B0000121002230460BF0C8F8074601AB02AACE +:1058C00003A93846FFF706FC039800B9FFDF4FB184 +:1058D000039807F59A7787612078222806D0242834 +:1058E00004D007E003990020886103E025212046C9 +:1058F000FDF738FC03980B21417046628580C0E9B2 +:105900000289029901610199416104A90CF062FCCC +:10591000022802D0002800D0FFDF0BB0BDE8F083E2 +:1059200070B586B00546FDF7E5FB017822291CD944 +:10593000807F00F00300012806D0002128460BF0EC +:105940008DF8040030D101E00121F7E7FFDF2BE003 +:10595000B4F8620004F1660630440178427831B14F +:1059600021462846FFF7E9FBB8B906B070BDADF88F +:1059700004200921284602AB04F059FB03900028BB +:10598000F3D011208DF80000694604F59A700CF0F0 +:1059900006FC022801D000B1FFDF022310223146AD +:1059A00004F162000AF0FDFEB4F864000028CFD1D3 +:1059B000DBE710B586B00446FDF79CFB0178222991 +:1059C00019D9807F00F00300012806D0002120466D +:1059D0000BF044F8040003D101E00121F7E7FFDFF9 +:1059E00012208DF80000694604F59A700CF0D7FB80 +:1059F000002800D0FFDF06B010BD2DE9F05F05469E +:105A00000C4600270078904601093E46BA4604F14C +:105A1000080B02297ED0072902D00A2909D142E0C9 +:105A200068680178092905D00C292CD00D292AD0C5 +:105A3000FFDFB2E114271C26002C6CD04088A08028 +:105A4000FDF758FB5FEA000900D1FFDF99F8170066 +:105A50005A46400809F11801FDF7D7FC68688089AB +:105A6000208269684868C4F812008868C4F8160083 +:105A7000A07E20F0060040F00100A07699F81E00FC +:105A800040F040014DE01A270A26002CD5D080882E +:105A9000A080FDF72FFB050000D1FFDF5946284607 +:105AA000FFF7E9FA79E10CB1A88BA080287A0D28DC +:105AB0007ED006DC01287CD0022808D0032804D13F +:105AC00035E00F2876D0102875D0FFDF65E11E275E +:105AD0000926002CB1D0A088FDF70CFB5FEA000975 +:105AE00000D1FFDF287B00F003000128207A1BD0C3 +:105AF00020F001002072297B890861F341002072A7 +:105B0000297BC90861F382002072297B090961F3AE +:105B1000C30001E036E1E9E0207299F81E0040F090 +:105B2000800189F81E1038E140F00100E2E71327F8 +:105B30000D26002CAAD0A088FDF7DCFA8146807FD4 +:105B400000F00300012806D00021A0880AF086FF9B +:105B5000050003D101E00121F7E7FFDF99F81E00FE +:105B600000F00302012A59D0E86F817801F00301A7 +:105B70000129217A54D021F00101217283789B08F8 +:105B800063F3410121728378DB0863F382012172A0 +:105B900083781B0963F3C3012172037863F3061151 +:105BA0002172437863F3C711217284F809A003E0DE +:105BB0005EE0A4E08BE09CE0C178A172012A32D0C3 +:105BC0004279E17A62F30001E1724279520862F3AC +:105BD0004101E1724279920862F38201E1724279F5 +:105BE000D20862F3C301E1720279217B62F3000102 +:105BF00021730279520862F34101217302799208FC +:105C000062F3820121730079C00860F3C30121733C +:105C100099F80000232859D9262168E0A86FA4E745 +:105C200041F00101A9E70279E17A62F30001E17232 +:105C30000279520862F34101E1720279920862F33B +:105C40008201E1720279D20862F3C301E172427902 +:105C5000217B62F3000121734279520862F3410112 +:105C600021734279920862F3820121734079CBE774 +:105C700018271026D4B3A088FDF73CFA8346807F0E +:105C800000F00300012807D00021A0880AF0E6FEFA +:105C90005FEA000903D101E00121F6E7FFDFE868D0 +:105CA000A06099F8000040F0040189F8001099F80C +:105CB0000100800708D5012020739BF800002328ED +:105CC0006BD9272158464FE084F80CA065E01527D2 +:105CD0000F265CB1A088FDF70DFA814606225946D1 +:105CE000E86808F01FFA0120A0739BE03FE04846F7 +:105CF0003AE016270926D4B3287B20724DE0287B92 +:105D000019270E269CB3C4F808A0A4F80CA00128FB +:105D100007D0022805D0032805D0042803D0FFDFD0 +:105D20000DE0207207E0697B042801F00F0141F0CB +:105D3000800121721CD0607A20F003006072A0887C +:105D4000FDF7D8F905460078212826D0232800D071 +:105D5000FFDFA87F00F00300012811D00021A088F8 +:105D60000AF08EFE22212846FDF7FCF915E004E03A +:105D7000607A20F00300401CE0E7A8F8006011E022 +:105D80000121ECE70CB16888A080287A03282BD089 +:105D900004280AD005284BD0FFDFA8F800600CB11A +:105DA000278066800020BDE8F09F15270F26002C75 +:105DB000E3D0A088FDF79EF9807F00F00300012862 +:105DC00006D00021A0880AF049FE050003D101E0B9 +:105DD0000121F7E7FFDFD5F821000622594608F038 +:105DE000A1F984F80EA0D8E717270926002CC4D003 +:105DF000A088FDF77FF98146807F00F0030001282D +:105E000006D00021A0880AF029FE050003D101E098 +:105E10000121F7E7FFDF6878800701D5022000E065 +:105E20000120207299F800002328B6D927215EE7C7 +:105E300019270E26002CA0D0A088FDF75BF95FEA99 +:105E4000000900D1FFDFC4F808A0A4F80CA084F872 +:105E500008A0A07A40F00300A07299F81F1061F327 +:105E60008200A07299F81F10C1F34002114205D0C0 +:105E700099F8201001F01F0110292CD020F0080003 +:105E8000A07299F81F004108607A61F3C300607244 +:105E9000697A01F003010129A5D140F00400607284 +:105EA00099F81E00E97A00F00300012816D0607B03 +:105EB00061F300006073AA7A217B62F30001217311 +:105EC000EA7A520862F341006073A87A400860F3EE +:105ED0004101217361E740F00800D1E7207B61F3C5 +:105EE00000002073AA7A617B62F300016173EA7A91 +:105EF000520862F341002073A87A400860F3410120 +:105F000061734AE710B5FE4C30B10146102204F12E +:105F100020001BF0F1FD012084F8300010BD10B509 +:105F20000446FFF724F8F64920461022BDE8104049 +:105F300020311BF0E1BD70B5F14D06004FF00004BB +:105F400012D00EF08DF908B110240BE00621304676 +:105F500008F0CFF8411C04D02866012085F85C00C9 +:105F600000E00724204670BD0020F7E7007810F01D +:105F70000F0204D0012A05D0022A0CD110E000093A +:105F800009D10AE00009012807D0022805D003281A +:105F900003D0042801D00720704708700020704704 +:105FA0000620704705282AD2DFE800F003070F1704 +:105FB0001F00087820F0FF001EE0087820F00F0096 +:105FC000401C20F0F000103016E0087820F00F00A0 +:105FD000401C20F0F00020300EE0087820F00F0088 +:105FE000401C20F0F000303006E0087820F00F0070 +:105FF000401C20F0F000403008700020704707205F +:1060000070472DE9F041804688B00D4600270846CC +:106010000EF073F9A8B94046FDF76CF8040003D000 +:106020002078222815D104E043F2020008B0BDE830 +:10603000F08145B9A07F010603D500F003000228D6 +:1060400001D01020F2E7A07FC10601D4010702D5DC +:106050000DB10820EAE7E17FC90601D50D20E5E78B +:1060600000F00300022805D125B12846FEF7F2FE14 +:106070000700DBD1A07F00F00300012806D000213B +:1060800040460AF0EBFC060002D00DE00121F7E7E4 +:10609000A07F00F0030001280CD000210022404620 +:1060A0000AF0D3FC060007D0A07F00F0030002280E +:1060B00004D009E00121F1E70420B7E725B12A4621 +:1060C00031462046FEF7EAFE07AB1A4669463046DF +:1060D000FFF700F8009800B9FFDF00990C20487026 +:1060E00006F59A70C1F82480486100200881A07FDD +:1060F00000F00300012828D0EDB302200871301D04 +:1061000088613078400908777078C0F3400048779C +:10611000287800F00102887F62F301008877E27F2F +:1061200062F382008877E27F520862F3C3008877C7 +:10613000727862F304108877A878C87701F1210299 +:1061400028462031FEF7CAFE22E001200871287897 +:1061500000F00102087E62F3010008762A785208F6 +:1061600062F3820008762A78920862F3C300087608 +:106170002A78D20800E007E062F3041008762421B0 +:106180002046FCF7EFFF0BE003200871052008769E +:1061900025212046FCF7E6FFA07F20F08000A077B5 +:1061A00001A900980CF016F8022801D000B1FFDF19 +:1061B00038463BE72DE9FF4F524A0D4699B09A46C3 +:1061C00007CA14AB002783E807001998FCF792FF71 +:1061D000060006D03078262806D008201DB0BDE87D +:1061E000F08F43F20200F9E7B07F00F00309B9F144 +:1061F000010F03D0B9F1020F07D008E03DB91B9899 +:10620000FEF728FE0028E9D101E01B9880BBB07F93 +:1062100000F00300012806D0002119980AF01EFCA6 +:10622000040003D101E00121F7E7FFDF852D28D02D +:1062300007DCF5B1812D1ED0822D1ED0832D08D113 +:106240001DE0862D1FD0882D1FD0892D1FD08A2DAF +:106250001FD00F2020710F281DD003F0A6F8E0B149 +:1062600001208DF83400201D0E902079B8B160E136 +:1062700011E00020EEE70120ECE70220EAE703202E +:10628000E8E70520E6E70620E4E70820E2E7092042 +:10629000E0E70A20DEE70720A0E711209EE7B9F13A +:1062A000010F17D0D4E91E50804602200190012032 +:1062B0000090A87898F80210C0F3C000C1F3C001A4 +:1062C00008405FEA000B63D050460DF0C9FF00287C +:1062D00072D133E0D4E91E850120019002200090A4 +:1062E000214630461B9AFEF7D9FD1B98007800F036 +:1062F0000101A87861F30100A870F17F04E00000BB +:10630000180200202420020061F38200A870F17FAF +:10631000490861F3C300A870617861F30410A870A4 +:106320002078400928706078C0F3400068701B989E +:106330008078E870002068712871BAE7DAF80C00FC +:106340000DF08EFFC0BBDAF81C000DF089FF98BB82 +:10635000DAF80C00A060DAF81C00E06098F80100A0 +:10636000617800F0010041EA4000607098F8021086 +:10637000C0B2C1F30011891E08406070002084F88B +:106380002000009906F1170002290BD001210AE034 +:1063900098F80110607801F00101FD2242EA410104 +:1063A0000840E2E7002104EB810188610199701C3B +:1063B000022902D0012101E028E0002104EB810143 +:1063C0008861A87800F00300012849D198F80200FC +:1063D00000F00300012843D1B9F1010F04D12A1DB7 +:1063E000691D1B98FEF77AFD287998F8041008407B +:1063F0008DF82C00697998F8052011408DF830103F +:1064000008432DD050460DF02BFF08B11020E5E6D3 +:106410000AF1100004F5DE7104F190020490B9F164 +:10642000020F3CD00090CDE9012100210BAB5A4670 +:106430002046FEF7B0FD0028E9D104F5E07104F133 +:10644000A802B9F1010F30D004980090CDE90121E4 +:1064500000210CAB5A462046FEF79DFD0028D6D100 +:106460006078800740D4A87898F80210C0F38000C4 +:10647000C1F38001084337D0297898F8000014AAA6 +:10648000B9F1010F17D032F810204B00DA4012F0AA +:10649000030718D0012F1ED0022F12D11DE0CDF816 +:1064A00000A0CDE901210121C0E7CDF800A0CDE990 +:1064B00001210121CDE732F811204300DA4002F03A +:1064C0000307032F07D0BBF1000F0DD0012906D021 +:1064D000042904D008E00227F5E70127F3E70128A3 +:1064E00001D0042800D10427F07F40F001006BF3B5 +:1064F0004100F077607881074FF003000CD5A07160 +:10650000BBF1000F15D100BF8DF85C0017AA314612 +:10651000199800F0C5FA0CE00221022F18D0012FC3 +:1065200018D0042F22D00020A071F07F20F00100AD +:10653000F07725213046FCF715FE0DA904F59A7079 +:106540000BF02DFE10B1022800D0FFDF002045E641 +:10655000A171D9E7A1710D2104F124001BF065FBA5 +:10656000207840F0020020700420CDE70120A071C7 +:10657000DFE72DE9F04387B09046894604460025C1 +:10658000FCF7B8FD060006D03078272806D0082092 +:1065900007B0BDE8F08343F20200F9E7B07F00F0F6 +:1065A0000300012806D0002120460AF057FA040013 +:1065B00003D101E00121F7E7FFDFA7795FEA0900D6 +:1065C00005D0012821D0B9F1020F26D110E0B8F191 +:1065D000000F22D1012F05D0022F05D0032F05D0A7 +:1065E000FFDF2DE00C252BE0012529E0022527E027 +:1065F00040460DF035FEB0B9032F0ED110224146B2 +:1066000004F121001BF078FA1AE0012F02D0022FCA +:1066100003D104E0B8F1000F12D00720B8E74046DC +:106620000DF01EFE08B11020B2E7102104F1210088 +:106630001BF0D9FA0621404607F05BFDC4F82100A3 +:106640002078252140F0020020703046FCF78AFDBA +:106650002078C10714D020F00100207002208DF8AE +:10666000000004F1210002908DF80450694604F501 +:106670009A700BF094FD022804D018B1FFDF01E0FE +:1066800084F82050002083E730B587B00D460446DB +:10669000FCF730FD88B1807F00F0030001280FD0A7 +:1066A000002120460AF0DAF904000ED028460DF049 +:1066B000D7FD38B1102007B030BD43F20200FAE731 +:1066C0000121EEE72078400701D40820F3E72946AE +:1066D00004F14100202205461BF00EFA207840F01C +:1066E0001000207001070FD520F008002070132043 +:1066F0008DF80000694604F59A7001950BF04FFD86 +:10670000022801D000B1FFDF0020D4E770B50D46AC +:106710000646FCF7EFFC18B1017827291FD102E0EB +:1067200043F2020070BD807F00F00300012806D014 +:10673000002130460AF092F9040003D101E0012162 +:10674000F7E7FFDFA079022809D16078C00706D0FB +:106750002A4621463046FEF7F0FC10B10FE0082033 +:1067600070BDB4F864000E280BD204F16601022358 +:106770001022081F09F0DFFF012101704570002081 +:1067800070BD112070BD70B5064686B014460D462A +:1067900008460DF065FD18B920460DF087FD10B1D3 +:1067A000102006B070BDA6F57F40FF380ED03046F1 +:1067B000FCF7A0FC38B1417822464B08811C1846F2 +:1067C000FCF723FE07E043F20200EAE72046FDF76C +:1067D00099FC0028E5D11021E01D0DF012FAE21D10 +:1067E00029466846FEF791FC102204F11700019932 +:1067F0001BF082F90020D4E72DE9F041044686B071 +:1068000015468846002708460DF077FD18B928463A +:106810000DF073FD10B1102006B008E42046FCF71F +:1068200069FC060003D03078272818D102E043F233 +:106830000200F1E7B07F00F00300012806D000213C +:1068400020460AF00BF9040003D101E00121F7E72B +:10685000FFDF2078400702D56078800701D4082048 +:10686000DAE7B07F00F00300012818D0D4E91E0158 +:10687000407800B1B5B1487810B1B8F1000F11D02F +:10688000C5B1EA1D6846E168FEF73FFC102205F13C +:10689000170001991BF004F930B104270AE0D4E98C +:1068A0001E10E5E70720B7E71022E91D04F13100CB +:1068B0001BF022F9B8F1000F06D0102208F10701F1 +:1068C00004F121001BF018F92078252140F0020086 +:1068D00020703046FCF746FC2078C10716D020F027 +:1068E0000100207002208DF8000004F121000290C8 +:1068F000103003908DF80470694604F59A700BF01F +:106900004EFC022804D018B1FFDF01E084F82070AB +:10691000002081E7F8B515460E460746FCF7EAFB6E +:10692000040004D02078222804D00820F8BD43F2C7 +:106930000200F8BDA07F00F00300022802D043F25D +:106940000400F8BD30460DF08BFC18B928460DF058 +:1069500087FC08B11020F8BD00953288B31C214691 +:106960003846FEF70EFC112814D00028F3D1297CFC +:106970004A08E17F62F30001E1772A7C62F341017A +:10698000E177297C890884F82010A17F21F080011B +:10699000A177F8BDA17F0907FBD4D6F80200C4F89F +:1069A0003600D6F80600C4F83A003088A0861022D7 +:1069B000294604F124001BF09FF8287C4108E07F61 +:1069C00061F38200E077297C61F3C300E077287CE3 +:1069D000800884F82100A07F40F00800A077002004 +:1069E000D3E770B596B00D46064613B1072016B032 +:1069F00070BDFCF77FFB040007D02078222802D36B +:106A0000A07F400604D40820F1E743F20200EEE73D +:106A1000C5B12D208DF80000ADF802601022294686 +:106A200001A81BF069F8287C4108E07F61F30000B1 +:106A3000E077297C61F34100E077287C800884F8C6 +:106A4000200004E02E208DF80000ADF802600BA9B4 +:106A5000684607F0FFFAA17F21F04001A177C6E761 +:106A600070B50D46FCF746FB040005D028460DF036 +:106A70001DFC20B1102070BD43F2020070BD2946FC +:106A80002046FEF7F8FA002070BD04E010F8012B54 +:106A90000AB100207047491E89B2F7D20120704721 +:106AA00070B51546064602F080FC040000D1FFDFF9 +:106AB000207820F00F00801C20F0F00020302070A3 +:106AC00066802868A060BDE8704002F071BC0000DC +:106AD00018B18178012938D101E010207047018870 +:106AE00042F60112881A914231D018DC42F60102B6 +:106AF000A1EB020091422AD00CDC41B3B1F5C05F9A +:106B000025D06FF4C050081821D0A0F57060FF3870 +:106B10001BD11CE001281AD002280AD117E0B0F5D9 +:106B2000807F14D008DC012811D002280FD0032860 +:106B30000DD0FF2809D10AE0B0F5817F07D0A0F57C +:106B40008070033803D0012801D0002070470F2047 +:106B500070470B2826D008DC1BD2DFE800F01C2091 +:106B600025251A25292325271E0011281CD008DCDD +:106B70000C2817D00D281DD00F2815D0102808D1AB +:106B800010E0822809D0842810D0852810D08728CA +:106B900012D003207047002070470520704743F251 +:106BA00003007047072070470F207047042070478C +:106BB000062070470C20704743F20200704738B53A +:106BC0000C46050041D06946FFF7D0F9002819D1DD +:106BD0009DF80010607861F3020060706946681CDF +:106BE000FFF7C4F900280DD19DF80010607861F31B +:106BF000C5006070A978C1F34101012903D00229C1 +:106C000005D0072038BD217821F0200102E021784D +:106C100041F020012170410704D0A978C90861F32F +:106C200086106070607810F0380F07D0A9780909D5 +:106C300061F3C710607010F0380F02D16078400621 +:106C400003D5207840F040002070002038BD70B59A +:106C500004460020088015466068FFF7B0FF002852 +:106C600016D12089A189884211D860688078C00730 +:106C70000AD0B1F5007F0AD840F20120B1FBF0F252 +:106C800000FB1210288007E0B1F5FF7F01D90C202E +:106C900070BD01F201212980002070BD10B504787B +:106CA000137864F3000313700478640864F34103F9 +:106CB00013700478A40864F3820313700478E40862 +:106CC00064F3C30313700478240964F3041313708A +:106CD0000478640964F3451313700078800960F345 +:106CE0008613137031B10878C10701D1800701D52F +:106CF000012000E0002060F3C713137010BD42783C +:106D0000530702D002F0070306E012F0380F02D05A +:106D1000C2F3C20300E001234A7863F302024A701F +:106D2000407810F0380F02D0C0F3C20005E04307EE +:106D300002D000F0070000E0012060F3C5024A70B5 +:106D400070472DE9F04F95B00D00804615D0B8F191 +:106D5000000F16D0122128461AF045FF4FF6FF7B90 +:106D600005AA0121584606F0C0FF002426463746F2 +:106D70004FF420596FF4205A75E0102015B0BDE88B +:106D8000F08F0720FAE700BF9DF81E0001280AD106 +:106D9000BDF81C0048450BD010EB0A000AD00128B2 +:106DA0000CD002280CD0042C0ED0052C0FD10DE0F5 +:106DB000012400E00224BDF81A6008E0032406E084 +:106DC0000424BDF81A7002E0052400E00624BDF892 +:106DD0001A10414547D12C74BEB34FF0000810AAD9 +:106DE0004FF0070ACDE90282CDE900A80DF13C0978 +:106DF0001023CDF8109042463146584607F028F847 +:106E000008BBBDF83C002A46C0B210A90BF084FABA +:106E1000C8B9AE81CFB1CDE900A80DF1080C0AAE1A +:106E200040468CE84102132300223946584607F0B9 +:106E30000FF840B9BDF83C00F11CC01EC0B22A1DBD +:106E40000BF06AFA10B1032098E70AE0BDF82900B8 +:106E5000E881062C05D19DF81E00A872BDF81C0023 +:106E6000288100208AE705A806F04BFF00288BD078 +:106E7000FFF76FFE82E72DE9F0471C46DDE9097850 +:106E8000DDF8209015460E00824600D1FFDF0CB1E0 +:106E9000208818B1D5B11120BDE8F087022D01D0AE +:106EA000012100E0002106F1140005F003FEA8F81E +:106EB000000002463B462946504603F0B8F8C9F8A0 +:106EC000000008B9A41C3C600020E5E71320E3E7BC +:106ED000F0B41446DDE904528DB1002314B1022C44 +:106EE00009D101E0012306E00D7CEE0703D025F077 +:106EF000010501230D742146F0BC03F02EBF1A805A +:106F0000F0BC70472DE9FE4F91461A881C468A4610 +:106F10008046FAB102AB494603F089F8050019D062 +:106F20004046A61C278809F0B5FE324607262946AA +:106F30003B46009609F074FA20882346CDE90050BC +:106F40004A4651464046FFF7C3FF002020800120FB +:106F5000BDE8FE8F0020FBE72DE9F04786B09146A3 +:106F6000DDE90E460F46824603AA05A904A8109D36 +:106F70008DE807009846324621465046FFF77BFFD2 +:106F8000049909B1012200E000222A70002817D1DB +:106F9000F84A03AB1060059A009104F11400CDE9A2 +:106FA00001204A463946504606F048F990B1082873 +:106FB0000ED2DFE800F00407040D0D090B0B0020D2 +:106FC00006B069E71120FBE70720F9E70820F7E79B +:106FD0000320F5E7BDF80C100498CDE90001434605 +:106FE000324621465046FFF773FFE8E72DE9F043AC +:106FF00089B00D46DDE9108781461C4616461421EE +:1070000003A81AF012FE012002218DF810108DF84D +:107010000C008DF81170ADF8146064B1A278D2073D +:1070200009D08DF81600E088ADF81A00A088ADF8F8 +:107030001800A068079008A80095CDE90110424605 +:1070400003A948466B68FFF787FF09B0BDE8F083E6 +:10705000F0B58BB0002406460694079407270894E1 +:1070600005A80994019400970294CDE903400D46C8 +:1070700010232246304606F0EBFE78B90AA806A98E +:10708000019400970294CDE90310BDF8143000225A +:107090002946304606F0B2FC002801D0FFF759FD22 +:1070A0000BB0F0BD06F052BB2DE9FC410C4680460A +:1070B000002602F07AF9054620780D287ED2DFE816 +:1070C00000F0BC0713B325BD49496383AF959B000E +:1070D000A848006820B1417841F010014170ADE04E +:1070E000404602F092F9A9E00421404609F0B6FCBE +:1070F000070000D1FFDF07F11401404605F06EFCE8 +:10710000A5BB13214046FDF787FB97E004214046CD +:1071100009F0A4FC070000D1FFDFE088ADF8000013 +:107120000020B8819DF80000010704D5C00602D5F3 +:10713000A088B88105E09DF8010040067ED5A088B2 +:10714000F88105B9FFDF22462946404601F068FC78 +:10715000022673E0E188ADF800109DF801100906E1 +:107160000FD5072803D006280AD00AE024E004211E +:10717000404609F073FC060000D1FFDFA088F081D3 +:107180000226CDB9FFDF17E00421404609F066FC76 +:10719000070000D1FFDF07F1140006F00EFB90F0AE +:1071A000010F02D1E079000648D5387C022640F074 +:1071B0000200387405B9FFDF224600E03DE02946B1 +:1071C000404601F02DFC39E00421404609F046FC20 +:1071D000017C002D01F00206C1F340016171017CC8 +:1071E00021F002010174E7D1FFDFE5E7022601216A +:1071F000404602F045F921E00421404609F02EFC0A +:107200000546606800902089ADF8040001226946B7 +:10721000404602F056F9287C20F0020028740DE068 +:10722000002DC9D1FFDFC7E7022600214046FBF74A +:10723000CDF8002DC0D1FFDFBEE7FFDF3046BDE84F +:10724000FC813EB50C0009D001466B4601AA002026 +:1072500006F080FE20B1FFF77CFC3EBD10203EBD55 +:1072600000202080A0709DF8050002A900F0070012 +:10727000FEF798FE50B99DF8080020709DF80500B3 +:1072800002A9C0F3C200FEF78DFE08B103203EBD87 +:107290009DF8080060709DF80500C109A07861F3B1 +:1072A0000410A0709DF80510890961F3C300A07057 +:1072B0009DF80410890601D5022100E0012161F347 +:1072C00042009DF8001061F30000A07000203EBD58 +:1072D00070B5144606460D4651EA040005D075B156 +:1072E00008460DF001F878B901E0072070BD294685 +:1072F000304606F090FE10B1BDE8704029E454B16C +:1073000020460CF0F1FF08B1102070BD2146304638 +:10731000BDE8704095E7002070BD2DE9FC5F0C468C +:1073200090460546002701780822007A3E46B2EBD7 +:10733000111F7DD104F10A0100910A31821E4FF024 +:10734000020A04F1080B0191092A72D2DFE802F067 +:10735000EDE005F528287BAACE006888042109F015 +:107360007DFB060000D1FFDFB08928B15227072638 +:10737000C3E000001403002051271026002C7DD00C +:107380006888A0800120A071A88900220099FFF7D9 +:107390009FFF002873D1A8892081288AE081D1E04D +:1073A000B5F81290072824D1E87B000621D5512793 +:1073B00009F1140086B2002CE1D0A88900220099BE +:1073C000FFF786FF00285AD16888A08084F806A0BD +:1073D000A88920810120A073288A2082A4F8129015 +:1073E000A88A009068884B46A969019A01F0F5FACD +:1073F000A8E0502709F1120086B2002C3ED0A889DF +:1074000000225946FFF764FF002838D16888A08021 +:10741000A889E080287A072813D002202073288AC0 +:10742000E081E87BC0096073A4F81090A88A01E0AD +:1074300085E082E0009068884B4604F11202A96959 +:10744000D4E70120EAE7B5F81290512709F11400BA +:1074500086B2002C66D06888042109F0FFFA8346C2 +:107460006888A080A88900220099FFF731FF0028D2 +:107470006ED184F806A0A889208101E052E067E07F +:107480000420A073288A2082A4F81290A88A009071 +:1074900068884B46A969019A01F09FFAA989ABF85F +:1074A0000E104FE06888FBF725FE07466888042128 +:1074B00009F0D4FA064607B9FFDF06B9FFDF687B9B +:1074C000C00702D05127142601E0502712264CB3E2 +:1074D0006888A080502F06D084F806A0287B5946E3 +:1074E00001F08BFA2EE0287BA11DF9E7FE49A8895F +:1074F0004989814205D1542706269CB16888A0801D +:1075000020E053270BE06888A080A889E08019E07C +:107510006888042109F0A2FA00B9FFDF5527082680 +:10752000002CF0D1A8F8006011E056270726002CA7 +:10753000F8D06888A080002013E0FFDF02E0012877 +:1075400008D0FFDFA8F800600CB12780668000201B +:10755000BDE8FC9F57270726002CE3D06888A08051 +:10756000687AA071EEE7401D20F0030009B14143A5 +:10757000091D01EB4000704713B5DB4A0020107174 +:10758000009848B10024684609F06BF8002C02D13D +:10759000D64A009911601CBD01240020F4E770B5A3 +:1075A0000D46064686B014465C2128461AF03DFB7F +:1075B00004B9FFDFA0786874A2782188284601F01A +:1075C00046FA0020A881E881228805F1140130469E +:1075D00005F0E9F96A460121304606F086FB19E01C +:1075E0009DF80300000715D5BDF806103046FFF7DB +:1075F0002FFD9DF80300BDF8061040F010008DF837 +:107600000300BDF80300ADF81400FF233046059ACF +:1076100006F0CCFC684606F074FB0028E0D006B00B +:1076200070BD10B50C4601F1140005F0F3F90146E8 +:10763000627C2046BDE8104001F03EBA70B50546B8 +:10764000042109F00BFA040000D1FFDF04F114015A +:107650000C46284605F0C2F921462846BDE8704090 +:1076600005F0C3B970B58AB00C460646FBF742FD7B +:10767000050014D02878222827D30CB1A08890B117 +:1076800001208DF80C0003208DF8100000208DF8EB +:10769000110054B1A088ADF81800206807E043F24B +:1076A00002000AB070BD0920FBE7ADF81800059094 +:1076B0000421304609F0D2F9040000D1FFDF04F1C3 +:1076C000140005F0BEF9C00601D40820E9E701F076 +:1076D0006CFE60B108A802210094CDE9011095F874 +:1076E000232003A930466368FFF736FCD9E7112051 +:1076F000D7E72DE9F04FB2F802A0834689B01546CE +:1077000089465046FBF7F6FC07460421504609F02F +:10771000A5F90026044605964FF002080696ADF836 +:107720001C6007B9FFDF04B9FFDF4146504603F094 +:107730007CFE60B907AA06A905A88DE807004246A5 +:10774000214650466368FFF796FB00B1FFDF6648AD +:1077500007AB0660DDE9051204F11400CDF80090D6 +:10776000CDE90320CDE9013197F823205946504651 +:107770006B6805F0AFF906000AD0022E04D0032E84 +:1077800014D0042E00D0FFDF09B03046BDE8F08FE2 +:10779000BDF81C000028F7D00599CDE9001042463D +:1077A000214650466368FFF793FBEDE7687840F0A9 +:1077B00008006870E8E72DE9F04F9BB004464FF0F1 +:1077C00000084948ADF85480ADF83080ADF85080DD +:1077D000A0F80880ADF81480ADF81880ADF82080CE +:1077E000ADF81C80007916460D464746012808D0A2 +:1077F000022806D0032804D0042802D008201BB099 +:10780000C4E720460CF02CFDD0BB28460CF028FD28 +:10781000B0BB60680CF071FD90BB606848B16089D6 +:107820002189884202D8B1F5007F01D90C20E6E712 +:1078300080460BAA06A92846FFF709FA0028DED1E0 +:1078400068688078C0F34100022808D19DF81900CB +:1078500010F0380F03D028690CF046FD80B905A957 +:107860002069FFF7ACF90028C9D1206950B16078D0 +:1078700080079DF8150000F0380002D5C0B301E084 +:1078800011E0A8BB9DF8140080060ED59DF81500E8 +:1078900010F0380F03D060680CF026FD18B960684E +:1078A0000CF02BFD08B11020A9E707A96069FFF7CC +:1078B00086F90028A3D1606940B19DF81D0000F051 +:1078C000070101293FD110F0380F3CD008A9A06969 +:1078D000FFF775F9002892D19DF81C00800632D47C +:1078E0009DF82000800604E014030020140000200E +:1078F00029E028D4A06940B19DF8210000F00701DB +:10790000012920D110F0380F1DD0E06818B100789F +:10791000C8B11C2817D20EAA611C2046FFF7BEF979 +:107920000120B94660F30F27BA4607468DF84E008E +:1079300042F60300ADF84C000DF13B0217A9286890 +:107940000AF009FD08B1072059E79DF85C0016A967 +:10795000CDF80090C01CCDE9019100F0FF0B002391 +:107960000BF20122514613A806F002F9F0BBBDF854 +:1079700058000990FE482A8929690092CDE9011032 +:107980006B89BDF82C202868069906F0F1F80100F3 +:107990007ED120784FF0020AC10601D480062BD593 +:1079A000ADF80C90606950B907A906A8FFF7A7F9D0 +:1079B0009DF81D0020F00700401C8DF81D009DF86B +:1079C0001C008DF84E7040F0C8008DF81C0042F687 +:1079D0000210ADF84C000CA903AACDF800A0CDE927 +:1079E0000121002340F2032213A800E01EE00799C2 +:1079F00006F0BEF801004BD1DD484D4608385B4625 +:107A00000089ADF839000EA8CDE90290CDF80490B8 +:107A1000CDF810904FF007090022CDF80090BDF886 +:107A200058104FF6FF7005F0E9FF10B1FFF791F81D +:107A3000E5E69DF83800000625D52946012060F3CB +:107A40000F218DF84E704FF42450ADF84C00ADF876 +:107A5000105062789DF81000002362F300008DF84A +:107A600010006278CDF800A0520862F341008DF852 +:107A7000100004AACDE9012540F2032213A806F064 +:107A800077F8010004D1606888B32069A8B900E0E4 +:107A900086E005A906A8FFF732F96078800706D4CA +:107AA0009DF8150020F038008DF8150005E09DF8D0 +:107AB000140040F040008DF814008DF84E7042F62E +:107AC0000110ADF84C00208940F20121B0FBF1F229 +:107AD00001FB1202606814ABCDF80080CDE9010310 +:107AE000002313A8059906F043F8010058D1207827 +:107AF000C00729D0ADF80C50A06950B908A906A854 +:107B0000FFF7FDF89DF8210020F00700401C8DF8DC +:107B100021009DF820008DF84E7040F040008DF857 +:107B2000200042F60310ADF84C0015A903AACDF8C9 +:107B300000A0CDE90121002340F2032213A80899F7 +:107B400006F016F801002BD1E06868B32946012041 +:107B500060F30F218DF84E7042F60410ADF84C0022 +:107B6000E068002302788DF8602040788DF861008D +:107B7000E06818AA4088ADF86200E06800798DF8E6 +:107B80006400E068C088ADF86500CDF80090CDE9EC +:107B900001254FF4027213A805F0EAFF010003D09B +:107BA000099800F0B5FF2AE67148032108380171F1 +:107BB00056B100893080BDF850007080BDF83000AB +:107BC000B080BDF85400F080002018E670B50125A3 +:107BD0008AB016460B46012802D0022816D104E0CE +:107BE0008DF80E504FF4205003E08DF80E5042F601 +:107BF0000100ADF80C005BB10024601C60F30F24A1 +:107C000004AA08A918460AF0A6FB18B1072048E5FF +:107C1000102046E504A99DF820205548CDE9002113 +:107C2000801E02900023214603A802F2012205F0E3 +:107C30009FFF10B1FEF78DFF33E54D4808380EB1B8 +:107C4000C1883180057100202BE5F0B593B007465F +:107C500001268DF83E6041F60100ADF83C0012AA05 +:107C60000FA93046FFF7B2FF002848D1404C00254D +:107C7000083CE7B31C2102A819F0D7FF9DF80800C3 +:107C80008DF83E6040F020008DF8080042F6052097 +:107C9000ADF83C000E959DF83A00119520F00600D5 +:107CA000801C8DF83A009DF838006A4620F0FF00ED +:107CB0008DF838009DF8390009A920F0FF008DF8F3 +:107CC00039000420ADF82C00ADF830000EA80A9061 +:107CD00011A80D900FA80990ADF82E5002A8FFF73B +:107CE0006AFD00280BD1BDF80000608100E008E0CB +:107CF000BDF80400A081401CE0812571002013B074 +:107D0000F0BD6581A581BDF84800F4E72DE9F74F86 +:107D10001749A0B00024083917940A79A146012A0E +:107D200004D0022A02D0082023B02FE5CA8882425C +:107D300001D00620F8E721988A46824201D1072027 +:107D4000F2E701202146ADF848004FF6FF7860F3D6 +:107D50000F21ADF84A808DF86E0042F6020B0691B5 +:107D60008DF87240ADF86CB0ADF870401CA901E020 +:107D70001C0300201391ADF8508012A805F0E5FF18 +:107D800000252E462F460DAB072212A9404605F0CE +:107D9000DFFF78B182285DD195B38EB3ADF8645022 +:107DA000ADF866609DF85E008DF8144019AC0128AE +:107DB00064D06BE09DF83A001FB3012859D1BDF89B +:107DC000381059451FD118A809A901940294CDE98A +:107DD000031007200090BDF8361010230022404603 +:107DE00006F036F8B0BBBDF86000042801D00628C4 +:107DF0004AD1BDF82410219881423AD10F2093E74F +:107E00003AE0012835D1BDF83800B0F5205F03D045 +:107E100042F6010188422CD1BAF80600BDF83610AE +:107E2000884201D1012700E0002705B19EB12198C9 +:107E300081421ED118A809AA01940294CDE9032019 +:107E4000072000900D4610230022404606F000F85F +:107E500000B902E02DE04E460BE0BDF860000228BC +:107E600001D0102810D1C0B217AA09A90AF054FAFB +:107E700050B9BDF8369086E7052055E705A917A843 +:107E8000221D0AF068FA08B103204DE79DF814009E +:107E90000023001DC2B28DF8142022980092CDE973 +:107EA00001401BA8069905F063FE10B902228AF86A +:107EB0000420FEF74EFE37E710B50B46401E88B093 +:107EC00084B205AA00211846FEF7E8FE00200DF155 +:107ED000080C06AA05A901908CE80700072000906D +:107EE0000123002221464FF6FF7005F087FD04466E +:107EF000BDF81800012800D0FFDF2046FEF729FE5C +:107F000008B010BDF0B5F94F044687B038790E4679 +:107F1000032804D0042802D0082007B0F0BD04AA2A +:107F200003A92046FEF793FE0500F6D1606880782D +:107F3000C0F3410002280AD19DF80D0010F0380F5F +:107F400005D020690CF0D0F908B11020E5E72089B0 +:107F500005AA21698DE807006389BDF81020206813 +:107F6000039905F005FE10B1FEF7F3FDD5E716B154 +:107F7000BDF814003080042038712846CDE7F8B5EC +:107F80000C0006460BD001464FF6FF7500236A46EB +:107F9000284605F0DFFF20B1FEF7DBFDF8BD10201D +:107FA000F8BD69462046FEF70AFE0028F8D1A07801 +:107FB000314600F001032846009A05F0F7FFEBE791 +:107FC00030B587B0144600220DF1080C05AD0192C2 +:107FD0008CE82C00072200920A46014623884FF6BF +:107FE000FF7005F00BFDBDF814102180FEF7B1FD08 +:107FF00007B030BD70B50D46042108F02FFD040018 +:1080000000D1FFDF294604F11400BDE8704004F000 +:1080100011BD70B50D46042108F020FD040000D10B +:10802000FFDF294604F11400BDE8704004F025BDCF +:1080300070B50D46042108F011FD040000D1FFDFEA +:10804000294604F11400BDE8704004F03DBD70B550 +:108050000546042108F002FD040000D1FFDF21469F +:1080600028462368BDE870400122FEF74BBF70B57B +:108070000646042108F0F2FC040000D1FFDF04F101 +:10808000140004F0C7FC401D20F0030511E0011DA1 +:1080900000880022431821463046FEF733FF0028AF +:1080A0000BD0607CABB2684382B2A068011D08F0BF +:1080B00078FBA06841880029E9D170BD70B50546FC +:1080C000042108F0CBFC040000D1FFDF2146284644 +:1080D0006368BDE870400222FEF714BF70B50E461B +:1080E000054601F062F9040000D1FFDF0120207293 +:1080F00066726580207820F00F00001D20F0F000EF +:1081000040302070BDE8704001F052B910B504460F +:10811000012900D0FFDF2046BDE810400121FAF719 +:1081200055B92DE9F04F97B04FF0000A0C00834687 +:10813000ADF818A0D04619D0E06830B1A068A8B159 +:108140000188ADF81810A0F800A05846FAF7D2FF41 +:10815000070043F2020967D03878222862D304214D +:10816000584608F07BFC050005D103E0102017B04D +:10817000BDE8F08FFFDF05F1140004F04BFC401D5B +:1081800020F00306A078012803D0022801D00720A0 +:10819000EDE7208878B1401C81B209AA584605F065 +:1081A000A4FD09A805F0ADFD9DF82E204FF4505117 +:1081B000012A0DD102E043F20300D8E7BDF82C20DC +:1081C000A2F52453023B03D1822801D0A0B901E0DB +:1081D0000846CCE7E068B0B1CDE902A0072006AAC6 +:1081E000CDF804A000900492A2882188BDF8183030 +:1081F000584605F003FC10B1FEF7ABFCB7E7A168E9 +:10820000BDF8180008809DF82700C00602D543F28B +:108210000140ACE70D9838B1A1780078012905D06C +:1082200080071AD40820A2E74846A0E7C007F9D083 +:1082300002208DF83C00A8684FF00009A0B1697CCD +:108240004288714391420FD98AB2B3B2011D08F03E +:108250005EFA8046A0F800A006E003208DF83C00FE +:10826000D5F800804FF001099DF8280010F0380F74 +:1082700000D1FFDF9DF828001D49C0F3C20008446B +:1082800097F8231010F8010C884201D90F206EE7EF +:108290002088ADF8400014A90095CDE9019143462E +:1082A00007220FA95846FEF757FE002885D19DF8F2 +:1082B000500050B9A078012807D1687CB3B2704350 +:1082C00082B2A868011D08F036FA00204FE770B5A9 +:1082D000064615460C460846FEF7FAFB002809D16B +:1082E0002A4621463046BDE870406FE41403002062 +:1082F0002E20020070BD09E570B51E4614460D0023 +:1083000009D044B1616831B138B1F849C9888142B6 +:1083100003D0072070BD102070BD2068FEF7D8FB89 +:108320000028F9D1324621462846BDE87040FFF7C3 +:1083300042BA70B515460C0006D038B1EB49098930 +:10834000814203D0072070BD102070BD2068FEF769 +:10835000BFFB0028F9D129462046BDE87040D1E591 +:1083600070B5064686B00D46144610460BF09EFFCB +:10837000D0BB60680BF0C1FFB0BBA6F57F40FF38F3 +:1083800003D03046FAF7B6FE80B128466946FEF7BC +:10839000D8FC00280CD19DF810100F2008293CD2E1 +:1083A000DFE801F008060606060A0A0843F20200A2 +:1083B00006B070BD0320FBE79DF80210012908D12B +:1083C000BDF80010B1F5C05FF2D06FF4C052D142D9 +:1083D000EED09DF8061001290DD1BDF80410A1F5CD +:1083E0002851062907D200E028E0DFE801F0030366 +:1083F00004030303DCE79DF80A1001290ED1BDF840 +:108400000810B1F5245FD3D0A1F524510239CFD0A3 +:108410000129CDD0022901D1CAE7FFDF606878B910 +:10842000002305AA2946304605F094FD10B1FEF759 +:1084300090FBBDE79DF81400800601D41020B7E73B +:108440006188224628466368FFF7BAFDB0E72DE948 +:10845000F043814687B08846144610460BF026FF4D +:1084600018B1102007B0BDE8F083002306AA4146EA +:10847000484605F06FFD10B1FEF76BFBF2E79DF883 +:108480001800C00602D543F20140EBE7002507279C +:1084900005A8019500970295CDE9035062884FF633 +:1084A000FF734146484605F0D3FC060013D16068CF +:1084B0000BF0FCFE60B960680195CDE902500097B1 +:1084C0000495238862884146484605F0C1FC06466B +:1084D000BDF8140020803046CEE739B1834B0A88BE +:1084E0009B899A4202D843F20300704719E610B5FF +:1084F00086B07E4C0423ADF81430638943B1A4895F +:108500008C4201D2914205D943F2030006B010BD5E +:108510000620FBE7ADF81010002100910191ADF8A5 +:10852000003002218DF8021005A9029104A90391DF +:10853000ADF812206946FFF7F4FDE7E72DE9FC47A7 +:1085400081460E4608460BF08BFE88BB4846FAF77C +:10855000D1FD5FEA00080AD098F80000222829D34C +:108560000421484608F07AFA070005D103E043F2F7 +:108570000200BDE8FC87FFDF07F1140004F061FA98 +:1085800005463078012803D0022804D00720F0E700 +:10859000A8070FD502E015F0340F0BD0B079341DC9 +:1085A000C00709D0E08838B1A0680BF059FE18B1B7 +:1085B0001020DEE70820DCE732782088002628B388 +:1085C000A0F201130721112B18D20CD2DFE803F01F +:1085D0000B090D0B1D0B121D100B0B1D1D1D1D0B73 +:1085E0001D00022A11D10846C3E7012AFBD00CE086 +:1085F000EA0600E0AA06002AF5DA06E0A0F5C07255 +:108600001F2A02D97D3A022AEDD8C6B200F0CDFE6B +:1086100050B198F82300CDE90006FA89234639467F +:108620004846FEF7E3FCA4E71120A2E72DE9F04F4E +:108630008BB01F4615460C4683460026FAF75AFDB6 +:1086400028B10078222805D208200BB090E543F22B +:108650000200FAE7B80801D00720F6E7032F00D19F +:1086600000274FF6FF79CCB1022D72D320460BF0D4 +:1086700044FE30B904EB0508A8F101000BF03DFE03 +:1086800008B11020E1E7AD1EAAB22146484605F028 +:108690005AFD38F8021C88425BD1ADB21349B807C5 +:1086A00002D58889401C00E001201FFA80F8F807F5 +:1086B00001D08F8900E04F4605AA4146584605F093 +:1086C00014FB4FF0070A4FF00009D4B3204608E02E +:1086D000408810283DD8361D304486B2AE4238D28C +:1086E000A01902884245F3D353E000001403002090 +:1086F0009DF8170002074CD594B304EB0608361D0D +:10870000B8F80230B6B2102B23D89A19AA4220D852 +:10871000B8F8002091421CD1C0061CD5CDE900A9B3 +:108720000DF1080C0AAAA11948468CE80700B8F810 +:1087300000100022584605F061F920B1FEF709FA51 +:1087400083E726E005E0B8F80200BDF8281088426B +:1087500001D00B2079E7B8F80200304486B207E078 +:10876000FFE7C00604D55846FEF772FC002889D101 +:108770009DF81700BDF81A1020F010008DF81700B2 +:10878000BDF81700ADF80000FF235846009A05F029 +:108790000DFC05A805F0B5FA18B9BDF81A10B942D4 +:1087A000A6D90421584608F059F9040000D1FFDF8A +:1087B000A2895AB1CDE900A94D4600232146584669 +:1087C000FEF714FC0028BBD1A5813EE700203CE762 +:1087D0002DE9FF4F8BB01E4617000D464FF00004E9 +:1087E00012D0B00802D007200FB0C1E4032E00D190 +:1087F00000265DB108460BF077FD28B93888691E60 +:1088000008440BF071FD08B11020EDE7C64AB0072F +:1088100001D5D18900E00121F0074FF6FF7802D0A1 +:10882000D089401E00E0404686B206AA0B9805F0AB +:108830005CFA4FF000094FF0070B0DF1140A38E015 +:108840009DF81B00000734D5CDF80490CDF800B09A +:10885000CDF80890CDE9039A434600220B9805F025 +:10886000F7FA60BB05B3BDF814103A882144281903 +:10887000091D8A4230D3BDF81E2020F8022BBDF816 +:10888000142020F8022BCDE900B9CDE90290CDF8F3 +:1088900010A0BDF81E10BDF8143000220B9805F092 +:1088A000D7FA08B103209FE7BDF814002044001D4B +:1088B00084B206A805F025FA20B1822806D0FEF77A +:1088C00048F991E7BDF81E10B142B9D934B17DB174 +:1088D0003888A11C884203D20C2085E7052083E755 +:1088E00022462946404605F02EFC01462819018003 +:1088F000A41C3C80002077E710B504460BF0D6FCA2 +:1089000008B1102010BD8848C0892080002010BD0B +:10891000F0B58BB00D460646142103A819F085F971 +:1089200001208DF80C008DF8100000208DF811004A +:10893000ADF814503046FAF7DDFB48B10078222834 +:1089400012D30421304608F089F8040005D103E071 +:1089500043F202000BB0F0BDFFDF04F11400074644 +:1089600004F06FF8400601D40820F3E7207C0221D0 +:1089700040F00100207409A80094CDE901100722FD +:1089800003A930466368FEF7E7FA20B1217C21F0A5 +:1089900001012174DEE729463046F9F708FD08A9F0 +:1089A000384604F03DF800B1FFDFBDF82040172C39 +:1089B00001D2172000E02046A84201D92C4602E04F +:1089C000172C00D2172421463046FFF722FB214600 +:1089D0003046F9F708FA0020BCE7F8B51C46154602 +:1089E0000E46069F08F044F92346FF1DBCB23146EF +:1089F0002A46009407F0DBFCF8BD70B50C4605462E +:108A00000E21204619F0EFF8002020802DB1012D15 +:108A100001D0FFDF70BD062000E00520A07170BD11 +:108A200010B548800878134620F00F00001D20F094 +:108A3000F00080300C4608701422194604F108003A +:108A400019F09FF800F0B4FC3748046010BD2DE920 +:108A5000F047DFF8D890491D064621F0030117467C +:108A60000C46D9F8000007F01AFE050000D1FFDF20 +:108A70004FF000083560A5F800802146D9F80000C5 +:108A800007F00DFE050000D1FFDF7560A5F800803E +:108A90007FB104FB07F1091D0BD0D9F8000007F0E6 +:108AA000FEFD040000D1FFDFB460C4F80080BDE823 +:108AB000F087C6F80880FAE72DE9F0411746491D0E +:108AC00021F00302194D064601681446286807F094 +:108AD00011FE22467168286807F00CFE3FB104FBC6 +:108AE00007F2121D03D0B168286807F003FE0420C6 +:108AF00007F05EFF0446042007F062FF201A0128F9 +:108B000004D12868BDE8F04107F0BEBDBDE8F081A2 +:108B100010B50C4605F0B5F800B1FFDF2046BDE802 +:108B20001040FEF716B800001403002014000020C7 +:108B300010B50C460246817B808819B1518981426B +:108B400000D908462080D18800F0C5FF032800D353 +:108B50000320C1B22088BDE8104000F0B1BF10B5BD +:108B60000C460246817B808819B11189814200D967 +:108B700008462080D18800F0AEFF022800D30220F2 +:108B8000C1B2208800F09CFF401CC0B210BD2DE98E +:108B9000F04F0C00F84999B08146D1E90201CDE9C6 +:108BA0000C0109F10300F54E20F003010091357E20 +:108BB00005F1010504D1E8B209F054FB00B1FFDF73 +:108BC00000984FF0000B00EB0510C01C20F00301D3 +:108BD00000915CB9707A327A81F800B01044C2B268 +:108BE000B08B80B204F0D5FE00B1FFDF0098F169D0 +:108BF000084400902146684600F02CFF0098C01CF5 +:108C000020F003000090737A327AB17A04B1002028 +:108C100007F016FE0099084400902146684600F0CF +:108C20006EFF00273D46B24696F801800CE02846CC +:108C300000F0F3FE064681788088F9F76EF97178C6 +:108C40006D1C00FB0177EDB24545F0D10098C01CCA +:108C500020F00300009004B100203946F9F768F9CC +:108C600000990027084400903D469AF801800CE0E6 +:108C7000284600F0D2FE0646C1788088FEF773FCD5 +:108C800071786D1C00FB0177EDB24545F0D100987D +:108C9000C01C20F00300009004B100203946FEF70C +:108CA0006BFC00994FF000080844009045469AF884 +:108CB00001700EE0284600F0B0FE0646807B30B121 +:108CC00006F1080001F0F9FE727800FB02886D1CC5 +:108CD000EDB2BD42EED10098C01C20F00300009020 +:108CE00004B10020414601F0ECFE00990844C01D8B +:108CF00020F007000090E4BBA24AA1491160111DB9 +:108D0000401E086001222C219F4807F062FCFAF700 +:108D10002EF99E484178806805F09CFB42208DF832 +:108D200004009A480C30C0788DF8060010B1012874 +:108D300004D005E001208DF8060001E08DF806B0B2 +:108D400001A806F0C5FE10B10EA805F042FC0021F6 +:108D50001E22084603F03CF8FBF778F987480CAA76 +:108D600000210C30F8F706FB00B1FFDF9AF819007C +:108D700000E015E0FEF769FF00B1FFDF7F484FF428 +:108D8000F671443018F051FF7C480421443080F8DB +:108D9000E91180F8EA11062180F8EB110321017135 +:108DA000009919B0A1EB0900BDE8F08F70B5734CC4 +:108DB00006464434207804EB4015E078083590B935 +:108DC000A01990F8E80100280ED0A0780F2800D351 +:108DD000FFDF2021284618F028FF687866F302009C +:108DE00068700120E070284670BD2DE9F04105460D +:108DF0000C4600270078052190463E46B1EB101F37 +:108E000000D0FFDF287A58B101280FD0FFDF00BF64 +:108E1000A8F800600CB1278066800020BDE8F081D2 +:108E20000127092674B16888A08008E0022714266B +:108E300044B16888A0802869E060A88A2082287BE5 +:108E40002072E5E7A8F80060E7E710B54F4C6068CE +:108E5000C11D21F00701814200D0FFDF47480121F9 +:108E60000022017042700172032343728172027307 +:108E7000052282821F22C282417345A202610A2218 +:108E8000027641764FF4B061C1616168416010BD06 +:108E900030B53E4C1568636810339D4202D2042001 +:108EA000136030BD354B5D785A6802EB05121070C7 +:108EB00051700320D080172090800120D0709070D6 +:108EC000002090735878401C5870606810306060C3 +:108ED000002030BD70B5064628480024457807E0DC +:108EE000204600F09AFD0178B14204D0641CE4B23F +:108EF000AC42F5D1002070BDF7B5064608780C46A7 +:108F000008B3FFF7E7FF0546202E08D0232E17D021 +:108F1000212E41D0222E3FD0242E2BD114E000F060 +:108F200087FD0DB1697800E00021401A81B2A07878 +:108F30000144FF291ED830B1A08802282CD219E0A4 +:108F40006088172828D215E0227A2AB36188172969 +:108F500010D3A08817280DD3A3795BB1E3794BB167 +:108F6000402A07D84FF6FB72914201D8904213D99C +:108F70000420FEBD0720FEBD342002003004002086 +:108F80000000002000060240600600201C000020B7 +:108F90006E5246357800000065B9207802AA01219A +:108FA000FFF776FF0028E6D12078FFF793FF050052 +:108FB00000D1FFDF203E052E18D2DFE806F0030BBC +:108FC0000E081100A0786870A088E8800FE0608823 +:108FD000A8800CE0A078A87009E0A078E87006E00E +:108FE00054F8020FA8606068E86000E0FFDF00202E +:108FF000C1E700B597B053218DF8001000780BA998 +:1090000000F001008DF80200684605F023F817B063 +:1090100000BD00B5017897B001F001018DF8021094 +:10902000417801F001018DF803100178C1F340018E +:109030008DF804104178C1F340018DF805100178D6 +:1090400089088DF80610417889088DF80710817815 +:109050008DF80810C1788DF8091000798DF80A0094 +:109060004D208DF800000BA9684604F0F3FFCEE711 +:109070002DE9F04FDFF8F883FE4C97B000271BE096 +:10908000012000F07FFD0120FFF790FE0546FA4821 +:1090900007F0C8FA686000B9FFDF686805F027F8D4 +:1090A000A0B12846FAF7CEFA284600F071FD18B9AB +:1090B000F148696807F0BFFA94F9E9010428DFDA9A +:1090C000022007F075FC06460025AAE0EA48696818 +:1090D00007F0B1FAF4E7B8F802104046491C89B22B +:1090E000A8F80210B14201D3002141800221B8F852 +:1090F000020007F0B3FC00286BD0B8F8020054213E +:109100008DF80010ADF802000BA9684604F0A2FF2C +:1091100000B1FFDF9DF8300010F0010F0FD0B8F85C +:10912000020007F0B7FD5FEA000900D1FFDF484603 +:1091300006F0A3FF18B1B8F8020002F065F9B8F81C +:10914000020007F095FD5FEA000900D1FFDF484605 +:1091500006F08CFFE8BB0321B8F8020007F07EFCA4 +:109160005FEA000B48D1FFDF46E000BFDBF81000EC +:1091700010B10078FF2849D0022000F003FD022042 +:10918000FFF714FE8246484607F0A2F8CAF804002A +:1091900000B9FFDFDAF8040007F07CF90021009045 +:1091A0000170B8F802105046AAF8021001F032FE21 +:1091B000484607F071F900B9FFDF504600F0E8FCBF +:1091C00018B99AF80100000704D50098CBF81000F0 +:1091D00012E024E0DBF8100038B10178491C11F0EE +:1091E000FF01017008D1FFDF06E00022114648466A +:1091F00000F011FC00B9FFDF94F9EA01022805DB59 +:10920000B8F8020001F0CAFD0028AFD194F9E901D5 +:10921000042804DB484607F0B5F900B101276D1CAE +:10922000EDB2B54204D294F9EA010228BFF653AF79 +:10923000002F7FF423AF17B00320BDE8F04F00F0FC +:10924000A1BC10B58A4CA0600868E060AFF2DF10E6 +:1092500002F031FD607010BD864800214438017075 +:109260008348017085494160704730B505464FF02D +:1092700080500C46D0F8A41097B0491C05D1D0F806 +:10928000A810C9430904090C08D050F8A01F01F028 +:10929000010129704168216080680EE02B208DF863 +:1092A00000000BA9684604F0D5FE00B1FFDF0120E5 +:1092B00028700C982060BDF83400A0802878002821 +:1092C00003D0607940F0C000607117B030BDF0B5D8 +:1092D0004FF080540746D4F8800097B00D462B26F7 +:1092E000401C0BD1D4F88400401C07D1D4F888006E +:1092F000401C03D1D4F88C00401C0BD0D4F8800063 +:109300003860D4F884007860D4F88800B860D4F865 +:109310008C0016E08DF82C6069460BA804F09AFECC +:1093200000B1FFDF01983860029878608DF82C60FA +:1093300069460BA804F08EFE00B1FFDF0198B8600B +:109340000298F860D4F89000401C0BD1D4F8940037 +:10935000401C07D1D4F89800401C03D1D4F89C00DD +:10936000401C08D054F8900F286060686860A068BE +:10937000A860E06816E08DF800600BA9684604F06C +:1093800069FE00B1FFDF0C9828600D9868608DF8C9 +:1093900000600BA9684604F05DFE00B1FFDF0C9889 +:1093A000A8600D98E86017B0F0BD32480079FDE480 +:1093B00070B5304CE07830B3207804EB4010407A40 +:1093C00000F00700204490F9E801002800DCFFDFEE +:1093D0002078002504EB4010407A00F007000119C6 +:1093E00091F8E801401E81F8E8012078401CC0B2E5 +:1093F00020700F2800D12570A078401CA0700AF0C2 +:109400001BFBE57070BDFFDF70BD3EB50546032157 +:1094100007F024FB0446284607F02AFC054604B959 +:10942000FFDF206918B10078FF2800D1FFDF01AA13 +:109430006946284600F0EFFA60B9FFDF0AE0002233 +:1094400002A9284600F0E7FA00B9FFDF9DF80800FE +:1094500000B1FFDF9DF80000411E8DF80010EED234 +:1094600020690199884201D1002020613EBD0000A1 +:109470001C000020740400206006002068130020F7 +:1094800070B50546A0F57F400C46FF3800D1FFDFE0 +:10949000012C01D0FFDF70BDFFF787FF040000D172 +:1094A000FFDF207820F00F00401D20F0F00050304A +:1094B000207065800020207201202073BDE870407C +:1094C00076E72DE9F04116460D460746FFF76DFF9A +:1094D000040000D1FFDF207820F00F00401D20F0B5 +:1094E000F0005030207067800120207228682061D1 +:1094F000A888A0822673BDE8F04159E730B599B03D +:10950000FFF7E8FC040000D1FFDF0CA92046FFF7BD +:109510000FFB05460BA92046FFF721FB0146522011 +:109520008DF80000BDF830008DF80250001DADF838 +:109530000400BDF82C008DF80310001DADF80600E6 +:10954000E088ADF808000DA9684604F083FD002806 +:1095500000D0FFDF19B030BD2DE9F047DFF80094EF +:109560000546002799F8000010B10820BDE8F087F3 +:1095700028460AF09BFE08B11020F7E7F94C207846 +:1095800008B9FFF762FC607A217A0844C6B200F09D +:109590004FFAB04207D2301AC1B22A460020FFF774 +:1095A00077FC0700E2D1D9F804004E46C01C20F039 +:1095B0000300C9F8040000F05EFB716800EB0108CD +:1095C00001214046FFF7E3FA0646296840448842F5 +:1095D00002D8B6F5803F15D328600020FFF77AFC4B +:1095E00005000DD005F11300D9F8041020F0030098 +:1095F0004E46884200D0FFDF6078401E6070756084 +:109600000420B3E700214046FFF7C1FA0446A64212 +:1096100000D0FFDF04EB0801C9F8041029604FF601 +:10962000FF71A9F80210012189F8001038469DE762 +:109630002DE9F0410446CA4817460D46007810B19E +:109640000820BDE8F08108460AF00AFE08B11020A3 +:10965000F7E7C44E307808B9FFF7F7FB601E1E2805 +:1096600007D8012C3FD12878FE283CD8307600203E +:10967000E7E7A4F120001F2805D8E0B23A462946C2 +:10968000BDE8F04138E4A4F140004FF000081F2885 +:1096900021D8402C02D0412C25D117E068782978B8 +:1096A0004418A97881421ED8FF2C08D808F0BEFFC4 +:1096B00007460AF07BF9381A801EA04201DA122010 +:1096C000BFE728883081A878B07224E02846BDE83A +:1096D000F04100F085BAA4F1A0001F2803D8A02C07 +:1096E00003D0A12C06D00720ABE7287800F00100BA +:1096F000707610E029680920F829A2D38A07A0D142 +:10970000727B02F00302012A04D1F28AD73293B2AB +:109710008B4296D8F161404693E72DE9F0478146A8 +:109720000E4608460AF0C2FD48B948460AF0DCFD7C +:1097300028B909F1030020F00301494501D01020A8 +:1097400014E788484FF0000A4430817869B14178C5 +:10975000804600EB41140834378832460021204609 +:1097600000F024FA050004D027E0A6F800A00520A8 +:10977000FCE6B9F1000F24D03088B84201D90C259D +:109780001FE0607800F00705284600F0FBF908EBC1 +:109790000507324697F8E8014946401C87F8E8017A +:1097A000204607F5F47700F001FA05463878401EA8 +:1097B0003870032000F0E6F92DB10C2D01D0A6F889 +:1097C00000A02846D2E66078654F00F00701012925 +:1097D00023D002290CD0032932D0FFDF98F80110E2 +:1097E0004046491CC9B288F801100F2933D034E033 +:1097F000616821B1000702D46088FFF706FE98F87F +:10980000EA014646012802D1787802F073FA96F907 +:10981000EA010428E2DBFFDFE0E7616811B15248AA +:1098200006F009FF98F8E9014646032802D1787846 +:1098300002F060FA96F9E9010428CFDBFFDFCDE7FB +:10984000C00602D56088FFF7E0FD98F9EB01062815 +:10985000C4DBFFDFC2E780F801A08178491E817078 +:10986000617801F0070101EB080090F8E811491C4C +:1098700080F8E811A5E770B50D4604460AF0F0FC43 +:1098800018B928460AF012FD08B1102070BD29460B +:109890002046BDE8704008F01CBD70B50446154672 +:1098A0000E4608460AF0DCFC18B928460AF0FEFC11 +:1098B00008B1102070BD022C03D0102C01D009205B +:1098C00070BD2A463146204608F026FD0028F7D014 +:1098D000052070BD70B514460D4606460AF0C0FC62 +:1098E00038B928460AF0E2FC18B920460AF0FCFC18 +:1098F00008B1102070BD22462946304608F02BFDE5 +:109900000028F7D0072070BD10B596B004460AF0C5 +:10991000CDFC10B1102016B010BD0F208DF8000046 +:109920000BA9684604F096FB0028F4D19DF834009A +:109930002070BDF836006080BDF83800A08000209F +:10994000E9E770B505460C4608460AF0CDFC20B99B +:1099500074B120680AF0AAFC40B1102070BD00006C +:109960001C0000203004002060060020A08828B1E0 +:1099700021462846BDE87040FDF774BE0920EDE79A +:1099800070B504460D4608460AF06AFC30B9601E00 +:109990001E2814D828460AF063FC08B11020DDE721 +:1099A000022C01D90720D9E704B9FFDFE64800EB14 +:1099B000840050F8041C2846BDE870400847A4F114 +:1099C00020001F28EED829462046BDE87040FAF74F +:1099D0007FBA70B504460D4608460AF067FC30B9F8 +:1099E000601E1E280DD828460AF03AFC08B1102047 +:1099F000B4E7012C01D0022C01D10620AEE70720EC +:109A0000ACE7A4F120001F28F9D829462046BDE87C +:109A10007040FAF7E1BA06F0E4BA30B5CB4D04462F +:109A20006878A04200D8FFDF686800EB041030BD02 +:109A300070B5C64800252C46467807E02046FFF75B +:109A4000ECFF4078641C2844C5B2E4B2B442F5D1BE +:109A5000284683E72DE9F0410C46064600F043F91D +:109A600007463068C01C20F0030232601CBBB748B8 +:109A70003B46092120300AF0CDFA002408E0092CE9 +:109A800011D2DFE804F005070509090B05050700F9 +:109A9000AF4804E0AF4802E0AF4800E0AF480AF04A +:109AA000D9FA054600E0FFDFA54200D0FFDF641CC5 +:109AB000E4B2092CE3D3306800EB07103060C0E556 +:109AC000021D5143452900D245210844C01CB0FB6A +:109AD000F2F0C0B2704700B597B055228DF8002063 +:109AE000001DADF80200ADF804100BA9684604F0A3 +:109AF000B1FA00B1FFDFBDF8300017B000BD2DE9AD +:109B0000FC5F064691484FF000088B4647464446A6 +:109B100090F8019022E02046FFF77FFF050000D17A +:109B2000FFDF687869463844C7B22846FFF700F877 +:109B3000824601A92846FFF712F80346BDF8040043 +:109B40005246001D81B2BDF80000001D80B206F033 +:109B5000DBFF6A78641C00FB0288E4B24C45DAD172 +:109B60003068C01C20F003003060BBF1000F00D053 +:109B700000204246394606F0D5FF3168084430607F +:109B8000BDE8FC9F7149443108710020C8707047DE +:109B90006E494431CA782AB10A7801EB4211083182 +:109BA000814201D001207047002070472DE9F0412B +:109BB00006460078154600F00F0400201080601E55 +:109BC0000F46052800D3FFDF5F482A46103000EB20 +:109BD0008400394650F8043C3046BDE8F04118474F +:109BE00038B50446407800F00300012803D002286D +:109BF0000BD0072038BD606858B10AF07EFBD0B9A1 +:109C000060680AF071FB20B915E060680AF028FB73 +:109C100088B969462046FCF7A9F90028EAD160789E +:109C200000F00300022808D19DF8000028B1606808 +:109C30000AF05AFB08B1102038BD6189F8290DD807 +:109C4000208988420AD8607800F003023F48012A40 +:109C500006D1D731C26989B28A4201D2092038BD02 +:109C600094E80E0000F10C0585E80E000AB9002109 +:109C70008182002038BD2DE9F05F4FF000093348A4 +:109C8000C8464F464E464D46CB464C4690F801A03E +:109C900011E02046FFF7C1FE4178827809F1010901 +:109CA000884412FB0177C27812FB0166807B10FBAF +:109CB0000155641CE4B25445EBD10BEB890000EB79 +:109CC000C80000EB870000EB860000EBC5011F48D1 +:109CD000027A01EBC201427A807A01EBC20101EB08 +:109CE000C000BDE8F09F2DE9F047DFF86090002547 +:109CF0002C4699F8092099F8081099F801700A443F +:109D0000D6B299F80A20114401F0FF0808E0204675 +:109D1000FFF783FE817B407811FB0055641CE4B2A1 +:109D2000BC42F4D199F80800401C3044304440440F +:109D3000401C0EB1012100E0002108444419FF2C11 +:109D400000D9FFDFE0B211E434200200300400202B +:109D5000633D00008DAB0000592F00003120010051 +:109D60002DE9F041074614468846084601F02EFDCD +:109D7000064608EB88001C22796802EBC0000D182B +:109D8000688C58B14146384601F028FD0146786894 +:109D90000078C200082305F120000CE0E88CA8B18F +:109DA0004146384601F021FD014678680823407895 +:109DB000C20005F1240006F0F4FC38B1062121723E +:109DC0006681D0E90010C4E9031009E02878092869 +:109DD0000BD00520207266816868E0600020287042 +:109DE0002046BDE8F04101F0E7BC07202072668103 +:109DF000F4E72DE9F04116460D460746406801EBB1 +:109E000085011C2202EBC1014418204601F00FFD20 +:109E100040B10021708865F30F2160F31F410820D5 +:109E20000AF0D2F909202070324629463846BDE8AA +:109E3000F04195E72DE9F0410E46074600241C212C +:109E4000F07816E004EB8403726801EBC303D25C84 +:109E50006AB1FFF7AAFA050000D1FFDF6F802A463A +:109E600021463046FFF7C5FF0120BDE8F081641CA4 +:109E7000E4B2A042E6D80020F7E770B50646002419 +:109E80001C21C0780AE000BF04EB8403726801EB78 +:109E9000C303D5182A782AB1641CE4B2A042F3D8CF +:109EA000402070BD2821284617F09DFE70688089EB +:109EB0002881204670BD70B5034600201C25DC7843 +:109EC0000DE000BF00EB80065A6805EBC606324481 +:109ED000167816B1128A8A4204D0401CC0B284425D +:109EE000F0D8402070BDF0B5044600201C26E5786F +:109EF0000EE000BF00EB8007636806EBC7073B443A +:109F00001F788F4202D15B78934204D0401CC0B2CC +:109F10008542EFD84020F0BD0078032801D0002012 +:109F20007047012070470078022801D00020704758 +:109F3000012070470078072801D0002070470120D9 +:109F400070472DE9F041064688461078F1781546AD +:109F5000884200D3FFDF2C781C27641CF078E4B221 +:109F6000A04201D8201AC4B204EB8401706807EB48 +:109F7000C1010844017821B14146884708B12C70DD +:109F800073E72878A042E8D1402028706DE770B5CB +:109F900014460B880122A240134207D113430B80C1 +:109FA00001230A22011D06F0C6FB047070BD2DE9D5 +:109FB000FF4F81B00878DDE90E7B9A4691460E4648 +:109FC00040072CD4019806F065FE040000D1FFDFA5 +:109FD00007F1040820461FFA88F105F0A9FE0500E4 +:109FE00000D1FFDF204629466A4606F092F9009824 +:109FF000A0F80370A0F805A0284606F04BFA0178F7 +:10A0000069F306016BF3C711017020461FFA88F14E +:10A0100005F0DEFE00B9FFDF019804F07CF906EBE5 +:10A020000900017F491C017705B0BDE8F08F2DE9DB +:10A03000F84F0E469A4691460746032106F00EFD5C +:10A040000446008DDFF8B085002518B198F80000AF +:10A05000B0421ED1384606F01DFE070000D1FFDFDA +:10A0600009F10401384689B205F062FE050010D0FE +:10A07000384629466A4606F04CF9009800210A46FF +:10A080000180817004F00AFA0098C01DCAF800002F +:10A0900021E098F80000B04216D104F1260734F808 +:10A0A000341F012000FA06F911EA090F00D0FFDF82 +:10A0B0002088012340EA090020800A22391D384601 +:10A0C00006F054FB067006E0324604F1340104F158 +:10A0D0002600FFF75CFF0A2188F800102846BDE83B +:10A0E000F88FFEB514460D46064602AB0C2206213B +:10A0F000FFF79DFF002826D00299687812220A7087 +:10A10000801C487008224A80A87020888880608857 +:10A11000C880A0880881E088488100240C20CDE90F +:10A1200000040523062229463046FFF740FF21465A +:10A1300066F31F41F0230022012009F09BFF68789D +:10A14000801C68700120FEBDFEB514460D46062237 +:10A15000064602AB1146FFF76AFF002812D0029BA9 +:10A16000132000211870A8785870022058809C8015 +:10A170000620CDE900010246052329463046FFF7B7 +:10A1800016FF0120FEBD2DE9FE430C46804644E04B +:10A1900002AB0E2207214046FFF749FF002841D0BD +:10A1A00060681C2267788678BF1C06EB860102EB8C +:10A1B000C101451802981421017047700A2141809D +:10A1C000698A0181E98A4181A9888180A98981817F +:10A1D000304601F0FBFA029905230722C8806F7010 +:10A1E0000420287000250E20CDE9000521464046B8 +:10A1F000FFF7DDFE294666F30F2168F31F41F023C8 +:10A200000022082009F036FF6078FC49801C60704D +:10A2100062682046921CFFF794FE606880784028B0 +:10A22000B6D10120BDE8FE83FEB50D46064638E0F6 +:10A2300002AB0E2207213046FFF7F9FE002835D089 +:10A2400068681C23C17801EB810203EBC202841809 +:10A25000029815220270627842700A224280A28916 +:10A260004281A2888281084601F0B0FA0146029834 +:10A270008180618AC180E18A0181A088B8B1002013 +:10A28000207000210E20CDE9000105230722294678 +:10A290003046FFF78CFE6A68D9492846D21CFFF782 +:10A2A00050FE6868C0784028C2D10120FEBD06205B +:10A2B000E6E72DE9FE430C46814644E0204601F0E6 +:10A2C000A0FAD0B302AB082207214846FFF7AFFE41 +:10A2D0000028A7D060681C2265780679AD1C06EBC3 +:10A2E000860102EBC10147180298B7F810800621D9 +:10A2F0000170457004214180304601F067FA014643 +:10A30000029805230722C180A0F804807D700820F0 +:10A3100038700025CDE9000521464846FFF747FE85 +:10A32000294666F30F2169F31F41F023002208201C +:10A3300009F0A0FE6078801C60706268B149204618 +:10A34000121DFFF7FEFD606801794029B6D101209A +:10A3500068E72DE9F34F83B00E4680E0304601F008 +:10A3600050FA002875D071681C2091F8068008EB1F +:10A37000880200EBC2000C184146304601F035FA65 +:10A380000146A078C30070684078C20004F1240040 +:10A3900006F023FA07468088E18B401A80B2002538 +:10A3A00081B3AA46218B814200D8084681460246E5 +:10A3B00002AB07210398FFF73AFE010028D0BAF15B +:10A3C000000F03D0029AB888022510808B46E28BDA +:10A3D0003968A9EB05001FFA80FA0A440398009235 +:10A3E00006F058FCED1D009A59465346009506F0BC +:10A3F00017F8E08B504480B2E083B988884209D1D5 +:10A40000012508E0FFE7801C4FF0010A80B2C9E790 +:10A41000002009E60025CDE90095238A0722314670 +:10A420000398FFF7C4FDE089401EE0818DB1A0785C +:10A43000401CA0707068F178427811FB02F1CAB23A +:10A44000816901230E3006F076F980F80080002043 +:10A45000E08372686C493046921DFFF772FD7068A8 +:10A46000817940297FF47AAF0120DDE570B5064699 +:10A4700048680D4614468179402910D104EB8401C7 +:10A480001C2202EBC101084401F0F2F9002806D0B9 +:10A490006868294684713046BDE8704059E770BD50 +:10A4A000FEB50C460746002645E0204601F0A9F916 +:10A4B000D8B360681C22417901EB810102EBC10134 +:10A4C0004518688900B9FFDF02AB0822072138462A +:10A4D000FFF7ADFD002833D00299607816220A708C +:10A4E000801C4870042048806068407901F06EF953 +:10A4F000014602980523072281806989C1800820CE +:10A50000CDE9000621463846FFF751FD6078801CF2 +:10A510006070A88969890844B0F5803F00D3FFDFE7 +:10A52000A88969890844A8816E81626837492046F4 +:10A53000521DFFF706FD606841794029B5D1012021 +:10A54000FEBD30B5438C458BC3F3C704002345B132 +:10A55000838B641EED1AC38A6D1E1D4495FBF3F3B5 +:10A56000E4B22CB1008918B1A04200D820460344BF +:10A570004FF6FF70834200D3034613800C7030BD4A +:10A580002DE9FC41074616460D46486802EB860158 +:10A590001C2202EBC101441801AA69462046FFF7BC +:10A5A000D0FFA1896389BDF80420C81880B2824217 +:10A5B0001FD001280AD99DF800C0BCF1000F03D0BC +:10A5C000B4F808C0844501D8002B12D0501A00D529 +:10A5D000002060816868407940280AD1204601F057 +:10A5E0003DF9002805D06868294646713846FFF7CE +:10A5F00057FFBDE8FC8100002C000020199F0000DF +:10A60000279F0000359F000071B800005DB8000072 +:10A610002DE9FE4F8946804615465088032106F0F5 +:10A620001DFA8346B8F80200402801D2402000E01D +:10A63000403880B282460146584601F0E2F80028D0 +:10A640007ED00AEB8A001C22DBF8041002EBC0006B +:10A650000C18204601F0EBF8002877D1B8F800007C +:10A66000E18A88423CD8A189D1B348456ED1002601 +:10A670005146584601F0B2F8218C0F18608B48B94A +:10A68000B9F1020F62D3B8F804006083618A88428E +:10A6900026D80226A9EB06001FFA80F9B888A28BFB +:10A6A000801A002814DD4946814500DA084683B245 +:10A6B00068886968029139680A44CDE9003206F079 +:10A6C000D7FADDE90121F61D009B009605F06FFE2B +:10A6D000A18B01EB090080B2A083618B884207D96E +:10A6E000688803B052465946BDE8F04F01F0DDB826 +:10A6F0001FD14FF009002872B8F802006881D7E92D +:10A700000001C5E90401608BA881284601F054F8D6 +:10A710005146584601F062F80146DBF80400082370 +:10A720000078C20004F1200006F03BF80020A0836E +:10A730006083A0890AF0FF02401EA081688800E0C3 +:10A7400004E003B05946BDE8F04F19E7BDE8FE8FBD +:10A750002DE9F041064615460F461C46184609F0FD +:10A760007FFD18B9206809F0A1FD08B1102007E4A9 +:10A770007168688C0978B0EBC10F01D3132005E430 +:10A780003946304601F02AF80146706808230078FF +:10A79000C20005F1200005F0CEFFD4E90012C0E9A7 +:10A7A00000120020E3E710B50446032106F056F935 +:10A7B0000146007800F00300012804D08A8A204670 +:10A7C000BDE81040C0E42046BDE8104001F114028D +:10A7D00087E470B50446032106F040F905460146BA +:10A7E0002046FFF766FD002816D029462046FFF7D1 +:10A7F00057FE002810D029462046FFF715FD0028F7 +:10A800000AD029462046FFF7BEFC002804D029467E +:10A810002046BDE870409CE570BD2DE9F0410C4636 +:10A8200080461EE0E178427811FB02F1CAB28169EC +:10A8300001230E3005F0B5FF077860681C22C1794E +:10A84000491EC17107EB8701606802EBC101461820 +:10A850003946204600F0D5FF18B1304600F0E0FF41 +:10A8600020B16068C1790029DCD180E7FEF79DFD49 +:10A87000050000D1FFDF0A202872384600F0A6FF4D +:10A8800068813946204600F0B0FF01466068082321 +:10A890004078C20006F1240005F083FFD0E90010E3 +:10A8A000C5E90310A5F80280284600F085FFB078BE +:10A8B00000B9FFDFB078401EB07058E770B50C46A5 +:10A8C0000546032106F0CAF801464068C2792244D1 +:10A8D000C2712846BDE870409FE72DE9FE4F8246D1 +:10A8E000507814460F464FF0000800284FD001283A +:10A8F00007D0022822D0FFDF2068B8606068F860C7 +:10A9000024E702AB0E2208215046FFF790FB0028F7 +:10A91000F2D00298152105230170217841700A2197 +:10A920004180C0F80480C0F80880A0F80C806288DC +:10A9300082810E20CDE90008082221E0A678304669 +:10A9400000F044FF054606EB86012C22786802EBF6 +:10A95000C1010822465A02AB11465046FFF767FB79 +:10A960000028C9D002980721017021784170042184 +:10A97000418008218580C680CDE9001805230A465C +:10A9800039465046FFF713FB87F80880DEE6A678C5 +:10A99000022516B1022E13D0FFDF2A1D914602AB0D +:10A9A00008215046FFF743FB0028A5D0029801215B +:10A9B000022E0170217841704580868002D005E02A +:10A9C0000625EAE7A188C180E1880181CDE90098E8 +:10A9D0000523082239465046D4E710B50446032122 +:10A9E00006F03CF8014600F108022046BDE81040A0 +:10A9F00073E72DE9F05F0C4601281DD0957992F898 +:10AA00000480567905EB85011F2202EBC10121F07C +:10AA1000030B08EB060111FB05F14FF6FF7202EA8A +:10AA2000C10909F1030115FB0611F94F21F0031AC1 +:10AA300040B101283DD124E06168E57891F80080BB +:10AA40004E78DFE75946786805F029FE606000B966 +:10AA5000FFDF5946606817F0E8F8E57051467868FE +:10AA600005F01DFE6168486100B9FFDF606842695A +:10AA700002EB09018161606880F8008060684670BF +:10AA800017E0606852464169786805F033FE5A461F +:10AA90006168786805F02EFE032005F089FF044602 +:10AAA000032005F08DFF201A012802D1786805F0F7 +:10AAB000EBFD0BEB0A00BDE8F09F024600210220EF +:10AAC00097E713B5009858B10024684605F0C9FD12 +:10AAD000CF490A22002C0A7001D1009A4A601CBD9D +:10AAE00001240020F2E770B50C46154638212046B7 +:10AAF00017F09BF8012666700A2104F11C0017F07C +:10AB000094F805B9FFDF297A207861F301002070FD +:10AB1000A879002817D02A4621460020FFF769FFB0 +:10AB20006168402088706168C870616808716168F8 +:10AB300048716168887161682888088161686888DF +:10AB400048816068868170BDC878002802D00022E4 +:10AB500001204EE7704770B50546002165F31F419F +:10AB6000012009F031FB0321284605F077FF04009E +:10AB700000D1FFDF21462846FFF75CF9002804D00A +:10AB8000207840F010002070012070BD2DE9FF41B9 +:10AB900080460E460F0CFEF708FC050007D06F80BC +:10ABA0000321384605F05AFF040008D106E004B03E +:10ABB0003846BDE8F0411321F9F72EBEFFDFB8F1AA +:10ABC000010F05D0B8F1080F18D0FFDFBDE8FF81F5 +:10ABD00020782A4620F0080020700020ADF80200FE +:10ABE00002208DF800004FF6FF70ADF80400ADF8BC +:10ABF000060069463846F9F717F9E7E7C6F3072173 +:10AC000001EB81021C23606803EBC202805C042814 +:10AC100003D008280AD0FFDFD8E7012000904FF4C6 +:10AC200040432A46204600F009FECFE704B02A46FA +:10AC30002046BDE8F041FFF7DCB82DE9F05F0027C2 +:10AC4000B0F80A9090460C4605463E46B9F1400FD2 +:10AC500001D2402001E0A9F140001FFA80FA287AD1 +:10AC6000C01E08286BD2DFE800F00D04192058360A +:10AC70003C4772271026002C6CD0D5E90301C4E9AB +:10AC800002015CE070271226002C63D00A2205F135 +:10AC90000C0104F1080016F074FF50E071270C2637 +:10ACA000002C57D0E868A06049E0742710269CB3B8 +:10ACB000D5E90301C4E902016888032105F0CEFE4D +:10ACC0008346FEF772FB024668885080514658461C +:10ACD000FFF746F833E075270A26ECB1A8892081F2 +:10ACE0002DE076271426BCB105F10C0004F1080311 +:10ACF00007C883E8070022E07727102664B1D5E96A +:10AD00000301C4E902016888032105F0A7FE01469A +:10AD10006888FFF782FD12E01CE073270826CCB19B +:10AD20006888032105F09AFE01460078C00606D522 +:10AD30006888FFF77FF810B96888F8F767FCA8F80B +:10AD400000602CB12780A4F8069066806888A080F7 +:10AD50000020B0E6A8F80060FAE72DE9FC410C46B7 +:10AD60001E4617468046032105F078FE05460A2C4C +:10AD70000AD2DFE804F005050505050509090907FC +:10AD8000042303E0062301E0FFDF0023CDE9007682 +:10AD9000224629464046FFF70AF92AE438B5054617 +:10ADA000A0F57F40FF3830D0284605F061FF040051 +:10ADB00000D1FFDF204605F08BFA002815D00146B0 +:10ADC0006A46204605F0A5FA00980321B0F8054030 +:10ADD000284605F043FE0546052C03D0402C05D23D +:10ADE000402404E0007A80B1002038BD403CA4B289 +:10ADF000214600F006FD40B1686804EB84013E2264 +:10AE000002EBC101405A0028EFD0012038BD0000FC +:10AE10002C0000202DE9F04F044689B0408805F051 +:10AE200027FF050000D1FFDF06AA2846616800F071 +:10AE3000C1FC069D001F81B235F8032F6B888A4242 +:10AE400005D1042B0AD0052B1DD0062B15D0224688 +:10AE50002846FFF7DDFB09B0BDE8F08F16462D1D33 +:10AE6000224629463046F7F78CFA0828F3D12246C5 +:10AE700029463046FCF73DFCEDE76088291D6368F4 +:10AE8000FAF7F0FCE7E717466088032105F0E6FDD6 +:10AE90004FF000088DF804800646ADF80680042FB8 +:10AEA000D9D36A79002AD6D028794FF6FF794FF0A6 +:10AEB0001C0A13282CD008DC012878D0062847D09B +:10AEC000072875D0122874D106E0142872D01528EE +:10AED00071D016286DD1ACE10C2F6AD1307800F01A +:10AEE0000301012965D040F0080030706879B07026 +:10AEF00001208DF804002889ADF808006889ADF8B4 +:10AF00000A00A889ADF80C00E889ADF80E0019E038 +:10AF1000B07890429FD1307801079CD5062F9AD106 +:10AF200020F0080030706088414660F31F41012026 +:10AF300009F04AF902208DF80400ADF8089028893C +:10AF4000ADF80A006088224601A9F8F76DFF82E794 +:10AF5000082F80D12F89B5F80A90402F01D24020C8 +:10AF600001E0A7F1400080B280460146304600F083 +:10AF700048FC08B3716808EB88002C2202EBC00083 +:10AF8000095A4945E3D1FE4807AAD0E90210CDE9A4 +:10AF9000071068798DF81C0008F0FF058DF81E5029 +:10AFA00060883146FFF799FC2246294639E0B6E031 +:10AFB00014E03CE039E0E6E0F148D0E90010CDE9EA +:10AFC00007106879ADF820708DF81C00ADF822905C +:10AFD000608807AA3146FFF780FC3CE7082FB6D10E +:10AFE0006889B5F80880402801D2402000E0403848 +:10AFF00087B23946304600F004FC0028A7D007EBA2 +:10B00000870271680AEBC2000844028A42459ED159 +:10B01000017808299BD140786979884297D1F9B2A3 +:10B0200022463046FEF7E5FE15E70E2F07D0CDF895 +:10B030001C80CDF8208068798DF81C00C8E76989EC +:10B04000EF898B46B5F80C903046FEF734FFABF134 +:10B050004001402901D309204AE0B9F1170F01D37B +:10B06000172F01D20B2043E040280ED000EB8002C6 +:10B0700071680AEBC20008440178012903D14078C5 +:10B0800069798842A9D00A2032E03046FEF7F5FE01 +:10B09000014640282BD001EB810372680AEBC30004 +:10B0A00002EB0008012288F800206A7988F8012064 +:10B0B00070682A894089B84200D938462D8A03230E +:10B0C0002372A282E7812082A4F80C906582084650 +:10B0D00000F07CFB6081A8F81490A8F81870A8F81C +:10B0E0000E50A8F810B0204600F066FBB3E604202E +:10B0F00005212172A4F80A80E08101212173A04971 +:10B10000D1E90421CDE9072169798DF81C10ADF84A +:10B110001E00608807AA3146FFF7DFFBE3E7062F32 +:10B12000E4D3B078904215D13078010712D520F0E1 +:10B13000080030706088414660F31F41012009F02B +:10B1400043F802208DF804002889ADF80800ADF816 +:10B150000A90F7E604213046FEF7C5FE0546402872 +:10B16000C4D002208303009022462946304600F0D6 +:10B1700065FB4146608865F30F2160F31F4108209D +:10B1800009F022F867E60E2FB0D104213046FEF711 +:10B19000AAFE81464028A9D04146608869F30F2164 +:10B1A00060F31F41082009F00FF8288A0790E8890A +:10B1B00000907068AF894089B84200D9384683460C +:10B1C000B5F80A8028890590484600F0FFFA6081AA +:10B1D000079840B10220079B00902246494630461E +:10B1E00000F02CFB37E6B8F1170F1ED3172F1CD336 +:10B1F0000420207200986082E781A4F810B0A4F8BF +:10B200000C8009EB890271680AEBC2000D180099E5 +:10B210000598A5F81480A5F818B0E9812882204681 +:10B2200000F0CAFA0620287015E601200B230090D2 +:10B23000D3E7082FA6D129893046FEF73CFE074602 +:10B2400040289FD007EB870271680AEBC2000844D0 +:10B25000804600F0ECFA002894D16D89B8F80E0011 +:10B260002844B0F5803F05D360883A46314600F067 +:10B270001CFBF0E5002D85D0A8F80E0060883A464A +:10B280003146FFF7F3F808202072384600F09EFAA6 +:10B290006081A58127E770B50D460646032105F0BC +:10B2A000DDFB040004D02078000704D5112070BD18 +:10B2B00043F2020070BD2A4621463046FEF711FFD8 +:10B2C00018B9286860616868A061207840F00800BB +:10B2D0002070002070BD70B50D460646032105F0B4 +:10B2E000BDFB040004D02078000704D4082070BD02 +:10B2F00043F2020070BD2A4621463046FEF724FF85 +:10B3000000B9A582207820F008002070002070BDD0 +:10B310002DE9F04F0E4691B08046032105F09EFBCB +:10B320000446404605F0B6FC07460020079008900A +:10B330000990ADF830000A9002900390049004B98F +:10B34000FFDF0DF1080917BBFFDF20E038460BA92E +:10B35000002204F046FE9DF82C0000F07F050A2D27 +:10B3600000D3FFDF6019017F491E01779DF82C0093 +:10B3700000060CD52A460CA907A8FEF708FE01E036 +:10B380005C20020019F80510491C09F80510761E0A +:10B39000F6B2DBD204F13400FC4D04F1260BDFF8E9 +:10B3A000F0A304F12A07069010E05846069900F031 +:10B3B0006EFA064628700A2800D3FFDF5AF82610D6 +:10B3C00040468847E08CC05DB04202D0208D002806 +:10B3D000EBD10A202870EE4D4E4628350EE00CA920 +:10B3E00007A800F054FA0446375D55F8240000B968 +:10B3F000FFDF55F82420394640469047BDF81E002F +:10B400000028ECD111B027E510B5032105F026FB8B +:10B41000040000D1FFDF0A2104F11C0016F005FC36 +:10B42000207840F00400207010BD10B50C460321B8 +:10B4300005F014FB01190A7F01211AB9808EA14081 +:10B44000084000D0012010BD2DE9F84F894615466F +:10B450008246032105F002FB070004D0284608F0CD +:10B46000FFFE40B903E043F20200BDE8F88F484612 +:10B4700008F01CFF08B11020F7E7786828B1698848 +:10B480000089814201D90920EFE7B9F800001C24A6 +:10B4900018B1402809D2402008E03846FEF7EDFCFC +:10B4A0008046402819D11320DFE7403880B280461B +:10B4B0000146384600F0A5F948B108EB88007968E4 +:10B4C00004EBC000085C012803D00820CDE705206C +:10B4D000CBE7FDF76AFF06000BD008EB8800796820 +:10B4E00004EBC0000C18B9F8000020B1E88910B1D5 +:10B4F00013E01120B9E72888172802D36888172895 +:10B5000001D20720B1E7686838B12B1D22464146B9 +:10B510003846FFF71DF90028A7D104F10C0269464F +:10B520002046FFF70EF8288860826888E082B9F824 +:10B53000000030B102202070E889A080E889A0B125 +:10B540002BE003202070A889A080786881784029AA +:10B5500005D180F8028039465046FEF714FE404679 +:10B5600000F034F9A9F8000021E07868218B4089C7 +:10B57000884200D908462083A6F802A00420307231 +:10B58000B9F800007081E0897082F181208B3082EF +:10B59000A08AB081304600F00FF97868C178402960 +:10B5A00005D180F8038039465046FEF73DFE002065 +:10B5B0005BE770B50D460646032105F04FFA04001F +:10B5C00003D0402D04D2402503E043F2020070BDB9 +:10B5D000403DADB2294600F014F958B105EB8501A4 +:10B5E0001C22606802EBC101084400F020F918B188 +:10B5F000082070BD052070BD2A462146304600F067 +:10B6000054F9002070BD2DE9F0410D4616468046E4 +:10B61000032105F023FA0446402D01D2402500E025 +:10B62000403DADB28CB1294600F0EBF880B105EB9E +:10B6300085011C22606802EBC1014718384600F002 +:10B64000F6F838B10820BDE8F08143F20200FAE7CD +:10B650000520F8E733463A4629462046FFF778F8B2 +:10B660000028F0D1EAB221464046FEF789FF0020CB +:10B67000E9E72DE9F0410D4616468046032105F025 +:10B68000EDF90446402D01D2402500E0403DAFB227 +:10B6900024B1304608F0E4FD38B902E043F202007C +:10B6A000D1E7306808F0DCFD08B11020CBE739465F +:10B6B000204600F0A6F860B107EB87011C22606805 +:10B6C00002EBC1014518284600F0B1F818B1082076 +:10B6D000B9E70520B7E7B088A98A884201D90C20CC +:10B6E000B1E76168E88C4978B0EBC10F01D3132052 +:10B6F000A9E73946204600F078F80146606808233B +:10B700004078C20005F1240005F015F8D6E90012D2 +:10B71000C0E90012FAB221464046FEF7A7FE00201B +:10B7200091E72DE9F0470D461F46904681460321DB +:10B7300005F094F90446402D01D2402001E0A5F126 +:10B74000400086B23CB14DB1384608F0CDFD50B155 +:10B750001020BDE8F08743F20200FAE76068C8B144 +:10B76000A0F80C8024E03146204600F04AF888B169 +:10B7700006EB86011C22606802EBC10145182846D1 +:10B7800000F055F840B10820E3E700002C0000204D +:10B79000742002000520DCE7A5F80880F2B22146FB +:10B7A0004846FEF7EDFE1FB1A88969890844388034 +:10B7B0000020CEE704F0ADBD017821F00F01491C57 +:10B7C00021F0F00110310170FDF7F2BD10B5044613 +:10B7D000402800D9FFDF4034A0B210BD4068426964 +:10B7E0000078484302EBC0007047C2784068037895 +:10B7F00012FB03F24378406901FB032100EBC10017 +:10B800007047C2788A4209D9406801EB81011C2245 +:10B8100002EBC101405C08B1012070470020704775 +:10B820000078062801D90120704700207047007871 +:10B83000062801D00120704700207047F0B401EBCA +:10B8400081061C27446807EBC6063444049D052680 +:10B850002670E3802571F0BCFEF782BA10B54189ED +:10B8600011B1FFF7DDFF08B1002010BD012010BDB0 +:10B8700010B5C18C8278B1EBC20F04D9C18911B166 +:10B88000FFF7CEFF08B1002010BD012010BD10B59C +:10B890000C4601230A22011D04F083FF0078218851 +:10B8A000012282409143218010BDF0B402EB820559 +:10B8B0001C264C6806EBC505072363554B681C79AD +:10B8C000402C03D11A71F0BCFEF7F3BCF0BC7047FA +:10B8D00010B5EFF3108000F0010472B6E94841782A +:10B8E000491C41704078012801D1F7F74BFB002C2F +:10B8F00000D162B610BD70B5E24CE07848B90125C0 +:10B90000E570FFF7E5FFF7F745FB20B1002008F0F1 +:10B910009AF8002070BD4FF080406571C0F8045364 +:10B92000F7E770B5EFF3108000F0010572B6D54C63 +:10B93000607800B9FFDF6078401E6070607808B9F9 +:10B94000F7F724FB002D00D162B670BDCD4810B5CD +:10B95000C17821B100214171C170FFF7E2FF0020E1 +:10B9600010BD10B50446F7F715FBC649C978084065 +:10B9700000D001202060002010BD2DE9F05FDFF82D +:10B9800004934278817889F80620002689F8071008 +:10B99000074689F808600078354620B101280FD0A5 +:10B9A00002280FD0FFDFF7F702FB98B1F7F706FB8D +:10B9B000B0420FD13046F7F705FB0028FAD047E038 +:10B9C0000126F0E7FFF784FFF7F7E4FA0028FBD041 +:10B9D0000226E8E701208407E060C4F80451AA4980 +:10B9E0000E600107D1F84412A74AC1F34231243254 +:10B9F0001160A549343108604FF0020BC4F804B35C +:10BA0000A060DFF888A2DAF80010C94341F3001102 +:10BA100001F10108DAF8001041F01001CAF8001035 +:10BA200000E020BFD4F804010028FAD03046F7F730 +:10BA3000C9FA0028FAD0B8F1000F05D1DAF80010E1 +:10BA400021F01001CAF80010C4F808B3C4F804517A +:10BA500099F807004C4670B1387860B9F7F79AFA50 +:10BA6000074608F09FF96FF0004117B1C4E90310D1 +:10BA700001E0C4E9030116B12571BDE8F09F01277B +:10BA8000BE0727714FF01908C6F80883B761C6F8DA +:10BA90000051C6F80C51C6F81051F7F77BFA10B1F7 +:10BAA000A770376100E02770FFF712FF7649A07991 +:10BAB00020310860C6F80483DFE770B5050000D1C7 +:10BAC000FFDF4FF080424FF0FF30C2F80803002143 +:10BAD000C2F80011C2F80411C2F80C11C2F810111A +:10BAE000684C6170F7F75CFA10B10120E07060708B +:10BAF0002846BDE8704040E72DE9F05F6448D0F883 +:10BB000000B0634A6349083211608406D4F8080122 +:10BB100010B14FF0010801E04FF00008D4F8000127 +:10BB200000B101208146D4F8040108B1012600E0EB +:10BB30000026D4F80C0100B101208246D4F810018F +:10BB400008B1012700E0002748EA090126EA0100C0 +:10BB500020EA0A00B84300D0FFDF0025B8F1000F4B +:10BB600004D0C4F80851012007F06DFF5FEA090016 +:10BB7000DFF810814FF0010913D0C4F8005198F894 +:10BB8000050020B188F80550002007F05CFF98F808 +:10BB9000000030B1F7F7FEF918B188F80290C4F848 +:10BBA00010900EB1C4F80451BAF1000F0CD0C4F8D3 +:10BBB0000C5198F80200464600B9FFDFB5703570A9 +:10BBC000C4F81490FFF7ADFE37B1C4F8105198F8DF +:10BBD000040008B100F020F82D49091DC1F800B09B +:10BBE0004BE770B5274DE87808B9F7F7CFF9012092 +:10BBF0008407A061A87850B1D4F80C0120B90020C6 +:10BC0000F7F7E0F90028F7D10020C4F80C014FF055 +:10BC1000FF30C4F8080370BD2DE9F041194C4FF016 +:10BC200080470125E079F0B1012803D0217A401E38 +:10BC3000814218DAF7F7AEF9064608F0B3F8E17971 +:10BC4000012902D9217A491C21720EB1216900E033 +:10BC5000E168411A022902DA11F1020F0BDC0EB180 +:10BC6000206100E0E060FFF733FEF7F793F928B1B9 +:10BC70003D61A57003E07D61BDE8F0812570002085 +:10BC80002072F9E7380000201805004010ED00E0B0 +:10BC900010050240010000014FF0E0214FF000705C +:10BCA000C1F88001C1F88002384B802283F800245B +:10BCB000C1F80001704700B502460420344903E092 +:10BCC00001EBC0031B792BB1401EC0B2F8D2FFDFDD +:10BCD000FF2000BD41F8302001EBC00100224A7175 +:10BCE0008A7101220A7100BD294A002102EBC000BD +:10BCF0000171704710B50446042800D3FFDF2448C3 +:10BD000000EBC4042079012800D0FFDF6079A1791D +:10BD1000401CC0B2814200D060714FF0E0214FF072 +:10BD20000070C1F8000210BD2DE9F0411948056806 +:10BD300018491948083108601448042690F800048E +:10BD4000134F4009154C042818D0FFDF16E0217866 +:10BD500007EBC1000279012A08D1427983799A421E +:10BD600004D04279827157F8310080472078401C16 +:10BD7000C0B22070042801D300202070761EF6B2D5 +:10BD8000E5D20448001D0560BDE8F08119E000E03F +:10BD90009006002010050240010000014C00002028 +:10BDA000F8B51D46DDE906470E000AD004F072FF23 +:10BDB0002346FF1DBCB231462A46009404F030FBF6 +:10BDC000F8BDD0192246194615F096FE2046F8BD5A +:10BDD000F84B586019721A80C90015F026BF70B56B +:10BDE0000D460446102115F0FEFE258117206081C6 +:10BDF000A07B40F00A00A07370BD4FF6FF720A806E +:10BE00000146032008F0E0B9704700897047827B43 +:10BE1000D30701D1920703D480890880002070479E +:10BE200005207047827B920700D5818170470146CB +:10BE30000020098847F2FE12114200D00120DD499E +:10BE4000497A002901D040F00800704700B5034648 +:10BE5000807BC00701D0052000BD59811846FFF73F +:10BE6000E6FFC00703D0987B40F004009873987BEE +:10BE700040F001009873002000BD827B520700D57E +:10BE800009B14089704717207047827B61F3C30274 +:10BE9000827370472DE9F04F0E46017804464FF04B +:10BEA000010B0BFA01F047F2FF1100EA010961688A +:10BEB0004FF6FF7887B008881D469646404506D065 +:10BEC000B9F1000F07D047F2FE12104203D0012053 +:10BED00007B0BDE8F08F40EA090008804FF0000A83 +:10BEE00095B185F800A022780027052003210223C0 +:10BEF000102A6FD2DFE802F06E0D2C35546F768079 +:10BF000054CBC79CCFFEFDFC20780B28EBD004203F +:10BF1000DEE762682089937B9B077DD5172851D384 +:10BF200013898342FBD39289172A01D3824249D1D4 +:10BF30002A7822F03F02921C2A70A5F80100318075 +:10BF4000616888816068817B21F00201817342E130 +:10BF5000042129702189A5F801106189A5F8031031 +:10BF60008FE0208A3188C01D1FFA80F84145D6D362 +:10BF7000062028702089A5F801006089A5F8030033 +:10BF8000A089A5F805000721208ACDE90001608875 +:10BF90002A4671466369FFF703FFA6F800801AE19D +:10BFA000082A10D0082129702189A5F8011061897B +:10BFB000A5F8031030806A1D694604F10C0006F0F4 +:10BFC000CAF910B1CCE01021EDE730889DF80010DF +:10BFD000084456E00EE10A2028702089A5F80100E7 +:10BFE0003180B2E00C2129702189A5F80110618906 +:10BFF000A5F803103080A8E0218933880BEB4102BB +:10C000001FFA82FA534576D3BAF1050F73D30E2285 +:10C010002A7008EA410100E07FE0CDE9001B60885A +:10C020002A467146E368FFF7BBFEA6F800A0D2E0FF +:10C030006048417A002970D0491E41724068217AD7 +:10C04000E26800EBC105D046A9882868D2F800C094 +:10C050000844A0F1080140F808CC506848608DF809 +:10C0600000308DF801A028680290A888ADF804007F +:10C0700060886946F5F7C6FEA5F80480002E01D059 +:10C0800040463080A7E0287840F080022A70287867 +:10C0900040F040022A7060893288C01C1FFA80F884 +:10C0A00042455DD3287820F03F0012302870228965 +:10C0B000A5F801206089CDE9000160882A46714613 +:10C0C000E368FFF76DFEA6F80080287841063CD5AE +:10C0D00000065ED58DF800B08DF801A03188CDE95D +:10C0E000025A091DADF804100420DFF8C88003E0EF +:10C0F00059E04FE02DE033E0049098F808008DF807 +:10C10000140060886946F5F77DFE074630880C30DC +:10C110003080022F02D0E7B36FE048E09DF8142092 +:10C12000D8F8041098F80830404601EBC2019A4252 +:10C1300016D28A88A2B9427A521C88F809200D606A +:10C1400030888880A6F800A057E061682089888040 +:10C1500041E0A1893288491D1FFA81F8424501D288 +:10C1600004274AE029782A4621F03F011631297038 +:10C170002189A5F801106189A5F80310A189CDE9ED +:10C180000010608871462369FFF70AFEA6F8008058 +:10C19000DBE720E0287820F03F0018302870207A74 +:10C1A0006870338017E060680188090404D40527AB +:10C1B00023E00000B0060020C0882189884201D019 +:10C1C00006271AE01E202870A6F800B060680188D3 +:10C1D00021F400410180B9F1000F0ED0DF486188E1 +:10C1E000002200888300032007F044FF6168207864 +:10C1F000887007E0A6F800A003276068018821EA9C +:10C2000009010180384663E62DE9F04F87B01746F3 +:10C21000109C0D0083461E461AD03078C10703D00B +:10C2200000F03F00192801D9012100E0002120463B +:10C23000FFF723FEA8420BD32088A0F57F41FF39EA +:10C2400006D03078410601D4000603D508203FE629 +:10C2500007203DE600208DF800008DF801003078C1 +:10C260006B1E00F03F0C0122A81E4FF0050A4FF094 +:10C27000020999B2BCF1200F76D2DFE80CF08C10E5 +:10C28000755F7569758D759E75B875BD75CB75D7FC +:10C2900075E4757575F475F275F175F0758C052D8D +:10C2A00079D104208DF80000A0788DF80400708802 +:10C2B000ADF8060030798DF80100707800F03F008D +:10C2C0000C2829D00ADCA0F10200092863D2DFE89B +:10C2D00000F0126215621A621D622000122824D03A +:10C2E00004DC0E281BD01028DAD11BE016281FD042 +:10C2F0001828D5D11FE02078800701E0207840077A +:10C30000002848DAF1E020780007F9E72078C00635 +:10C31000F6E720788006F3E720784006F0E72078FB +:10C320000006EDE72088C005EAE72088C004E7E7BB +:10C3300020888004E4E720884004E1E72078800733 +:10C3400029D5032D27D18DF800A0B6F8010083E090 +:10C35000217849071FD5062D1DD381B27078012899 +:10C3600003D0022817D102E0CCE0022000E0102028 +:10C3700006228DF8002072788DF80420801CB1FB15 +:10C38000F0F2ADF8062092B242438A4203D10397FD +:10C39000ADF80890A9E07BE02078000778D5072168 +:10C3A00098B28DF800108108ADF80410B0EB810F41 +:10C3B0006ED10297ADF8062097E02178C90667D5BF +:10C3C000022D65D381B208208DF800007078022814 +:10C3D0005ED300BFB1FBF0F28DF80400ADF806208B +:10C3E00092B242438A4253D1ADF808907CE0207863 +:10C3F00080064DD5092003E02078400648D50A2064 +:10C400008DF80000A088ADF80400ADF80610ADF876 +:10C41000082069E02078000672D50B20ADF80410E2 +:10C420008DF80000ADF8062002975EE02188C9056E +:10C4300066D5022D64D381B20C208DF8000070788F +:10C4400004285DD3C6E72088C00459D5012D57D1F3 +:10C450000D208DF80000A088ADF8040045E021E033 +:10C4600026E016E0FFE72088800449D5052D47D354 +:10C470000E208DF80000A088ADF80400B6F8030087 +:10C480006D1FADF80850ADF80600ADF80AA02BE01E +:10C4900036E02088400433D5012D31D10F208DF8AE +:10C4A000000022E0208800042AD4B6F80100E080D1 +:10C4B000A07B000724D5032D22D3307800F03F0065 +:10C4C0001B2819D011208DF80000208840F400406E +:10C4D000A4F80000B6F80100ADF80400ED1E03203A +:10C4E000ADF80650ADF80800039769465846F5F7D1 +:10C4F00089FC050008D016E010208DF80000E9E75F +:10C50000072510E008250EE0307800F03F001B28DA +:10C5100009D01D2807D05946032007F055FE208872 +:10C5200000F400402080A07B400708D52046FFF79C +:10C530007EFCC00703D1A07B20F00400A073284636 +:10C54000C6E400B587B0032805D18DF8000088B295 +:10C550006946F5F757FC07B000BD0000B0060020A3 +:10C56000F8B51D46DDE906470E000AD004F092FB3F +:10C570002346FF1DBCB231462A46009403F050FF0B +:10C58000F8BDD0192246194615F0B6FA2046F8BD76 +:10C590002DE9FF4F8DB09B46DDE91B57DDF87CA0F0 +:10C5A0000C46082B05D0E06901F00CF950B11020C1 +:10C5B000D2E02888092140F0100028808AF8001075 +:10C5C000022617E0E16901208871E2694FF42051E9 +:10C5D0009180E1698872E06942F601010181E069B8 +:10C5E000002181732888112140F0200028808AF8DA +:10C5F0000010042638780A900A2038704FF002099B +:10C6000004F118004D460C9001F09FFBB04681E00C +:10C61000BBF1100F0ED1022D0CD0A9EB0800801C2D +:10C6200080B20221CDE9001005AB52461E990D984B +:10C63000FFF796FFBDF816101A98814203D9F74804 +:10C6400000790F9004E003D10A9808B138702FE008 +:10C650004FF00201CDE900190DF1160352461E9963 +:10C660000D98FFF77DFF1D980088401B801B83B24B +:10C67000C6F1FF00984200D203461E990BA8D9B11B +:10C680005FF00002DDF878C0CDE9032009EB060178 +:10C6900089B2CDE901C10F980090BDF816100022B3 +:10C6A0000D9801F0D5FB387070B1C0B2832807D067 +:10C6B000BDF8160020833AE00AEB09018A19E1E788 +:10C6C000022011B0BDE8F08FBDF82C00811901F0F7 +:10C6D000FF08022D0DD09AF80120424506D1BDF881 +:10C6E0002010814207D0B8F1FF0F04D09AF80180E2 +:10C6F0001FE08AF80180C94800680178052902D145 +:10C70000BDF81610818009EB08001FFA80F905EBCF +:10C71000080085B2DDE90C1005AB0F9A01F018FB9B +:10C7200028B91D980088411B4145BFF671AF022D05 +:10C7300013D0BBF1100F0CD1A9EB0800801C81B203 +:10C740000220CDE9000105AB52461E990D98FFF776 +:10C7500007FF1D980580002038700020B1E72DE903 +:10C76000F8439C46089E13460027B26B9AB3491FB4 +:10C770008CB2F18FA1F57F45FF3D05D05518AD88EE +:10C780002944891D8DB200E000252919B6F83C80A6 +:10C790000831414520D82A44BCF8011022F8021B78 +:10C7A000BCF8031022F8021B984622F8024B91466F +:10C7B00004F05EFA4FF00C0C41464A462346CDF891 +:10C7C00000C003F0F4FDF587B16B00202944A41DDF +:10C7D0002144088003E001E0092700E08327384670 +:10C7E000BDE8F88310B50B88848F9C420CD9846B0C +:10C7F000E018048844B1848824F40044A41D234430 +:10C800000B801060002010BD822010BD2DE9F04784 +:10C810008AB00025904689468246ADF81850072711 +:10C820004BE0059806888088000446D4A8F800608C +:10C8300007A8019500970295CDE903504FF40073C6 +:10C8400000223146504601F003FB04003CD1BDF804 +:10C850001800ADF82000059804888188B44216D1EC +:10C860000A0414D401950295039521F40041009720 +:10C87000049541F4804342882146504601F0BEF8B9 +:10C8800004000BD10598818841F40041818005AAFC +:10C8900008A94846FFF7A6FF0400DCD000970598DA +:10C8A00002950195039504950188BDF81C3000227E +:10C8B000504601F0A3F8822C06D105AA06A94846E5 +:10C8C000FFF790FF0400ACD0ADF8185004E00598D5 +:10C8D000818821F40041818005AA06A94846FFF716 +:10C8E00081FF0028F3D0822C03D020460AB0BDE897 +:10C8F000F0870020FAE710B50C46896B86B051B17D +:10C900000C218DF80010A18FADF80810A16B0191DA +:10C910006946FAF7C9FB00204FF6FF71A063E18773 +:10C92000A08706B010BD2DE9F0410D460746896B82 +:10C930000020069E1446002911D0012B0FD132464B +:10C9400029463846FFF762FF002808D1002C06D0A0 +:10C95000324629463846BDE8F04100F042BFBDE806 +:10C96000F0812DE9FC411446DDE9087C0E46DDE945 +:10C970000A15521DBCF800E092B2964502D207207B +:10C98000BDE8FC81ACF8002017222A70A5F80160F0 +:10C99000A5F803300522CDE900423B462A46FFF7C1 +:10C9A000DFFD0020ECE770B50C4615464821204617 +:10C9B00015F03BF904F1080044F81C0F00204FF675 +:10C9C000FF71E06161842084A5841720E08494F8DD +:10C9D0002A0040F00A0084F82A0070BD4FF6FF726A +:10C9E0000A800146042007F0EFBB30B585B00C4645 +:10C9F0000546FFF780FFA18E284629B101218DF859 +:10CA000000106946FAF750FB0020E0622063606383 +:10CA100005B030BDB0F84000704700005000002065 +:10CA200090F84620920703D4408808800020F3E75E +:10CA30000620F1E790F846209207EDD5A0F84410C3 +:10CA4000EAE70146002009880A0700D5012011F015 +:10CA5000F00F01D040F00200CA0501D540F00400FB +:10CA60008A0501D540F010004A0501D540F02000AC +:10CA70000905D1D540F04000CEE700B5034690F857 +:10CA80004600C00701D0062000BDA3F8421018469A +:10CA9000FFF7D7FF10F0760F05D093F8460040F06F +:10CAA000040083F8460013F8460F40F001001870A8 +:10CAB000002000BD90F84620520700D511B1B0F813 +:10CAC0004200A9E71720A7E710F8462F61F3C30239 +:10CAD0000270A1E72DE9FF4F9BB00E00DDE92B347A +:10CAE000DDE92978289D25D02878C10703D000F0FA +:10CAF0003F00192801D9012100E000212046FFF75D +:10CB0000D9FFB04216D3287841060FD400F03F0178 +:10CB10001E2909D0218811F47F6F0BD13A884AB1C0 +:10CB2000A1F57F42FF3A05D0010606D500F03F008F +:10CB3000122802D004201FB0C4E5FC491D984FF014 +:10CB4000000A08718DF818A08DF830A00CAA0A60B0 +:10CB5000ADF81CA0ADF824A02978994601F03F0259 +:10CB6000701F5B1C04F1180CD3464FF0030ECDF878 +:10CB700028C01F2A7ED2DFE802F07D7D107D227D55 +:10CB8000AE7DF77DF67DF57DF47DF77DF37D7D7DD2 +:10CB9000F27DF17D7D7D7D7DF00094F84610B5F845 +:10CBA0000100890767D5032E65D14FF40061ADF808 +:10CBB000241060808DF830E0ADF83400E9E2052EF5 +:10CBC000F2D1B5F801002083ADF81C00B5F80310D0 +:10CBD0006183002870D088426ED884F80AB0A4F827 +:10CBE00008B04FF6FF7020840A9801F0AEF80520D7 +:10CBF00089F8000002208346029011AB1D9A0A9921 +:10CC00001B9801F0A5F820B15EE000BF8DF8180078 +:10CC1000FEE29DF84A00012804D0022089F80100B4 +:10CC2000102003E0012089F8010002200390002277 +:10CC300004A912A805F08FFBE8BB9DF8101003981B +:10CC400088423ED13A88891CA2EB0B00884238DB2F +:10CC500002990220CDE900010DF146034A46414602 +:10CC60001B98FFF77DFC02980BF1020B801C81B230 +:10CC700017AA01E0ACE2B1E0029104A912A805F004 +:10CC80006AFB02999DF81000CDE9000117AB4A46F6 +:10CC900041461B98FFF764FC9DF8100011AB0BEBAD +:10CCA00000011FFA81FB02991D9A084480B202908C +:10CCB0000A991B9801E004E091E001F049F800288E +:10CCC000B5D0BBF1020F03D10A208DF818005DE248 +:10CCD000A7F800B05AE2CDF80CB0072E7ED3B5F815 +:10CCE00001002083ADF81C00B5F803206283002802 +:10CCF00075D0904273D84FF0010B84F80AB0B5F8A4 +:10CD0000050020810020A073E06900F05BFD80B980 +:10CD1000E16942F6010081F806B0E2694FF4205162 +:10CD20009180E16981F80AB0E1690881E169002038 +:10CD30008873F01F20841E984FF0070B6062A4F8E0 +:10CD400022B00A9801F001F889F800B0012083466A +:10CD500004900020ADF846002AE026E2B0E147E169 +:10CD6000EDE01FE2B0E088E04FE000BFBBF1010F53 +:10CD700015D0E0698079012803D1BDF84400ADF8F1 +:10CD80000E0004990420CDE9000103AB4A46414658 +:10CD90001B98FFF7E5FB0498001D80B20490BDF8D6 +:10CDA0004600ADF80C00ADF80E0005981FFA80FBA8 +:10CDB00011AB1D9A0A991B9800F0CAFF28B939884F +:10CDC0000BF1040005908142D0D2BBF1010F3FF47A +:10CDD0001BAFE0698079012808D001E098E023E0EA +:10CDE000BDF84410A1F57F40FF3803D1BDF84400E1 +:10CDF000ADF80E0004990420CDE9000103AB4A46CA +:10CE000041461B98FFF7ACFB62E7072E01D0152EB9 +:10CE10007ED1B5F801102183ADF81C10B5F80320C0 +:10CE2000628309B1914201D90120EFE60121A1728B +:10CE3000A4F808B084F80EB0052E07D0C0B2691D62 +:10CE4000E26905F069FA00287FF4DEAE4FF6FF7064 +:10CE5000208401A806AA09A9CDF800B080E88603BD +:10CE60002878214600F03F031D9A1B98FFF790FB9E +:10CE70008246208BADF81C0088E10120032EC7D12B +:10CE80004021ADF82410B5F801102183ADF81C1035 +:10CE90000AAAB8F1000F00D00023CDE902030492E2 +:10CEA0001D98CDF80480009038880022401E83B27F +:10CEB0001B9800F0CDFF8DF8180050BB0B2189F8AE +:10CEC0000010BDF8280038E04FF0010C052E9FD16E +:10CED0008020ADF82400B5F801102183B5F80300D7 +:10CEE0002084ADF81C10B0F5007F01D907208DE635 +:10CEF00040F47C42228412A8B8F1000F00D0002335 +:10CF0000CDE90330CDE9018C1D980090388801E00F +:10CF10009CE007E0401E83B21B9800F099FF8DF85B +:10CF2000180028B18328A7D10220C7E050000020B4 +:10CF30000D2189F80010BDF84800401C25E1C80902 +:10CF400000EB40020EEB8200B04203D948067DD5CB +:10CF500058461AE1B5F80110ADF81C102A785206AF +:10CF600008D506228DF830202A78120605D58DF8CE +:10CF700030B02FE107228DF830200323CDE9023BAA +:10CF8000DDF878C0CDF810B01D9AA6EB000800922D +:10CF9000CDF804C01FFA88F300221B9800F02EFD84 +:10CFA0008DF818008DF830B0297849060DD5208805 +:10CFB000C00506D5208BBDF81C10884201D1C4F8ED +:10CFC00024B058468DF818B0DFE0832801D14FF027 +:10CFD000020A4FF48070ADF82400BDF81C002083D5 +:10CFE000A4F820801E986062032060841321C9E0A9 +:10CFF000052E2BD3B5F80110ADF81C10A28F32B35B +:10D00000A2F57F43FE3B29D008228DF8302005236E +:10D01000CDE9023BDDF878C0CDF810B01D9A80B2A2 +:10D02000CDF804C040F400430092B5F803201B98EB +:10D0300000F0E4FC4FF400718DF818008DF830B06A +:10D04000ADF82410832813D010B301E0DBE005E035 +:10D05000A08FA0F57F41FE3907D0D9E00B228DF8D3 +:10D0600030204FF6FE72A287D1E7A4F83CB0CFE0A3 +:10D0700000942B4631461E9A1B98FFF770FB8DF8E3 +:10D08000180008B183284BD1BDF81C0020834BE762 +:10D0900000942B4631461E9A1B98FFF760FB8DF8D3 +:10D0A0001800E8BBE18FA06B0844831D8DE888035E +:10D0B0004388828801881B98FFF753FC824665E00D +:10D0C00095F80180022E6FD15FEA080002D0B8F116 +:10D0D000010F7FD109208DF8300007A800908DF84E +:10D0E00034804346002221461B98FFF71CFC8DF834 +:10D0F00036008DF837B050B9B8F1010F11D0B8F142 +:10D10000000F04D1A08FA0F57F41FF3909D0A08F77 +:10D1100038B14FF480608DF830B0ADF824000EE0E7 +:10D1200034E00CA91B98F9F7BFFF82464FF48060EA +:10D130008DF830B0ADF82400BAF1020F06D0FB48EC +:10D140000068C07928B18DF8180027E0A4F818808D +:10D1500042E0BAF1000F03D081208DF818003BE0C7 +:10D1600007A800904346012221461B98FFF7DBFBEE +:10D170008DF8180021461B98FFF7BDFB9DF818009D +:10D1800020B9192189F80010012038809DF830005D +:10D1900020B10CA91B98F9F787FF8246BAF1000F5E +:10D1A00033D019E0062031E514E02078000711D5CE +:10D1B000012E0FD10A208DF83000E088ADF8340040 +:10D1C00004201B9907F000F80820ADF824007FE543 +:10D1D000480618D54FF0040A2088BDF824100843EB +:10D1E0002080BDF8240080050BD5A18FA1F57F40DC +:10D1F000FE3806D11E98E06228982063A6864FF07C +:10D20000030A504697E4042000E59DF8180078B121 +:10D21000012089F80000297889F80110BDF81C1058 +:10D22000A9F802109DF8180089F80400052038803C +:10D230002088BDF8241088432080E2E72DE9FF4FC5 +:10D240008846087895B0012181404FF20900249C5E +:10D250000140ADF820102088DDF88890A0F57F42CD +:10D260004FF0000AFF3A02D029B1000703D5012090 +:10D2700019B0BDE8F08F239E4FF0000B0EA886F882 +:10D2800000B018995D460988ADF83410A7498DF8AB +:10D290001CB0179A0A718DF838B0086098F8000031 +:10D2A00001283BD0022809D003286FD1307820F024 +:10D2B0003F001D303070B8F80400E08098F800108E +:10D2C0000320022904D1317821F03F011B31317054 +:10D2D00094F84610090759D505ABB9F1000F13D0E2 +:10D2E000002102AA82E80B000720CDE90009BDF861 +:10D2F0003400B8F80410C01E83B20022159800F064 +:10D30000A7FD0028D1D101E0F11CEAE7B8F804003C +:10D31000A6F80100BDF81400C01C04E198F805103F +:10D320008DF81C1098F80400012806D04FF4007AFC +:10D3300002282CD00328B8D16BE12188B8F8080066 +:10D3400011F40061ADF8201020D017281CD3B4F8D8 +:10D350004010814218D3B4F84410172901D38142F8 +:10D3600012D1317821F03F01C91C3170A6F80100BB +:10D370000321ADF83410A4F8440094F8460020F0DE +:10D38000020084F8460064E105257DE176E120880D +:10D3900008F1080700F4FE60ADF8200010F0F00F6F +:10D3A0001BD010F0C00F03D03888228B9042EBD1F5 +:10D3B00099B9B878C00710D0B9680720CDE902B193 +:10D3C000CDF804B00090CDF810B0FB88BA88398849 +:10D3D000159800F013FB0028D6D12398BDF8201033 +:10D3E000401C80294ED006DC10290DD020290BD0FE +:10D3F000402987D124E0B1F5807F70D051456DD0B0 +:10D40000B1F5806F97D1DDE0C80601D5082000E0B6 +:10D41000102082460DA907AA0520CDE902218DF82A +:10D420003800ADF83CB0CDE9049608A93888CDE9BC +:10D4300000015346072221461598FFF7A9F8A7E0F7 +:10D440009DF81C2001214FF00A0A002A9BD105AB50 +:10D45000B9F1000F00D00020CDE902100720CDE97E +:10D460000009BDF834000493401E83B2218B0022D2 +:10D47000159800F0EDFC8DF81C000B203070BDF805 +:10D48000140020E09DF81C2001214FF00C0A002A16 +:10D4900022D113ABB9F1000F00D00020CDE902106A +:10D4A0000720CDE900090493BDF83400228C401E0A +:10D4B00083B2218B159800F0CBFC8DF81C000D2059 +:10D4C0003070BDF84C00401CADF8340005208DF8DC +:10D4D0003800208BADF83C00BBE000E028E0388845 +:10D4E000218B88427FF450AF9DF81C004FF0120A48 +:10D4F00000281AD1606A98B1B878C0073FF444AFE9 +:10D50000BA680720CDE902B2CDF804B00090CDF89A +:10D5100010B0FB88BA88159800F070FA8DF81C00DE +:10D52000132030700120ADF8340092E0500000204C +:10D530003988208B8142D5D19DF81C004FF0160A06 +:10D540000028A06B08D0E0B34FF6FF7000215F46C3 +:10D55000ADF808B0019027E068B1B978C907C1D12A +:10D56000E18F0DAB0844821D03968DE80C024388C1 +:10D570008288018809E0B878C007BFD0BA680DABCF +:10D5800003968DE80C02BB88FA881598FFF7E9F935 +:10D5900005005ED0072D72D076E0019005AA02A9A1 +:10D5A0002046FFF71FF90146E28FBDF808008242CE +:10D5B00001D00029F1D0E08FA16B084407800198C9 +:10D5C000E08746E09DF81C004FF0180A40B1208B20 +:10D5D000C8B13888208321461598FFF78CF938E0C8 +:10D5E00004F118000090237E012221461598FFF7D0 +:10D5F0009AF98DF81C000028EDD119203070012017 +:10D60000ADF83400E7E7052521461598FFF773F9D3 +:10D610003AE0208800F40070ADF8200050452DD18C +:10D62000A08FA0F57F41FE3901D006252CE0D8F867 +:10D6300008004FF0160A48B1A063B8F80C10A18793 +:10D640004FF6FF71E187A0F800B002E04FF6FF70DF +:10D65000A087BDF8200030F47F611AD07823002223 +:10D660000420159906F006FD98F800002071208826 +:10D67000BDF82010084320800EE000E00725208838 +:10D68000BDF8201088432080208810F47F6F1CD0C4 +:10D690003AE02188814321809DF8380020B10EA90D +:10D6A0001598F9F701FD05469DF81C000028EBD000 +:10D6B00086F801A001203070208B70809DF81C003E +:10D6C00030710520ADF83400DEE7A18EE1B1189885 +:10D6D0000DAB0088ADF834002398CDE90304CDE903 +:10D6E0000139206B0090E36A179A1598FFF7F2F959 +:10D6F000054601208DF838000EA91598F9F7D4FCDD +:10D7000000B10546A4F834B094F8460040070AD5A5 +:10D710002046FFF796F910F0760F04D114F8460F63 +:10D7200020F0040020701898BDF8341001802846BD +:10D730009EE500B585B0042806D102208DF80000D2 +:10D7400088B26946F9F7B0FC05B000BD10B5384C99 +:10D750000B782268012B02D0022B2AD111E013781A +:10D760000BB1052B01D10423137023688A889A809A +:10D770002268CB88D38022680B8913814989518123 +:10D780000DE08B8893802268CB88D38022680B8938 +:10D7900013814B8953818B899381096911612168B8 +:10D7A000F9F782FC226800210228117003D00028BA +:10D7B00000D0812010BD832010BD806B002800D0D8 +:10D7C000012070478178012909D10088B0F5205FD8 +:10D7D00003D042F60101884201D1002070470720A2 +:10D7E0007047F0B587B0002415460E460746ADF8E1 +:10D7F000144010E0069801882980811DCDE902417E +:10D800000721019404940091838842880188384656 +:10D8100000F0F4F830B906AA05A93046FEF7E2FF99 +:10D820000028E7D0822800D1002007B0F0BD00001A +:10D830005000002010B58B7883B102789A4205D150 +:10D840000B885BB102E08B79091D4BB18B789A4252 +:10D85000F9D1B0F801300C88A342F4D1002010BDFA +:10D86000812010BD072826D012B1012A27D103E05C +:10D87000497801F0070102E04978C1F3C2010529A6 +:10D880001DD2DFE801F00318080C12000AB10320D2 +:10D8900070470220704704280DD250B10DE00528D2 +:10D8A00009D2801E022808D303E0062803D00328EB +:10D8B00003D005207047002070470F20704781205B +:10D8C0007047C0B282060BD4000607D5FE48807AA6 +:10D8D0004143C01D01EBD00080B27047084670473D +:10D8E0000020704770B513880B800B781C0625D577 +:10D8F000F54CA47A844204D843F01000087000204C +:10D9000070BD956800F0070605EBD0052D78F54051 +:10D9100065F304130B701378D17803F0030341EA25 +:10D92000032140F20123B1FBF3F503FB15119268CB +:10D93000E41D00FB012000EBD40070BD906870BDB9 +:10D9400037B51446BDF8041011809DF804100A067E +:10D950001ED5C1F30013DC49A568897A814208D835 +:10D96000FE2811D1C91DC9085A422846F5F73FFBC8 +:10D970000AE005EBD00100F0070201250878954088 +:10D98000A843934018430870207820F010002070BE +:10D990003EBD2DE9F0410746C81C0E4620F00300AD +:10D9A000B04202D08620BDE8F081C74D0020344649 +:10D9B0002E60AF802881AA72E8801AE0E988491CAD +:10D9C000E980810614D4E17800F0030041EA0020E8 +:10D9D00040F20121B0FBF1F201FB12012068FFF7D8 +:10D9E00070FF2989084480B22881381A3044A06029 +:10D9F0000C3420784107E1D40020D4E72DE9FF4F13 +:10DA000089B01646DDE9168A0F46994623F440454B +:10DA1000084600F00DFB04000FD0099802F0E6FF65 +:10DA20000290207800060AD5A748817A02988142A0 +:10DA300005D887200DB0BDE8F08F0120FAE7224617 +:10DA400001A90298FFF74EFF834600208DF80C00D5 +:10DA50004046B8F1070F1AD001222146FFF702FF16 +:10DA60000028E7D12078400611D502208DF80C005F +:10DA7000ADF81070BDF80400ADF81200ADF81460F8 +:10DA80001898ADF81650CDF81CA0ADF818005FEA54 +:10DA9000094004D500252E46A84601270CE0217830 +:10DAA000E07801F0030140EA012040F20121B0FBDF +:10DAB000F1F2804601FB12875FEA494009D5B8457B +:10DAC00007D1A178207901F0030140EA0120B0429A +:10DAD00001D3BE4201D90720ACE7A8191FFA80F98B +:10DAE000B94501D90D20A5E79DF80C0028B103A97F +:10DAF0000998F9F7D7FA00289CD1B84507D1A07842 +:10DB00004FEA192161F30100A07084F804901A987B +:10DB100000B10580199850EA0A0027D0199830B151 +:10DB20000BEB06002A46199913F0E6FF0EE00BEB0B +:10DB300006085746189E099803F09AF82B46F61DDA +:10DB4000B5B239464246009502F031FC224601A9A1 +:10DB50000298FFF7C7FE9DF80400224620F010004F +:10DB60008DF80400DDE90110FFF7EAFE002061E70F +:10DB70002DE9FF4FDFF8509182461746B9F806109D +:10DB8000D9F8000001EB410100EB810440F20120D3 +:10DB9000B2FBF0F185B000FB11764D46DDF84C800C +:10DBA00031460698FFF78DFE29682A898B46611A4F +:10DBB0000C3101441144AB8889B28B4202D88420D5 +:10DBC00009B038E70699CDB2290603D5A90601D5D3 +:10DBD0008520F5E7B9F806C00CF1010C1FFA8CFCA2 +:10DBE000A9F806C0149909B1A1F800C0A90602D588 +:10DBF000C4F8088007E0104480B2A9F80800191A98 +:10DC000001EB0B00A0602246FE200699FFF798FE6C +:10DC1000E77026712078390A61F30100320AA17891 +:10DC200040F0040062F30101A17020709AF8020034 +:10DC30006071BAF80000E08000262673280602D53D +:10DC400099F80A7000E00127A80601D54FF00008F6 +:10DC50004D4600244FF007090FE0CDE90268019618 +:10DC6000CDF800900496E9882046129B089AFFF7A9 +:10DC7000C5FE0028A4D1641CE4B2BC42EDD3002050 +:10DC80009EE72DE9F047804600F0D2F9070005D065 +:10DC9000002644460C4D40F2012919E00120BDE860 +:10DCA000F087204600F0C4F90278C17802F0030240 +:10DCB00041EA0222B2FBF9F309FB13210068FFF7E6 +:10DCC00000FE304486B201E0BC060020641CA4B211 +:10DCD000E988601E8142E4DCA8F10100E88028891F +:10DCE000801B288100203870D9E710B5144631B167 +:10DCF000491E218002F07AFEA070002010BD012094 +:10DD000010BD10B5D24904460088CA88904201D39C +:10DD1000822010BD096800EB400001EB80025079C1 +:10DD2000A072D08820819178107901F0030140EA37 +:10DD30000120A081A078E11CFFF7D4FD206120889C +:10DD4000401C2080E080002010BD0121018270472E +:10DD50002DE9FF4F85B04FF6FF788246A3F800808B +:10DD600048681F460D4680788DF806004868008890 +:10DD7000ADF8040000208DF80A00088A0C88A04243 +:10DD800000D304462C8241E0288A401C2882701D62 +:10DD90006968FFF74FFDB8BB3988414501D1601E66 +:10DDA00038806888A04236D3B178307901F0030119 +:10DDB00040EA012901A9701DFFF73CFD20BB29891C +:10DDC00041452CD0002231460798FFF74BFDD8B9CA +:10DDD0002989494518D1E9680391B5F80AC0D6F8F0 +:10DDE00008B05046CDF800C002F042FFDDF800C098 +:10DDF0005A460CF1070C1FFA8CFC4B460399CDF8E0 +:10DE000000C002F097FA50B1641CA4B2204600F0A2 +:10DE10000FF90600B8D1641E2C828220D0E67C80E7 +:10DE20007079B871F088B8803178F07801F003012A +:10DE300040EA01207881A7F80C90504602F0D6FD08 +:10DE4000324607F10801FFF74DFD38610020B7E6C3 +:10DE50002DE9FF4F87B081461C469246DDF860B041 +:10DE6000DDF85480089800F0E3F805000CD048462F +:10DE700002F0BCFD2978090608D57549897A8142E6 +:10DE800004D887200BB0D6E50120FBE7CAF30906CA +:10DE90002A4601A9FFF726FD0746149807281CD03B +:10DEA00000222946FFF7DEFC0028EBD12878400647 +:10DEB00013D501208DF808000898ADF80C00BDF8C6 +:10DEC0000400ADF80E00ADF81060ADF8124002A9E4 +:10DED0004846F9F7E7F80028D4D12978E87801F026 +:10DEE000030140EA0121AA78287902F0030240EAFE +:10DEF0000220564507D0B1F5007F04D9611E81424A +:10DF000001DD0B20BEE7864201D90720BAE7801B5E +:10DF100085B2A54200D92546BBF1000F01D0ABF870 +:10DF20000050179818B1B9192A4613F0E5FDB8F159 +:10DF3000000F0DD03E4448464446169F02F0AAFE0C +:10DF40002146FF1DBCB232462B46009402F068FA0F +:10DF5000002097E72DE9F04107461D461646084682 +:10DF600000F066F804000BD0384602F03FFD21783F +:10DF7000090607D53649897A814203D8872012E5F8 +:10DF8000012010E522463146FFF7ACFC65B121784F +:10DF9000E07801F0030140EA0120B0F5007F01D8EC +:10DFA000012000E0002028700020FCE42DE9F04171 +:10DFB00007461D461646084600F03AF804000BD006 +:10DFC000384602F013FD2178090607D52049897AE1 +:10DFD000814203D88720E6E40120E4E4224631466A +:10DFE000FFF7AEFCFF2D14D02178E07801F003029A +:10DFF00040EA022040F20122B0FBF2F302FB1300E0 +:10E0000015B900F2012080B2E070000A60F301014E +:10E0100021700020C7E410B50C4600F009F828B1C3 +:10E02000C18821804079A070002010BD012010BD62 +:10E030000749CA88824209D340B1096800EB400011 +:10E040006FF00B0202EB800008447047002070471D +:10E05000BC06002010B50C4601F03AFD80B3204606 +:10E0600000F0B7FA68B32278102A09D0112A07D035 +:10E07000022A05D0032A03D0162A2ED0FFDF1DE086 +:10E08000A0781E282BD00EDC0C2824D008DC092810 +:10E0900027D2DFE800F013261726261E1E1A1C00C2 +:10E0A00012281ED11BE0302819D01ADDA0F13A0049 +:10E0B000032816D2DFE800F011150B00002010BD78 +:10E0C00013E010E043F20200F9E70420F7E70D2027 +:10E0D000F5E70F20F3E70820F1E71120EFE707202D +:10E0E000EDE70320EBE7FFDFE8E7FFDFE6E700F01F +:10E0F00070BA70B50346002002466FF02F050EE09F +:10E100009C5CA4F130060A2E02D34FF0FF3070BDA4 +:10E1100000EB800005EB4000521C2044D2B28A4242 +:10E12000EED370BD30B50A240AE0B0FBF4F304FB73 +:10E1300013008D18303005F8010C521E1846D2B26B +:10E14000002AF2D130BD30B500234FF6FF7510E044 +:10E15000040A44EA002084B2C85C6040C0F303149F +:10E16000604005EA00344440E0B25B1C84EA4010A1 +:10E170009BB29342ECD330BD10B50AF0FFF90428EE +:10E1800003D00AF0FBF9052802D108F0A0FC28B959 +:10E190000BF056FB20B107F047FB08B1012010BD82 +:10E1A000002010BD0178406819B190F8721059B97B +:10E1B00001E001F017BD90F8041129B190F80401B5 +:10E1C000042801D0012070470020704770B50C462C +:10E1D0000546062102F042FC606008B1002006E01E +:10E1E0000721284602F03AFC606018B10120207037 +:10E1F000002070BD022070BD2DE9FC470C4606468C +:10E200006946FFF7E3FF00287DD19DF8000050B17B +:10E2100007F09CFAB0427CD0214630460EF0A1F9BE +:10E22000002873D12DE008F065F9B04271D0214685 +:10E2300030460CF041FC002868D1019D95F8C800DB +:10E2400022E0012000E00020804695F835004FF0E4 +:10E25000010A4FF00009F0B195F8360080071AD591 +:10E2600084F8019084F800A084F80290A68095F8C4 +:10E270003710A171298F2181698F618185F83590CF +:10E2800044E0019D95F8040158350028DBD1A87EB3 +:10E290000028D8D0D5E7304602F0FCFC070000D1BA +:10E2A000FFDF384601F051FE40B184F801900E21A5 +:10E2B0002170A680E08084F802A027E0304602F0BA +:10E2C000D7FC070000D1FFDFB8F1000F21D038469E +:10E2D00001F0CCFEB8B19DF8000038B90198D0F833 +:10E2E000F0004188B14201D180F80090304607F03B +:10E2F000C3F884F801900B21217084F80290A68065 +:10E30000E97EA17100E004E085F81A900120BDE8E3 +:10E31000FC870020FBE71CB56946FFF757FF00B1FB +:10E32000FFDF684601F06CFCF94900208968A1F81C +:10E33000CA001CBD2DE9FC4104460E46062002F031 +:10E3400037FB0546072002F033FB2844C7B20025FF +:10E35000A8463E4417E02088401C80B22080B0428E +:10E3600002D34046A4F8008080B2B84204D3B04241 +:10E3700002D20020BDE8FC816946FFF727FF002894 +:10E38000F8D06D1CEDB2AE42E5D84FF6FF7020809C +:10E390001220EFE738B54FF6FF70ADF800000DE042 +:10E3A0000621BDF8000002F06BFB04460721BDF812 +:10E3B000000002F065FB0CB100B1FFDF00216846F0 +:10E3C000FFF7B8FF0028EBD038BD2DE9F047D1A109 +:10E3D0000F79D1F8008007F0BDF810F003F8CF4CAA +:10E3E0004FF004091020A4F8389060874FF6FF76AC +:10E3F000A4F85460A4F85660002584F8315004F85D +:10E400002E5BC6492570A5713E39A573C1F87B8086 +:10E4100081F87F707B31481E0CF029FD25751B208B +:10E42000E0824FF4A47121836083A1830321A1774B +:10E4300084F81F9020846084B848A1843E38057019 +:10E440004680B3480C300570B448103805704680DB +:10E45000BDE8F08770B5AE4C0D466060217006F0E7 +:10E46000F3FFFFF797FFFFF7B0FF207809F031FDCA +:10E4700008F02EF9217860680CF00CFC20780FF081 +:10E4800011FA28460AF071FE07F06AF921786068EF +:10E490000EF068F9BDE870400FF0A4BF10B501247C +:10E4A0000AB1002010BD21B1012903D0002420466B +:10E4B00010BD022111F0C6FBF9E72DE9F047040079 +:10E4C00000D1FFDF954D002695F8310058B16670F8 +:10E4D0001620207095F83200A07095F83300E07097 +:10E4E00085F8316068E0287840B12C22A91C2046CC +:10E4F00013F002FB102020702E705DE095F82E00C6 +:10E5000060B10120E07095F82F00A07095F8300000 +:10E5100060701120207085F82E604DE07F48022148 +:10E5200056308246FFF706FF00B1FFDFB5F8569080 +:10E53000062002F03DFA0746072002F039FA384477 +:10E54000C7B2781C00F0FF08B5F85600B84212D1E7 +:10E55000204607F04BFF50BB95F8340070B366704F +:10E56000132020702021A01C13F03DFB0220A0707E +:10E5700085F8346020E040451AD1204607F09CF829 +:10E58000E0B12078132817D1A0783C2814D1A088B6 +:10E59000072102F063FA050000D1FFDF288806F0AA +:10E5A0006BFFA088072102F06BFA00B1FFDF03E0E8 +:10E5B0002146FFF721FE08B1012049E7022150461C +:10E5C000FFF7B8FE18B9B5F856104945BCD1002080 +:10E5D0003EE772E710B5514C207828B10A21BDE81A +:10E5E0001040102001F0A1BAFFF7C6FD08B10C20C1 +:10E5F00002E00FF042FF00202071012060710A212B +:10E60000E170207010BD70B5444D0446287828B1E3 +:10E61000BDE870403221102001F087BA207818B18F +:10E62000012801D0122010E001F090FA20B110F082 +:10E630006EF808B10C2008E0207801F057FA04F1D8 +:10E640001703E21D611C0FF06FFF28710120687134 +:10E650003221E970287070BD70B5304C05462078C5 +:10E6600028B1BDE870400B21102001F05EBA287877 +:10E6700018B1012801D012200EE0FFF77DFD08B18E +:10E680000C2009E0287801F031FA691C0FF0BCFE7B +:10E6900008B1002000E007202071012060710B21EB +:10E6A000E170207070BD10B51C4C217829B130216B +:10E6B000BDE81040102001F038BA008810F02AF8A8 +:10E6C000302110B10020207100E021710120607123 +:10E6D000E170207010BD70B5104C0546207828B14F +:10E6E000BDE870403121102001F01FBA01F02EFA70 +:10E6F00008B10C2005E0287800F0010010F004F8C3 +:10E7000000202071012060713121E170207070BD06 +:10E7100058000020FFFFFFFF1F0000000607002039 +:10E7200010B5FB4C207828B13421BDE810401020F2 +:10E7300001F0FBB901F00AFA20B10FF0E8FF08B1CF +:10E740000C2002E00FF044FF0020207101206071D6 +:10E750003421E170207010BDED48017819B10F210E +:10E76000102001F0E2B900210171102181700F2108 +:10E77000C170FF2181714FF6FF710181E549496840 +:10E780000A7882728A8882814988C1810121417117 +:10E790000170704710B5DE4C207828B12B21BDE800 +:10E7A0001040102001F0C1B90821A01D05F029FA80 +:10E7B00000202071012060712B21E170207010BDBC +:10E7C00070B5D34C217829B1BDE8704043211020A9 +:10E7D00001F0ABB990F90000042816D0032814D03A +:10E7E00098B1011D11D010F1080F0ED010F10C0FCF +:10E7F0000BD010F1100F08D010F1140F05D010F14C +:10E80000280F02D01220207103E0002506F020F826 +:10E8100025714320E07001206071207077E710B50A +:10E82000BB4C217829B12A21BDE81040102001F00D +:10E830007CB9A31D012200F1100110F03AFE002066 +:10E8400020711020A0702A20E070012060712070DB +:10E8500010BD70B5AE4C0546207828B1BDE87040BB +:10E860004621102001F061B909F088FE052804D086 +:10E87000284609F01BFB002000E00C20207101203D +:10E8800060714621E170207041E770B5A04C0546EB +:10E89000207828B1BDE870404421102001F045B92E +:10E8A00001F054F938B10C2020710120607144212D +:10E8B000E17020702BE72946002006F04CFE002076 +:10E8C000F2E770B5924C0546207828B1BDE870405B +:10E8D0004221102001F029B909F091FB50B10AF052 +:10E8E000A2FF38B128780AF064FC287808F026F9ED +:10E8F000002000E00C202071012060714221E170B5 +:10E90000207004E770B5824C0546207828B1BDE838 +:10E9100070401721102001F008B901F017F938B143 +:10E920000C202071012060711721E1702070EEE64B +:10E930002946012006F00FFE0020F2E738B5744D9D +:10E940000446287828B1BDE838404D21102001F058 +:10E95000ECB8A079E179884213D021791F2910D829 +:10E9600061791F290DD80022114612F0C7FA40B96B +:10E970000022E079114612F0C1FA10B9207A072876 +:10E9800001D9122012E04FF6FF70ADF800000AF036 +:10E9900057FF90B909F0F2FD78B900216846FFF7FA +:10E9A000C9FC50B1204605F070FE002028710120FE +:10E9B00068714D21E970287038BD0C20F6E72DE90B +:10E9C000FC47534C054694F82E0020B12821112015 +:10E9D00001F0ABF89BE4282084F83000012184F892 +:10E9E0002E10A8784FF000091A2825D00EDC162822 +:10E9F00031D2DFE800F0303030303021303030308C +:10EA00003030303030303030302121212A2822D0AF +:10EA10000BDCA0F11E000C281DD2DFE800F01C1C4E +:10EA20001C1C1C1C1C1C1C1C1C0D3A38042812D25B +:10EA3000DFE800F0110211022888B0F5706F0AD2E9 +:10EA40001F20884684F82F0028886946FFF7BEFB00 +:10EA500018B1022019E0122017E09DF80000019F74 +:10EA6000002806D007F5B377019E05D106F1ED0623 +:10EA700004E007F1EC07F7E706F267166846FFF7D0 +:10EA800091FB08B1387818B10C2084F82F003EE4CF +:10EA900087F80080A878307084F82F90684601F0DD +:10EAA000AFF834E47CB51A4C0546207820B1252116 +:10EAB000102001F03AF87CBD28886946FFF786FBF4 +:10EAC000020013484FF00001A0F13E000DD00222D9 +:10EAD000227140F8461F0171E1801020A0702520AE +:10EAE000E0700120607120707CBD019A134658329D +:10EAF00082F83E109E68C0F846601E7B80F84A602F +:10EB000092F83E60002EF3D12888E080E5E700000F +:10EB1000060700205800002010B540B10478406876 +:10EB200013B1B0F8480003E0B0F84A0000E0FB2061 +:10EB30001B2908D3814206D8B2F5A47F03D340F63F +:10EB40004800824201D9122010BD002010BD2DE9DD +:10EB5000FC41FA4D0446287828B1BDE8FC4150211B +:10EB6000102000F0E2BF4FF0010885F805801F215A +:10EB700029711021A9705021E9702188E98085F858 +:10EB8000008020886946FFF721FB08B102200DE0D4 +:10EB90002289E18801236846FFF7BEFF30B9A288C9 +:10EBA000618800236846FFF7B7FF10B12871BDE800 +:10EBB000FC819DF800103A20019E002749B186F89B +:10EBC0008981019991F8C81106F5C476B9B1287107 +:10EBD00013E086F8FD80019991F82011FC36002998 +:10EBE000F5D12F71E08870802089B0806088F08036 +:10EBF000A0883081012201990CE07770D7E72F714E +:10EC0000E08870802089B0806088F080A0883081A2 +:10EC100001990022304610F091FD86F80080ECE763 +:10EC200070B5C64D044686B0287830B106B0512183 +:10EC3000BDE87040102000F078BF01206871002608 +:10EC40002E711021A9705121E9702870208803A924 +:10EC5000FFF7BCFA18B10220287106B057E59DF8FD +:10EC60000C0040B100220499E088B1F84830984285 +:10EC700003D9C01A02E00122F5E70020E88063888A +:10EC8000B1F84A00834201D9181A00E00020288117 +:10EC9000009601960296E088ADF802002089ADF852 +:10ECA00004006088ADF80600A088ADF8080068464A +:10ECB00010F044FD2089BDF80410401A6881A08836 +:10ECC000BDF80810401AA881E088BDF80210401A6B +:10ECD000E988884200DC0846E8806088BDF80610B4 +:10ECE000401A2989884200DC08462881B5E770B5BA +:10ECF000924D0446287828B1BDE870403E2110208E +:10ED000000F013BF00F022FF20B10FF000FD08B1AA +:10ED10000C2008E0E2792078611C0FF07BFE08B13E +:10ED2000002000E002202871012068713E21E97076 +:10ED30002870ECE47CB5814C05461F2084F82F0038 +:10ED400028886946FFF742FA18B1022084F82F009C +:10ED50007CBDAA7802B90322EB7803B903239DF89E +:10ED600000603A2501210020002E019E06D086F881 +:10ED70009311019E96F8DC6146BB1FE086F80711EF +:10ED8000019E96F82C613EB9019E96F806611EB967 +:10ED9000019E96F87B6016B184F82F500AE0019D21 +:10EDA00085F80611019981F80821019981F8093146 +:10EDB00084F82F00019981F807017CBD019E96F827 +:10EDC00092611EB9019E96F87B6016B184F82F50AF +:10EDD0000AE0019D85F89211019981F89421019929 +:10EDE00081F8953184F82F00019981F893017CBD59 +:10EDF000524930B491F82E2022B1562130BC112056 +:10EE000000F093BE562281F83020012281F82E2096 +:10EE10008378DA0802D1C278D40801D0122004E045 +:10EE20005B0701D4520704D5112081F82F0030BCB4 +:10EE3000704730BC7EE770B5404C0546207828B15D +:10EE4000BDE870401D21102000F06FBE1F20207112 +:10EE5000012060711D21E170207009F08FFB0428F2 +:10EE60000BD0052809D0A9791220012907D031B18A +:10EE7000022904D0032929D101E00C2026E02978B9 +:10EE800009B1012922D1E97929B1012903D0022947 +:10EE900001D003291AD1698843F6FD720B1F302077 +:10EEA000934213D2AB881B1F93420FD22187A888AD +:10EEB0006087A87907F065FDE87907F0D0FD28782C +:10EEC000012805D00120002107F0F8FD20711EE483 +:10EED0000220F8E770B5194C217829B1BDE87040DF +:10EEE0001E21102000F021BE1F212171012161711E +:10EEF0001E22E270217002781221012A00D01AB974 +:10EF0000407818B1012801D0217187E40025012A39 +:10EF100009D009F033FB0C26052802D008F008FFC1 +:10EF200088B126717AE407F022FD48B107F031FD7F +:10EF3000618F208F09F070F803E0000006070020C1 +:10EF4000122020716AE4257168E42DE9F047F94C3C +:10EF500007469246B4F84400B7F84A200E4690425D +:10EF600000D31046804697F85210104600F0D4FDAA +:10EF7000B4F84610814200D208460546A146B4F8CE +:10EF80004840B7F84800844200D3044697F851102F +:10EF900000F0C2FDB9F84A10814200D208464FF491 +:10EFA000A4721B2C01D0904204D1B8F11B0F0DD0DC +:10EFB00095420BD0A6F8068035817480B080524609 +:10EFC0003946304610F0BAFB01203070BDE8F087BA +:10EFD0002DE9F04786B00546AFF6C800D0E90090AD +:10EFE000D44E804696F82E0028B12121112000F041 +:10EFF0009CFD06B0EAE71F2086F82F00212086F846 +:10F0000030004FF0010A86F82EA0284600F007FED7 +:10F01000002811D109F0B2FA05280CD009F0AEFA97 +:10F02000042808D096F8340028B907F063FAA0F550 +:10F030007F41FF3901D00C20AAE0BE4801AA3E382A +:10F040000190BD480290BB4806211038039004A8E7 +:10F0500001F0D4FC04007DD003210FF0DAFFB6F8F4 +:10F060004E00A4F84800B6F85000A4F84A0096F8FC +:10F070004D00009096F84C30B6F85020B6F84E107F +:10F08000208801F07EFD00B1FFDF208806F0F3F953 +:10F09000218804F10E0000F068FDA8A004F1120719 +:10F0A000006800900321684604F033FD00206946A3 +:10F0B0000A5C3A54401CC0B20328F9D3288A608005 +:10F0C000688AA080A88AE08094F8522094F85110B1 +:10F0D000B6F8520009F01DF80146A062204609F07A +:10F0E00038F8002784F85E7084F85F70687900F063 +:10F0F000FDFC6076D5F80600C4F81A006889E08344 +:10F10000C4F8089084F80C8084F8F8A0012204F177 +:10F11000FC012046FFF719FF8DF8007001216846B9 +:10F1200004F0F7FC9DF8000000F00701C0F3C102F5 +:10F130001144C0F3401008448DF80000401D2076B3 +:10F14000092801D208302076002120460FF061FF07 +:10F15000287B00E010E007F014FC69792879AA1DEB +:10F1600007F0E5FB50B107F014FC69792879AA1D76 +:10F1700007F080FC78B118E0092009E0208806F04B +:10F180007BF92088062101F07BFC00B1FFDF122013 +:10F1900086F82F002DE72146032007F08FFC20B9C9 +:10F1A0006A882988204608F0C0FE86F82F000028CB +:10F1B000F0D0208806F060F92088062101F060FC7C +:10F1C0000028E7D0FFDF14E738B55A4C207820B18B +:10F1D0002221102000F0A9FC38BD1F20207101253C +:10F1E00065712220E070257094F8340018BB09F096 +:10F1F000C5F9052805D007F07DF9A0F57F41FF3955 +:10F2000019D000202071684608F055FF0028E3D18E +:10F210000098008806F030F900980621008801F077 +:10F220002FFC00B1FFDF444884F834500C380078DC +:10F23000FCF760FD38BD0C20207138BD2DE9F04190 +:10F240003C4D044695F82E0028B1BDE8F04123213D +:10F25000112000F06ABC1F2085F82F00232085F8BC +:10F260003000012085F82E00618840F67B438A1F1C +:10F2700030209A4252D2A288961F9E424ED291428C +:10F280004CD8E188B1F5FA7F48D2218940F677461B +:10F29000A1F10A03B34241D2B1EBD20F3ED9618949 +:10F2A000A28991423AD84FF000082088062101F047 +:10F2B000D5FB06004FF0020707D000F093FC20B109 +:10F2C000D6F8F000017841B903E085F82F70BDE869 +:10F2D000F081D6F83C11097809B13A201EE00521E9 +:10F2E0008171D6F8F0004146A0F80880D6F8F020E9 +:10F2F000A0885081D6F8F020E0889081D6F8F020E0 +:10F300002089D081D6F8F000028943899A4204D836 +:10F310008279082A01D89A4203D3122085F82F0057 +:10F32000D5E722884280D6F8F000077085F82F10C4 +:10F33000CDE7000006070020640000201122330002 +:10F34000FEB5F84C0646207820B12421102000F0AC +:10F35000ECFBFEBD012565712420E0702570304670 +:10F3600010F042F808B1002000E0122020710028BF +:10F37000EFD1EC4884F83C503E38316840F87B1FB0 +:10F3800031790171002684F83C606946062001F05D +:10F39000F0FA00B1FFDF684601F0C9FA60B9BDF8C4 +:10F3A0000470029880F8F850684601F0C0FA18B965 +:10F3B000BDF80400B842F4D12671FEBD2DE9F0413C +:10F3C000D84D064695F82E0028B1BDE8F0412C2115 +:10F3D000112000F0AABB1F2085F82F002C2085F8F3 +:10F3E0003000012085F82E003088062101F036FB20 +:10F3F000040007D000F0F6FB20B1D4F8F010087834 +:10F4000030B901E0022026E0D4F83C01007808B1D0 +:10F410003A2020E094200027005D10F0010F19D061 +:10F42000D6F802004860D6F80600886054F8F00F5D +:10F43000718910228181206806F10C010E3012F0D2 +:10F440005BFB21680320087021683088488085F8BC +:10F450002F703CE70C2085F82F0038E72DE9F041AC +:10F46000B04D04460C26287828B1BDE8F04118219B +:10F47000102000F05ABB0AF0E3F9012730BB607995 +:10F48000032824D8A179012921D8A17B03291ED8DA +:10F49000617BE1B107291AD82179052917D2DFE864 +:10F4A00001F0030C030303002288202A0FD3618894 +:10F4B0008A420CD8B1F5804F09D806F0D6F92079E8 +:10F4C00085F83600204606F098FA064600E0122637 +:10F4D0002E716F711820E8702F70F8E610B5914CFE +:10F4E000217829B11A21BDE81040102000F01DBB81 +:10F4F00001781F2902D91220207106E00021217114 +:10F500000278411C104606F0FCFA012060711A21B5 +:10F51000E170207010BD10B5824C217829B12021F6 +:10F52000BDE81040102000F000BB01781F2902D96F +:10F530001220207106E0002121710278411C104642 +:10F5400006F0CEFA012060712021E170207010BD1C +:10F550002DE9FC41734C217829B1BDE8FC411B2108 +:10F56000102000F0E2BA012767710C2121710078A8 +:10F5700000261225012802D0002866D167E006F097 +:10F5800024F900285ED006F056F900285AD00AF077 +:10F5900057F900286CD106F06FF994F8360050B195 +:10F5A000012808D0042806D0002009F005FE00B18B +:10F5B000FFDF26715CE006F0C9F8A0F57F41FF3956 +:10F5C00056D10022072101A801F018FA05004FD0FA +:10F5D00055480321856028460FF0E2FB284606F0D7 +:10F5E000BAFBB4F84E00A5F84800B4F85000A5F8EE +:10F5F0004A00B4F8520001214C3409F016FF0146CC +:10F60000A8620022284608F0CEFF6078009014F827 +:10F61000043B288834F8022934F84E1901F0B1FA75 +:10F6200000B1FFDF288805F026FF284609F0C4FD59 +:10F6300000B1FFDF2671002205F5C4712846FFF7EF +:10F6400084FC15E006F0C1F890B1257110E008F0D7 +:10F65000A7FF054609F0E8FC50B9267145B1288896 +:10F6600005F00AFF2888072101F00AFA00B1FFDF40 +:10F670001B20E0702770BDE8FC812DE9F041294C8A +:10F680000646207828B1BDE8F0412D21102000F079 +:10F690004CBA3088072101F0E1F905004FF001076D +:10F6A00020D095F8690140B995F86400142801D07C +:10F6B000152802D195F8AA0150B10C202071102014 +:10F6C000A0702D20E0703088E08067712770FEE523 +:10F6D0001022B11C05F5B57012F00EFA85F86971AB +:10F6E0000020EBE70220E9E770B50E4C05462078D4 +:10F6F00028B1BDE870402E21102000F016BA2888ED +:10F70000072101F0ABF90221A0B190F869212AB9D3 +:10F7100090F86420142A09D0152A07D00C202071F3 +:10F7200009E00000060700205800002080F8691159 +:10F730000020F4E721711020A0702E20E0702888AE +:10F74000E08001206071207070BD2DE9FC47FD4C08 +:10F750000646207828B13821102000F0E6F9BDE8EF +:10F76000FC8770884BF68032122190420AD848B14B +:10F770004FF0000830886946FEF728FD20B10220CE +:10F78000207110E021710EE0019800F15809851CEC +:10F790002F887288394648460FF0BCFA2888B8424C +:10F7A000F6D184F80480012060713821E170207066 +:10F7B000D5E77CB5E34C0546207820B149211020DF +:10F7C00000F0B3F97CBD28886946FEF7FFFC38B12C +:10F7D00002202071012060714921E17020707CBD00 +:10F7E00001987F22014680F8602080F86120002285 +:10F7F00080F86220A87801F82C0FE8784870287902 +:10F8000088702271E6E71CB5CE4C217821B15421D5 +:10F81000102000F08AF91CBD00886946FEF7D6FC6E +:10F8200048B102202071012060715421E170102143 +:10F83000A17020701CBD019890F8720000B10120E9 +:10F8400000212171A071EEE71CB5BE4C217821B1D9 +:10F850001321102000F069F91CBD00886946FEF7ED +:10F86000B5FC08B1022005E0019890F82C100129A0 +:10F8700002D00C20207106E0602100222271095C78 +:10F8800021720088E080012060711321E170102155 +:10F89000A17020701CBD2DE9F041AA4C05462078CE +:10F8A00028B1BDE8F0414A21102000F03EB9288877 +:10F8B000072101F0D3F8012358B382886D88C688E8 +:10F8C000418803EB4207BD4217D342F210777E43D3 +:10F8D000BF107943B6FBF1F1491E89B24FF4FA76B5 +:10F8E000B14200D931468D4200D22946491C521CF2 +:10F8F000B1FBF2F15143491E8AB290F8961101B959 +:10F900000284E2800020207163714A20E07023703D +:10F91000DDE40220F7E770B58A4C0546207828B16F +:10F92000BDE870404C21102000F0FFB82888072166 +:10F9300001F094F890B1A97811F0010180F8D71086 +:10F9400004D090F8D51009B109F08AFD002020718B +:10F95000012060714C21E170207070BD0220F6E73B +:10F9600078490A781AB15221102000F0DEB80278E6 +:10F970009AB142788AB142881B2A0ED382881B2A08 +:10F980000BD3C288022A08D36E4A0368423242F877 +:10F990000A3F40685060002000E0122008710120FA +:10F9A00048715222CA700870704770B5654C0546A0 +:10F9B000207828B1BDE870405321102000F0B5B880 +:10F9C000287800F0010008F0A1FB287800F0010081 +:10F9D00009F0F7FC00202071012060715321E170D3 +:10F9E000207070BD70B5574D0646287828B1BDE827 +:10F9F00070405521102000F098B8012270881146FF +:10FA000008F087FB04467088012109F00EFD84424E +:10FA100000D204463088012100F06FF8064601212B +:10FA2000002000F06AF8304401219630844206D963 +:10FA300000F19601201AB0FBF1F0401C81B2E98080 +:10FA400000202871012068715521E970287070BD6F +:10FA500070B53C4D0446287828B1BDE870404E2171 +:10FA6000102000F062B800F071F808B10C200DE031 +:10FA7000601C0EF0A5FF207800F0010005F0F8FEF4 +:10FA8000207800F0010006F080FF0020287101209E +:10FA900068714E21E970287070BD70B5294C05461B +:10FAA000207828B1BDE870404B21102000F03DB80F +:10FAB00009F0C6FE08B10C2003E0287806F031F802 +:10FAC00000202071012060714B21E170207070BD19 +:10FAD00010B50178572907D21B4A52F8211019B1E5 +:10FAE000801C8847012010BD002010BD18B10228DD +:10FAF00001D0012070470020704710B5012904D0C3 +:10FB0000022905D0FFDF204610BDC000503001E0C3 +:10FB100080002C3084B2F6E7022903D0C000703098 +:10FB200080B2704780003C30FAE7064A92F83130E4 +:10FB3000002B06D182F8320082F83310012082F8BF +:10FB40003100704706070020C420020010B508F0FD +:10FB500015FD042807D008F011FD052803D009F091 +:10FB60006FFE002800D0012010BD2DE9FE430025C6 +:10FB70000F4680460A260421404604F042F84046DB +:10FB80000FF00EFC062000F013FF044615E0694656 +:10FB9000062000F0EEFE0AE0BDF80400B84206D0F0 +:10FBA0000298042241460E3011F07AFF50B16846A7 +:10FBB00000F0BDFE0500EFD0641E002C06DD002D18 +:10FBC000E5D005E040460FF0F4FBF5E705B9FFDFAF +:10FBD000D8F800000FF0A8F8761E01D00028CAD08F +:10FBE000BDE8FE8390F8721041B990F8C81029B1B1 +:10FBF00090F8C800042801D00120A2E70020A0E767 +:10FC0000017801299DD1416891F8D520002A98D02A +:10FC1000002281F8D520406809F022BC91E710B598 +:10FC2000038843F6FD711A1F8A4223D24288141FAB +:10FC30008C421FD29A421DD8C28940F67B43911F45 +:10FC4000994217D2018A8C1F9C4213D28A4211D842 +:10FC5000428AB2F5FA7F0DD2828A40F67744A2F149 +:10FC60000A03A34206D2B2EBD10F03D9C18A028B99 +:10FC7000914201D9302010BD017911B1012910D173 +:10FC800007E0417929B1012903D0022901D00329D4 +:10FC900007D1007B38B1012805D0022803D0032802 +:10FCA00001D0122010BD002010BD00000844083013 +:10FCB000424301F14A00104480B27047F0B51D463E +:10FCC0000446A818059B083000FB03F205F14A0022 +:10FCD000104486B2B14238BFFFDF0027276067605B +:10FCE000A760E76027616761A761E76127624FF658 +:10FCF000FF706762A082A6F1280080B265776080FD +:10FD0000B0F5004F88BFFFDF608805F13C018842F5 +:10FD100038BFFFDF6088401B3C3880B220801B2842 +:10FD200038BF1B202080A777F0BD816188617047B4 +:10FD30002DE9F04F0D46C188044600F128080089DE +:10FD400021F4004320F4004221F4004620F400474F +:10FD50004FF0010A4FF000099A4208D100F4004028 +:10FD600001F4004188421CBF0020BDE8F08FB7427B +:10FD70000BD9617FB81B401A083885421BDC08EBA1 +:10FD800006000021058041801EE06088617F801BA5 +:10FD9000401AB0F1080B0ED4BBF11B0FB8BFFFDF48 +:10FDA0005D45D4BF29461FFA8BF1681A0204120C74 +:10FDB00018BFBA4204DD84F817900020BDE8F08F28 +:10FDC00008EB06000180428084F817A0BDE8F08FA0 +:10FDD0002DE9F041044600F12802C08820F40043D8 +:10FDE000E07D002808BFBDE8F081D0180288438874 +:10FDF00013448B423CBF0020BDE8F08100279142B4 +:10FE00009CBF0180478013D9891A0D042D0C4580B1 +:10FE10000ED0E088A61D20F40040854288BFFFDF99 +:10FE200030884FF4004121EA0000284330800AE086 +:10FE3000627F008802F108031044083081B26288B2 +:10FE4000A01D00F0A8FBE7750120BDE8F08130B4EB +:10FE5000B0F804C0C488034600F128052CF4004023 +:10FE60002844A44503D10020188230BC7047B3F861 +:10FE70000CC00488A44509D34088ACEB040CA0EB6B +:10FE80000C0084B20CEB0500C01E06E0A4EB0C04D1 +:10FE90005D7FA4B2AC446044401DB1F800C0A445ED +:10FEA00088BF0C80B3F80CC0BCF1000F0CBF4FF042 +:10FEB000010C4FF0000C82F800C00988198230BC98 +:10FEC00070472DE9F041044600F12801808820F4B4 +:10FED00000404518208A002808BFBDE8F081A089AD +:10FEE00010B9A069807F2871A089218A084480B256 +:10FEF000A08129886A881144814238BFFFDF2888A1 +:10FF00006D88A2894119002791421AD175B1A08844 +:10FF1000261D20F40040A84238BFFFDF30884FF490 +:10FF2000004121EA00002843308009E0627F10444C +:10FF3000083081B202F108036288201D00F02BFB1B +:10FF4000A78127820120BDE8F0812DE9F047418992 +:10FF5000B0F804800027044600F1280A414518BF84 +:10FF60004FF400493AD000BF21F400405044468885 +:10FF70006EB1608904F10A0520F40040B04238BF38 +:10FF8000FFDF288829EA00003043288021E0637FD2 +:10FF9000008803F1080C18446389083023F40045F5 +:10FFA0006288284480B204F10A0190420BD2121AEE +:10FFB00092B20CF11B0C62452CBF03F4004229EAFB +:10FFC000030004D204E0801A80B229EA030210433D +:10FFD0000880781C618987B24145C5D13846BDE8A3 +:10FFE000F0872DE9F047B0F808800B46044600F191 +:10FFF0002801B0F80A90808828F4004C01EB0C0529 +:020000040001F9 +:10000000804504BF0020BDE8F087002A1CBF681DA2 +:10001000106023B1627F691D184611F06DFD2F88B5 +:100020006D888DB1E81987B2208904F1080620F4A3 +:100030000040A84238BFFFDF30884FF4004121EA7A +:100040000000284330800AE0607F6288C1190831CF +:1000500000F1080389B204F1080000F09CFAC845D9 +:1000600004BF208960813846BDE8F0878188C08858 +:1000700081420CBF012000207047018980888142A5 +:100080000CBF01200020704730B48488C28800F182 +:10009000280324F4004C22F40041634494421BD012 +:1000A0008289048A15191C885A88A3189D4216D380 +:1000B00012B18A4210D212E0437F0CF1080C1A19D7 +:1000C0006244408892B2801A80B22333984201D2AF +:1000D00011B104E08A4202D130BC0020704730BC2C +:1000E000012070472DE9F007B0F806C0048900F13F +:1000F000280702462CF400457E1924F400492CF40C +:10010000004A002024F400434FF00108D1450AD1F1 +:1001100004F400440CF4004C644504D05082BDE863 +:10012000F00700207047AB4208D992F81DC05B1B56 +:10013000A3EB0C03A3F10804002308E0B2F802C00B +:10014000547FACEB050CACEB040CACF10804002CB8 +:10015000E4DBB2F80EC0BCF1000F0DD0B6F800C061 +:1001600075884DB15B1B10778B42D7DBD089384443 +:10017000A0EB0C00C01E09E0A4EB0C0410778C422D +:1001800008DB507FD38918443044401D5182BDE8BC +:10019000F00770478B42A8BF82F81C80E6DABDE703 +:1001A0002DE9F05F044600F1280AC088934620F448 +:1001B00000400AEB0005608A894608B1484502D232 +:1001C0000020BDE8F09FE08980B1B5F800806E881E +:1001D00008EB0601884218BFFFDF207F4FF00007C1 +:1001E00050EA060108D0002840D04AE04FF000084D +:1001F000A17F46462971F0E7E08948B1617F01445B +:100200004819B4F81F10A0F8051094F82110C17116 +:10021000E18908EB09004944E18128806F80BBF146 +:10022000000F19D0607F298800F1080301440831CC +:1002300089B26288A01D00F0AEF9E781A07F401C62 +:10024000A077A07D00281CBFE088A082A7756782E8 +:10025000E7750120BDE8F09F607FE18908442844EC +:10026000B0F80510A4F81F10C0792EE0E089B4F8AA +:100270001F105044A0EB080020F8031D94F8211033 +:10028000817006EB090086B2E089BBF1000F48449B +:10029000E081A5F800806E800ED0E088A51D20F4D6 +:1002A0000040B04238BFFFDF28884FF4004121EA08 +:1002B000000030432880C0E7E0895044A0EB0800EC +:1002C00030F8031DA4F81F10807884F82100BEE7E1 +:1002D000818800F1280221F4004C6244B0F814C077 +:1002E000C388614518BF99420FD0818969B9806977 +:1002F00068B101898388994209D021F400412830EE +:10030000084411790079884201D1002070471046D5 +:10031000704700F12803407F01F1050C6044106034 +:100320000888002804BFD81E10600888498808443F +:1003300080B270472DE9F04115460A4600F12806C3 +:100340001C46407F531D0344108857880699002897 +:100350001CBFC01C80B226D088429CBF081A80B245 +:1003600013D9401AA042A8BF20461FFA80F8581897 +:100370004246294611F094FB002818BFBDE8F081E1 +:100380004544A4EB080084B2002001198F423CBF11 +:100390004FF0FF30BDE8F081304422462946BDE8E9 +:1003A000F04111F07DBBFA1C97B2F61ED4E72DE99F +:1003B000F04100F128071D46407F4B1D03441646BF +:1003C00008880024B1F80280069A00281CBFC01CCF +:1003D00080B21FD090429CBF101A80B20DD9801AF3 +:1003E000A842A8BF284684B299182246304611F088 +:1003F00083FB281B85B2264400204119414506D8BD +:1004000039182A46304611F077FB601984B220462D +:10041000BDE8F08108F103011FFA81F8FF1ED9E75A +:100420002DE9F04116460A4600F128071D46407F97 +:10043000531D034410880024B2F802800699002856 +:100440001CBFC01C80B21FD088429CBF081A80B25B +:100450000DD9401AA842A8BF284684B2581822468F +:10046000314611F049FB281B85B226440020411972 +:10047000414506D838442A46314611F03DFB601903 +:1004800084B22046BDE8F08108F103021FFA82F829 +:10049000FF1ED9E7401D704770B5044600F12801E2 +:1004A000C288808820F400431944904208D0A28971 +:1004B000002A04BF228A002A02D1A28A904201D1D6 +:1004C000002070BDB1F800C04D8885B1261D20F414 +:1004D0000040A84238BFFFDF30884FF4004121EAD6 +:1004E00000002843308000202082012070BD607F02 +:1004F0000CF1080100F10803084481B26288201D54 +:1005000000F049F8EFE70021C18101774182C17510 +:100510008175704703881380C289002A04BF0020B8 +:100520007047C28800F1280322F400421A440A608E +:10053000C089704710B50446808AA0F57F41FF3915 +:1005400018BFFFDFE088A082E089002818BF0120E3 +:10055000A07510BD4FF6FF71818200218175704733 +:1005600010B50446808AA0F57F41FF3908BFFFDF40 +:10057000A07D28B9A088A18A884204BF002010BDB0 +:10058000012010BD8188828A914205BF807D0028AC +:1005900000200120704710B4B0F800C02CF40044D3 +:1005A000214489B24FF4004491420AD2521A92B2C5 +:1005B0001B339A422CBF0CF4004224EA0C0104D2F3 +:1005C00004E0891A89B224EA0C021143018010BCAC +:1005D000704770B516464FF6FC72C91C01EA020559 +:1005E000D8B10446C01C20F00301A14200D0FFDFB7 +:1005F000201D012108E00246284401D2034600E004 +:100600000023491CC9B21360B142F4D916B104F1F8 +:10061000040001E04FF00000206005FB06F000F14F +:10062000040070BD024600201168002902D008466F +:1006300009681160704702680A60016070474FF6F0 +:10064000FC73C91C1940101A001F90FBF1F0C0B2D6 +:1006500070474FF6FC73C91C1940001D01FB0200D6 +:10066000704770B50C00054609D0082C00D2FFDF9A +:100670001DB1A1B2286800F044F8201D70BD0DB175 +:1006800000202860002070BD0021026803E09388EC +:100690001268194489B2002AF9D100F032B870B555 +:1006A00000260D460446082900D2FFDF206808B95D +:1006B0001EE0044620688188A94202D00168002912 +:1006C000F7D181880646A94201D100680DE005F105 +:1006D000080293B20022994209D32844491B0260C0 +:1006E00081802168096821600160206000E00026A7 +:1006F000304670BD00230B608A8002680A6001608A +:10070000704700234360021D018102607047F0B50D +:100710000F460188408815460C181E46AC4200D38F +:10072000641B3044A84200D9FFDFA019A84200D9B9 +:10073000FFDF3819F0BD2DE9F041884606460188F3 +:10074000408815460C181F46AC4200D3641B384441 +:10075000A84200D9FFDFE019A84200D9FFDF708866 +:100760003844708008EB0400BDE8F0812DE9F041C9 +:10077000054600881E461746841B8846BC4200D3A7 +:100780003C442C8068883044B84200D9FFDFA0196F +:10079000B84200D9FFDF68883044688008EB040065 +:1007A000E2E72DE9F04106881D460446701980B243 +:1007B000174688462080B84201D3C01B208060883D +:1007C000A84200D2FFDF7019B84200D9FFDF60886D +:1007D000401B608008EB0600C6E730B50D46018877 +:1007E000CC18944200D3A41A4088984200D8FFDF66 +:1007F000281930BD2DE9F041C14D04469046A87836 +:100800000E46A04200D8FFDF05EB8607B86A50F815 +:10081000240000B1FFDFB868FFF704FF05000CD02B +:10082000B86A082E40F8245000D3FFDFB54842468E +:10083000294650F82630204698472846BDE8F081E2 +:100840002DE9F0471E460400074602EB06009146DC +:100850008A46C5B227D000218846FF2800D9FFDF8D +:10086000E01C20F00300A04200D0FFDFB24500D919 +:10087000FFDFA34880F800A080F801908570C57064 +:10088000057145718671DFF87CA280F8079000261B +:100890000AF1400A8146FF1C27F003000746B8F121 +:1008A000000F03D005E04FF00101D5E709EB860109 +:1008B00088603AF8161019F8062001D04FF00000B1 +:1008C000FFF787FE761CF6B20744082EE3D3FF1C21 +:1008D00027F003002A460646B8F1000F0DD000208D +:1008E0000221FFF776FE4346002130440F46C846FA +:1008F000C01C20F003021BB110E0C9F84800EFE76C +:1009000008EB81060020B26206E000BFD6F828C0DE +:100910004CF82070401CC0B2A842F7D3491CC9B2A1 +:1009200002EB85000829E3D3001BBDE8F08710B572 +:10093000044603F0BBFC08B1102010BD2078704ABB +:10094000618802EB800092780EE0836A53F82130D0 +:1009500043B14A1C6280A180806A50F82100A060E7 +:10096000002010BD491C89B28A42EED86180052062 +:1009700010BD70B505460C46084603F097FC08B15B +:10098000102070BD082D01D3072070BD25700020F8 +:10099000608070BD0EB56946FFF7EBFF00B1FFDF69 +:1009A0006846FFF7C4FF08B100200EBD01200EBD50 +:1009B00010B50446082800D3FFDF5148005D10BD84 +:1009C0003EB5054600246946FFF7D3FF18B1FFDFA7 +:1009D00001E0641CE4B26846FFF7A9FF0028F8D0E4 +:1009E0002846FFF7E5FF001BC0B23EBD44498978A9 +:1009F000814201D9C0B27047FF2070472DE9F04114 +:100A000090460C460546062901D0072C10D13C4FD4 +:100A1000B86CFFF707FE02004FF6FF7604D0022104 +:100A2000B86CFFF70CFE00E030462880B04201D1E0 +:100A3000002003E742462146FFF7DCFE040002D116 +:100A4000288800F04FF82046F8E6A0F57F43FF3BEA +:100A500001D0082901D300207047CBE6A0F57F42E2 +:100A6000FF3A0BD0082909D2254A9378834205D949 +:100A700002EB8101896A51F820007047002070471D +:100A80002DE9F04105460C46A5F57F4143F20200F1 +:100A9000FF3902D0082C01D30720CFE618494FF0C8 +:100AA00000088A78AA42F8D901EB8406B26A52F8A3 +:100AB0002570002FF1D013483946203050F82420FB +:100AC00028469047B16A062C41F8258001D0072CB2 +:100AD00002D1284600F006F83946B068FFF7ABFDB2 +:100AE0000020ABE610B5064CC2B20221A06CFFF7A5 +:100AF000B0FD0146A06CBDE81040FFF79CBD0000B2 +:100B0000600700202022020070B50E461D461146E7 +:100B100000F0D4F804462946304600F0D8F82044C6 +:100B2000001D70BD2DE9F04190460D4604004FF0C8 +:100B3000000610D00027E01C20F00300A04200D0E7 +:100B4000FFDFDDB141460020FFF78BFD0C3000EBED +:100B5000850617B112E00127EDE7614F04F10C00A3 +:100B6000A9003C602572606000EB85002060606831 +:100B700011F05BF841463868FFF773FD3046BDE879 +:100B8000F0812DE9FF4F564C804681B020689A468F +:100B9000934600B9FFDF2068027A424503D94168D5 +:100BA00051F8280020B143F2020005B0BDE8F08FF3 +:100BB0005146029800F082F886B258460E9900F02D +:100BC00086F885B27019001D87B22068A1463946A3 +:100BD0000068FFF764FD04001FD067802580294668 +:100BE000201D0E9D07465A4601230095FFF766F823 +:100BF0002088314638440123029ACDF800A0FFF73F +:100C00005DF82088C1193846FFF78FF8D9F8000041 +:100C10004168002041F82840C7E70420C5E770B5C7 +:100C20002F4C0546206800B9FFDF2068017AA942F1 +:100C30000ED9426852F8251051B1002342F82530F0 +:100C40004A880068FFF756FD216800200A7A08E00C +:100C500043F2020070BD4B6853F8203033B9401C9A +:100C6000C0B28242F7D80868FFF70EFD002070BDC1 +:100C700070B51B4E05460024306800B9FFDF3068B0 +:100C8000017AA94204D9406850F8250000B1041D3A +:100C9000204670BD70B5124E05460024306800B97C +:100CA000FFDF3068017AA94206D9406850F8251064 +:100CB00011B131F8040B4418204670BD10B50A4636 +:100CC0000121FEF7F3FFC01C20F0030010BD10B59A +:100CD0000A460121FEF7EAFFC01C20F0030010BD08 +:100CE0006C00002070B5044600780E46012813D031 +:100CF000072802D00B2813D10EE0A068616905789F +:100D0000052003F061FA052D0AD078230022052082 +:100D1000616903F0AFF903E00520616903F054FA5B +:100D200031462046BDE8704001F0A8B910B500F189 +:100D30003902C3799478411D64F003042340C371E0 +:100D4000DB070DD04B79547923404B710B79127925 +:100D500013400B718278C9788A4200D9817010BD26 +:100D600000224A710A71F5E74178012900D00C216F +:100D7000017070472DE9F74F88B000208C698DF81D +:100D800004000878012617460D464FF007094FF07A +:100D9000110A4FF00A0B292876D2DFE810F029005B +:100DA000D20215032D036F037E039903C703DC03EF +:100DB0000604330457047004AE04BF04E204EA04DA +:100DC0000A052C0557057A05A605C605D605F605BC +:100DD000F805050637065906AD06EA06EC061B07B8 +:100DE0003B074407550792071B08410808080D08F0 +:100DF00014B120781E2829D0D5F808805FEA0800B1 +:100E000042D001208DF80400686A02228DF8082083 +:100E100006908DF809B0286A0390A8880028EFD0C2 +:100E200098F8001091B10F2910D27DD2DFE801F0BF +:100E30007C134BDCFEFDFCFBFAF9F8089EF7F6008C +:100E4000022821D124B120780C2801D00026F9E312 +:100E50008DF80420B3E10520696A03F0B5F9A8888C +:100E60000728EED1204601F003F9022809D02046D8 +:100E700001F0FEF8032808D9204601F0F9F8072808 +:100E800003D20120207005E003E2002CB8D02078C6 +:100E90000128D6D198F80400C11F0A2903D300BF46 +:100EA00085F81CB04CE2A070D8F80010A163B8F827 +:100EB0000410A18798F8060084F83E0001202870ED +:100EC0000320207046E00728BBD1002C98D0207862 +:100ED0000D28B6D198F8031094F83B20C1F3C00058 +:100EE000C2F3C002104201D0062000E007208907AB +:100EF00007D198F805100142D2D198F806100142A6 +:100F0000CED194F83D2098F8051020EA0202114253 +:100F1000C6D194F83E2098F8061090430142BFD104 +:100F200098F80400C11F00E008E20A29B8D2617FE6 +:100F3000814201D906209AE3D8F800106160B8F820 +:100F40000410218198F80600A072012028700E205C +:100F5000207003208DF80400686A069004F13900BF +:100F60000290601D039017300490DBE0412890D17F +:100F7000204601F07DF8042802D1E078C00704D1B2 +:100F8000204601F075F80F289ED1A88CD5F80C806A +:100F900080B24FF04009666AFFF76AFE32460826C3 +:100FA00041464B460096FFF702FA0D208DF80400EB +:100FB000686A0690606A0290002101A8FFF792FE1D +:100FC0002078042808D0A07F48B1012807D0032842 +:100FD00008D0102020709CE005202070CEE184F81D +:100FE00000A033E71220F5E71128C0D1204601F018 +:100FF0003FF8042802D1E078C00719D0204601F05C +:1010000037F8062805D1E078C00711D1A07F022863 +:101010000ED0204601F02CF8112808E0B3E083E060 +:1010200072E156E136E109E1EAE0D0E017E09ED155 +:10103000102208F1010104F1480010F05DFD607814 +:10104000012809D012202070E078C00765D0A07F69 +:1010500090B301285DD060E084F8009059E0112839 +:1010600085D1204601F004F8082804D0204600F07D +:10107000FFFF132888D12869D0B16869C0B104F195 +:101080007800102208F10101064610F035FD2078A5 +:10109000082812D014202070E078C0070FD0A07F5D +:1010A000022818D06178022912D0032831D034E008 +:1010B00000208DF80400ECE02BE00920EBE70B208A +:1010C0002870296901204870206CC1E9010662E29C +:1010D00008B101287AD10B202870296981F8019084 +:1010E000606A4860206AC1E9020648E2206CE27842 +:1010F0000068C2F34402521ED04000F0010040F0EC +:10110000800000E000200874E06A48614CE2064676 +:10111000FEE3042028700520BAE185F800B08DF8C0 +:1011200004B08EE33946F4E31128C4D1204600F020 +:101130009FFF0A2802D1E078C00704D1204600F0C2 +:1011400097FF1528B7D1102208F1010104F14800DA +:1011500010F0D2FC20780A2810D01620207012201F +:10116000287029690920487004F15800486020302F +:1011700088601038C860206C086184E30B20207000 +:10118000B9E22870FEE3022895D1204600F070FFF6 +:10119000042804D3204600F06BFF082809D320461A +:1011A00000F066FF0E2886D3204600F061FF12286B +:1011B0006FD2A07F0228B8D110208DF80400686A91 +:1011C000069098F801008DF80800F6E33DE2022849 +:1011D000ABD1204600F04CFF00285AD0204600F04A +:1011E00047FF0128F9D0204600F042FF0C28F4D038 +:1011F00004208DF8080098F801008DF809005AE7DE +:101200001128FCD1002CFAD020781728F7D161786A +:10121000E06A022910D0002101EB4101182606EBFB +:10122000C1011022405808F1010110F065FC0520B1 +:10123000696A00F010FF1DE10121EDE70B28DED106 +:10124000002CDCD020781828D9D16178E06A0229F6 +:101250001BD0002101EB4101102202EBC1014158DA +:10126000B8F8010008806078E16A02280FD00020F9 +:1012700000EB4002142000EBC2000958404650F831 +:10128000032F0A604068486039E00121E2E701204D +:10129000EEE7A1E11128B2D1002CB0D020781928B6 +:1012A000ADD16078E16A022811D0002000EB400245 +:1012B0001C2000EBC2001022085808F1010110F0B8 +:1012C0001BFC0520696A00F0C6FE1A20D4E001204C +:1012D000ECE7082893D1002C91D020781A288ED1E1 +:1012E000E06A98F80120017862F347010170E16A31 +:1012F000D8F8022041F8012FB8F8060088800520B0 +:10130000696A00F0A8FE3CE3112898D1002C98D01F +:1013100020781B2893D16178E06A02290CD0002143 +:1013200001EB4101202202EBC1011022405808F1DB +:10133000010110F0E1FBE2E70121F1E785F81C90E3 +:10134000EFE338780128A6D11C2204F11C0079684B +:1013500010F017FCE079C10894F83B0001EAD001D5 +:10136000E07861F30000E070217F09B1297733E173 +:10137000217803290AD0C0073FF42DAE032028703E +:101380008DF804B0686A06904120B1E3607FA178CF +:1013900088423FF6CFAD02262671E179204621F042 +:1013A000E001E171617A21F0F0016172A17A21F02E +:1013B000F001A172FFF7BAFC2E708DF804B0686AD4 +:1013C00006908DF80890ADE638781128CFD18DF8C9 +:1013D0000490696A0691916800208DF814000391C9 +:1013E000ADF8089008466168016021898180A17A82 +:1013F000817104202070E0E238781128B7D18DF88F +:101400000490686A0690381D02AB07C883E807009D +:101410004120ADF8080000208DF8140008460C218A +:101420000170A88CCA4680B2FE684FF04009D4F81B +:101430002080FFF72FFC3146082642464B46009697 +:10144000FEF7EEFF002101A8FFF74CFCE07820F04A +:101450003E00801CE0702078052801D00F200BE0B2 +:10146000A07F20B1012802D0032803D03DE184F8F9 +:1014700000A04EE62670E9E42070E7E438780328FF +:10148000A4D178680168A1664068E06605202870EC +:101490008DF80400686A069044E63878032895D1F0 +:1014A00078680168216740686067206C68B9A07F30 +:1014B00028B1012803D0062028700420E8E785F829 +:1014C0000090FE4820646064F9E385F80090F6E33C +:1014D0003878022892D1387900287CD1A07F022860 +:1014E0000BD00328F1D1607801280BD0A07994F8B3 +:1014F0003A1001280AD0F1480BE0B86800286BD0F8 +:10150000206411E0A17994F83A00F2E7B868002865 +:10151000F5D02064E078C00701D0012901D0E74868 +:1015200002E0F8680028EAD06064CEE78DF804B0E5 +:10153000696A0691E1785846C90709D0617802299D +:1015400003D1A17F29B1012903D0A17F032900D0B4 +:101550000820287064E33878112891D1B86828628F +:1015600009202870E0782969C0070DD081F8019022 +:10157000206A4860606A886004F16800C860A07FE3 +:1015800002287FF4BFADB1E501204870206C4860AF +:1015900004F16800886004F13800C860201D08610B +:1015A000206B4861606B88612AE2E1783878C9076E +:1015B00001D0062100E00A2188428BD1207807283B +:1015C0001DD084F800A000BF8DF80490686A0690D2 +:1015D000286A039001E0CAE08DE20024ADF808A07B +:1015E0008DF81440032100F8011B5168102210F0FF +:1015F00083FA002101A8FFF775FB2C6226E408207E +:101600002070E1E738781128A7D18DF80490686A36 +:1016100006909068039000208DF814000398ADF8B0 +:1016200008A0042100F8011B102204F1680110F049 +:1016300063FA002101A8FFF755FB2078092802D0A2 +:10164000132019E73CE384F800B016E0E17838781D +:10165000C90701D0062100E00A218842ADD110223D +:1016600004F14800796810F01BFA10B104202877C3 +:10167000EAE3207809283FF4EEAC0C2081E5E0781D +:10168000C10738D0A17F012902D002291BD02EE04A +:101690000D202870296981F801B06078012809D0EF +:1016A000206A4860606A886004F16800C860103091 +:1016B000086129E5606A4860206A886004F1780062 +:1016C000C8601038F4E7C0F3440114290FD24FF07A +:1016D000006101EBB0104FEAB060E0706078012863 +:1016E00003D010202070042057E10620C4E6607863 +:1016F00001283FF476AC0E2043E538780928ADD1B7 +:1017000085F800B00F208DF80400686A06905068D4 +:101710000290002101A8FFF7E5FAE8E7E078C007AA +:101720000AD0A07F012803D10F202870042036E1C1 +:10173000102028700E2032E115202870296902201F +:101740004870206C48606078012805D004F178006A +:1017500088601038C86053E104F168008860103078 +:10176000F8E738780228CAD138790028E0D02877FD +:1017700068E338781328FBD185F800A02969082090 +:10178000487078684860607801280DD004F16800DE +:1017900088601030C860206B0861606B486104F19C +:1017A00058008861A06A22E004F17800886010384F +:1017B000F0E738780728DBD16078012801D01320C2 +:1017C00029E2A178A06A0844C1F1100110F00BFAD7 +:1017D0001220287029690920487004F158004860D7 +:1017E000203088601038C860206C086144E0C8610F +:1017F000E06A086204E138780828B9D1102204F1BF +:101800004800796810F04CF908B10B202FE72078D8 +:101810000B2812D02046FFF789FAA178A06A084465 +:10182000C1F1100110F0DFF91620287008208DF8A2 +:101830000400686A0690002072E0132028708DF87A +:1018400004B0686A06908DF808A06BE43878112817 +:101850008ED1B86828621420287029690920487040 +:1018600004F158004860103088601030C860606C27 +:1018700008616078012806D004F139004861206BC6 +:101880008861606BB3E7601D4861606B8861206BA5 +:10189000ADE7387808288ED18DF80490686A0690F4 +:1018A000286A00260D210390ADF808A08DF8146079 +:1018B00000F8011B1022796802E000007423020086 +:1018C00010F01AF9002101A8FFF70CFA2E626078D7 +:1018D000012801D01520CFE51620287008208DF8AA +:1018E0000400686A029606901BE038780B2884D1C1 +:1018F000162028706078022802D12046FFF716FAD9 +:10190000A17878680844C1F1100110F06CF901E089 +:1019100083E215E008208DF80400686A0690786874 +:101920000290A0788DF80C004DE538780F288FD103 +:10193000E079C00773D01720287009202FE01146E6 +:1019400001A8FFF7CFF9FFF7E2BB38781028A2D142 +:101950001422391D04F11C0010F013F9E16A208DE6 +:10196000A1F80900E16AA078C871E179E26A01F0A2 +:1019700003011172E16A627A0A73E16AA07A81F85E +:10198000240000E09BE1242078E6192043E1387828 +:101990001128ACD1B86828621A20287005208DF86B +:1019A0000400686A0690CAE7387803289FD16078F7 +:1019B000E16A022802D0012001E05CE2002000EB95 +:1019C0004002142000EBC2027B688A58196811603B +:1019D000596851601B212970D5E9041205234B7009 +:1019E000636A4B606678E36A022E01D0012600E04C +:1019F000002606EB460600EBC6001858C1E90202B5 +:101A0000686A4862089800F050FB9CE738780E2816 +:101A100071D16078E26A022802D0012001E0ADE1D4 +:101A2000002000EB4001102000EBC1000223105801 +:101A3000093279680EF01EFB1C20287029690420E9 +:101A40004870206A4860E06A09308860FB4881E697 +:101A500038780D284FD16178E06A022901D0012140 +:101A600000E0002101EB4101182606EBC101A2783C +:101A70004058796810F040F86078E16A022801D097 +:101A8000012000E0002000EB400206EBC200B0465F +:101A90000858A1780844C1F1100110F0A4F88DF89D +:101AA0000490686A0690286A00260390ADF808A0A2 +:101AB0008DF81460062101706178E26A022901D074 +:101AC000012100E0002101EB410308EBC301401CB0 +:101AD0005158102210F010F8002101A8FFF702F968 +:101AE0001D202E6228708DF804B0686A06900B20C5 +:101AF0008DF8080067E481E0387811287ED18DF8F0 +:101B00000490686A0690B86803900B20ADF808004E +:101B1000039880F800906278E16A022A02D00122DC +:101B200001E091E1002202EB4202102303EBC2022A +:101B300089580988A0F801106178E26A022901D069 +:101B4000012100E0002101EB4103142101EBC3015D +:101B500051580A6840F8032F4968416056E0272031 +:101B6000287001208DF814002DE424202870002016 +:101B70009FE01F204FE0387811283FD18DF8049066 +:101B8000686A0690B868039000208DF814000398E6 +:101B9000ADF808A0082606706178E26A022901D033 +:101BA000012100E0002101EB41031C2101EBC301F5 +:101BB000401C515810220FF09FFF002101A8FFF791 +:101BC00091F8202028708DF804B0686A06908DF88E +:101BD000086061E43878112810D18DF80490686AA3 +:101BE0000690B86803900820ADF808000398092112 +:101BF0000170E16909784908417000E094E0E16909 +:101C000051F8012FC0F802208988C18020781D2852 +:101C1000ABD1A4E7222028708DF804B0686A069042 +:101C20008DF808A08BE6387811287DD1B868286235 +:101C300023202870296904204870206A4860E06ADF +:101C4000093088607E4885E538780D286CD1617848 +:101C5000E06A022901D0012100E0002101EB4101ED +:101C6000202606EBC1011022405879680FF044FF8E +:101C70008DF80490686A0690286A0390ADF808A071 +:101C800080F800B06278E16A022A01D0012200E007 +:101C9000002202EB420206EBC202401C89581022CD +:101CA0000FF02AFF0020286221781D29B1D02421BD +:101CB00029708DF81400002101A8FFF713F80326FE +:101CC000DFE0E078C00702D04FF0060C01E04FF0F3 +:101CD000070C6078022809D04FF0000000EB0401E7 +:101CE00001F1090105D04FF0010004E04FF00100BF +:101CF000F4E74FF000000B78204413EA0C030B705C +:101D000010F8092F02EA0C02027004D14FF01C0CEB +:101D100084F800C092B394F801C0BCF1010F00D068 +:101D2000E3B990F800C000E053E05FEACC7804D05B +:101D30002CF00106067018260EE05FEA8C7804D5B8 +:101D40002CF0020606701E2606E05FEA4C7805D5E8 +:101D50002CF00406067021262E70032694F801C08C +:101D6000BCF1020F00D0DAB991F800C05FEACC787C +:101D700005D02CF001060E7017210FE01AE05FEA83 +:101D80008C7804D52CF002060E70192106E05FEA6B +:101D90004C7805D52CF004060E701B21217000260E +:101DA0000078D0BBCAB3C3BB1D20207035E03878A3 +:101DB000122847D1282061E42078012842D00C283D +:101DC00040D02046FEF7D0FF0B208DF80400686A53 +:101DD000069037E038784FF02608112805D01220F9 +:101DE0001070032685F800804BE08DF80490686A37 +:101DF0000690B86803900220ADF8080001208DF825 +:101E00001400039805210170297F4170114601A833 +:101E1000FEF768FF064685F80080012E12D030E0FC +:101E200001208DF80400686A069003208DF80800F0 +:101E3000287F8DF809000020287716E06C23020027 +:101E400070220200287F80B11E202070252028707B +:101E50008DF804B0686A069002208DF808003946B3 +:101E600001A8FEF73FFF06460BE00CB1FE202070F4 +:101E70009DF8040028B1002101A8FEF733FFFEF70A +:101E8000E5BF0BB03046BDE8F08FF0B587B00C462B +:101E90004E6900218DF804100120257803460227A1 +:101EA0004FF0070C85B1012D50D0022D36D1FE2008 +:101EB00030708DF80030606A059003208DF80400C2 +:101EC000207E8DF8050060E02179012922D00229C9 +:101ED00029D0032924D0042920D1B17F02291DD182 +:101EE00031780D1F042D04D30A3D032D01D31E2983 +:101EF00014D12189022911D38DF80470237020890F +:101F00009DF80410884217D20A208DF80000606AFC +:101F1000059057E070780128EED0052007B0F0BD9D +:101F20001E203070E8E771780229F6D131780C294B +:101F3000F4D18DF804C0E1E71120083402F8040B55 +:101F400094E80B0082E80B000320E7E71578112DD9 +:101F5000E4D18DF800C0656A0595956802958DF805 +:101F6000101094F804E0BEF1010F13D0BEF1020F7F +:101F70002DD0BEF1030F1CD0BEF1040FCED1ADF8B1 +:101F800004700E202870207E687000216846FEF7DD +:101F9000A9FE0CE0ADF804700B202870207E002113 +:101FA00000F01F0068706846FEF79CFE3770002046 +:101FB000B4E7ADF804708DF8103005202870207E4D +:101FC0006870277011466846FEF78CFEA6E7ADF8EC +:101FD00004C02B70207F6870607F00F00100A87043 +:101FE000A07F00F01F00E870E27F2A71C0071CD0BC +:101FF00094F8200000F00700687194F8210000F0C8 +:102000000700A87100216846FEF76CFE2868B063DF +:10201000A888B087A87986F83E00A06940787077D4 +:102020002879B0700D203070C1E7A9716971E9E7B6 +:1020300000B587B005280CD101208DF800008DF87F +:102040000400002005918DF8050001466846FEF762 +:1020500049FE07B000BD70B50C46054602F0B4F865 +:1020600021462846BDE870407823002202F002B8DD +:1020700008B1007870470C207047000070B50C0064 +:1020800005784FF000010CD021702146F3F79DF840 +:1020900072482178405D884201D1032070BD022042 +:1020A00070BDF3F792F8002070BD027B032A05D0C3 +:1020B00000220A704B780B2B02D003E004207047FB +:1020C0000A770A62027B9300521C0273C1500320FC +:1020D0007047F0B587B00F4605460124287B05EB15 +:1020E000800050F8046C7078411E0C290AD25B49BC +:1020F0003A46123101EB8000314650F8043C284644 +:10210000984704460CB1012C11D1287B401E10F0D9 +:10211000FF00287301D00324E0E70C208DF80000B5 +:10212000706A0590002101966846FFF7A7FF032C0F +:10213000D4D007B02046F0BD70B515460A46044617 +:1021400029461046FFF7C5FF064674B12078FE28E1 +:102150000BD1207E30B100202870294604F10C00FC +:10216000FFF7B7FF2046FEF7FFFD304670BD704712 +:1021700070B50E46044688210FF057FD0225012E4A +:1021800003D0022E04D0052070BD0120607000E055 +:1021900065702046FEF7E8FDA577002070BD28B1E8 +:1021A000027E1AB10A4600F10C01C5E70120704712 +:1021B00010B5044686B0052002F006F82078FE2807 +:1021C00006D000208DF8000069462046FFF7E7FFA3 +:1021D00006B010BD7FB50E4600218DF80C10417879 +:1021E0000B2903D00C2903D0002405E0846900E00A +:1021F00044690CB1217E91B16D4601462846FFF736 +:1022000054FF032809D1324629462046FFF794FFA0 +:102210009DF80C10002900D0042004B070BD04F11A +:102220000C05EAE710B590B00C4607900B48042166 +:10223000801E08900A488DF8191009900F9269467F +:1022400006A8FFF7C7FF002805D1102220460199F4 +:102250000FF052FC002010B010BD000076220200EA +:102260006C23020070B50D46040011D085B1210128 +:1022700028460FF0B8FC10224E4928460FF03CFCCF +:102280004C4801210838018044804560002070BD21 +:10229000012070BD70B5474E00240546083E10E091 +:1022A0007068AA7B00EB0410817B914208D1C17B4E +:1022B000EA7B914204D10C2229460FF0F1FB30B1A8 +:1022C000641C30888442EBDB4FF0FF3070BD204649 +:1022D00070BD70B50D46060006D02DB1FFF7DAFFD0 +:1022E000002803DB401C14E0102070BD314C083C7A +:1022F00020886288411C914201D9042070BD616828 +:10230000102201EB001031460FF0F6FB2088401C34 +:1023100020802870002070BD70B514460D0018D0C4 +:10232000BCB10021A170022802D0102811D105E013 +:10233000288870B10121A170108008E02846FFF7BD +:10234000A9FF002805DB401CA070A8892080002080 +:1023500070BD012070BD70B5054614460E000BD04F +:1023600000203070A878012808D005D91149A1F1C2 +:1023700008010A8890420AD9012070BD24B128784A +:1023800020702888000A5070022008700FE064B1A5 +:102390004968102201EB0011204610390FF0ACFB08 +:1023A000287820732888000A60731020307000207D +:1023B00070BD0000780000202DE9F04190460C46E9 +:1023C00007460025FE48072F00EB881607D2DFE8F6 +:1023D00007F00707070704040400012500E0FFDFFA +:1023E00006F81470002D13D0F548803000EB8801FA +:1023F00091F82700202803D006EB4000447001E04C +:1024000081F8264006EB44022020507081F82740D6 +:10241000BDE8F081F0B51F4614460E460546202A59 +:1024200000D1FFDFE649E648803100EB871C0CEB6A +:10243000440001EB8702202E07D00CEB46014078C8 +:102440004B784870184620210AE092F825304078F1 +:1024500082F82500F6E701460CEB41000570407854 +:10246000A142F8D192F82740202C03D00CEB440471 +:10247000637001E082F826300CEB41042023637086 +:1024800082F82710F0BD30B50D46CE4B441900221E +:10249000181A72EB020100D2FFDFCB48854200DD43 +:1024A000FFDFC9484042854200DAFFDFC548401CD3 +:1024B000844207DA002C01DB204630BDC148401CB5 +:1024C000201830BDBF48C043FAE710B50446016884 +:1024D000407ABE4A52F82020114450B102200844EC +:1024E00020F07F40F0F751FB94F90810BDE8104050 +:1024F000C9E70420F3E72DE9F047B14E803696F89E +:102500002D50DFF8BC9206EB850090F8264034E0B1 +:1025100009EB85174FF0070817F81400012806D0BB +:1025200004282ED005282ED0062800D0FFDF01F089 +:10253000E5F8014607EB4400427806EB850080F899 +:10254000262090F82720A24202D1202280F82720BE +:10255000084601F0DEF82A4621460120FFF72CFF4D +:102560009B48414600EB041002682046904796F8CD +:102570002D5006EB850090F82640202CC8D1BDE8F0 +:10258000F087022000E003208046D0E710B58C4C95 +:102590002021803484F8251084F8261084F8271030 +:1025A000002084F8280084F82D0084F82E10411EA5 +:1025B000A16044F8100B2074607420736073A073E2 +:1025C0008449E07720750870487000217C4A103CEF +:1025D00002F81100491CC9B22029F9D30120F0F7F3 +:1025E000C2F90020F0F7BFF9012084F82200F9F7C2 +:1025F00053FB7948F9F75FFB764CA41E20707748AF +:10260000F9F759FB6070BDE81040F0F739B910B523 +:10261000F0F75BF96F4CA41E2078F9F765FB607842 +:10262000F9F762FBBDE8104001F0A0B82020704728 +:102630002DE9F34F624E0025803606EB810A89B002 +:102640009AF82500202822D0691E02916049009541 +:1026500001EB00108146D0E90112C0680391CDE979 +:102660000420B08BADF81C00B07F8DF81E009DF8E3 +:102670001500C8B10227554951F820400399E219C5 +:10268000114421F07F41019184B102210FE001202A +:10269000F0F769F90020F0F766F9F0F734F901F086 +:1026A00065F886F82F508AE00427E4E700218DF8CA +:1026B0001810022801D001281BD1039839190144B0 +:1026C0000998081A20F07F4033280BD903208DF891 +:1026D00015000398C4F13201401A20F07F403224E3 +:1026E00003900CE096F8240018B9F0F753FC00288A +:1026F0004DD0322C03D214B101F02CF801E001F0DE +:1027000035F8344A107820B393465278039B121B55 +:1027100000219DF81840984601281BD0032819D0A5 +:102720005FF000008DF81E00002A04DD981A039067 +:1027300001208DF818009DF81C0000B102210398BB +:10274000274A20F07F40039003AB099801F01AF864 +:1027500010B110E00120E5E79DF81D0018B99BF8C5 +:102760000000032812D08DF81C50CDF80C808DF895 +:1027700018408DF81E509DF8180058B10398012399 +:10278000C11900221846F0F741F906E000200BB00D +:10279000BDE8F08F0120F0F7E6F899F90C2001234D +:1027A00000200199F0F732F9012086F82F008AF80D +:1027B000285003482022694680300FF0E2F911E0EA +:1027C000AC090020FF7F841E0020A107B822020070 +:1027D000AC0700208A000020233F0100F7240100FD +:1027E000FFFF3F000120D2E72DE9F05FDFF84084D2 +:1027F000064608EB860090F82550202D1FD0A8F142 +:1028000080002C4600EB8617A0F50079DFF824B491 +:1028100005E0A24607EB4A004478202C0AD0F0F7E6 +:1028200041F909EB04135A4601211B1D00F0AAFFD0 +:102830000028EED0AC4202D0334652461EE0FE489D +:1028400008B1AFF30080F0F72DF998F82F206AB1A6 +:10285000D8F80C20411C891A0902CA1701EB126131 +:102860000912002902DD0020BDE8F09F3146FFF784 +:10287000DFFE08B10120F7E733462A462021042075 +:10288000FFF7C8FDEFE72DE9F041E94C2569F0F7C6 +:1028900009F9401B0002C11700EB1160001200D4BF +:1028A000FFDF94F8220000B1FFDF012784F82270D7 +:1028B00094F82E00202800D1FFDF94F82E6020200D +:1028C00084F82E00002584F82F5084F8205084F8D6 +:1028D0002150DA4825600078022833D0032831D00F +:1028E00000202077A068401C05D04FF0FF30A0608A +:1028F0000120F0F738F80020F0F735F8F0F733F959 +:10290000F0F72BF9EFF7FFFF0EF094FBCC480560D2 +:1029100005604FF0E0214FF40040B846C1F8800256 +:10292000F0F7BBF994F82D703846FFF75DFF0028EB +:10293000FAD0BF48803800EB871010F81600022844 +:1029400002D006E00120CCE73A4631460620FFF7E8 +:1029500033FD84F8238004EB870090F826002028BC +:1029600004D0B648801E4078F9F7C4F9207F0028CB +:1029700003D0F0F7E8F82577657749E50146AC48DC +:1029800010B590F82D200024803800EB821000BF95 +:1029900010F814302BB1641CE4B2202CF8D32020A2 +:1029A00010BDA84800EB0410016021460120FFF78C +:1029B00003FD204610BD10B5012801D0032800D129 +:1029C00071B39B4A92F82D30994C0022803C04EB65 +:1029D000831300BF13F812400CB1082010BD521C25 +:1029E000D2B2202AF6D3954A48B1022807D0072947 +:1029F00016D2DFE801F01506080A0C0E10000021BF +:102A00000AE01B2108E03A2106E0582104E0772182 +:102A100002E0962100E0B52151701070002010BD39 +:102A2000072010BD854810B54078F0F7AEF880B2A9 +:102A300010BD10B5202811D27D4991F82D30A1F19B +:102A4000800202EB831414F810303BB191F82D3062 +:102A500002EB831212F81020012A01D0002010BDD1 +:102A600091F82D2001460020FFF7A6FC012010BDA3 +:102A700010B5F0F717F8BDE81040F0F786B82DE96B +:102A8000F0410E466A4F01782025803F0C4607EB47 +:102A9000831303E0254603EB45046478944202D097 +:102AA000202CF7D108E0202C06D0A14206D103EB60 +:102AB00041014978017007E00020A9E403EB4400DC +:102AC00003EB4501407848705F4F7EB127B100218C +:102AD00040F2DA30AFF300803078A04206D127B15F +:102AE000002140F2DD30AFF30080357027B10021C6 +:102AF00040F2E230AFF30080012089E410B5426873 +:102B00000B689A1A1202D41702EB1462121216D42E +:102B1000497A91B1427A82B94C4A006852F8211040 +:102B2000126819441044001D891C081A0002C117BC +:102B300000EB11600012322801DB012010BD0020E3 +:102B400010BD2DE9F047814639483E4E00EB81002B +:102B5000984690F825402020107006F50070154624 +:102B600000EB81170BE000BF06EB04104946001D87 +:102B7000FFF7C4FF28B107EB44002C704478202CE9 +:102B8000F2D1297888F8001013E000BF06EB041595 +:102B9000291D4846FFF7B2FF68B988F80040A97BB5 +:102BA00099F80A00814201D80020E8E407EB4400CC +:102BB0004478202CEAD10120E1E42DE9FC410E46C5 +:102BC000074600241F4D08E09DF8000005EB0010AB +:102BD0008168384600F0EAFD01246B4601AA3146BF +:102BE0003846FFF7AEFF0028EED02046BDE8FC8156 +:102BF00070B504460E4801258038A54300EB8411CA +:102C000000EB851040220EF077FF0F4E26B1002119 +:102C100040F25C40AFF30080054800EB850100EB1B +:102C20008400D0F82500C1F82500AEB100210FE0E6 +:102C30002C0A0020FFFF3F00000000008A00002057 +:102C400000F50040AC07002000000000B8220200A0 +:102C50004FF48C60AFF30080284670BD2DE9FC4135 +:102C60008446FF481546089C00EB85170E4617F86A +:102C70001400012803D0022801D00020B6E70B463B +:102C8000F84A0121604600F07DFDA8B101AB6A461B +:102C900029463046FFF755FF70B1F1489DF80420F2 +:102CA0009DF80010803000EB85068A4208D02B4644 +:102CB0000520FFF7AFFB0BE02A462146042014E075 +:102CC000202903D007EB4100407801E096F8250069 +:102CD00007EB440148709DF80000202809D007EB5D +:102CE000400044702A4621460320FFF765FB01207F +:102CF0007CE706F8254F0120F070F3E7DA4901EB95 +:102D00000010001DFFF7E1BB7CB51D4613460446CD +:102D10000E4600F1080221461846EFF743FF94F9EA +:102D200008000F2804DD1F3820722068401C206036 +:102D300096B10220CD4951F8261046182068694600 +:102D4000801B20F07F40206094F908002844C01CBC +:102D50001F2803DA012009E00420EBE701AAEFF7BE +:102D600021FF9DF8040010B10098401C00900099CC +:102D7000206831440844C01C20F07F4060607CBD66 +:102D80002DE9FE430C460646097860799072207959 +:102D900098461546507241B1B148803090F82E10D7 +:102DA00020290AD00069401D0BE0D4E902232179D3 +:102DB00003B02846BDE8F043A6E7AD484178701D52 +:102DC000084420F07F47217900222846A368FFF7B6 +:102DD0009BFF3946284600F0E9FCD4E9023221790C +:102DE0006846FFF791FF41462846019CFFF7E5FE44 +:102DF0002B4622460021304600F0C4FC002803D1B7 +:102E00003146284600F0D2FCBDE8FE832DE9FE4F96 +:102E1000814600F087FC38B15FF0000799F80000A8 +:102E200020B10020BDE8FE8F0127F7E78C4D914CC3 +:102E30004FF0000A803524B1002140F2D340AFF3B7 +:102E4000008095F82D8085F823A0002624B100216C +:102E50004FF49B60AFF300801FB94046FFF7C8FEF8 +:102E6000804624B100214FF49C60AFF30080EFF75F +:102E700019FE43466A464946FFF782FF24B1002106 +:102E800040F2E640AFF3008095F82E0020280CD0E9 +:102E900029690098401A0002C21700EB1260001264 +:102EA00003D5684600F082FC012624B100214FF4CE +:102EB0009E60AFF3008095F823000028BBD124B1B9 +:102EC000002140F2F640AFF30080EFF7EBFD6B46D8 +:102ED000644A002100F056FC0028A3D027B94146DF +:102EE0006846FFF76AFE064326B16846FFF7EDFA2B +:102EF000C9F8080024B1002140F20950AFF3008066 +:102F000001208FE72DE9FF5F8A46814600F00AFC29 +:102F1000534C803410B39AF80000002710B10128F8 +:102F200000D0FFDF534D25B1002140F27F50AFF3B9 +:102F300000800120A84600905FEA080604D0002126 +:102F400040F28750AFF30080009800F0E2FB94F865 +:102F50002D50002084F8230067B119E094F82E006A +:102F60000127202800D1FFDF9AF800000028D9D0DF +:102F7000FFDFD7E72846FFF73BFE054626B10021D5 +:102F800040F29150AFF3008094F823000028D3D191 +:102F900026B1002140F29B50AFF30080EFF782FD95 +:102FA00083462B4601AA5146FFF7EAFE5FEA060870 +:102FB00004D0002140F2A250AFF300803B462A46E5 +:102FC00001A95846CDF80090FFF748FE064604EBED +:102FD000850090F828B0B8F1000F04D0002140F22D +:102FE000A950AFF3008000F089FB0090B8F1000F0A +:102FF00004D0002140F2AF50AFF3008094F82300DA +:10300000002899D1B8F1000F04D0002140F2B75048 +:10301000AFF3008014490DF1040C01EB09109CE89A +:103020000E0000F1040080E80E002EB35FEA0806EF +:1030300004D0002140F2C450AFF300803BEA070007 +:1030400020D094F82E0020281CD126B1002140F277 +:10305000C950AFF300802846FFF7C6FB90B90CE0DB +:10306000AC090020FFFF3F00AC070020B82202009F +:103070008A0000200000000010E09AF80000D8B399 +:10308000012849D0B8F1000F04D0002140F2E650E9 +:10309000AFF30080284600F02AFB01265FEA08050E +:1030A00004D0002140F2EF50AFF30080009800F010 +:1030B00030FB25B1002140F2F350AFF300808EB118 +:1030C00094F82D0004EB800090F82600202809D009 +:1030D00025B1002140F2FA50AFF30080F948407862 +:1030E000F8F708FE25B1002140F2FF50AFF3008051 +:1030F00004B03046BDE8F09FFFE7B8F1000F04D000 +:10310000002140F2D150AFF3008094F82D204946C1 +:103110000420FFF751F9C0E7002E3FF40DAF002166 +:1031200040F2DC50AFF3008006E72DE9F84FE64DA2 +:10313000814695F82D004FF00008E44C4FF0010B4C +:10314000474624B1002140F20D60AFF3008058469D +:1031500000F0DFFA85F8237024B1002140F21260FC +:10316000AFF3008095F82D00FFF742FD064695F875 +:10317000230028B1002CE4D000214FF4C3604BE0C1 +:1031800024B1002140F21C60AFF30080CE488038AB +:1031900000EB861111F81900032856D1334605EBD0 +:1031A000830A4A469AF82500904201D1012000E0A6 +:1031B000002000900AF125000021FFF760FC014685 +:1031C0000098014203D001228AF82820AF77E1B3AA +:1031D00024B1002140F22160AFF30080324649461D +:1031E0000120FFF7E9F89AF828A024B1002140F265 +:1031F0002C60AFF3008000F081FA834624B10021F7 +:1032000040F23160AFF3008095F8230038B1002C14 +:1032100097D0002140F23560AFF3008091E7BAF11A +:10322000000F07D095F82E00202803D13046FFF775 +:10323000DBFAE0B124B1002140F24960AFF3008035 +:10324000304600F054FA4FF0010824B1002140F25A +:103250005260AFF30080584600F05BFA24B10021C1 +:1032600040F25660AFF300804046BDE8F88F002C76 +:10327000F1D0002140F24460AFF30080E6E7002087 +:10328000EFF74ABB0120EFF747BB8E480078704745 +:103290002DE9F0418C4C94F82E0020281FD194F891 +:1032A0002D6004EB860797F82550202D00D1FFDF15 +:1032B0008549803901EB861000EB4500407807F81E +:1032C000250F0120F87084F82300294684F82E5039 +:1032D000324602202234FFF76FF8002020700CE401 +:1032E0002DE9F0417A4E784C012538B1012821D0E2 +:1032F000022879D003287DD0FFDFF0E700F02AFA1A +:10330000FFF7C6FF207E00B1FFDF84F821500020C8 +:10331000EFF729FBA168481C04D0012300221846BE +:10332000EFF774FB14F82E0F217806EB01110A68F1 +:10333000012154E0FFF7ACFF0120EFF714FB94F8F4 +:10334000210050B1A068401C07D014F82E0F21783E +:1033500006EB01110A68062141E0207EDFF8648156 +:10336000002708F10208012803D002281ED0FFDF41 +:10337000B5E7A777EFF7E7FB98F80000032801D13E +:1033800065772577607D534951F8200094F8201027 +:1033900051B948B161680123091A00221846EFF7B4 +:1033A00035FB022020769AE7277698E784F82050AC +:1033B00000F0D0F9A07F50B198F8010061680123B6 +:1033C000091A00221846EFF721FB257600E0277640 +:1033D00014F82E0F217806EB01110A680021BDE8D0 +:1033E000F041104700E005E036480078BDE8F041C4 +:1033F000F8F780BCFFF74CFF14F82E0F217806EB8E +:1034000001110A680521EAE710B52F4C94F82E0047 +:10341000202800D1FFDF14F82E0F21782C4A02EB70 +:1034200001110A68BDE81040042110477CB5264C04 +:10343000054694F82E00202800D1FFDFA068401C2C +:1034400000D0FFDF94F82E00214901AA01EB001003 +:10345000694690F90C002844EFF7A4FB9DF904009D +:103460000F2801DD012000E0002000990844616878 +:10347000084420F07F41A16094F82100002807D083 +:1034800002B00123BDE8704000221846EFF7BEBA33 +:103490007CBD30B5104A0B1A541CB3EB940F1FD3EC +:1034A000451AB5EB940F1BD3934203D9101A431856 +:1034B0005B1C15E0954211D9511A0844401C434247 +:1034C0000EE00000880000202C0A00200000000010 +:1034D000AC070020B8220200FF7F841EFFDF00231C +:1034E000184630BD0123002201460220EFF78EBAB4 +:1034F0000220EFF738BAEFF7D5BA2DE9FC47B14C07 +:10350000054694F82E00202800D1FFDF642D58D303 +:10351000AD4A0021521B71EB010052D394F82E20CA +:10352000A0462046DFF8A49290F82D7009EB021413 +:10353000D8F8000001AA28446946EFF733FB9DF94B +:103540000400002802DD0098401C0090A06800994B +:1035500062684618B21A22F07F42B2F5800F30D26C +:1035600008EB8702444692F82520202A0AD009EB6E +:1035700002125268101A0002C21700EB1260001209 +:1035800088421EDBA068401C10D0EFF78BFAA168C0 +:10359000081A0002C11700EB11600012022810DDAA +:1035A0000120EFF7E0F94FF0FF30A06020682844D9 +:1035B000206026F07F402061012084F82300BDE8D0 +:1035C000FC870020FBE72DE9F0477E4C074694F886 +:1035D0002D00A4F1800606EB801010F8170000B94A +:1035E000FFDF94F82D50A046794C24B1002140F61D +:1035F0006500AFF3008040F6710940F67A0A06EBE9 +:10360000851600BF16F81700012818D0042810D01E +:1036100005280ED006280CD01CB100214846AFF377 +:10362000008020BF002CEDD000215046AFF3008079 +:10363000E8E72A4639460120FEF7BEFEF2E74FF0E2 +:10364000010A4FF00009454624B1002140F68100EF +:10365000AFF30080504600F05CF885F8239024B169 +:10366000002140F68600AFF3008095F82D00FFF7AB +:10367000BFFA064695F8230028B1002CE4D00021BB +:1036800040F68C001FE024B100214FF40960AFF335 +:10369000008005EB860000F1270133463A462630CC +:1036A000FFF7EDF924B1002140F69400AFF300805C +:1036B00000F024F8824695F8230038B1002CC3D0DE +:1036C000002140F69A00AFF30080BDE785F82D6039 +:1036D000012085F82300504600F01BF8002C04D090 +:1036E000002140F6A700AFF30080BDE8F087354920 +:1036F00081F82D00012081F82300704710B535486E +:1037000008B1AFF30080EFF3108000F0010072B653 +:1037100010BD10B5002804D12F4808B1AFF30080C8 +:1037200062B610BD2D480068C005C00D10D010381D +:1037300040B2002806DA00F00F0000F1E02090F817 +:10374000140D03E000F1E02090F8000440097047F8 +:103750000820704710B51B4C94F82400002804D1B1 +:10376000F8F7B6F8012084F8240010BD10B5154C08 +:1037700094F82400002804D0F8F7D3F8002084F847 +:10378000240010BD10B51C685B68241A181A24F0B8 +:103790007F4420F07F40A14206D8B4F5800F03D2C9 +:1037A000904201D8012010BD002010BDD0E90032A8 +:1037B000D21A21F07F43114421F07F41C0E900314A +:1037C000704700002C0A0020FF1FA107AC07002053 +:1037D00000000000000000000000000004ED00E018 +:1037E000F0B5734AD2F80032724D002401212E78D0 +:1037F00056B9714E3460704F03263F1D3E606E4FC8 +:1038000004260C373E602970C2F80042D160116076 +:10381000694C4834D16425688542FBD35160D1603E +:10382000C2F80032F0BD2DE9F041044680074FF0A8 +:1038300000054FF0010604D560480560066024F0DD +:103840000204E0044FF0FF3705D55D484660C0F83C +:10385000087324F48054600003D55A48056024F0AE +:103860008044E0050FD55248C0F80052C0F80873F4 +:1038700051490D60091D0D604F4A04210C32116041 +:10388000066124F48074A00409D54F484660C0F84E +:103890000052C0F808734D48056024F40054C4F386 +:1038A0008030C4F3C031884200D0FFDF14F4404FB1 +:1038B00014D047484660C0F8087346488660C0F890 +:1038C0000052C0F8087344490D600A1D16608660F6 +:1038D000C0F808730D60166024F4404420050AD532 +:1038E0003E4846608660C0F80873C0F848733C489C +:1038F000056024F400640DF077FB3A48044200D0E0 +:10390000FFDFBDE8F08170B5202500224FEA0203F9 +:1039100020FA02F1C90719D051B201F01F060124A3 +:10392000B4404E09B60006F1E026C6F88041C6F85C +:103930008042002906DA01F00F0101F1E02181F84F +:10394000143D03E001F1E02181F80034521CAA4249 +:10395000DED370BD70B5174C0D466060FFF763FF96 +:103960006068FFF7D0FF2846F8F7A7F80CF05EFF75 +:1039700000F0ABF80DF038FB0DF083FAF8F78CF996 +:10398000BDE870400DF000B810B50A4C6068FFF754 +:103990004AFF6068FFF7B7FF0DF026FBF8F721F943 +:1039A0000020606010BD0348406870470A207047DF +:1039B000008000408C00002004850040FC1F004077 +:1039C00000C0004004E5014000D0004004D50040A4 +:1039D00000E0004000F0004000F5004000B0004072 +:1039E00008B50040FEFF0FFD70B522490A680AB312 +:1039F0000022154601244B685B1C4B60092B00D349 +:103A00004D600E7904FA06F30E681E420FD0EFF3F4 +:103A1000108212F0010272B600D001220C689C43A1 +:103A20000C6002B962B649680160002070BD521C8A +:103A3000092AE0D3052070BD4FF0E0214FF480004B +:103A4000C1F800027047EFF3108111F0010F72B658 +:103A50004FF0010202FA00F20648036842EA03024C +:103A6000026000D162B6E7E70248002101604160D0 +:103A70007047000094000020AD4911F8410F4978CB +:103A8000884201D3401A02E0C1F141010844C0B2AA +:103A90007047A749433111F8410F4978884201D353 +:103AA000401A02E0C1F141010844C0B27047A04988 +:103AB000863111F8410F4978884201D3401A02E05B +:103AC000C1F141010844C0B270479A4910B5802045 +:103AD00081F8000496490020433101F8410F4870F5 +:103AE000934901F8410F48709149863101F8410F1F +:103AF000487091480DF00EF98F48401C0DF00AF9FE +:103B0000EFF7DAF8BDE8104000F006B94020704742 +:103B1000B2E770B50C4605460026FFF7ADFF844AB4 +:103B2000A04214D30021641EE4B20FD392F84200E5 +:103B3000105C05F8010B92F84200401CC0B282F8FC +:103B400042004128EFD182F84210ECE7012600F054 +:103B5000E3F8304670BD402070479AE770B50C46D8 +:103B600005460026FFF795FF714A4332A04214D361 +:103B70000021641EE4B20FD392F84200105C05F8F5 +:103B8000010B92F84200401CC0B282F8420041286A +:103B9000EFD182F84210ECE7012600F0BDF8304684 +:103BA00070BD402101700020704710B50446FFF73A +:103BB0007EFF2070002010BD70B50C460546FFF753 +:103BC00076FF5B4A8632A04215D30021641EE4B220 +:103BD0000FD392F84200105C05F8010B92F84200F6 +:103BE000401CC0B282F842004128EFD182F8421056 +:103BF000ECE7002401E042F2070400F08DF82046D3 +:103C000070BD70B50C460546412900D9FFDF4B4811 +:103C10000068103840B200F066F8C6B20D2000F01F +:103C200062F8C0B2864203D2FFDF01E0EFF794F8FA +:103C300021462846FFF76DFF0028F7D070BD2DE91B +:103C4000F0413D4F0025064617F10407412257F881 +:103C5000254094F8421094F8410000F053F888B3DE +:103C60006D1CEDB2032DF1D331484122433090F861 +:103C7000421090F8410000F045F8002831D02C485F +:103C8000412290F8421090F8410000F03BF80028E3 +:103C900027D027484122863090F8421090F8410002 +:103CA00000F030F800281CD0EFF72CF822480DF077 +:103CB00039F8B0F5005F00D0FFDFBDE8F0411E48E5 +:103CC0000DF046B894F84100265494F84100401C89 +:103CD000C0B284F841004128C6D1002084F84100D8 +:103CE000C2E7BDE8F081002806DA00F00F0000F11D +:103CF000E02090F8140D03E000F1E02090F80004BB +:103D000040097047401C884204D0904200D109B15C +:103D1000002070470120704710B507480DF002F8E9 +:103D2000002803D1BDE81040EEF7D7BF10BD00005A +:103D30005C0A00200DE000E09C00002004ED00E0A3 +:103D4000164908784A78401CC0B2904205D0144BFE +:103D500001221A60BFF34F8F087070472DE9F041C0 +:103D60000E4C4FF0E02600BFEFF77CF820BF40BFBD +:103D700020BF677820786070D6F80052EDF7CCFA53 +:103D8000854305D1D6F8040210B92078B842EBD0AB +:103D9000EFF763F80020BDE8F0810000AC000020E0 +:103DA000180502402DE9F041012528034FF0E021DC +:103DB0000026C1F880011E4CC4F800610C2000F000 +:103DC0002CF81C4801680268C94341F3001142F015 +:103DD00010020260C4F804532560491C00E020BFB3 +:103DE000D4F80021002AFAD019B9016821F0100195 +:103DF0000160114807686560C4F80853C4F80061A1 +:103E00000C2000F00AF83846BDE8F08110B50446F1 +:103E1000FFF7C8FF2060002010BD00F01F02012145 +:103E200091404009800000F1E020C0F88012704706 +:103E300000C0004010ED00E008C500402DE9F0474B +:103E4000FF4C0646FF21A06800EB06121170217896 +:103E5000FF2910D04FF0080909EB011109EB0617F3 +:103E60004158C05900F0F4F9002807DDA168207816 +:103E700001EB061108702670BDE8F08794F8008009 +:103E800045460DE0A06809EB05114158C05900F006 +:103E9000DFF9002806DCA068A84600EB08100578CA +:103EA000FF2DEFD1A06800EB061100EB08100D709C +:103EB0000670E1E7F0B5E24B0446002001259A6860 +:103EC0000C269B780CE000BF05EB0017D75DA742DE +:103ED00004D106EB0017D7598F4204D0401CC0B262 +:103EE0008342F1D8FF20F0BD70B5FFF704FBD44C3E +:103EF00008252278A16805EB0212895800F0A8F97C +:103F0000012808DD2178A06805EB01114058BDE8C3 +:103F10007040FFF7E7BAFFF7B8F9BDE87040F7F770 +:103F2000E9BE2DE9F041C64C2578FFF7E4FAFF2DF4 +:103F30006ED04FF00808A26808EB0516915900F002 +:103F400087F90228A06801DD80595DE000EB0511CA +:103F500009782170022101EB0511425C5AB1521E11 +:103F60004254815901F5800121F07F418151284659 +:103F7000FFF764FF34E00423012203EB051302EB97 +:103F8000051250F803C0875CBCF1000F10D0BCF5DF +:103F9000007F10D9CCF3080250F806C00CEB423C6D +:103FA0002CF07F4C40F806C0C3589A1A520A09E018 +:103FB000FF2181540AE0825902EB4C3222F07F4209 +:103FC0008251002242542846FFF738FF0C21A06896 +:103FD00001EB05114158E06850F82720384690471A +:103FE0002078FF2814D0FFF786FA2278A16808EB22 +:103FF00002124546895800F02BF9012893DD2178FB +:10400000A06805EB01114058BDE8F041FFF76ABA1E +:10401000BDE8F081F0B51D4614460E460746FF2B5D +:1040200000D3FFDFA00700D0FFDF8548FF2100227B +:10403000C0E90247C5700671017042708270104677 +:10404000012204E002EB0013401CE154C0B2A8427C +:10405000F8D3F0BD70B57A4C064665782079854274 +:1040600000D3FFDFE06840F825606078401C607096 +:10407000284670BD2DE9FF5F1D468B460746FF248D +:10408000FFF739FADFF8B891064699F80100B8420F +:1040900000D8FFDF00214FF001084FF00C0A99F81B +:1040A0000220D9F808000EE008EB0113C35CFF2BD7 +:1040B0000ED0BB4205D10AEB011350F803C0DC451A +:1040C0000CD0491CC9B28A42EED8FF2C02D00DE0B8 +:1040D0000C46F6E799F803108A4203D1FF2004B09A +:1040E000BDE8F09F1446521C89F8022008EB041129 +:1040F0000AEB0412475440F802B00421029B00224C +:10410000012B01EB04110CD040F801204FF4007892 +:1041100008234FF0020C454513D9E905C90D02D01B +:1041200002E04550F2E7414606EB413203EB04134F +:1041300022F07F42C250691A0CEB0412490A8154E2 +:104140000BE005B9012506EB453103EB041321F023 +:104150007F41C1500CEB0411425499F800502046A5 +:10416000FFF76CFE99F80000A84201D0FFF7BCFEF3 +:104170003846B4E770B50C460546FFF7BCF906466D +:1041800021462846FFF796FE0446FF281AD02C4DFC +:10419000082101EB0411A8684158304600F058F896 +:1041A00000F58050C11700EBD14040130221AA68EE +:1041B00001EB0411515C09B100EB4120002800DC47 +:1041C000012070BD002070BD2DE9F0478846814672 +:1041D000FFF770FE0746FF281BD0194D2E78A86800 +:1041E0003146344605E0BC4206D0264600EB0612B6 +:1041F0001478FF2CF7D10CE0FF2C0AD0A6420CD18A +:1042000000EB011000782870FF2804D0FFF76CFE47 +:1042100003E0002030E6FFF76BF941464846FFF720 +:10422000A9FF0123A968024603EB0413FF20C85429 +:10423000A878401EB84200D1A87001EB041001E03C +:10424000280B002001EB061100780870104613E6D9 +:10425000081A0002C11700EB11600012704700003D +:1042600070B50446A0F500002D4EB0F1786F02D273 +:104270003444A4F500042B48844201D2012500E017 +:10428000002500F043F848B125B9B44204D32648CC +:10429000006808E0012070BD002070BD002DF9D13C +:1042A000B442F9D321488442F6D2F3E710B504466C +:1042B000A0F50000B0F1786F03D219480444A4F5CA +:1042C000000400F023F84FF0804130B11648006838 +:1042D00004E08C4204D2012003E014488442F8D266 +:1042E000002080F0010010BD10B520B1FFF7DEFF07 +:1042F00008B1012010BD002010BD10B520B1FFF79E +:10430000AFFF08B1012010BD002010BD08480949C9 +:104310000068884201D101207047002070470000EA +:1043200000000020003002002000002008000020D3 +:10433000B0000020BEBAFECA0548064A0168914294 +:1043400001D100210160044901200860704700008C +:10435000B0000020BEBAFECA40E50140534800212B +:104360000170417010218170704770B50546164686 +:104370000C460220EEF73FFA4C49012008704C49E8 +:10438000F01E08604B480560001F046070BD10B54A +:104390000220EEF730FA4549012008704648002116 +:1043A000C0F80011C0F80411C0F8081143494FF4D7 +:1043B0000000086010BD3D480178C9B1404A4FF483 +:1043C000000111603C49D1F800310022002B1CBFD4 +:1043D000D1F80431002B02D0D1F8081111B142708C +:1043E000102103E001214170364909688170027093 +:1043F0000020EEF700BA2D480178002904BF40786C +:1044000070472D48D0F80011002904BF02207047E2 +:10441000D0F8001100291CBFD0F80411002905D0E4 +:10442000D0F80801002804BF012070470020704721 +:104430001E4800B50278204B4078C821491EC9B2F9 +:1044400082B1D3F800C1BCF1000F10D0D3F8000145 +:1044500000281CBFD3F8040100280BD0D3F80801B2 +:1044600050B107E0022802D0012805D002E000295F +:10447000E4D1FFDF002000BD012000BD0B48017822 +:10448000002904BF807870470B48D0F8001100293C +:104490001CBFD0F80411002902D0D0F8080108B1DF +:1044A0001020704707480068C0B27047B400002071 +:1044B00010F5004008F5004000F0004004F5014010 +:1044C00008F5014000F400404C48002101704170A3 +:1044D000704770B5064614460D460120EEF78BF97D +:1044E00047480660001D0460001D056070BD70B582 +:1044F000424A012540EA01411570424A41F080716B +:104500001160414C0026C4F80461404A4FF04071EC +:104510001160002802BFC4F80052256070BD012858 +:1045200018BFFFDFC4F8006225604FF00070384903 +:10453000086070BD3148017879B1344A4FF040715C +:1045400011603149D1F804210021002A08BF4170CF +:1045500002D0304A1268427001700020EEF74BB969 +:1045600026480178002904BF407870472648D0F8D3 +:104570000401002808BF704726480068C0B2704791 +:10458000002808BF704730B51C480078002808BFD5 +:10459000FFDF1D48D0F80411002918BF30BD0224E8 +:1045A000C0F80443DFF870C0DCF80010C1F3001558 +:1045B000DCF8001041F01001CCF80010D0F8041124 +:1045C000002904BF4FF400414FF0E02207D100BFA3 +:1045D000C2F8801220BFD0F80431002BF8D02DB9DA +:1045E000DCF8001021F01001CCF80010C0F80843EE +:1045F00030BD05490120886070470000B7000020E9 +:1046000008F5004004F5004000F0004008F50140C6 +:1046100004F5014000F4004010ED00E070B5FF4CDF +:1046200000250120657025706572A572E07284F81E +:104630002150A56204F1380065630CF06BFB002883 +:1046400018BFFFDFA577F6480DF0F6FBF5494FF0F0 +:10465000FF300860091D0860091D0D60091D086014 +:10466000091D0D60091D0860091D0860091D08600D +:10467000091D0860091D0860091D0860091D086002 +:10468000091D0860091D086070BD30B4E349026867 +:10469000DFF898C34A6142688A61007A08770A7D28 +:1046A000E14BACF1040401204AB10A7E00FA02F2A7 +:1046B0001A608D7D002D0CBF2260CCF800204A7D51 +:1046C000002A04BF30BC70474A7E90401860C97D04 +:1046D00000290CBF2060CCF8000030BC7047D549E1 +:1046E000D3480860091DD4480860704710B50446D7 +:1046F000012908BF002105D002291ABFFFDF0021D0 +:104700004FF0807141F48470CA4940F48010086011 +:10471000E0B240F44030091D40F000700860C74826 +:10472000D0F80001002818BFFFDF10BD01202DE9DF +:10473000F04102254FF0E0270026C7F88051C0491C +:104740000E600860BF490A6822F0770242F08802D2 +:1047500042F000420A60091D0A6822F47F4242F4D6 +:10476000B0520A60AD4CB84965770D60B84AB74998 +:104770001160121FB7491160B74A40F25B611160C6 +:10478000121F40F203111160111F0860B34903208A +:104790000860B3499620086094F91E000CF06AFD89 +:1047A000607F002814BF4FF4C020AE48AE490860B7 +:1047B000AF49AE480860091FAE480860C7F880528C +:1047C0009E491020C1F8040384F82D60BDE8F081F3 +:1047D000A948016821F0010141F080710160704732 +:1047E0008E4A0368C2F802308088D0801172704708 +:1047F0008A4890F821007047884A517010707047BD +:10480000F0B50546800000F1804000F580508B88AF +:10481000C0F820360B78D1F8011043EA0121C0F826 +:10482000001605F10800012707FA00F6934C002A4C +:1048300004BF2068B04304D0012A18BFFFDF2068FE +:1048400030432060206807FA05F108432060F0BD7E +:1048500010B504460CF00EFD7048847710BD6F480B +:1048600090F82E0070476D4890F830007047844AE9 +:10487000C1781160006883490002086070472528EC +:1048800008BF02210ED0262808BF1A210AD02728E7 +:1048900008BF502106D00A2894BF0422062202EB4A +:1048A0004001C9B2784A116078490860704770B415 +:1048B0005A4B93F80AC0BCF1010F21D0BCF1020F92 +:1048C0001CBF70BC70475C7D002C04BF70BC70477F +:1048D0004FF47A74BCF1010F6D4E16D0DD7D93F864 +:1048E00019C0002D18BF0125012908BF292121D099 +:1048F000022A08BF674E06F2E141B1FBF4F119E06C +:104900001C7D002CE4D170BC70479D7D93F818C0CD +:10491000002D18BF0125012947D0022A06BF5E4E8F +:104920004FF47A714FF4C861314401F5FA7100BF58 +:10493000B1FBF4F1491F0844584908605849002068 +:10494000C1F84C014FEA0C2085F0010140EA01500A +:1049500040F00311187F820002F1804202F5C0424C +:10496000C2F810154F4901EB8001987EC20002F198 +:10497000804202F5F832C2F81415DFF82CC1C2F8F3 +:1049800010C5DA7ED30003F1804303F5F833C3F892 +:1049900014153849C3F81015012101FA00F09140AF +:1049A00008434249086070BC7047022A14BF4FF4A4 +:1049B000C8614FF47A7149F6FC621144B8E72DE9F9 +:1049C000F0411E4D0746032014468846C5F80002F4 +:1049D000124E707F002814BF4FF4C0202148334985 +:1049E000086040460CF094FC20460CF071FC01205D +:1049F00017B1012F60D062E02D4B19685A06022CC6 +:104A0000D2F8202314BFC2F30622C2F3066221F4B7 +:104A1000FE4141EA02211960B0724BE0380B0020E0 +:104A20004C0B0020000E0040180500500C050050F3 +:104A3000060102001415004025000302001000408A +:104A4000FC1F00403C1700406015004044800040BF +:104A50009CF5014028110040381500401015004019 +:104A6000441500400000040408F501404080004067 +:104A7000A4F501401011004074170040401600409A +:104A8000241500401C150040081500405415004036 +:104A9000A224020004360200683602004C85004061 +:104AA00000800040006000404C81004004F501405F +:104AB00088150040286002E00221B1726860F9495F +:104AC000C864F948006822464146BDE8F041EEE678 +:104AD0002DE9F0418846F549074603201546C1F8FF +:104AE0000002F34C607F002814BF4FF4C020F1484F +:104AF000F14E306040460CF00BFC28460CF0E8FB11 +:104B000017B1012F19D021E0EC490A684806022D9F +:104B1000D0F8200314BFC0F30620C0F3066022F4CF +:104B2000FE4242EA002008600120A072606B40F45F +:104B3000801060634FF4801007E00220A072606B69 +:104B400040F4001060634FF4001030602A46414684 +:104B5000BDE8F0410020AAE62DE9FF4FD34C824684 +:104B6000002681B003208946C4F80002D04D687F3A +:104B7000002814BF4FF4C020CE48CF4F38600398B0 +:104B80000CF0C6FB04980CF0A3FBCD494FF00108D4 +:104B9000BAF1000F03D0BAF1010F32D03BE0C74B9E +:104BA00004981A684FF0805C0228DCF8200314BFD8 +:104BB000C0F30620C0F3066022F4FE4242EA002061 +:104BC00018600C6095F82D00012806D0022818BF47 +:104BD000FFDF0CD085F80A801DE0DDE9031395F8AE +:104BE0002C2048460CF0E6FBA96A4618F2E7DDE9FE +:104BF000031295F82C3048460CF097FBA96A46182A +:104C0000E8E7B048086095F82D00012818BFFFDFDD +:104C100020D00220A872AC480660AD49AB480860BD +:104C2000686B40F400206863D4F800924FF0100ADB +:104C3000C4F808A30025C4F80052A6484FF4802BFE +:104C4000C0F800B0FF208DF80000C4F81051C4F87F +:104C500010800EE0DDE9031395F82C2096200CF06F +:104C600087FBA96A4618D4E79DF80000401E8DF81E +:104C700000009DF8000018B1D4F810010028F3D00E +:104C80009DF80000002808BFFFDFC4F80051C4F8F9 +:104C90000C51C4F81051C4F80451C4F81451C4F8AC +:104CA0001851C4F828518C4800680090C4F800924C +:104CB000C7F800B0C4F804A34FF400203860794866 +:104CC000C0F84C8078480068B04228BFFFDF30460B +:104CD000DDE9031205B0BDE8F04FE8E52DE9F8473E +:104CE000724CD4F8000220F00309D4F804034FF00A +:104CF000100AC0F30018C4F808A30026C4F8006224 +:104D00006B4D687F002814BF4FF4C020694871497B +:104D10000860A87A0127012802D0022803D014E0F5 +:104D2000287D10B911E0687D78B1A87EEA7E07FA87 +:104D300000F007FA02F210430860287F800000F1BB +:104D4000804000F5C040C0F81065FF208DF80000DD +:104D5000C4F81061276104E09DF80000401E8DF842 +:104D600000009DF8000018B1D4F810010028F3D01D +:104D70009DF80000002808BFFFDFC4F81061C4F8E8 +:104D800028616E72AE72EF72C4F80092B8F1000F33 +:104D900018BFC4F804A3BDE8F88700684F4920F0A5 +:104DA0007F40086070474FF0E0200221C0F880117A +:104DB000C0F8801270474FF0E0210220C1F80001D6 +:104DC000704747490870704710B546480BF0AAFF76 +:104DD000002818BFFFDF10BD42480BF0B9BF4249A1 +:104DE0000860704730B5324C0546A06AA84228BF1B +:104DF000FFDF012020732561607F40B128442061DE +:104E00002A48D0F8001241F04001C0F800122549AC +:104E10000020C1F84401354920690860606B2649CB +:104E200040F4800060634FF48000086030BD70B5CE +:104E30001F4C0546022020730CF057FA024694F8E6 +:104E40002C1028460CF0E0FA2061617F41B1084443 +:104E500020611648D0F8001241F04001C0F800125D +:104E600010490020C1F844012169A06A08441F4983 +:104E7000086070BD17494FF4800008600C48416B12 +:104E800021F480014163002101737047054801212D +:104E90004160C1600021C0F8441114480160044819 +:104EA00081627047008000404C8500400010004047 +:104EB000380B00200000040404F501408815004070 +:104EC000ACF5014004100040488500404881004096 +:104ED000A8F5014008F50140181100403C150040BC +:104EE000B9000020700B00200415004044850040EC +:104EF000FE4940204877FE490860FE48D0F800127D +:104F000041F04001C0F800127047FA48D0F8001292 +:104F100021F04001C0F80012F549022008607047F6 +:104F2000F448D0F8001221F01001C0F8001201215D +:104F300081617047EF480021C0F81C11D0F80012C1 +:104F400041F01001C0F800127047EA4981B0D1F871 +:104F50001C21012A1EBF002001B07047E64A1268DA +:104F600002F07F02524202700020C1F81C01E348A7 +:104F700000680090012001B0704730B50C00054674 +:104F800008BFFFDF14F0010F1CBF012CFFDF002D55 +:104F90000CBF01200220D54901284872CC72D549A6 +:104FA00004BFD1F8000240F0040007D0022807BF78 +:104FB000D1F8000240F00800FFDF30BDC1F8000268 +:104FC00030BD70B5C94C0023E17A11F0020F18BF53 +:104FD00010F0040F16D111F0100F1CBF94F82F2001 +:104FE000002A02D094F8312062B111F0080F1CBFE2 +:104FF00094F82020002A05D111F0040F03D094F872 +:10500000211001B9012394F809C00122B949BCF16A +:10501000000F06D000F00200184312D0BDE8704027 +:105020005CE6607F002814BF4FF4C020B448B54B45 +:105030001860D1F8000220F00300C1F80002E2720B +:1050400070BD00252846BCF1010F0BD0BCF1020F4A +:1050500018BFFFDF16D0A06A01222844BDE87040C7 +:10506000002124E4D1F8003223F00403C1F8003217 +:105070006072E272A27201231A46002196200CF09F +:1050800054F90FE0D1F8003223F00803C1F80032E0 +:105090006072E2720220A07201231A46002196205B +:1050A0000CF066F90546D6E72DE9F84F964FD7F88C +:1050B0004C218E4C93494FF00108A07A0026CAB1CA +:1050C000012802D0022803D014E0227D12B911E099 +:1050D000627D7AB1A27EE37E08FA02F208FA03F357 +:1050E0001A430A60227F920002F1804202F5C04218 +:1050F000C2F81065626B0A606663217B29B1D7F83C +:105100004411012908BF012200D00022794DD5F8B1 +:10511000101101290CBF40210021012805BFD5F83D +:105120000C31012B002320231943012805BFD5F89A +:105130000431012B002310230B437449022804BFC0 +:10514000D1F800C0BCF1010F07D1D5F80CC1BCF1FA +:10515000010F08BF4FF0080C01D04FF0000C4CEAD3 +:105160000303022804BF0968002905D1D5F80C11F2 +:10517000012908BF042100D000211943022803D1CE +:10518000002A18BF022200D100221143022804BFC6 +:10519000D5F80401012805D1D7F84401012818BF2A +:1051A000012000D1002040EA01095948016811F0AE +:1051B000FF0F03D0D5F81411012900D0002184F885 +:1051C0002E10006810F0FF0F03D0D5F81801012849 +:1051D00000D0002084F82F004E48006884F830008A +:1051E00043480068402803D1FFF705F9012800D0A3 +:1051F000002084F83100C5F80061C5F80C61C5F8DD +:105200001061C5F80461C5F81461C5F81861C5F8E6 +:105210002861414800680090C7F844613F48006831 +:105220004D46DFF8FC900090D9F800106162607F75 +:1052300000281CBF081A60623A480068A0620CF09F +:1052400054F884F82C00A07ADFF8DCA084F82D0054 +:1052500002280CD1607850B1DAF8001009780840C3 +:10526000217831EA000008BF84F8208001D084F85A +:105270002060DFF8B88015F0010F15D098F8001005 +:105280002B4A4908606A52F8211088470121294AAF +:1052900098F80030A06A52F82320904798F8000050 +:1052A00010F0010F0BD01FE015F0200F18BF0221E6 +:1052B000EDD115F0020F18BF0021E8D1EEE7DAF8C2 +:1052C0000000062200F10901A01C0CF0E9FB40B926 +:1052D000207ADAF800100978B0EBD11F08BF01205E +:1052E00000D0002084F82100284625E0380B00205B +:1052F0006015004000100040481500401C1100409F +:105300000000040408F50140008000400014004043 +:105310004016004010140040181100404481004025 +:10532000448500404085004004150040B90000203D +:10533000D022020008230200FFF743FE15F0020FFF +:1053400005D03D4898F8001050F82100804715F02E +:105350000C0F07D0394898F8001050F82110C5F309 +:10536000C000884715F0200F05D0354898F8001088 +:1053700050F82100804798F80000022805D105F078 +:105380006E00402806D101F0DDFB98F800000428EB +:1053900028BFFFDFA07A022818BFBDE8F88F207B66 +:1053A000002808BFBDE8F88FC7F84461022815D06F +:1053B000012818BFFFDFA16A2069884298BFFFDF7C +:1053C000D4F81000C9F80000606B1E4940F480005A +:1053D00060634FF480000860BDE8F88F2169A06A1F +:1053E0000844EFE7012804BF28207047022804BFC3 +:1053F0001820704700B5FFDF282000BD012804BF3A +:1054000041F6A4707047022804BF41F2883070470B +:1054100000B5FFDF41F6A47000BD012804BF41F2D2 +:10542000D4707047022804BF41F20400704700B5F1 +:10543000FFDF41F2D47000BDD8220200E822020052 +:10544000F822020004F5014010B53F480AF0F7FBCE +:1054500000213D480AF022FC01213B480AF0F2FB02 +:105460003A49002081F822004FF6FF7088843849BD +:105470000880488010BD704734498A8C824218BF2A +:105480007047002081F822004FF6FF708884704733 +:105490002D49016070472E49088070472B498A8C3E +:1054A000A2F57F43FF3B03D000210160084670470F +:1054B00091F822202549012A1ABF0160012000200D +:1054C0007047224901F1220091F82220012A04BFED +:1054D00000207047012202701D4800888884104611 +:1054E00070471B49488070471849194B8A8C5B8864 +:1054F0009A4206D191F82220002A1EBF01600120A5 +:105500007047002070471148114A818C528891429F +:1055100009D14FF6FF71818410F8221F19B10021C3 +:10552000017001207047002070470848084A818CAC +:105530005288914205D190F8220000281CBF00201B +:1055400070470120704700009A0B0020740B002068 +:10555000BA0000207047574A012340B1012818BF04 +:105560007047137008689060888890817047537006 +:105570000868C2F802008888D08070474D4A10B190 +:10558000012807D00EE0507860B1D2F80200086020 +:10559000D08804E0107828B19068086090898880ED +:1055A0000120704700207047424910B1012803D004 +:1055B00006E0487810B903E0087808B10120704788 +:1055C0000020704730B58DB00C4605460D2104A86B +:1055D0000CF02BFBE0788DF81F0020798DF81E0071 +:1055E00060798DF81D002868009068680190A868AF +:1055F0000290E868039068460BF0B2F920789DF8B5 +:105600002F1088420CD160789DF82E10884207D167 +:10561000A0789DF82D10884202BF01200DB030BD4A +:1056200000200DB030BD30B50C4605468DB04FF0B2 +:10563000030104F1030012B1FEF790FA01E0FEF756 +:10564000E0FA60790D2120F0C00040F04000607168 +:1056500004A80CF0EAFAE0788DF81F0020798DF8A4 +:105660001E0060798DF81D00286800906868019020 +:10567000A8680290E868039068460BF071F99DF8FD +:105680002F0020709DF82E0060709DF82D00A070F6 +:105690000DB030BD10B5002904464FF0060102D010 +:1056A000FEF75CFA01E0FEF7ACFA607920F0C0008A +:1056B000607110BDBE00002070B5FA4E044696F829 +:1056C00092000025012828D096F88C00012833D0BC +:1056D00096F86A0001281CBF002070BD6570132079 +:1056E0002070202206F16C01A01C0CF005FA0120AC +:1056F000A07186F86A50B6F86E10A6F88E10EA49C6 +:1057000049684A7B86F8902086F88C000888FBF769 +:10571000AFFAFAF71FFF012070BD657019202070E5 +:10572000D6F89300C4F80200D6F89700C4F8060033 +:1057300086F89250012070BD657006202070D6F862 +:105740008E00C4F8020086F88C50E4E7D54890F843 +:105750006A10002914BFB0F86E004FF6FF70704752 +:1057600070B5D14800250570017800291CBFFFDF06 +:1057700070BDCC4C84F8625084F8635084F8645057 +:1057800084F8655084F85E5084F8605084F8565070 +:1057900084F8365084F867507F21817094F8660051 +:1057A00028B1FFF7B2FBFEF706FE84F8665084F8D6 +:1057B0006A5084F88C5084F89250BC480AF0D6F8AD +:1057C000BDE87040BA480AF0D1B8B64890F8620017 +:1057D0007047B44900B591F8580091F85710C0F3DC +:1057E0008002C0F340031A4400F001001044052970 +:1057F00010D2DFE801F00B070B030900AD4931F8C7 +:10580000100000BDAC4800BDAC4900E0AC4931F827 +:10581000100000BDFFDF002000BDA24840F2712152 +:10582000B0F85A00484370479E4890F86800002836 +:1058300018BF0120704710B59A4C207A022818BF73 +:10584000032808D1207C04F1110108F071FF082819 +:105850001CBF012010BD207A002816BF022800209E +:105860000120BDE81040FFF79FBE8E4908727047C7 +:105870008C4981F8600070472DE9F041894C82B075 +:10588000207A002816BF022800200120607204F14F +:105890000A01FFF773FE207A022816BF03280121B0 +:1058A000002184F85F10082084F85D00607A0126EA +:1058B000002504F10A02012804BF527912F0C00F3A +:1058C0000AD004F10A02012804D1507900F0C00086 +:1058D000402801D0002000E0012084F85E0029B9B2 +:1058E00094F85700012818BF042806D1207C04F141 +:1058F000110108F01DFF84F85D002560FDF7B8F880 +:1059000060604FF0000894F85D0008F02DFF074636 +:1059100094F85F00002818BF002F04D010213846EB +:1059200009F093FD68B194F8600000281CBF94F85A +:105930005E0000281DD0607A04F10A0101280ED013 +:1059400012E06672424604F10A013846FFF76BFE28 +:1059500094F85D1004F10A0008F0FEFF09E04879B0 +:1059600000F0C000402840D0294604F10A00FFF7AB +:1059700091FE04F10A014D480AF01EF8617A4B4885 +:105980000AF03FF804F10A0149480AF015F8617A73 +:1059900047480AF036F894F8570001281EBF04283B +:1059A00002B0BDE8F081002594F85D0008F0E5FE46 +:1059B000040004BF02B0BDE8F081102109F045FDEC +:1059C00000281CBF02B0BDE8F0812A466946204687 +:1059D000FFF729FE6946354809F0FCFF01213348ED +:1059E0000AF01CF802B0BDE8F08108F0EEFF424674 +:1059F00004F10A01FFF717FEBBE770B5294C417BA4 +:105A000084F85810017984F8571001290CBF00223E +:105A10000288A4F85A20827B84F868208279002AC0 +:105A200016BF022A002201222274D0F80720C4F8EF +:105A30001120B0F80B00A4F8150094F856000125C9 +:105A4000002818BF84F8635094F83600002818BF67 +:105A500084F8645005293AD2DFE801F0030C1E34C3 +:105A60000C000021114809F084FF01210F4809F0C2 +:105A7000BFFF2DE001210D4809F07BFF04F111016A +:105A80000A4809F0A7FF217C084809F0C7FF012157 +:105A9000064809F0ADFF1BE00621044809F069FF44 +:105AA00016E00000BC0B0020CC000020580C0020A9 +:105AB000800C002028230200D0891300302302002C +:105AC000202302000221FE4809F053FF00E0FFDF1F +:105AD0000421FC4809F04DFF84F86250002070BD9D +:105AE00070B5F94C0546002084F864002A4604F19C +:105AF00017000CF001F884F83650012084F8640097 +:105B000070BD10B5F04C002284F8632084F8560074 +:105B1000024604F137000BF0EFFF012084F8630028 +:105B200010BDE94981F8670070472DE9F041E74E63 +:105B300082B0307808BBE44C94F86200E8B1FFF71B +:105B400043F9002584F8615075702846FFF739F94C +:105B5000FEF7ECFDFEF7C3FDDD48FEF788FEDD48ED +:105B6000FFF71BF994F85800002610F0010F08D039 +:105B70002520FEF784FE012612E002B00C20BDE8CD +:105B8000F08110F0020F04D02620FEF778FE0226E6 +:105B900006E010F0040F03D02720FEF770FE042665 +:105BA000FEF79DFD84F85C60FFF705F900210122F6 +:105BB0000846FEF78DFF0F210520FEF71DFE94F825 +:105BC0005E00002804BF94F85F00002805D194F817 +:105BD0005700012818BF042874D1FCF749FF064676 +:105BE00031466068FDF755FCBB4990FBF1F701FBBE +:105BF000170041423046FCF746FC6060206838449C +:105C0000206008F092FD2168884274D8C4E90056EB +:105C10004FF0010894F85D0008F0A6FD064694F8E0 +:105C20005F000127002818BF002E04D01021304645 +:105C300009F00BFC68B194F8600000281CBF94F8D0 +:105C40005E0000281DD0617A04F10A0001290ED0FF +:105C500012E03A46677204F10A013046FFF7E3FCAE +:105C600094F85D1004F10A0008F076FE09E040792E +:105C700000F0C00040281DD0414604F10A00FFF7A3 +:105C800009FD04F10A018E4809F096FE617A8C48FC +:105C900009F0B7FE04F10A018A4809F08DFE617A25 +:105CA000884809F0AEFE94F85700012818BF042870 +:105CB00021D108E008F089FE3A4604F10A01FFF715 +:105CC000B2FCDEE717E0012794F85D0008F055FD0F +:105CD000060010D0102109F0B8FB60B93A466946B9 +:105CE0003046FFF7A0FC6946754809F073FE0121B4 +:105CF000734809F093FE617A04F10A00FEF770FD23 +:105D000094F8570001281EBF042894F86300002867 +:105D100008D094F8562004F13701694809F09CFE38 +:105D200084F8635094F8640040B194F8362004F18C +:105D30001701644809F0BCFE84F8645008F069FD5E +:105D4000664808F0FAFD84F86600FFF745F802B0EF +:105D50000020BDE8F0815D494860704770B55A4C3D +:105D600006002BD094F8581094F85C20002521EA06 +:105D7000020010F0010F04D02520FEF780FD012560 +:105D800015E011F0020F02D012F0020F06D011F050 +:105D9000040F0CD012F0040F05D008E02620FEF707 +:105DA0006EFD022503E02720FEF769FD0425FEF7BE +:105DB00096FC94F85C00284384F85C0094F8610039 +:105DC00040B194F85700012808BFFFDFBDE87040DC +:105DD00000F0BFBA36B1002201234FF4967110468D +:105DE000FEF7BAFE3648FEF7FAFF94F8570005288A +:105DF00009D2DFE800F0030303090300012108468C +:105E0000FFF7BBF800E0FFDF94F8580094F85C104F +:105E100030EA01014FF0010002D02C49087070BD3A +:105E200094F85710012912BF84F86100002184F80A +:105E30005C10F2E710B5FEF7C7FF2448007840B9C0 +:105E4000214890F8620020B10020FFF787FF002072 +:105E500010BDFFF71BF8FFF70DF8FEF73FFFFEF749 +:105E6000A2FFFEF7B9FF0C2010BD184901204870B1 +:105E70007047154981F86500704770B5002503F03B +:105E8000A3FA48B1114E3078012809D0022801D078 +:105E9000032842D0FFDF70BDBDE8704000F059BA62 +:105EA000094C94F85700032837D094F8660018B1CD +:105EB000FEF76DFAFFF71CF80848FEF790FF0FE0B9 +:105EC000580C0020800C0020BC0B0020CC000020CF +:105ED0001B2302001823020040420F00A80C0020E0 +:105EE0009620FEF7A4FF94F85700012818BF042855 +:105EF0000AD094F86800012814BF0328102545F043 +:105F00000E010020FFF739F894F86700012808BF58 +:105F1000FFF710F80220307070BDBDE8704001201E +:105F20001CE770B5FE4DFF4C95F86700012817D0AF +:105F300095F8660018B1FEF7E8FFFEF73CFA03F0AB +:105F400043FAB8B12078022818BFFFDF0120FFF71D +:105F500005FF207800281EBF20780128FFDF70BDD4 +:105F6000F148FEF7F2FF002804BF7F20A070FEF783 +:105F7000D7FFDDE7BDE8704000F0EBB92DE9F05F39 +:105F800007464FF00009FEF76AFCE64E824630787D +:105F9000022818BFFFDFE24D7F2495F86700012833 +:105FA00030D0E24809F004FD83464FF0FF08002F8F +:105FB00000F0E480DD4809F00EFE002800F0DE80ED +:105FC000FEF716FC002800F0D98095F86600D74F40 +:105FD00068B108F003FC8046FF2808D00146F81C91 +:105FE00008F0EBFB404608F004FC40EA0A0A584679 +:105FF0004FF0000B062880F0C180DFE800F0BFBF43 +:10600000BF0CBF69C848FEF7A0FF002808BFB470E6 +:10601000FEF786FFC5E795F85700012818BF04284A +:1060200070D0BAF1000F18D195F86800002818BF99 +:10603000022867D13878F91CC0F3801008F078FB8B +:10604000824608F0DAFC40B1504608F096FB20B1D9 +:10605000102109F0FAF9002854D095F867000128BA +:1060600004BF95F89200002805D0B148FEF7B7FEAE +:106070000320307084E0012085F89200B8F1FF0F12 +:106080000FD005F19402511E404608F07FFB002816 +:1060900008BFFFDF95F8930040F0020085F89300F9 +:1060A0000CE03878C0F3801085F89300D5F8EF0045 +:1060B000C5F89400B5F8F300A5F89800B07805F19C +:1060C0009A077F2808BFFFDFB0783870B470CCE73C +:1060D0003878297CC0F38010884209D1062205F166 +:1060E0001101F81C0BF0DCFC002808BF012000D0D7 +:1060F0000020B8F1FF0F06D0C0B995F85D0040450B +:106100001AD113E03AE0B8B13878F91CC0F3801026 +:1061100008F00EFB044608F070FC38B1204608F089 +:106120002CFB18B1102109F090F928B195F857000F +:10613000012818BF04281DD095F85700F0B9BAF10E +:10614000000F17D195F86800002818BF012815D155 +:106150003878F91CC0F3801008F0EAFA044608F019 +:106160004CFC38B1204608F008FB18B1102109F0AA +:106170006CF918B195F865002C46D8B14FF00109BB +:1061800095F8660018B1FEF7C0FEFEF714F9B9F1F4 +:10619000000F1CBF0120FFF7E1FD307800281ABF77 +:1061A00030780128BDE8F09F3078032818BFFFDF62 +:1061B000BDE8F09F7068D4F8FB10C0F80E10B4F87A +:1061C000FF10418294F801110175B97D4175B7F84E +:1061D0001710C182B7F819104180B7F81B108180E1 +:1061E000B7F81D10C180534908300BF02AFE97F80C +:1061F000240000F01F017068017697F82410490907 +:1062000080F864113A78417BC2F340121140417327 +:1062100094F86A00002818BFFFDF84F86CB0D6F845 +:1062200004A0BAF80000A4F86E00BAF80200A4F8BE +:106230008400BAF80400A4F88600BAF80600A4F8AE +:1062400088009AF8640184F88A0094F85F0048B1E5 +:10625000607A04F10A01012804D1487900F0C000F5 +:10626000402835D094F8600040B1607A04F10A010A +:10627000012804BF487910F0C00F29D0C4F878B0C5 +:10628000A4F87CB03878B8F1FF0FC0F380108AF81A +:106290001900D4F8EF00CAF81A00B4F8F310AAF8FD +:1062A0001E101CD0C4F87E00BAF81E00A4F88200AC +:1062B00004F17202511E404608F068FA002808BF37 +:1062C000FFDF94F8710040F0020084F8710015E0DF +:1062D000D4F80A00A067E089A4F87C00D2E7164849 +:1062E0000BF0A6FD9AF8190084F87100DAF81A008C +:1062F000C4F87200BAF81E00A4F87600012084F8F1 +:106300006A0070680088FAF7B3FCFAF713F986F8A8 +:1063100000B0FEF7BBFDFEF7ADFDFEF7DFFC0DE0C4 +:10632000BC0B0020CC000020CE000020A80C0020D8 +:10633000800C0020C70C00203A0C0020FEF733FD33 +:10634000FEF74AFD012003F09CF919E7012203F052 +:1063500048BA70B5FEF79AFDFEF78CFDFEF7BEFC5D +:10636000FEF721FD1F4C002694F8660028B1FEF7C9 +:10637000CCFDFEF720F884F866601B4D2E70FEF70A +:106380002BFD94F85700012804D0BDE87040002090 +:1063900003F077B9022003F074F994F86A0000283A +:1063A00018BFFFDF6878002808BF70BD207C84F824 +:1063B0007100D4F81100C4F87200B4F81500A4F804 +:1063C00076003C2084F86C0068680188A4F86E10A0 +:1063D000012184F86A100088FAF74AFCFAF7AAF853 +:1063E0006E7070BDBC0B0020CC0000202DE9F04188 +:1063F000FF4F044600207978FE4D4FF00108064615 +:1064000011B1012923D007E095F85310002918BFD6 +:1064100087F8018000D0012079782B2211FB02F14E +:10642000294491F82820104318D02A22A01C293191 +:106430000BF062FB66700420207084F8028078788C +:106440002B2110FB01F0284480F8286023E095F808 +:106450002810002918BF7E70DDD1DDE795F87E0099 +:10646000E0B1D5F87F00C4F80200D5F88300C4F885 +:106470000600D5F88700C4F80A00D5F88B00C4F8E8 +:106480000E0095F88F00A07466701220207084F8BA +:10649000028085F87E600120BDE8F08195F8220039 +:1064A00001281ED0287801281CBF0020BDE8F081FB +:1064B0006670132020702022A91CA01C0BF01CFB6E +:1064C000A6712E70A888A884D5F89C00417B85F819 +:1064D000261085F822800088FAF7CAFBFAF73AF806 +:1064E000D9E7667006202070686AC4F8020085F853 +:1064F0002260D0E7BF480178002914BF80884FF69A +:10650000FF7070472DE9F041BA4C064694F8280018 +:10651000002818BFBDE8F081304609F049FA01466D +:1065200001250020072937D2DFE801F00A040736E9 +:106530003636090084F82A5009E0032000E00220E2 +:1065400084F82A0004F13301304609F09BFA84F8FC +:10655000320094F8AF0018B1FDF74DFF01281FD0AD +:10656000304609F057FA84F82B0004F12C0130462C +:1065700009F029FA9E4E04F1520730787F2808BFAF +:10658000FFDF307838707F20307084F82850BDE805 +:10659000F041032001F005BF84F83200BDE8F0812E +:1065A000FDF76CFF04F12C02511E08F0EFF80028F3 +:1065B00008BFFFDF94F82B1041F0020184F82B1084 +:1065C000D8E710B5002001F0F6FD8A4CA8B1FEF71F +:1065D000F2FB012200211046FEF7F1F904F1BC00A4 +:1065E000FEF7FDFBD4F8B400FEF7FCFB94F8A00026 +:1065F000032818BF02281FD022E0FEF747FCFEF751 +:1066000039FCFEF76BFBFEF7CEFB94F8AF0030B120 +:10661000FEF77BFCFDF7CFFE002084F8AF000120E1 +:1066200084F8B800022084F8B200FEF7D5FBBDE87C +:106630001040002001F0B5BE01210020FEF79DFCB6 +:10664000FEF778FC94F8AF0018B1FDF7A0FEFEF756 +:106650004FFC032084F8B20010BD66490028B1F851 +:10666000BA202CD0FF2A0BD24FF6FF7000EA42006E +:10667000A1F8BA00FF2888BFFF2001D9A1F8BA000D +:106680005B484268012A12BF002A0D224260D243B1 +:10669000C2EBC20303EB021291F8B930DB4303EB08 +:1066A000830CCCEB83131A444260900CB1F8BA20EF +:1066B000B0FBF2F302FB130081F8B9007047012A26 +:1066C000DED95008A1F8BA0008BF0120D8D1D5E71B +:1066D00070B5484C002584F8B250012684F8B260A9 +:1066E00094F8B20002281BBF94F8B20001280020E1 +:1066F000FFDF18BF70BD2B2101FB004181F828503E +:10670000401CC0B20228F6D3257084F8225094F8B9 +:10671000AF0028B1FEF7F9FBFDF74DFE84F8AF504E +:1067200084F8AE5084F89B60324884F8A05084F816 +:10673000B15040F2011120F8981F817070BD2DE911 +:10674000F0412C4C05460C2794F8B20001281FBFDD +:1067500094F8B20002280C20BDE8F081FEF734FB6B +:10676000FDF7E4FFFDF7BBFF94F898000126002831 +:1067700001BF94F89900002894F89A00002874D07A +:1067800094F8A000032802D0022805D008E00521D3 +:10679000194800F0DEFE03E00321174800F0D9FE9F +:1067A00094F8AC00002804BF94F8AD00002847D04E +:1067B000FCF75EF907463946D4F8A800FCF769FEF5 +:1067C0000E4990FBF1F801FB180041423846FBF7F7 +:1067D0005AFEC4F8A800D4F8A4004044C4F8A400A9 +:1067E00007F0A3FFD4F8A410884229D8002007E0BE +:1067F000D4000020D00C0020B40D002040420F0037 +:10680000C4E9290794F8AD0000281CBF012008F056 +:10681000AFF8012194F8AE0000281CBF94F8AC003A +:1068200000280DD094F8910004F19202012804D1BF +:10683000507900F0C00040280ED01046FEF72AFF25 +:1068400094F8911004F19200FDF7CAFF94F8B20099 +:106850000027012818D112E008F0B7F8324604F1F9 +:106860009201FEF7E0FEEBE7FFE794F8B2000228A2 +:1068700004BF84F8B2600C2006D1BDE8F08184F832 +:10688000B860022084F8B20094F89B0080B108F050 +:1068900018F8FE4808F051F884F8AF00FC48C4F836 +:1068A000B450FEF77AFAFEF797FA3846BDE8F08161 +:1068B00007F0AFFFEDE770B5FEF786FAF54C94F8F8 +:1068C000B200022803D0FEF787FA0C2070BD012029 +:1068D00084F8B900A4F8BA000220FEF772FAEE4874 +:1068E000FDF7C5FFED4B002004F1980294F8B110BC +:1068F000491CA3FB015C4FEA5C0CACEB8C0C6144C3 +:10690000C9B284F8B110895C012907D0401CC0B21B +:106910000328EBD3FFF755FE002070BD94F8B100BB +:10692000DF49085CFDF7ABFFFDF7D9FEF2E710B5D4 +:10693000D84C94F89030022B14BF032B00280BD1B5 +:1069400000291ABF022901200020114607F0F0FE9D +:1069500008281CBF012010BD94F89000002816BF25 +:10696000022800200120BDE81040FEF71DBEC948E6 +:1069700090F89000002816BF022800200120FEF7A2 +:1069800013BEC44981F890007047C24981F8AE0037 +:10699000704770B5BF4C94F89000002816BF0228CD +:1069A0000020012084F8910004F19201FEF7E6FD39 +:1069B00094F89000022816BF03280121002184F8D2 +:1069C000AD1094F89100002504F19202012804BF53 +:1069D000527912F0C00F0AD004F19202012804D1BA +:1069E000507900F0C000402801D0002000E00120D4 +:1069F00084F8AC00002804BF002970BDC4F8A4507E +:106A0000FCF736F8C4F8A80094F8AD0000281CBFC5 +:106A1000002007F0ADFF002694F8AE0000281ABF52 +:106A200094F8AC00002870BD94F8910004F1920134 +:106A3000012804D1487900F0C000402806D029463A +:106A400004F19200BDE87040FEF724BE07F0BDFFE0 +:106A5000324604F19201BDE87040FEF7E4BD002823 +:106A600016BF0228012200228A4981F89B2081F862 +:106A7000A100704770B5874D0C4600280CBF01215E +:106A8000002185F89B1085F8A2004FF0080085F8DA +:106A9000A3000BD1002C1ABF022C012000201146AC +:106AA00007F046FE85F8A300082801D0002070BD3D +:106AB000022C14BF032C1220F8D170BD754A032894 +:106AC00008BFC2F89C1082F8A000002070477149EE +:106AD00091F8A000032804D0012818BF022807D08D +:106AE00004E091F8A200012808BF70470020704719 +:106AF00091F8A100012814BF03280120F6D17047A6 +:106B000010B5FEF7C3F9FEF7B5F9FEF7E7F8FEF7A3 +:106B10004AF9604C94F8AF0030B1FEF7F6F9FDF792 +:106B20004AFC002084F8AF00012084F8B80002205D +:106B300084F8B200FEF750F9002010BD554981F8E5 +:106B4000B300704710B5FEF7A1F9FEF793F9FEF711 +:106B5000C5F8FEF728F94F4C94F8AF0030B1FEF7B6 +:106B6000D4F9FDF728FC002084F8AF00012084F858 +:106B7000B800022084F8B200FEF72EF9BDE81040FC +:106B8000002001F00EBC2DE9F84F424CFF217F2779 +:106B9000444E84F8B0104FF00008002800F0DC826A +:106BA00004F1BC0008F0E7FF30B904F1BC0009F0C3 +:106BB00002F8002800F0D08294F8B200334D052886 +:106BC00080F0C782DFE800F0F1F1F103F0002F4818 +:106BD00008F0EEFEB07094F89B0030B9FDF73FFE70 +:106BE000002808BF4FF0000801D04FF0010894F8CA +:106BF000AF0078B107F0F2FD84F8B0000146FF283D +:106C00000CD0E81C07F0D9FD94F8B00007F0F1FDB6 +:106C100040EA080894F8B000FF2812D107F081FE7E +:106C200084F8B00094F89B1059B1082809D128784D +:106C3000E91CC0F3801007F07BFD082818BF4FF057 +:106C40000008B078072880F0C781DFE800F04BB873 +:106C500004FCFCFC300094F8AF0018B1FEF755F9C5 +:106C6000FDF7A9FB0F48FEF770F9002808BF377041 +:106C7000FEF756F9B8F1000F00F0598194F8A00022 +:106C8000012818BF022840F052810DE08C0D002031 +:106C900038230200D00C00203E230200ABAAAAAA8F +:106CA0003B230200D4000020FEF718F868E094F8B7 +:106CB000AF0018B1FEF729F9FDF77DFBFE48FEF79E +:106CC00044F9002808BF3770FEF72AF9B8F1000F21 +:106CD00000F02D8194F8A00002284AD001284FD05E +:106CE00000F025B994F8AF0018B1FEF70EF9FDF7E2 +:106CF00062FBF148FEF729F9002808BF3770FEF75C +:106D00000FF9B8F1000F00F0128194F8A0000228EA +:106D10002FD0012834D003281CBFFFDFBDE8F88F37 +:106D2000E978D4F89C00827E91421BD12979C27EF9 +:106D3000914217D16979027F914213D1A979427F9B +:106D400091420FD1E979827F91420BD1297AC27F9A +:106D5000914207D12978427EC1F38011914208BF48 +:106D6000012100D0002194F8A220012A0ED0E9B11F +:106D7000D9E0D248FFF7C6FBBDE8F84F00F002BBF0 +:106D8000CE48FFF7BFFBBDE8F84F1AE4002974D1E5 +:106D900000F11A01C94808F016FEC84808F03AFE8A +:106DA000D4F89C104876BEE024E1D2E194F8A30028 +:106DB00008287DD094F8B01081425ED0B7E094F8F6 +:106DC000AF0018B1FEF7A1F8FDF7F5FABA48FEF7E3 +:106DD000BCF8002808BF3770FEF7A2F894F8AD00A1 +:106DE00000280CBF4FF0010B4FF0000B4FF00009D3 +:106DF0002878C10905F1090007D0407900F0C000EA +:106E0000402808BF4FF0010A01D04FF0000A94F863 +:106E1000A000032806D194F89B00002818BF94F81E +:106E2000A30001D194F8B00007F09EFC009088B157 +:106E3000102108F00AFB002818BF4FF0010BBAF12F +:106E4000000F07D000E0C7E005F109010098FEF748 +:106E5000B9FB814694F8A00003280FD0FDF73EFF50 +:106E6000B8F1000F69D0FDF7C3FC50EA090064D007 +:106E70009248FFF747FB00F041B954E0D4F89C007A +:106E8000E978827E91421DD12979C27E914219D141 +:106E90006979027F914215D1A979427F914211D13E +:106EA000E979827F91420DD1297AC27F914200E037 +:106EB0003DE007D12978407EC1F38011814208BFAF +:106EC000012500D0002594F8B000082805D094F8DA +:106ED000A310884208BF012600D00026B9F1000F98 +:106EE00005D1BBF1000F04D0FDF782FC08B10121F0 +:106EF00000E00021B8F1000F09D094F8A2000128A9 +:106F000003D020B955EA060001D0012000E000209E +:106F100001420CD094F8A200012804BF002DD4F83F +:106F20009C003FF435AFBDE8F84F00F08ABAFDF79A +:106F3000D5FEBDE8F84FFFF744BB94F8A100032845 +:106F400018BF02287ED1BAF1000F7BD0B9F1000F33 +:106F500078D1DFF8688194F87E00002872D101258D +:106F600084F8805094F8AF0018B1FDF744FA012876 +:106F700021D0404608F04EFD84F8810004F18201E2 +:106F8000404608F020FD404608F051FD84F8880096 +:106F900004F18901404608F024FD307804F18F089F +:106FA0007F2808BFFFDF307888F80000377084F84A +:106FB0007E500320A0E0FDF761FA04F18202511E29 +:106FC00007F0E4FB002808BFFFDF94F8810040F0E1 +:106FD000020084F88100D6E794F8AF0018B1FDF7FD +:106FE00094FFFDF7E8F93448FDF7AFFF00286CD1B6 +:106FF0003770CAE0314808F0DBFCB0703048E978FF +:10700000427A91421CD12979827A914218D16979C8 +:10701000C27A914214D1A979027B914210D1E979C7 +:10702000427B91420CD1297A827B914208D1297806 +:107030000078C1F38011B1EBD01F08BF012500D04B +:10704000002500E042E0FDF749FEB07804286BD14E +:10705000D5B31948FDF779FF002808BF3770FDF751 +:107060005FFF94F8B80000281CBF0020FFF7F5FA76 +:107070004FF0010884F8B880104D94F8530028BBF5 +:10708000042084F8550094F8AF00A5F1910918B1D7 +:10709000FDF7B1F9012835D0284608F0BBFC0949B5 +:1070A00081F8560009F12C01284608F08CFC00BF3D +:1070B00004F15E0128460AE0D40000208C0D002077 +:1070C000B40D0020D00C00202EE05EE016E008F0A9 +:1070D00005FD84F85D001F2884BF1F2084F85D0033 +:1070E00004F17D0530787F2808BFFFDF30782870F5 +:1070F000377084F85380042001F053F9BDE8F84F4D +:10710000FFF75FBAFDF7BAF909F12C02511E07F03B +:107110003DFB002808BFFFDFFE4890F8560040F016 +:10712000020089F82B00C3E7FB48FDF70EFF00289B +:1071300008BF3770FDF7F4FE94F8B800002804BFCC +:107140000120FFF78AFA84F8B880BDE8F84FFFF70E +:1071500038BAFFDFBDE8F88F94F8B200052828BFE1 +:10716000BDE8F88FDFE800F0030303041900F1E73E +:1071700094F8AF0018B1FDF7C8FEFDF71CF9E6481A +:10718000FDF7E3FE00283FF433AFFDF7C9FEFDF73E +:10719000A5FDBDE8F84FFFF714BADF48FDF7D5FEAF +:1071A000002808BF3770FDF7BBFE94F8B800002830 +:1071B00004BF0120FFF751FA84F8B880FDF78EFD77 +:1071C000BDE8F84FFFF7FDB970B5D24C94F8B200A6 +:1071D000072878D2DFE800F08D8D8D8D8D041000AA +:1071E000CE48FDF7FCFDFDF7A5FE9620FDF71FFE3E +:1071F000042084F8B20070BDFDF748FEFDF73AFEAA +:10720000FDF76CFDFDF7CFFD012584F8B850022095 +:1072100084F8B200FDF7E0FD2078002818BFFFDFFA +:107220000026A670D4F89C000188A1804188618363 +:107230008188A183C088E08384F8206094F8AD1031 +:10724000B74849B10178C21CC1F3801121B151790D +:1072500001F0C00140292ED094F8AE1041B110F8D1 +:10726000031BC1F3801119B1407910F0C00F22D077 +:10727000AC480AF0DDFD00BF94F8AF0018B1FDF78F +:10728000BAF8012820D0D4F89C00417EE171D0F8F2 +:107290001A10A160C08BA081666126832570D4F886 +:1072A0009C000088F9F7E4FCF9F744F9BDE8704068 +:1072B000022001F076B8D4F8E700C4F80E00B4F864 +:1072C000EB006082D8E714E0FDF7D8F804F108027B +:1072D000E11D07F05BFA002808BFFFDFE07940F00E +:1072E0000200E071D4F8BF006061B4F8C3002083ED +:1072F000D4E7FFDF70BD70B5864C94F8B20000256E +:10730000052828BF70BDDFE800F03939391B0300BC +:107310008148FDF71AFE10B97F497F200870FDF7FC +:10732000FFFD94F8B800002804BF0120FFF795F98D +:1073300084F8B850FDF7D2FCBDE87040FFF741B9C2 +:10734000FDF7A4FDFDF796FDFDF7C8FCFDF72BFD4D +:1073500094F8AF0028B1FDF7D8FDFDF72CF884F8BC +:10736000AF50012084F8B800022084F8B200FDF785 +:1073700033FDBDE87040002001F013B870BD01225C +:1073800001F0E1B870B5012000F015FF614CC8B103 +:1073900004F1E401A1F1280008F04CFB04F1E4063B +:1073A00094F89110304608F02CFB04F1920130461D +:1073B00008F002FB94F8AD00C0B394F8A0000328D5 +:1073C0001FD025E0FDF762FDFDF754FDFDF786FCBB +:1073D000FDF7E9FC94F8AF0030B1FDF796FDFCF73E +:1073E000EAFF002084F8AF00012084F8B8000220F2 +:1073F00084F8B200FDF7F0FCBDE87040002000F01A +:10740000D0BF94F89B00002818BF94F8A30001D1C6 +:1074100094F8B00007F0DBFA050007D001213046F0 +:1074200008F0EFFA2946304608F0C6FA3C48FDF766 +:10743000D6FC01210846FDF7A0FD052084F8B20026 +:1074400070BD70B5022000F0B6FE324C68B301206A +:1074500000F0A7FF04F1E401A1F1280008F0EAFA26 +:10746000D4F89C00417B04F1E40008F0C1FAD4F8A0 +:107470009C0004F1BC0204F1E4061278417BC2F3E3 +:1074800040121140417394F89110304608F0B9FA57 +:1074900004F19201304608F08FFA94F8AD00B8B3C9 +:1074A00094F8A00003281FD025E0FDF7EFFCFDF7BE +:1074B000E1FCFDF713FCFDF776FC94F8AF0030B16A +:1074C000FDF723FDFCF777FF002084F8AF000120D3 +:1074D00084F8B800022084F8B200FDF77DFCBDE816 +:1074E0007040002000F05DBF94F89B00002818BF9A +:1074F00094F8A30001D194F8B00007F068FA0500F1 +:1075000014D00121304608F07CFA294630460BE0C1 +:107510000CE00000D00C0020D40000208C0D0020D6 +:10752000B40D0020DE0C002008F046FAD4F89C00D0 +:10753000C18A324808F0FEFAD4F89C00417D2F48F9 +:1075400008F0FCFA2D48FDF74AFC062084F8B2004A +:1075500070BD70B50C46054608F008FA032C47D0FC +:10756000052C18BF70BD0521284608F002FA244CEE +:10757000D4F89C0000F10E01284608F0C5FAD4F8B2 +:107580009C0000F11201284608F0C2FAD4F89C00D1 +:10759000417D284608F0D2FAD4F89C00C18A2846DA +:1075A00008F0C8FAD4F89C004188284608F0B6FADA +:1075B000D4F89C008188284608F0B4FAD4F89C00DE +:1075C000C188284608F0B2FAD4F89C0000F10801FE +:1075D000284608F0CDFAD4F89C00017E284608F031 +:1075E000AFFA94F8B3102846BDE8704008F0B2BA7C +:1075F0002846BDE87040032108F0BBB9B40D002057 +:10760000D00C00202DE9FF4F06460C46488881B07B +:1076100040F2E24148430090E08A002500FB01FB74 +:1076200094F8630091460D2818BF0C281ED0252819 +:107630001EBF94F8640025284FF0000A16D0049865 +:1076400018B10121204603F029FB94F8510094F869 +:10765000528094F8C810074659B1012958D0022920 +:107660003DD0032918BFFFDF52D0A6E04FF0010A3A +:10767000E5E7B9F1000F08BFFFDFFE4D686800289D +:1076800008BFFFDF94F85100FDF7C7FE00F2E731B5 +:107690004FF47A70B1FBF0F0696800EB010994F8DF +:1076A0005100FDF7BAFE94F85110022907BFF249C4 +:1076B0004FF47A72F1494FF4C8621144084400F261 +:1076C000E7314FF47A70B1FBF0F040F2E241081A72 +:1076D0002969584449440844051D012015E0E5483E +:1076E000A9F101014068084308BFFFDFE448B9F190 +:1076F000000F006800EB0B0506D0DE48406800F282 +:107700002230A84288BFFFDF032084F8C80053E07E +:1077100094F86310009D25291CBF94F86410252956 +:1077200036D1B4F85810B4F8EA20891A491C09B2C5 +:1077300000292DDB94F8E81009B30F4694F8E910FE +:10774000002918BF8846022807BFCB484FF47A713A +:10775000CA484FF4C8610144022F07BFC6484FF41E +:107760007A72C6484FF4C8621044814208D9081A98 +:1077700000F5FA714FF47A70B1FBF0F0054407E0C0 +:10778000401A00F5FA714FF47A70B1FBF0F02D1A3F +:10779000B9F1000F10D0DFF8DC92D9F8040020B95D +:1077A000B9F80200002818BFFFDFD9F8040000F282 +:1077B0002230A84288BFFFDF05B9FFDF2946D4F891 +:1077C000CC00FAF760FEC4F8CC00B0600020307046 +:1077D0004FF0010986F80490204603F04CFBAAF113 +:1077E0000101084208BF86F8059006D094F8C80049 +:1077F00001280CBF0220032070714046D4F824B049 +:10780000FDF7FCFD0146022F07BF9B484FF47A723B +:107810009A484FF4C8621044084400F23F614FF4A4 +:107820007A70B1FBF0F0584400F5C970F06004982C +:1078300030EA0A0004BF05B0BDE8F08F29463046A3 +:1078400007F010FF87B2204603F015FBB8420FD8AF +:10785000074686F8059005FB07F1D4F8CC00FAF747 +:1078600012FEB0602946304607F0FCFE384487B26D +:107870003946204603F012FAB068C4F8CC0005B0CF +:10788000BDE8F08F2DE9F04304467E4885B00D46F3 +:1078900090F80004DFF8F091400999F800144909C4 +:1078A000884218BFFFDFDFF8CC81002708F13C06D3 +:1078B000082D80F0FA80DFE805F0045B656560F86C +:1078C000F894202C28BFFFDF36F814000621F9F7C2 +:1078D000C5F8050008BFFFDF202C28BFFFDF36F802 +:1078E00014002988884218BFFFDF95F8C8000028D7 +:1078F00008BFFFDF284602F0BCFEC8F80470A8F8F5 +:10790000027029460020C8F8107007F0EFFE00F161 +:107910009804686AA04218D995F85200FDF76EFDE8 +:1079200095F85110022907BF53494FF47A72534911 +:107930004FF4C862114408444FF47A7100F23F607A +:10794000B0FBF1F1686A0844071B29460020C8F81B +:10795000087007F0CBFE698840F2E242514398304C +:10796000081AA0F22230C8F80C0005B0BDE8F08378 +:1079700005B0BDE8F04303F05DB805B0BDE8F043E5 +:10798000FDF792BB99F8140D4049400991F8001495 +:107990004909884218BFFFDF202C28BFFFDF36F8D7 +:1079A00014000621F9F75AF8050008BFFFDF202C64 +:1079B00028BFFFDF36F814002988884218BFFFDF90 +:1079C0000022012329466846FFF71CFE95F8D200E5 +:1079D0006946FBF797FA002808BFFFDF05B0BDE84E +:1079E000F083202C28BFFFDF36F814000621F9F7BA +:1079F00035F8050008BFFFDF202C28BFFFDF36F871 +:107A000014002988884218BFFFDF95F8C8000428B1 +:107A100018BFFFDF85F8C87095F8D2404FF6FF79A0 +:107A2000202C28BFFFDF26F8149095F8D200FBF732 +:107A300000F8002808BFFFDF202085F8D200D5F825 +:107A4000D800002804BFD5F8D400C8F8140008D026 +:107A5000D5E937121144826911448161D5E93501B4 +:107A6000C860D5F8D40000281CBFD5F8D810016133 +:107A700014D10EE0DC0D002068360200A2240200C2 +:107A8000E000002001E000E00BE000E019E000E091 +:107A90000BE0D5F8D800002818BF8761FC480078B3 +:107AA00005B0BDE8F043F4F725B9FFDF05B0BDE848 +:107AB000F0832DE9F047F74D0746E88B6C68401CD2 +:107AC000E88328784FF00008002808BFFFDF07D0C0 +:107AD000DFF8C4A3042814D0052818BFFFDF40D066 +:107AE00021462869FAF7CFFCB86087F800800120AA +:107AF0003871A86800F5B370F860287804287CD144 +:107B000085E00029ECD02E69DAF8141039B38946E3 +:107B1000C9680029FBD1B9F1000F20D099F8000005 +:107B2000002808BFFFDFD9F81410D9F80400014479 +:107B30003046FBF7AEFC002807DA211A4A1E92FBFA +:107B4000F4F202FB0406214604E090FBF4F202FB8F +:107B5000140621468E4288BFFFDF3446C0E7444604 +:107B6000BEE70029BCD0D5F81890B9F1000F08BFC6 +:107B7000FFDF0026D9F8DC10DAF814403046721E18 +:107B80005CB1A069884228BF824284BF0246264673 +:107B90002046E468002CF4D106B9064609F1C80471 +:107BA000C9F8D860002E04BFC4F80C80CAF814408D +:107BB00005D0F068F460E060002818BF0461D4F8D4 +:107BC0001090C4F81880B9F1000F0ED0D9F8180041 +:107BD00048B1D4F814A0504538BFFFDFD9F81800D9 +:107BE000A0EB0A00A061C9F81880002E08BFC5F8F4 +:107BF000208009D03078002800E00DE008BFFFDFCA +:107C0000716970680844286240F6B83468E7E88B08 +:107C10000A2838BF032000D302207871E88B01289E +:107C200006D93846696807F01DFDE98B0844E883EA +:107C3000B8682861BDE8F0872DE9F0418046974893 +:107C400084B00E4690F80004954F410997F800045F +:107C50004009814218BFFFDF01210025082E8D4C0D +:107C600062D2DFE806F0041A35353061614D617388 +:107C70002173607800281CBF04B0BDE8F0818648FD +:107C8000456005612573A068C138FEF758FD0028DE +:107C900018BFFFDF04B0BDE8F081607850B1207BF1 +:107CA000002808BFFEF72CFF657304B0BDE8F04163 +:107CB000FAF7E9BDA173FEF7FEFD002818BFFFDF4C +:107CC00004B0BDE8F08104B0BDE8F041FDF7ECB9C7 +:107CD00097F8140D7349400991F800144909884236 +:107CE00018BFFFDF00216846FFF7E3FE6946404604 +:107CF000FBF708F9002808BFFFDF04B0BDE8F081FA +:107D00002078052818BFFFDF207F002808BFFFDF8D +:107D100025772570207DFAF78CFE002808BFFFDF4D +:107D2000257504B0BDE8F081FFDF04B0BDE8F08147 +:107D30002DE9F041574C0026207804281FBF2078F9 +:107D400005280C20BDE8F08101206070607B0025D3 +:107D5000A8B1EFF3108010F0010F72B60CBF00272E +:107D60000127607B00281CBFA07B002805D0FEF700 +:107D7000C7FE6573A573FAF786FD2FB903E0207D72 +:107D8000FBF7D3F900E062B6207DFBF71CFC207FF7 +:107D900028B125772078052818BFFFDF0C266570ED +:107DA0002570207DFAF745FE002808BFFFDF257506 +:107DB0003046BDE8F0812DE9F04F364883B00078B9 +:107DC000002818BFFFF7B4FF0120DFF8CC8088F847 +:107DD000000069460620F8F7CCFD002818BFFFDF39 +:107DE00000274FF6FF7934E0029800281CBF90F876 +:107DF000C81000292DD0008848451CBFDFF8A8A076 +:107E00004FF0200B3BD00621F8F728FE040008BFF6 +:107E1000FFDF94F8D200FBF7D6FB84F8C87094F823 +:107E2000D2504FF6FF76202D28BFFFDF2AF81560CD +:107E300094F8D200FAF7FDFD002808BFFFDF84F8B0 +:107E4000D2B069460620F8F794FD002818BFFFDF7E +:107E500010E06846F8F76BFD0028C5D00FE00298E7 +:107E600000281CBF90F8C810002903D0008848459E +:107E7000C9D104E06846F8F75AFD0028EFD088F829 +:107E80000070C8F8147003B00020BDE8F08F000047 +:107E9000DC000020F40D0020DC0D002001E000E0FB +:107EA0000BE000E019E000E0180E002010B50078AB +:107EB000F84C60B101280CBF40F6C410FFDF06D0BB +:107EC000A06841F66A01884228BFFFDF10BDA060AC +:107ED000F6E710B5EF4C00232070EF4803704370B5 +:107EE000037703734373837320218361017518380B +:107EF00043703A3010214FF6FF72428020F8042F71 +:107F0000491EFAD1180008BFA36005D0002B0EBF90 +:107F1000FFDF40F6C410A060A06841F66A01884205 +:107F200028BFFFDFBDE8104045E72DE9F043DA4CFC +:107F3000054685B0207816460F4600281EBF0C2047 +:107F400005B0BDE8F08395F8519095F85200D5F84A +:107F50002480FDF753FAB9F1020F07BFCF494FF460 +:107F60007A72CF494FF4C862114408444FF47A79C9 +:107F700000F23F60B0FBF9F0404400F22230C5F857 +:107F8000DC00A56195F8C800002818BFFFDF40F2AB +:107F90007120784360600120FDF730FA00F2E7308D +:107FA000B0FBF9F040F2712106FB0100A0606168AE +:107FB000A1F2F621884298BF01460020A160B9498C +:107FC00008610521217060702077E083B648FAF7D8 +:107FD000D5FC2075202808BFFFDFFAF749FD206196 +:107FE00001216846FFF765FD207D6946FAF78AFFA3 +:107FF000002808BFFFDF002005B0BDE8F083A648D9 +:10800000007800281CBF0020704710B50620F8F744 +:10801000C1FC80F0010010BD30B59F4C85B02278C6 +:10802000002A1EBF0C2005B030BD0D4640F2712164 +:10803000484360600120FDF7E1F94FF47A7100F2E6 +:10804000E730B0FBF1F040F2712105FB0100A060C8 +:108050006168A1F2F621884298BF01460020A16024 +:10806000607004212170E0838F48FAF787FC207547 +:10807000202808BFFFDF8B48406938B10146C0683F +:108080000028FBD111B1FAF7F3FC05E0FAF7F0FC98 +:1080900040F6B831FAF7F7F9206101216846FFF799 +:1080A00008FD207D6946FAF72DFF002808BFFFDF95 +:1080B000002005B030BD70B5774CA1690160FFF7B5 +:1080C00037FE002300BBA169D1F8D8205AB1D1E90D +:1080D00037C5AC449569AC44C2F818C0D1E9352C19 +:1080E000CCF80C2005E0DFF8BCC1D1F8D420CCF8E6 +:1080F0001420D1F8D420D1F8D810002A18BF11616B +:1081000002D1002918BF8B61A36170BD6549487019 +:10811000704770B540F2E24300FB03F510460C4691 +:10812000FDF76CF9022C07BF5C494FF47A725C4989 +:108130004FF4C862114408444FF47A7100F23F6072 +:10814000B0FBF1F000F2223085428CBF281A0020EB +:1081500070BD70B50D4606460146002007F0C6FA10 +:10816000044696F85200FDF749F996F85110022995 +:1081700007BF4A494FF47A7249494FF4C862114423 +:1081800008444FF47A7100F23F60B0FBF1F071885F +:1081900040F271225143C0EB4100A0F22230A542CF +:1081A00034BF21462946814203D2A5422CBF28462E +:1081B0002046706270BD3B4910B54968002801F146 +:1081C000980408BF04F5BC7409D0012808BF04F561 +:1081D000317404D0022814BFFFDF04F5B0742E48B8 +:1081E0008068A0428CBF0120002010BD10B52D4C2E +:1081F000607828B1D4E90201626807F05BFAA060F8 +:10820000D4E9010188429CBF2078002814BF0020D7 +:10821000012010BD04222DE9F043204FDFF88080BB +:1082200085B04FF47A79052980F0B980DFE801F054 +:108230000A2B033E890080F8C82005B0BDE8F04352 +:10824000FAF721BB044617480078002818BF84F8C5 +:10825000C82004D005B0BDE8F043FAF714BB0122F2 +:10826000002321466846FFF7CDF994F8D20069460D +:10827000FAF748FE002808BFFFDFB4F85800401C9A +:10828000A4F85800E6E7032180F8C81005B0BDE85F +:10829000F0830000DC000020F40D002068360200AE +:1082A000A2240200DC0D0020397C01000446408835 +:1082B00040F2E2414843B3490860D4F8F000214657 +:1082C0000089E082D4F8F00080796075D4F8F0007D +:1082D00040896080D4F8F0008089A080D4F8F00054 +:1082E000C089E0800020A66A07F000FA054694F8ED +:1082F0005200FDF783F894F8511002290EBF4FF495 +:108300007A7147464FF4C8613944084400F23F602F +:10831000B0FBF9F1608840F271225043C1EB40009C +:10832000A0F22230AE4234BF29463146814203D208 +:10833000AE422CBF304628466062022084F8C80056 +:10834000A4E706460146856A002007F0CFF90446F7 +:1083500096F85200FDF752F896F8511002290EBF18 +:108360004FF47A7147464FF4C8613944084400F22B +:108370003F60B0FBF9F0718840F271225143C0EBCD +:108380004100A0F22230A54234BF21462946814255 +:1083900003D2A5422CBF28462046706276E7FFDF55 +:1083A00074E72DE9F041DFF8E0810025774C98F87B +:1083B000001084B0052880F0C180DFE800F00316CB +:1083C0006DB9B900E5830846F3F794FC607800289E +:1083D00073D100216846FFF76CFB207D6946FAF7F0 +:1083E00091FD002808BFFFDF67E00120FDF706F8D8 +:1083F0006749684E08444FF47A71B0FBF1F0216987 +:10840000726840F2E2431144081AA16900F2DE608A +:108410004A88C83102FB03F772698A4208BF002507 +:1084200014D0216AFBF735F8002807DA391A4A1EFA +:1084300092FBF7F202FB0705394604E090FBF7F2E6 +:1084400002FB170539468D4288BFFFDFD8F80800C8 +:10845000854208D2A06940F271224188C1824A4314 +:1084600005EB420505E040F2E240B5FBF0F0A16902 +:10847000C882A06905214175C08A6FF41C71484308 +:1084800005EB400040F635413061B0EB410F28BFAD +:10849000FFDF04B0BDE8F081E5830846F3F72AFC6E +:1084A00001202077A0692169C0F8CC1080F8C8505D +:1084B0002178052918BFFFDF06D0FAF7E4F96573C4 +:1084C000A57304B0BDE8F081002808BFFFDFA069F4 +:1084D00090F8C800002818BFFFDFA06990F8D2000C +:1084E000202818BFFFDF2C48FAF748FAA169064692 +:1084F000202881F8D2000F8828BFFFDF274820F806 +:108500001670A06990F8D200202808BFFFDF002372 +:1085100001226846A169FFF775F8A069694690F8DD +:10852000D200FAF7EFFC002808BFFFDFA561C4E71F +:1085300004B00846BDE8F041F3F7DCBBFFDF04B050 +:10854000BDE8F081704770B5124D0446002912BF96 +:108550000129686070BD02291CBFFFDF70BD6888FB +:10856000401C68801046FCF758FF4FF47A7100F207 +:10857000E730B0FBF1F0201A686070BD0348007866 +:1085800070470000E0000020DC000020F40D002017 +:10859000C92E0200DC0D002085780100180E002095 +:1085A000FE48406870472DE9F0410D4606460146F9 +:1085B0001746012007F09AF8044696F85200FCF797 +:1085C0001DFF96F8521002290CBFF549F5490844E1 +:1085D0004FF47A7100F2E140B0FBF1F0718840F2A3 +:1085E00071225143C0EB4100C01BA0F55970A54258 +:1085F00034BF21462946814203D2A5422CBF2846DA +:1086000020467062BDE8F0812DE9FF4F8FB004462F +:1086100090F85200DDF8709098460B9049EA0800F7 +:108620000C9094F86400002617460D280CBF01201A +:1086300000200890B8F1000F04BF94F8040103284B +:1086400071D1089800286ED0B4F87C01B8426AD184 +:10865000D4F80C01C4F8F800608840F2E2414843C5 +:10866000C4F8FC00B4F85201B4F8DE100844C4F8B1 +:108670000001204604F00DFDB4F88001E08294F87A +:108680007E016075B4F882016080B4F88401A08036 +:10869000B4F88601C549E080C348097894F864318C +:1086A000628830F8111030F81300D4F828A008447C +:1086B0000004000C4FF0000105D000FB02F1BC48A3 +:1086C000B1FBF0F0411C1FFA81FB2146012007F0AD +:1086D0000DF8054694F85200FCF790FE94F85210FD +:1086E00002290CBFAE49AF49084400F2E1414FF402 +:1086F0007A70B1FBF0F1608840F271225043C1EB17 +:108700004000A0EB0B00A0F55970AA4534BF2946E4 +:108710005146814203D2AA452CBF5046284660628A +:10872000022084F80401D4E956ABB4F8DE000390CB +:10873000B4F85001D4F84C110691B8F1000F03D0F1 +:1087400094F8181149B17FE004F1D8010091743117 +:10875000099104F59C75091D07E004F596710091D7 +:10876000091D099104F58E75091D0A91B4F8581078 +:10877000381A791A09B200B20491002805DAD4F83F +:108780004801069001200C90084694F80411002935 +:108790005ED0012900F0668102297DD0032918BF2F +:1087A000FFDF00F0A98131460698F9F76CFE0999C0 +:1087B00008600A9801210780002028702971099813 +:1087C0000068A8607948D0E90520824287BF009AF6 +:1087D0001060009802600098626A0068104400F21D +:1087E0008310E8606971B4F8C800C01B00B20028AB +:1087F000C4BF032068710898002800F0F181B9F126 +:10880000000F18D0B4F8F020002A0CBF0020B4F8F4 +:10881000F200A4F8F20094F8F430401C584390425F +:1088200009D26879401E002805DD6971B4F8F200AC +:10883000401CA4F8F200B8F1000F00F0F58194F8A4 +:108840001801002800F0EC8113B00220BDE8F08F81 +:10885000BAF1000F08BFFFDFE08A40F27121484300 +:10886000490001EB400210980021002806D000FBCF +:1088700002F14F48B1FBF0F000F10101C4F808111A +:10888000608840F2E24100FB01F210994FF00000D5 +:1088900008D001FB02F100E042E04548B1FBF0F0F6 +:1088A00000F10100C4F80C010AF101064FF00100CB +:1088B000FCF7A4FD3F494FF47A7B0844B0FBFBF082 +:1088C000E18A40F271225143C0EB4101D4F8080122 +:1088D0000190091A314401F2C246607D510010FB3B +:1088E00001F00C900120FCF789FD33490844B0FBEE +:1088F000FBF1019801EB40010C9801EB000B01200A +:10890000FCF770FD584400F1620128484161816123 +:10891000A6EB0A00401EB0F53D7F38BFFFDF42E7FF +:10892000E28A40F271215143D4F8FC00109A00EB26 +:1089300041010020002A06D01D4802FB01F2B2FBD3 +:10894000F0F000F10100C4F80801628840F2E2434F +:1089500002FB03FC109B4FF0000206D0144A03FBFD +:108960000CF3B3FBF2F202F10102C4F80C21039AFA +:108970009AB9B9F1000F38D094F85200FCF73EFDD7 +:10898000014694F8520002280CBF054A054A1144DA +:1089900001F2E1424FF47A7110E026E0580E002017 +:1089A00004360200A224020042230200E800002054 +:1089B00040420F007D2A020083290200B2FBF1F140 +:1089C000D4F80821E38A114440F2712CD4F8FC2039 +:1089D00003FB0CF302EB4302561AFCF703FDABEB6F +:1089E00000003044A0F1200600E00E1AD4F8002167 +:1089F000D4F8F810D4F8080101FB020B607D40F2B6 +:108A0000E24110FB01F00C9094F852A05046FCF7A4 +:108A1000F5FC0146BAF1020F0CBFF948F9480844C9 +:108A200000F2E1414FF47A70B1FBF0F000EB4B0142 +:108A30000C9801EB000B5046FCF7D4FC584400F1B5 +:108A40006001F14840F2712341616288D4F80C1151 +:108A50005A43C1EB4201A1F213318161012084F834 +:108A60000401A0E6628840F27123D4F80C115A4345 +:108A7000C1EB420202FB00F6DDE903020244D4F836 +:108A80000001D4F8F8C0121AD4F80831521E0CFBB9 +:108A9000003002FB010B607D40F2E24110FB01F06F +:108AA0000C9094F852000190FCF7A8FC0146019844 +:108AB000022814BFD348D248084400F2E1414FF4E1 +:108AC0007A70B1FBF0F000EB4B010C9801EB000B5E +:108AD0000198FCF787FC584400F16001CA48B9F1DD +:108AE000000F4161A6F2133181613FF45CAEBAF12F +:108AF000000F08BFFFDF56E6628840F27123D4F80A +:108B00000C115A43C1EB420101FB00F694F86300DB +:108B100025281CBF94F8640025280AD1B4F87C01EC +:108B2000381A00B2002804DB94F87F01002818BF2F +:108B30000B900C9828B1039880B3BBF1000F18BFBD +:108B4000FFDFDDE903010144D4F80C0101FB00FA69 +:108B50000B98FCF753FC01460B9802280CBFA84861 +:108B6000A848084400F2E1414FF47A70B1FBF0F0FC +:108B700000EB4A0A0B98FCF735FC504400F1600109 +:108B8000A14840F2712341616288D4F80C115A4324 +:108B9000C1EB4201A1F21331816104E6FFE7BBF1B1 +:108BA000000F14BFBAF1000FFFDF0B98FCF726FC93 +:108BB0000B9902290CBF92499249084400F2E14105 +:108BC0004FF47A70B1FBF0F0361A94F85200FCF7CB +:108BD00009FCABEB00003044A0F12006B1E700BF78 +:108BE000B9F1000F7FF40EAE94F8040100283FF4B1 +:108BF00022AE618840F27122D4F80C015143C0EBDF +:108C00004101284606F02EFD0004000C3FF413AE8F +:108C10001D99002918BF0880012013B0BDE8F08F0E +:108C200094F85401FAF781FA94F854012946FAF7B6 +:108C300069F900281CBF88F0010084F819010020A0 +:108C400013B0BDE8F08F2DE9F04F704C804683B033 +:108C500020788A4600256C4E4FF00209032804BF95 +:108C6000207B40457CD1606830612078032818BFA4 +:108C7000FFDF0327BAF1080F70D2DFE80AF0040E15 +:108C80001B1B166F6F6A6562FCF74FFF002818BF49 +:108C9000FFDFB77003B0BDE8F08FFDF7CBF8002819 +:108CA00018BFFFDF03B0BDE8F08F03B0BDE8F04FA1 +:108CB000FCF7FAB927752574E07A012658B14FF40C +:108CC0007A71A069F9F7DFFBA061002104F11000BF +:108CD00006F0C8FC1AE001216846FAF71AFF9DF871 +:108CE000000042F210710002B0FBF1F201FB12052C +:108CF000FCF793FD05442946A069F9F7C4FBA06180 +:108D0000294604F1100006F0ADFC461C208C411CE5 +:108D10000A293CBF30442084606830B1208C401C5C +:108D20000A2828BF84F8159000D26775607A002859 +:108D30001CBF03B0BDE8F08F207B04F11001FAF7EF +:108D4000E1F8002808BFFFDF03B0BDE8F08F07E0BF +:108D500004E0207BF9F76DFE2570F5E7FFDFF3E710 +:108D6000B8F1200F28BFFFDF294F072137F818007F +:108D7000F7F774FE040008BFFFDFB8F1200F28BF2B +:108D8000FFDF37F818002188884218BFFFDF4FF057 +:108D900001083461BAF1080F80F04481DFE80AF07D +:108DA000049AA2A29DEEEEEDC4F85851F580C4F8E5 +:108DB0005C5194F8190138B9F9F75AFED4F8241126 +:108DC000FAF767FB002825DCB4F81611B4F8580050 +:108DD000814206D1B4F8CC10081AA4F8CE0020467F +:108DE00005E0081AA4F8CE00B4F816112046A4F83D +:108DF0005810D4F84011C4F82411C0F8481127E0E5 +:108E000004360200A2240200E8000020580E0020D0 +:108E1000800E0020B4F81411B4F85800081AA4F811 +:108E2000CE00B4F814112046A4F85810D4F8241138 +:108E3000C4F84011C4F84811D4F82C11C4F8D81063 +:108E4000D4F83011C4F84C11B4F83411A4F850110E +:108E500003F0D7FFF9F7E6FD94F852A00746504615 +:108E6000FCF7CCFABAF1020F0CBFFE49FE490844E8 +:108E70004FF47A7100F2E140B0FBF1F1D4F80C014B +:108E800040F27122014460885043C1EB4000A0F1E0 +:108E9000300AB72F98BFB7272146012006F026FCDD +:108EA0003844AAEB0000A0F21937A246214601205F +:108EB00006F01CFCDAF824109C30814288BF0D1AA1 +:108EC000F760BD4228BF3D46B56084F8188186F83A +:108ED000029039E704F0DBF801E0FCF7E5F884F8EC +:108EE000188131E7F9F7C4FDD4F84821014610464E +:108EF000FAF7CFFA48B1628840F27123D4F80C1126 +:108F00005A43C1EB4201B0FBF1F094F864100D2913 +:108F10000FD0B4F85810B4F816210B189A42AEBF0F +:108F2000501C401C0844A4F8160194F81A0178B9A2 +:108F300005E0B4F81601401CA4F8160108E0B4F8E6 +:108F40001601B4F8CC10884204BF401CA4F81601E6 +:108F5000B4F85201DFF81493401CA4F85201B4F89D +:108F60007E00B4F87C100DF1080B401AB4F85810CC +:108F7000401E08441FFA80FA17E045E052E03078BE +:108F8000002339F81000CDE9005B94F8641139F83A +:108F90001110084481B22046FFF736FB00283FF449 +:108FA000D3AE012818BFFFDF26D0B4F81621AAEBF4 +:108FB000020000B20028E2DA082084F8730084F886 +:108FC0007280204603F0D2FB84F8045194F8545187 +:108FD0004FF6FF78202D00D3FFDF27F8158094F897 +:108FE0005401F9F726FD202084F85401307903B0AC +:108FF000BDE8F04FF2F77EBEB4F81601BDF80810D8 +:109000000844A4F81601D0E794F80401042818BF16 +:10901000FFDF84F8045194F854514FF6FF78202D67 +:10902000DBD3D9E7FFDF8FE610B5914C207850B144 +:1090300001206072FCF71DFF2078032805D0207AFC +:10904000002808BF10BD0C2010BD207BFAF76DF87A +:10905000207BFAF7B8FA207BF9F7EBFC002808BF71 +:10906000FFDF0020207010BD2DE9F04F804F83B04E +:10907000387801244FF0000840B17C720120FCF7E1 +:10908000F8FE3878032818BF387A0DD0DFF8E4915D +:1090900089F8034069460720F7F76BFC002818BFE2 +:1090A000FFDF4FF6FF7440E0387BFAF73EF8387B7D +:1090B000FAF789FA387BF9F7BCFC002808BFFFDF14 +:1090C00087F80080E2E7029800281CBF90F804119E +:1090D00000292AD00088A0421CBFDFF89CA14FF0D5 +:1090E000200B3AD00721F7F7B9FC040008BFFFDFD7 +:1090F00094F85401FAF767FA84F8048194F854510B +:109100004FF6FF76202D28BFFFDF2AF8156094F870 +:109110005401F9F78EFC84F854B169460720F7F73B +:1091200028FC002818BFFFDF12E06846F7F7FFFBB6 +:109130000028C8D011E0029800281CBF90F8041144 +:10914000002905D00088A0F57F41FF39CAD104E08D +:109150006846F7F7ECFB0028EDD089F8038087F824 +:109160000B8003B00020BDE8F08F70B50446434883 +:1091700090F80004424D400995F8001449098842CE +:1091800018BFFFDF95F8140D40093E4991F800140F +:109190004909884218BFFFDF3649002001220C71BF +:1091A00088700A704870C87031490870BDE8704016 +:1091B0005AE73049087070472DE9F8432C4C0646B1 +:1091C0002078002875D13048F9F7D8FB2073202883 +:1091D0006FD0032766602770002565722572AEB1D7 +:1091E000012106F1F400FAF70CFD0620F7F7E0FB89 +:1091F00080460720F7F7DCFB96F8F4104044B1FBFB +:10920000F0F200FB1210401C86F8F400F9F70AFC9B +:109210001E49091838BF40F2F65000F59D7086B21D +:10922000FCF7D7FAE061FCF7F8FA4FF0010878B3E1 +:1092300084F80A8001216846FAF76BFC9DF800006B +:1092400042F210710002B0FBF1F201FB1200064481 +:10925000F9F70EFC3146F9F716F9A0612775677525 +:10926000257416E004360200A22402004223020004 +:10927000580E0020E8000020800E002001E000E0F1 +:109280000BE000E019E000E0478C01000AFAFFFF64 +:1092900012E0207B04F11001F9F734FE002808BF2A +:1092A000FFDF25840020FCF7E4FD0020BDE8F88303 +:1092B000FFE70C20BDE8F883F9F7DAFB3146F9F750 +:1092C000E2F8A061A57284F80B80C7E72DE9F047AA +:1092D00082B00026044680F80461A0F85061DFF8EF +:1092E00000944288FD4FD0F8288099F8000094F847 +:1092F000641137F8100037F8111008440104090C04 +:10930000304605D001FB02F0F649B0FBF1F0401CFD +:109310001FFA80FA2146012006F0E8F9054694F884 +:109320005200FCF76BF894F8521002290CBFEE497A +:10933000EE4908444FF47A7100F2E140B0FBF1F1DC +:10934000608840F271225043C1EB4000A0EB0A005C +:10935000A0F55970A84534BF29464146814203D241 +:10936000A8452CBF4046284660620096019699F8B1 +:10937000000094F86411002337F8100037F811103A +:109380001A46084481B22046FFF73EF9002818BF6C +:10939000FFDFC4F800610120C4F8F86084F804011C +:1093A000A4F81661A4F8146184F81A61B4F858009E +:1093B000401EA4F85800A4F8526102B00020BDE895 +:1093C000F087C74948707047C94810B5417A0124F1 +:1093D000002918BF002408D1C17A31B1406AC549BB +:1093E000884284BF0024FCF740FD204610BD70B5C4 +:1093F000BB4C0546E088401CE080D4E9020162785D +:10940000D5F85861002A1CBF324606F053F9A06017 +:10941000864208D895F80401012804D0E078002895 +:1094200004BF012070BD002070BD70B50D4640F234 +:10943000E24100FB01F42846FBF7E0FF022D0CBFE0 +:10944000A949AA4908444FF47A7100F2E140B0FBFF +:10945000F1F000F54D7084428CBF201A002070BDE1 +:109460002DE9F04383B00026044680F8186190F897 +:10947000D600002807BF94F80401032803B0BDE814 +:10948000F083F9F7F5FAD4F8482101461046FAF7C7 +:1094900000F80028DCBF03B0BDE8F083628840F22A +:1094A0007123D4F80C115A43C1EB4201B0FBF1F027 +:1094B000411CB4F858000144A4F81411B4F8CC10BD +:1094C000B4F81421891A09B20029DCBF03B0BDE841 +:1094D000F083012184F81A11B4F87E10B4F87C20CE +:1094E0007E4F891A491E084485B2DFF8F4810DF1D8 +:1094F00008091EE098F8000037F81000CDE900696F +:10950000B4F8142194F86411012337F811100844B9 +:1095100081B22046FFF778F8002804BF03B0BDE809 +:10952000F08301280FD0022812BFFFDF03B0BDE88F +:10953000F083B4F81401281A00B20028BCBF03B0AD +:10954000BDE8F083D6E7B4F81401BDF8081008446C +:10955000A4F81401EDE7F0B5DFF884C104265F4BF1 +:109560009CF80020002583B006297DD2DFE801F0B9 +:10957000073C03191941044680F8046107E00446DA +:109580009CF80300002818BF84F804610BD0F9F799 +:109590007AF9A4F85251B4F85800A4F8160184F8E6 +:1095A0001A5103B0F0BD33F8120094F804210121E0 +:1095B000032A13BF94F80421C4F80051C4F8F850EA +:1095C000012AE4D1CDE9001594F86411B4F8CC2057 +:1095D00033F811100023084481B22046FFF714F835 +:1095E000002818BFFFDFD2E7032180F8041103B081 +:1095F000F0BD0446B0F802C0866A90F8640133F802 +:10960000121033F8100008440104090C4FF0000058 +:1096100005D001FB0CF03349B0FBF1F0401C87B2E0 +:109620002146012006F062F8054694F85200FBF747 +:10963000E5FE94F8521002290CBF2B492B4908442F +:109640004FF47A7100F2E140B0FBF1F0618840F232 +:1096500071225143C0EB4100C01BA0F55970AE42CE +:1096600034BF2946314600E008E0814203D2AE42D1 +:109670002CBF30462846606203B0F0BDFFDF03B068 +:10968000F0BD2DE9F8431A4C0327154EE27AA17A72 +:1096900042F21079002550B1012843D002281CBFA6 +:1096A000FFDFBDE8F8834FF000081AB95EE04FF025 +:1096B00000080AB1E5722EE051B101216846FAF7BF +:1096C0004DFA9DF800000002B0FBF9F109FB11080A +:1096D000FCF7A3F800EB0801A0690DE042230200AB +:1096E000E800002040420F0004360200A2240200DD +:1096F000580E0020DB821300F8F7C5FEA061257428 +:109700006775607A30B9207B04F11001F9F7FAFB34 +:1097100000284BD02584F9F7B6F83079BDE8F84336 +:10972000F2F7E8BAE572A7692570012020720021DE +:10973000606805F035FB6068C0F84871217B80F8EF +:109740005411616AC0F84C71C0F8581190F8545126 +:109750000788202D28BFFFDF3C4820F8157060687F +:10976000FFF7B4FD002818BFFFDFD4E751B1012196 +:109770006846FAF7F3F99DF800000002B0FBF9F132 +:1097800009FB1108FCF749F800EB0801A069F8F79C +:109790007AFEA06125746775607A0028BAD1207BB3 +:1097A00004F11001F9F7AEFB0028B3D1FFDFB1E7F8 +:1097B00070B5274CA178022906BFE188002970BD49 +:1097C0002569C5F85C0195F85200FBF70BFED5F84A +:1097D0005C11081AA1680144A160E1680844E060D6 +:1097E00070BD70B505461A488378022B06BF006924 +:1097F00000F5AC74174C002904BF256070BD012929 +:1098000008BF681E0DD002291CBFFFDF70BD1046C7 +:10981000FBF703FE4FF47A7100F2E140B0FBF1F088 +:10982000281A206070BD0C48007800281CBF00205A +:10983000704710B50720F7F7ADF880F0010010BDB4 +:1098400005480078002818BF01207047800E0020CE +:10985000E80000207C0E0020580E0020F8490C285B +:10986000896881F8C3001ABF13281828704700229E +:1098700011280FD0072808BF704715280AD00128E3 +:109880001ABF002802287047A1F88220012081F821 +:1098900086007047A1F88820704770B5E84CA16831 +:1098A0000A88A1F8362181F8340191F85100012885 +:1098B00008BF012508D0022808BF022504D00428CB +:1098C00016BF08280325FFDFA06880F8385190F8FC +:1098D0005200012808BF012508D0022808BF022530 +:1098E00004D0042816BF08280325FFDFA068012143 +:1098F00080F8395180F83211002180F80611E078A3 +:10990000BDE87040F2F7F6B9F0B4CD48806890F841 +:109910004E30478EC68E458FB0F84010C28FB0F8DB +:1099200042C0022B1FD08D4238BF294601866245B6 +:1099300028BF62468286018FB0F84430994238BF12 +:109940000B464386818FB0F84640A14238BF0C4693 +:10995000C486BB4228BF1F464786B44228BF26465E +:10996000C686F0BC7047038E9D4228BF1D46838E7D +:109970009A4228BF1A46A94298BF0D4605869445CB +:1099800098BF62468286002180F84E10D3E7AC4A29 +:10999000012992681BD0002302290FD0032921D06E +:1099A00028B301282ED0032818BF704792F863000F +:1099B00013281CBF1628182805D1704792F8C30039 +:1099C000002808BF7047D2F8F0000370704792F883 +:1099D000C300012808BF7047D2F8F4000178491E7F +:1099E0000170704792F8C3000328ECD17047D2F899 +:1099F000F000B2F858108288891A09B20029A8BF6D +:109A000003707047B2F85800B2F8FA10401A00B26A +:109A10000028E1DA70472DE9F04100260327884C41 +:109A20000125A0B1206906F0CCF9A16881F8C20037 +:109A300005FA00F010F4000F08BFFFDFA06880F8FF +:109A40006370A0F8826080F88650BDE8F081A0685D +:109A50000023194690F86420583005F0A2FD002834 +:109A600004BF6570BDE8F0816078002818BFBDE8CC +:109A7000F081206906F0A5F9A16881F8C10081F89C +:109A80006470A1F8886081F88A50BDE8F08170B5F3 +:109A90006B4C84B0207910F0010F04BF04B070BD8E +:109AA000206900230521C578A06890F8632058300C +:109AB00005F077FD002818BF022D0FD00B2D18BF21 +:109AC000042D0BD0052D18BF062D07D00D2D18BF66 +:109AD000112D03D0607840F0080060706078002895 +:109AE0001CBF04B070BD2069C078801E162880F0AD +:109AF0005283DFE800F00BFBA7C5FA26FBF9FB9ABF +:109B0000F8FCFBFBFBE3F6F5F4F3F2F1A0680023AD +:109B1000012190F86620583005F043FD002840F000 +:109B2000B583206906F0A8F9A16881F8EE00072046 +:109B300081F86600002081F88A0081F8860000F034 +:109B4000A5BBA0680921002390F86320583005F0D8 +:109B500028FD20B1206906F0DFF9122814D0A06892 +:109B60000A21002390F86320583005F01AFD20B137 +:109B7000206906F0D1F9142821D0206906F0CCF92B +:109B8000162840F0838342E0A0680125002390F866 +:109B900063200921583005F004FD002808BF6570D6 +:109BA00000F074836078002840F07083A16881F829 +:109BB0007A0081F8860081F8630000F067BBA06836 +:109BC0000021012580F86310A0F8821080F886102B +:109BD0000421FEF71FFBA06890F84E10012900F049 +:109BE0007C820288A0F81621028EA0F81821828EAD +:109BF000A0F81A21428E00F58671A0F81C21C08EB3 +:109C000048820D72E078F2F775F800F03FBBA0686B +:109C100090F86310202940F03983002180F8631008 +:109C200080F886101A2000F02FBBA06890F863100F +:109C30000F292AD1002180F8681012213AE0000093 +:109C400004010020A06890F8631013291DD1D0F8FA +:109C5000F01000884988814218BFFFDFA068D0F863 +:109C6000F00000F12601206906F033F9A06800F148 +:109C7000BC01206906F035F91620A16800F064B92E +:109C8000A26892F86300162802D0022000F064BA9D +:109C9000D2F8F00002F1A80300F11E0100220E30FC +:109CA00005F007FCA0680021C0E92611012180F819 +:109CB0006810182180F8631000F0E8BA206906F0F7 +:109CC000B0F9032840F0E282206906F0AEF900BF47 +:109CD00001F022FC00F0DABA8DE202E2AEE152E1DC +:109CE0001EE135E103E050E0C4E004E0D5E1206985 +:109CF00006F00EF9ECE7A06890F863101B29C4D1B8 +:109D0000002580F88B5080F88650D0F8F01000883D +:109D10004988814218BFFFDFA068D0F8F0100D70AD +:109D2000D0F83C110A78002A18BFFFDF40F0F3801A +:109D300090F88C207AB180F88C500288CA80D0F8D4 +:109D40003C110D71D0F83C210D211170D0F83C214F +:109D50000188518010E00288CA80D0F83C110D7152 +:109D6000D0F83C2101211172D0F83C210C21117056 +:109D7000D0F83C21018851800088F6F779FFF6F78A +:109D8000D9FBE078F1F7B6FFC5E0A06800231946DB +:109D900090F86420583005F004FC50B9A068002306 +:109DA000082190F86320583005F0FBFB002800F0F4 +:109DB00027826078002840F06982A06890F88E00C1 +:109DC00010F0020F17D1206906F098F8A16881F809 +:109DD0008F00206906F094F8A168A1F8900020692E +:109DE00006F091F8A168A1F8920091F88E0040F079 +:109DF000020081F88E00A06890F88E1011F0010F1B +:109E000012D190F8642000231946583005F0C9FBA0 +:109E1000002808BFFFDF0121A06880F8641080F8E7 +:109E20008A100021A0F88810A06890F8631001291A +:109E300007D1002180F8631080F88610E078F1F7F0 +:109E400059FFA168D1F8F000098842888A4204BF0E +:109E50000178042940F01A8200250570E078F1F7B6 +:109E600049FFA06890F86310002908BF80F8865069 +:109E700000F00CBAA0680023072190F86320583046 +:109E800005F08FFB002800F0BB816078002840F0CF +:109E9000FD8102A9206906F079F8A0689DF80820E4 +:109EA000002590F89410114001F02F0180F89410D3 +:109EB00090F895109DF80920114001F0410180F8BB +:109EC000951080F88650D0F8F010008849888142BB +:109ED00018BFFFDFA068D0F8F0100D70D0F83C116B +:109EE0000A78002A18BFFFDF15D10288CA80D0F88F +:109EF0003C110D71D0F83C11029A8A60039ACA6035 +:109F0000D0F83C21072111700188D0F83C01418034 +:109F1000E078F1F7EFFEA06880F8635000F0B6B982 +:109F2000A0680023092190F86320583005F039FB20 +:109F3000002800F065816078002840F0A781A168C2 +:109F400081F87A0081F8860081F8630000F09EB9FC +:109F5000A0680023194690F86420583005F021FBD2 +:109F6000002800F04D816078002840F08F81A068C3 +:109F70000021A0F88810012180F88A10022180F8C1 +:109F8000641000F083B9A0680023194690F864209B +:109F9000583005F006FB00287ED0206905F0E0FF70 +:109FA00000287AD0206905F0D7FFA16808872069CA +:109FB00005F0CEFFA1684887206905F0CFFFA168B2 +:109FC0008887206905F0C6FFA168C88791F86300FB +:109FD0001D2813BF91F84E00012081F84E00012882 +:109FE00007D091F8FD00002804BF91F8FC0000287C +:109FF00003D01F2081F8640017E01E2081F8640060 +:10A000000A88A1F822210A8FA1F824214A8FA1F8F9 +:10A0100026218A8F01F58670A1F82821C98FC18376 +:10A0200001210175E078F1F765FEA0680021A0F834 +:10A030008810012180F88A1000F028B9A068002358 +:10A040000A2190F86320583005F0ABFA20B320695C +:10A0500005F086FFA8B1206905F07EFFA16808879A +:10A06000206905F075FFA1684887206905F076FF33 +:10A07000A1688887206905F06DFFA168C887FFF790 +:10A0800043FCA068002180F8861080F8631004214A +:10A09000FEF7C0F8A06801E01AE07CE090F84E10EE +:10A0A00001291AD00288A0F81621028EA0F81821E2 +:10A0B000828EA0F81A21428E00F58671A0F81C212C +:10A0C000C08E488201200872E078F1F713FEDDE0CF +:10A0D000607840F001006070D8E0022180F84E10F6 +:10A0E000D4E0A0680023194690F86420583005F0A9 +:10A0F00058FA80B3A06890F86300242812BF25287E +:10A10000607840F0200027D06846FBF7EDF9002882 +:10A1100008BF002105D0009805F053FE8DF8080017 +:10A1200002A9A06801AB162290F8630005F001FCBB +:10A13000A0B1A0689DF80420162180F8E42080F8E2 +:10A14000E5101A2180F86410012180F88A1000219E +:10A15000A0F888109AE053E0607097E0206905F05D +:10A1600022FFC0B1206905F018FFA16800F00700C8 +:10A1700081F84F00206905F014FF00F00701A06886 +:10A1800080F8501090F80721002A04BF90F80621AB +:10A19000002A04D024E00020FFF73DFC76E090F890 +:10A1A0004F3090F852C000F151029C4501BF127827 +:10A1B0008A42012180F87B1012D00288A0F82E215B +:10A1C00090F84F2000F5867180F8302190F850000B +:10A1D00081F82500012081F82000E078F1F78AFD60 +:10A1E000A068222180F86410012180F88A100021E3 +:10A1F000A0F888104AE0A06890F86300202801D0F9 +:10A200000120A9E7206905F0D8FEC0B3206905F058 +:10A21000C4FE00F0070060F30705206905F0C1FEE9 +:10A2200000F0070060F30F25A2680120002682F8E5 +:10A230008600A2F88260242082F86300D2F8080128 +:10A24000B2F851202946ADF8002005F020FB9DF81A +:10A250000020C1B28A4207BFA16881F8E860A26805 +:10A2600082F8E8109DF80110C0F30720814219BF61 +:10A27000A16881F8E900A06880F8E96006E0FFE7DE +:10A280000120FFF7C8FB1E20FFF707FBA068D0E9FD +:10A2900028134A1C43F10001C0E9282104B070BD15 +:10A2A0002DE9F047FE4D04464FF00007687808435B +:10A2B0006870287910F0200F2846806818BFA0F831 +:10A2C0007C7004D1B0F87C10491CA0F87C1090F888 +:10A2D0006910012639B990F863200023062158300F +:10A2E00005F05FF958B3A88810F4006F07D0A8688C +:10A2F00090F86910002918BFA0F874701FD1A868E1 +:10A30000B0F87410491C89B2A0F87410B0F8762027 +:10A310008A422CBF511A00218288521D8A4228BFCE +:10A3200080F87A60B0F87410B0F87620914206D3C5 +:10A33000A0F8747080F81261E878F1F7DBFC2879F6 +:10A3400010F0600F08D0A86890F8671021B980F865 +:10A3500067600121FDF75EFF4FF00808002C56D121 +:10A360006878002851D1287910F0040F0DD0A86822 +:10A3700090F86300032808BFFFDFA86890F8661014 +:10A38000072904BF2E7080F8667001F015F928794E +:10A3900010F0080F19D06878B8B9A868002190F8B3 +:10A3A000C300FFF7F4FAA86890F8C300FF2808BFBD +:10A3B000FFDFFF21A86880F8C31090F86610082915 +:10A3C00003D10221297080F86670FFF760FBA8783E +:10A3D00010F0080F16D0A8680023052190F863201C +:10A3E000583005F0DEF850B185F80180A868D0F843 +:10A3F0003C1108780C2808BF0020087002E00020FB +:10A4000003F04DFDA86801F010F800F06CFDA8689D +:10A41000A14600F1580490F8EC0030B9A27B00236B +:10A420000121204605F0BDF810B1208D401C20858B +:10A430003D21B9F1000F18D12878022808BF162055 +:10A440000ED0012804BFA86890F8EE0008D0687804 +:10A45000E8B110F0140F1CBF1E20E07602D005E01A +:10A46000E07603E010F0080F02D0E176A67641E036 +:10A4700010F0030F03D02A20E076A6763AE010F021 +:10A48000200F08BFFFDF2320E076A67632E094F8A5 +:10A490002E0028B1608D411C6185A18D884213D2A8 +:10A4A00094F8320028B1208E411C2186A18D88426B +:10A4B0000AD2218DE08C814203D3AA6892F8EC2065 +:10A4C00012B9A28D914203D32220E076A67611E044 +:10A4D000E17B31B1A18C814228BF84F81B80C5D2B9 +:10A4E00006E0A08C062803D33E20E076A67601E0A5 +:10A4F000A07EA0B1E7722773E7730221A868FDF779 +:10A5000089FEA86890F8C310012904D1D0F8F4009E +:10A510000178491E0170E878F1F7ECFB03E00021B7 +:10A52000A868FDF777FEBDE8F047FAF7ECBF5C4995 +:10A530004A788B781A430ED101280AD0087910F096 +:10A54000040F04D0886890F86600072803D0012023 +:10A550007047FDF74BBE0020704770B5504C064663 +:10A560000D46A0883043A08016F0020F04D016F0EC +:10A57000010F18BFFFDFE56016F0010F18BF25615E +:10A5800016F0020F12D0284605F01BFC062802D058 +:10A590000B282ED00AE0A06890F86310182905D186 +:10A5A0000021C0E92811012180F8691016F0800F00 +:10A5B0001CBF0820A07016F4806F08BF70BDA06893 +:10A5C000B0F8581080880844801D86B2284605F0EF +:10A5D000F8FB012804BFA068A0F8FA6015D028464F +:10A5E00005F0EFFB68B1284605F0EBFB182823D0F7 +:10A5F0000BE0A06890F86310122908BF0021D5D1A4 +:10A60000D2E7A068D0F8F0008680284605F0D9FB94 +:10A6100001281DD0284605F0D4FB08B3284605F0D4 +:10A62000D0FB182818BF70BDA068B0F8EA10284603 +:10A63000BDE8704005F0D3BCA06890F8E810002990 +:10A6400002BF90F8E91000290026A0F8EA60DCE7D4 +:10A65000A068B0F8FA102846BDE8704005F003BCC9 +:10A66000A068D0F8F00081882846BDE8704005F069 +:10A67000CABBF0B50A4C85B00026A060A680667003 +:10A68000A670054626700088FAF705FFA0680088C6 +:10A69000FAF727FFB5F8D000A168401C82B201E0AC +:10A6A0000401002001F1580004F085FD002818BFC6 +:10A6B000FFDF95F8640025280AD1B5F85810B5F8E1 +:10A6C000EA00081A00B20028A4BF6078002804D06D +:10A6D00095F8630025283BD119E0A06890F8E810B0 +:10A6E000002908BF90F8511080F8511090F8E91037 +:10A6F000002908BF90F8521080F852100020FFF790 +:10A70000CCF885F86460A16881F87B6020E0B5F83A +:10A710005810B5F8EA00081A00B20028A4BF607803 +:10A72000002815D1A06890F8E810002908BF90F81B +:10A73000511080F8511090F8E910002908BF90F8E6 +:10A74000521080F852100020FFF7A7F885F86360D8 +:10A75000A5F8D060A06890F8861039B1B0F88210E2 +:10A76000B0F88420914224BF05B0F0BD90F88A1063 +:10A7700039B1B0F88810B0F88420914224BF05B0F8 +:10A78000F0BDB0F88020B0F87E108A4224BF05B03A +:10A79000F0BD90F867208AB3B0F87C208A4224BFCD +:10A7A00005B0F0BD90F8C370FF2F00F02A81684615 +:10A7B000FAF774FE002808BFFFDF009805F03FFAA3 +:10A7C0000321009805F052FA0098017821F0100159 +:10A7D0000170394605F0C7FA192F80F0E780DFE8ED +:10A7E00007F02A22144EE5E5E61B7CE5E6E66CE57B +:10A7F000E5E5E5D8E6E6869FB8E5C500B0F87C104B +:10A80000062924BF05B0F0BDCCE7A06890F8ED1094 +:10A81000009805F02FFBCAE0A06890F8C4100098DB +:10A8200005F078FBC3E0A068D0F8F400411C009864 +:10A8300005F011FBBBE0A068D0F8F000817900982A +:10A8400005F0DDFAA068D0F8F0000189009805F065 +:10A85000CFFAA068D0F8F0004189009805F0B3FA6B +:10A86000A068D0F8F0008189009805F0B3FAA068DC +:10A87000D0F8F000C189009805F0B3FA97E0A0681D +:10A88000D0F8F000011D009805F0F8FAA068D0F8A3 +:10A89000F00000F10C01009805F0FAFAA068D0F879 +:10A8A000F00000F11E01009805F0F8FAA06800F130 +:10A8B000B801009805F000FB79E060690178009824 +:10A8C00005F012FB60698188009805F00FFB606954 +:10A8D0004188009805F00EFB69E0FE49D1E90001CE +:10A8E000CDE9020102A9009805F018FB5FE0A0681D +:10A8F000B0F84410009805F01BFBA068B0F84610B3 +:10A90000009805F019FBA068B0F84010009805F019 +:10A9100017FBA068B0F84210009805F015FB46E060 +:10A92000A068B0F84010009805F00AFBA068B0F8E5 +:10A930004210009805F008FBA068B0F84410009899 +:10A9400005F0F6FAA068B0F84610009805F0F4FAA1 +:10A950002DE0A06890F80811009805F01CFBA06895 +:10A9600090F80911009805F01AFB20E0A06890F813 +:10A97000E80004F087FF0146009805F028FBA06876 +:10A9800090F8E90004F07EFF0146009805F023FBF3 +:10A990000DE0A06890F8E510009805F040FBA06875 +:10A9A00090F8E410009805F03EFB00E0FFDFFAF7B6 +:10A9B00088FD002808BFFFDF009F384605F001FA38 +:10A9C000012809D0384605F0FCF960B1384605F099 +:10A9D000F8F918280FD014E0A068B0F8FA1038463B +:10A9E00005F041FA0DE0A068D0F8F0008188384603 +:10A9F00005F009FA05E0A068B0F8EA10384605F05D +:10AA0000EEFAB5480090B54BB54A2946304603F0FA +:10AA100081F9A0680023052190F86320583004F0E4 +:10AA2000C0FD002804BF05B0F0BD05B0BDE8F04092 +:10AA300002F041BFAB48806890F8861029B1B0F8A9 +:10AA40008210B0F8842091421AD290F88A1029B16D +:10AA5000B0F88810B0F88420914211D2B0F880206C +:10AA6000B0F87E108A420BD290F86720B0F87C00D4 +:10AA700022B1884204D200BF03F0ECB90628FBD310 +:10AA8000002001460CE470B50C46064615464FF40E +:10AA9000A071204607F0C9F82680002D08BFFFDF0F +:10AAA0002868C4F8F0006868C4F8F400A868C4F81E +:10AAB0003C0170BDF6F7B3B82DE9F0410D460746ED +:10AAC0000621F5F7CBFF040008BFBDE8F081D4F8FC +:10AAD0003C110026087858B14A8821888A4207D15B +:10AAE000082810D00D281FD00C2835D0072850D0AA +:10AAF00094F8120100285ED06E700F20287084F840 +:10AB000012616F8042E06E7008202870D4F83C011A +:10AB10004168C5F802108168C5F80610808968810F +:10AB2000D4F83C01067031E00846F6F7A1F8074674 +:10AB3000F5F716FDB8B96E700D202870D4F83C01F9 +:10AB40004068C5F80200D4F83C0106703846F5F7B5 +:10AB500001FD0120BDE8F0810846F6F789F80746B7 +:10AB6000F5F7FEFC10B10020BDE8F0816E700C20FE +:10AB70002870D4F83C014168C5F802100089E880CB +:10AB8000D4F83C0106703846F5F7E4FC0120BDE836 +:10AB9000F0816E7007202870D4F83C01416882680B +:10ABA000C068C5F80210C5F80620C5F80A00D4F838 +:10ABB0003C010670EAE794F81401C8B16E701420E5 +:10ABC000287094F814010028E0D000BF84F81461C4 +:10ABD000D4F81601C5F80200D4F81A01C5F8060029 +:10ABE000B4F81E01688194F814010028EED1CDE775 +:10ABF00094F8200180B16E701A20287084F82061CA +:10AC0000D4F82201C5F80200D4F82601C5F80600E0 +:10AC1000B4F82A016881B9E794F82C0148B16E7044 +:10AC20001B20287084F82C61D4F82E01C5F802008E +:10AC3000ACE794F80C0190B16E701820287094F86D +:10AC40000C010028A2D000BF84F80C61D4F80E01DA +:10AC5000C5F8020094F80C010028F5D196E794F8A5 +:10AC60003201002808BFBDE8F0816E701520287001 +:10AC700094F83201002889D084F83261D4F8340184 +:10AC8000C5F80200B4F83801E88094F832010028D1 +:10AC9000F2D17BE7134A5061D17070472DE9F0473C +:10ACA0000446481E85B238BFBDE8F08704F10808A5 +:10ACB0000126DFF830904FF0080A0027B4F8D000E2 +:10ACC000401CA4F8D000B4F87C00401CA4F87C0020 +:10ACD0000AE000005C230200A1A201002FA50100F0 +:10ACE0005BA501000401002094F8690040B994F8C4 +:10ACF00063200023062104F1580004F052FCD8B16F +:10AD0000B4F87400401C80B2A4F87400B4F8761053 +:10AD100081422CBF0A1A0022A3885B1D934228BFE0 +:10AD200084F87A60884207D3A4F8747084F81261BA +:10AD300099F80300F0F7DEFF94F8860020B1B4F82C +:10AD40008200401CA4F8820094F88A0020B1B4F874 +:10AD50008800401CA4F8880094F8EC0040B994F8EE +:10AD600066200023012104F1580004F01AFC20B1F0 +:10AD7000B4F88000401CA4F8800094F863000C280C +:10AD800002D00D2820D067E0B4F85800411CB4F878 +:10AD9000FA00814260D1D4F8F400411C404607F02B +:10ADA00050F80221204604F034F9D4F8F400007879 +:10ADB000002808BFFFDF0121FF20FEF7E8FD84F82F +:10ADC000637084F8966047E0B4F85800411CD4F8EA +:10ADD000F000808881423FD1D4F83C0101780029FD +:10ADE00018BFFFDF22D12188C180D4F8F00041894B +:10ADF000D4F83C010181D4F8F0008189D4F83C01F9 +:10AE00004181D4F8F000C189D4F83C018181D4F8A3 +:10AE10003C010771D4F83C0180F800A0D4F83C0153 +:10AE20002188418099F80300F0F764FF0121204652 +:10AE300004F0EFF803212046FDF7ECF9D9F80800FB +:10AE4000D0F8F0000078022818BFFFDF0221FF20B1 +:10AE5000FEF79DFD84F86370B4F85800401C691E2D +:10AE6000A4F858008DB2BFF429AFBDE8F087FE4AC0 +:10AE7000C2E90601704770B50446B0F87C0094F84A +:10AE80006710002908BFC0F1020503D0B4F87E1096 +:10AE9000081A051F94F87A0040B194F86320002343 +:10AEA000092104F1580004F07CFBA0B1B4F87460EF +:10AEB00094F8690058B994F863200023062104F13E +:10AEC000580004F06EFB002808BF284603D0B4F8F1 +:10AED0007600801B001F8542C8BF0546002DD4BFE9 +:10AEE0000020A8B270BDF0B5DF4C83B0A06890F828 +:10AEF000C310FF2907BF6178002903B0F0BD90F8A7 +:10AF0000662000230121583004F04BFB00281CBFB1 +:10AF100003B0F0BDA06890F8EC1029B103B0022096 +:10AF2000BDE8F040FEF79ABC90F863200023194674 +:10AF3000583004F036FB48B1A06890F87A0028B188 +:10AF400003B01220BDE8F040FEF788BCA0680025E1 +:10AF500090F86320122A23D004DC032A47D0112A58 +:10AF600024D003E0182A3CD0242A4CD0002304210A +:10AF7000583004F016FB00281CBF03B0F0BDD4F815 +:10AF800008C0022701269CF864001A2800F01E81E0 +:10AF900041DC012873D002287FD0032863D03EE033 +:10AFA00003B00B20BDE8F040FEF758BCF8F7D5FD24 +:10AFB0000C283CBF03B0F0BDA0680821D0F8F00019 +:10AFC0001E30F8F7CBFD28B1A0680421B830F8F79F +:10AFD000C5FD00B9FFDF03B00320BDE8F040FEF778 +:10AFE0003DBC03B00620BDE8F040FEF737BC90F84A +:10AFF000C21080F8C4100720FEF730FCA06880F86B +:10B00000635003B0F0BD1820FEF728FCA068A0F83C +:10B01000825003B0F0BD1F2847D022287ED0DCF834 +:10B02000F0000178002900F010814088BCF8001081 +:10B03000884274D100239CF8632019460CF1580013 +:10B0400004F0AFFA00286AD0A068D0F8F0100978B0 +:10B05000022972D0032971D0042970D0052908BFB4 +:10B0600008206DD0F1E09CF8C1008CF8C4000720E6 +:10B07000FEF7F4FBA06800F0B0B900E00DE00C2092 +:10B08000FEF7ECFBA068A0F8885090F88E1041F015 +:10B09000010180F88E1000F0A0B91320FEF7DEFB4E +:10B0A000A068A0F8885000F098B99CF8FD0000282E +:10B0B0001CBF03B0F0BD9CF8FC0088B1BCF8FE00DA +:10B0C000ACF84000BCF80001ACF84200BCF802014A +:10B0D000ACF84400BCF80401ACF846008CF8FC5015 +:10B0E000FEF712FC0421A068FDF794F8A06890F820 +:10B0F0004E10012908BF80F84E7016D00288A0F8C3 +:10B100001621028EA0F81821828EA0F81A21428EF4 +:10B1100000F58671A0F81C21C08E01E011E094E0DA +:10B1200048820E72E078F0F7E5FD1520FEF796FBF9 +:10B13000A068A0F8885000F050B94CE051E071E0F0 +:10B1400058E09CF87B0058B18CF8E8508CF8E95036 +:10B150001820FEF783FBA068A0F8885003B0F0BD6C +:10B160009CF8070100281CBF03B0F0BD9CF8060145 +:10B17000002804BF03B0F0BDBCF84F10DCF8080194 +:10B18000ADF80410BCF85110ADF80010019904F0AE +:10B190007EFB9DF80020C1B28A4207BFA16881F8FA +:10B1A000E850A26882F8E8109DF80110C0F307206B +:10B1B000814219BFA16881F8E900A06880F8E950D0 +:10B1C000182003B0BDE8F040FEF748BB1120FEF7A1 +:10B1D00045FBA06801E190F8640004F0D5F9A0BB3C +:10B1E00008E090F8681041B190F86900002808BFA5 +:10B1F000FFDF0A20FEF732FB27E0F8F7AEFC0C2851 +:10B2000023D3A0680821D0F8F0001E30F8F7A6FC80 +:10B2100028B1A0680421B830F8F7A0FC00B9FFDF1E +:10B220000320E7E790F88E0010F0030F0DD10C20FB +:10B23000FEF714FBA068A0F8825080F8866090F8B2 +:10B240008E1041F0010180F88E10A06890F8C310B4 +:10B25000FF291CBF03B0F0BD90F8632000231946FE +:10B26000583004F09EF901E004010020002804BFDA +:10B2700003B0F0BDA06890F8F810E9B3A1690978AF +:10B28000D1BB90F8640004F07FF9A8BBA068B0F8C7 +:10B2900058100A2935D900F108010522E06906F0A5 +:10B2A000FFFB0028A06802BF80F8F85003B0F0BD93 +:10B2B000D0F8F400017869B1411C0522E06906F07C +:10B2C000EFFB00281CBF03B0F0BDA068D0F8F4006D +:10B2D000007830B9A068E169D0F8F400401C06F0AD +:10B2E000B0FDA068D0F8F4000178491C017001207D +:10B2F000FEF7B4FAA06800E003E080F8F85003B06D +:10B30000F0BDA06890F8FC1011B190F8FD1011B3D9 +:10B3100090F80611002904BF03B0F0BD90F80711A2 +:10B3200000291CBF03B0F0BD90F8640004F02CF9B4 +:10B3300000281CBF03B0F0BDA06890F8512090F821 +:10B340000811012A4DD0022A4ED0042A14BF082A1F +:10B3500004294BD05DE0B0F8FE10A0F84010B0F822 +:10B360000011A0F84210B0F80211A0F84410B0F893 +:10B370000411A0F8461080F8FC5090F864001E28D4 +:10B3800005D003B01420BDE8F040FEF767BAFEF721 +:10B39000BBFA0421A068FCF73DFFA06890F84E10AE +:10B3A000012908BF80F84E7013D00288A0F816213A +:10B3B000028EA0F81821828EA0F81A21428E00F584 +:10B3C0008671A0F81C21C08E48820E72E078F0F7DA +:10B3D00091FC1520FEF742FAA06880F8645003B093 +:10B3E000F0BD012915D101E0022912D190F85210C7 +:10B3F00090F80901012907D0022908D0042914BFB7 +:10B40000082904280BD004E0012802D107E0022813 +:10B4100005D003B01620BDE8F040FEF71FBA03B018 +:10B420000020BDE8F040FEF738BA70B5044690F849 +:10B43000630000250C2814D00D2818BF70BDB4F887 +:10B440005800D4F8F010401C8988884218BF70BD9D +:10B45000D4F83C01FE4E0178002918BFFFDF45D12A +:10B4600022E0B4F85800B4F8FA10401C884218BF23 +:10B4700070BDD4F8F400411C04F1080006F0E1FCB2 +:10B480000221204603F0C5FDD4F8F400007800281E +:10B4900008BFFFDF0121FF20FEF779FA84F863502F +:10B4A000012084F8960070BD2188C180D4F8F00096 +:10B4B000D4F83C1140890881D4F8F000D4F83C114C +:10B4C00080894881D4F8F000D4F83C11C089888183 +:10B4D000D4F83C010571D4F83C1108200870D4F868 +:10B4E0003C1120884880F078F0F704FC01212046C8 +:10B4F00003F08FFD03212046FCF78CFEB068D0F8E6 +:10B50000F0000078022818BFFFDF0221FF20FEF7BD +:10B510003EFA84F8635070BD70B5CD4CA16891F8C7 +:10B520006320162A11BF132A91F88C20002A627812 +:10B530001BBF02206070002A70BD81F8C00000258A +:10B5400081F88B5081F88650D1F8F0000988408846 +:10B55000884218BFFFDFA068D0F8F0000078032809 +:10B5600018BFFFDF0321FF20FEF711FAA068D0F813 +:10B570003C110A78002A18BFFFDF19D10288CA805F +:10B58000D0F83C2190F8C0101171D0F83C110D7228 +:10B59000D0F83C210C211170D0F83C210188518059 +:10B5A0000088F5F765FBF4F7C5FFE078F0F7A2FB3C +:10B5B000A06880F8635070BD10B5A54C207910F0DC +:10B5C000020F08BF10BD6078002818BF10BDE068EA +:10B5D000C078192880F06981DFE800F05F4F0D8F97 +:10B5E000F8F8A6223FF86F83B1F8F8F8F8F7E3E02F +:10B5F000F9F5F4F8F300A0680023012190F8662023 +:10B60000583003F0CEFF002818BF10BD0821A068F5 +:10B6100080F86610002180F8861080F88A1010BD2E +:10B62000A0680023194690F86420583003F0B9FF51 +:10B6300018B1A168002081F88A00A068002319468B +:10B6400090F86320583003F0ACFF002808BF10BD0D +:10B650000020A16881F8860010BDA068002319466B +:10B6600090F86320583003F09CFF002808BFFFDFEC +:10B670000420A16881F8630010BDA068002319466A +:10B6800090F86320583003F08CFF002808BFFFDFDC +:10B690000C20A16881F8630010BDA0680023194642 +:10B6A00090F86320583003F07CFF002808BFFFDFCC +:10B6B0000D20A16881F8630010BDA0680023194621 +:10B6C00090F86320583003F06CFF002808BFFFDFBC +:10B6D0000121A06880F88B105FF00F0180F86310E3 +:10B6E00010BDA06890F86300122818BFFFDF012189 +:10B6F000A06880F88C101121F0E7A068002319469B +:10B7000090F86320583003F04CFF28B9A06890F8F7 +:10B710008C00002808BFFFDF0121A06880F88B1093 +:10B72000132180F8631010BDA06890F863001828FA +:10B7300018BFFFDF1B20A16881F8630010BDA0685F +:10B74000D0F8F01003884A889A4204BF0978042987 +:10B7500019D190F8632000231946583003F021FFD7 +:10B76000002808BFFFDFA06890F88E1011F0020FCC +:10B7700004BF012180F8631005D0002180F88610F5 +:10B78000D0F8F0000170A0680023194690F86420FA +:10B79000583003F006FF002808BF10BD0020A16844 +:10B7A00080E0A0680023194690F86320583003F029 +:10B7B000F8FE002808BFFFDF0520A16881F86300BC +:10B7C00010BD30E01FE012E001E067E06DE0A0682E +:10B7D0000023194690F86320583003F0E2FE002859 +:10B7E00008BFFFDF1D20A16881F86300E8E7A068BB +:10B7F0000023194690F86420583003F0D2FE002848 +:10B8000008BFFFDFCAE7A0680023194690F863204D +:10B81000583003F0C6FE002808BFFFDF2020A168D3 +:10B8200081F86300CCE7A06890F8641022291DD04D +:10B8300090F86310242918BFFFDFC1D190F8E810F9 +:10B84000002906BF90F8E9100029252102E0000038 +:10B850000401002018BF80F863107FF4F9AE0021C6 +:10B8600080F863100846FEF718F8F1E690F8E81043 +:10B87000002907BF90F8E9100029252180F86410FD +:10B880008CD1002180F8641080F87B1090F80601BC +:10B8900000281CBF0020FEF700F87FE7A168002009 +:10B8A00081F8640081F88A008AE7FFDF88E70000FA +:10B8B00070B5FC4CE1680A88A1F8E62181F8E40142 +:10B8C00091F85100012808BF012508D0022808BFBF +:10B8D000022504D0042816BF08280325FFDFE068EE +:10B8E00080F8E85190F85200012808BF012508D0DF +:10B8F000022808BF022504D0042816BF0828032503 +:10B90000FFDFE068012180F8E95180F8E2110021B1 +:10B9100080F89211E078BDE87040F0F7EBB9F0B430 +:10B92000E048C06890F84E30478EC68E458FB0F81C +:10B930004010C28FB0F842C0022B1FD08D4238BFDA +:10B9400029460186624528BF62468286018FB0F88B +:10B950004430994238BF0B464386818FB0F8464049 +:10B96000A14238BF0C46C486BB4228BF1F4647864B +:10B97000B44228BF2646C686F0BC7047038E9D425F +:10B9800028BF1D46838E9A4228BF1A46A94298BFF7 +:10B990000D460586944598BF62468286002180F850 +:10B9A0004E10D3E72DE9F04FBE4C83B0207910F054 +:10B9B000010F04BF03B0BDE8F08F606901230521CA +:10B9C000C578E06890F86420583003F0EAFD00285C +:10B9D00018BF022D0BD00A2D18BF0B2D07D0032D39 +:10B9E00018BF062D03D0607840F0080060706078C2 +:10B9F00000281CBF03B0BDE8F08F60690227012654 +:10BA000090F8038000254FF02009B8F1000F1CBF0B +:10BA1000B8F1010FB8F1160F1FD1E06890F863007C +:10BA200003F0B2FDC8B1E16891F86300202814D09A +:10BA3000212808D0B8F1160F0CBF84F80190677068 +:10BA400003B0BDE8F08F262081F86300B8F1160F2F +:10BA500000F0AE822A20FFF72BFFB8F1190F80F01B +:10BA6000E282DFE808F046230DC1FEFEFDFCFBFE8E +:10BA700091B8FAFEFEFEFEF9F8F7F6F5F4FEF300D3 +:10BA8000E0680123194690F86620583003F089FDDC +:10BA9000002840F04D84606904F0EEF9E16881F817 +:10BAA0006801072081F8660000F042BCE0680123CD +:10BAB000002190F86420583003F073FD002800F056 +:10BAC000F083606904F0D3F9E168A1F87C01B1F872 +:10BAD0005820801A00B247F6FE728242A8BF0028A2 +:10BAE0004BDD01F5BF71606904F0B8F90B20E16826 +:10BAF0003FE0E0680123002190F86420583003F013 +:10BB000050FD002800F0CD83606904F083F900281F +:10BB100000F08982606904F07AF9E168A1F87C019B +:10BB2000B1F85820801A00B247F6FE728242A8BFD0 +:10BB3000002822DD606904F064F9E16881F87E0183 +:10BB4000606904F059F9E168A1F88001606904F0C6 +:10BB50003EF9E168A1F88201606904F03FF9E1680B +:10BB6000A1F88401606904F040F9E168A1F8860158 +:10BB70000D2081F8640000F0DBBB282081F8730001 +:10BB800081F8726000F0D4BBE0680123002190F8D6 +:10BB90006420583003F005FD0028E0680CD0A0F8C0 +:10BBA000885090F88A10491C80F88A105FF01001C4 +:10BBB00080F8641000F0BCBB90F8642001230521DC +:10BBC000583003F0EEFC00281CBF0820607040F0E5 +:10BBD000AF8300F066BBE06890F86410112908BFDD +:10BBE000122140F09282E3E7E0680123002190F8FF +:10BBF0006420583003F0D5FC80B9E06890F86420E8 +:10BC0000122A0BD001230521583003F0CAFC00286A +:10BC100018BF082000F0458300F0C7B9E06890F82D +:10BC20008C1031B9A0F8885090F88A10491C80F81F +:10BC30008A1000F1E001606904F037F9E06800F172 +:10BC4000B801606904F03CF9E0680BE01BE2AFE189 +:10BC500059E1F1E0CFE0DBE0EAE23AE0A2E0FFE226 +:10BC600022E072E190F8AA01002818BFFFDFE06827 +:10BC70000188A0F8AC1100F5D771606904F003F9F0 +:10BC8000E06800F5DB71606904F005F9E06880F8B0 +:10BC9000AA61142180F86410E078F0F72BF800F026 +:10BCA00047BB000024010020E06890F864101729C9 +:10BCB00040F02B8290F88A10491E49B280F88A1011 +:10BCC0000029B8BFFFDF1C20E16881F8640000F0A4 +:10BCD0002FBBE06890F8651011F0020F09D090F8C2 +:10BCE000632001230821583003F05BFC002800F09A +:10BCF000D882E06890F88E0010F0020F17D16069CA +:10BD000004F0FCF8E16881F88F00606904F0F8F84D +:10BD1000E168A1F89000606904F0F5F8E168A1F825 +:10BD2000920091F88E0040F0020081F88E00E068E9 +:10BD300090F88E1011F0010F05D0E06890F86310B4 +:10BD400006291CD114E090F8650010F0020F18BF0E +:10BD5000FFDFE06890F8651041F0020180F865109F +:10BD6000A0F8885090F88A10491C80F88A10E4E7FF +:10BD700080F8635080F88650E078EFF7BBFFE0680A +:10BD800090F87A11042940F0D38280F87A51E07853 +:10BD9000EFF7B0FFE06890F86310002940F0C88228 +:10BDA00000F043BAE06890F8650010F0010F7BD115 +:10BDB0006946606904F0B7F8E0689DF8002090F8E3 +:10BDC0009410114001F02F0180F8941090F8951014 +:10BDD0009DF80120114001F0410180F89510A0F874 +:10BDE000885090F88A10491C80F88A1090F86510E5 +:10BDF00041F001011CE0E0680123092190F8632073 +:10BE0000583003F0CEFB002800F04B8200F041BA1E +:10BE1000E06890F8651011F0040F40F04282A0F83D +:10BE2000885090F88A2041F00401521C80F88A2042 +:10BE300080F8651000F07CBAE06890F8650010F0BA +:10BE4000300F31D1606904F08BF800287DD0606933 +:10BE500004F082F8E1680887606904F079F8E16825 +:10BE60004887606904F07AF8E1688887606904F0BF +:10BE700071F8E168C887207910F0020F03D02069BB +:10BE8000C078142811D091F863001D280DD091F8C6 +:10BE90004E0001280BD091F88901002804BF91F8C9 +:10BEA000880100280AD002E074E081F84E6091F821 +:10BEB000650040F0100081F865001AE091F8650017 +:10BEC00040F0200081F865000A88A1F8CA210A8F95 +:10BED000A1F8CC214A8FA1F8CE218A8F01F5CB7031 +:10BEE000A1F8D021C98F818780F83260E078EFF720 +:10BEF00001FFE068A0F8885090F88A10491C80F88B +:10BF00008A1000F015BAE06801230A2190F8632036 +:10BF1000583003F046FBE8B3606904F021F8B8B18B +:10BF2000606904F019F8E1680887606904F010F8A6 +:10BF3000E1684887606904F011F8E1688887606902 +:10BF400004F008F8E168C88700E06CE0FFF7E7FC60 +:10BF5000E068052180F8865080F86350FDF7FBFA11 +:10BF6000E06890F84E10012908BF80F84E7000F08C +:10BF7000DF810288A0F8BE21028EA0F8C021828E47 +:10BF8000A0F8C221428E00F5CB71A0F8C421C08E6A +:10BF9000088600E006E081F82660E078EFF7AAFE68 +:10BFA00000F0C6B9607840F00100607000F0C0B9E0 +:10BFB000E06801230B2190F86420583003F0F1FA77 +:10BFC00020B100BF84F8019000F0B2B9E06801230D +:10BFD000002190F86420583003F0E3FA002800F0C4 +:10BFE0006081E06890F863002528EBD0606903F079 +:10BFF000DAFFC0B1606903F0D4FFE16800F0070028 +:10C0000081F85000606903F0C8FF00F00701E068A4 +:10C0100080F84F1090F89321002A04BF90F89221E5 +:10C02000002A04D022E001F0DEF900F081B990F896 +:10C0300052C090F8503000F151028C4502BF117887 +:10C04000994280F87B6011D000F5CB7180F8DC61FB +:10C050000288A0F8DE2190F84F2080F8E02190F8C7 +:10C06000500081F84B00E078EFF744FEE0682221B1 +:10C0700080F86410A0F8885090F88A10491C80F865 +:10C080008A1000F055B9E06890F8631021290CBFC0 +:10C090004FF001084FF0000890F86410232908BF02 +:10C0A00000F1640705D0B8F1000F18BF00F1630775 +:10C0B0002BD0606903F099FFF0B3D4F81490484690 +:10C0C00003F087FF0090484603F087FF8146E06851 +:10C0D00090F89211002907BF4FF0000BDA4690F854 +:10C0E00094B190F895A1484603F05AFBB0B1E268CC +:10C0F00092F85110814211D019EA0B0F41D0B8F1DA +:10C10000000F08BF012802D008E0677010E1022983 +:10C1100004BF92F8500010EA090F32D0009803F0E3 +:10C120003FFB68B1009803F03BFBE16891F85210C7 +:10C13000884205D0009800E023E010EA0A0F20D0E2 +:10C140006A466169E06803F03AFBD8B3606903F0BE +:10C150004AFFE168A1F87C01B1F85820801A00B2CA +:10C1600047F6FE728242A8BF00284ADD9DF8000013 +:10C1700081F87E019DF8010081F87F01252038704B +:10C1800044E0E06890F8920100281CBF1E20FFF7F1 +:10C190008FFBB8F1000F16D0606903F012FEE16862 +:10C1A00081F8C20006FA00F010F0807F08BFFFDFC0 +:10C1B0000A21E06880F8631090F88600002808BF24 +:10C1C000FFDF0DE010E03D70E16891F88A00401E4D +:10C1D00040B281F88A000028B8BFFFDF01F003F900 +:10C1E000E06880F87B50A3E0E06890F892010028B6 +:10C1F0001CBF0020FFF75CFB3D70E06880F87B50BF +:10C2000004E0282081F8730081F87260E06800F192 +:10C2100064018F4209D190F88A10491E49B280F812 +:10C220008A100029B8BFFFDF82E080F886507FE0E7 +:10C23000606903F0F6FE16287AD1E06890F8630092 +:10C24000212802D0262805D072E0606903F0EDFEB7 +:10C25000FFF72EFBE06880F8635080F8865067E0B7 +:10C26000E06890F863000E2804D1606903F054FE82 +:10C27000122805D0E06890F863001D2818D112E05C +:10C28000E0680123092190F86320583003F089F910 +:10C2900038B1E06880F87A5080F8865080F86350B2 +:10C2A00046E0667044E0606903F036FE142805D06D +:10C2B000E06890F8630021282BD125E0E068052193 +:10C2C00080F8635080F88650FDF745F9E16891F8F1 +:10C2D0004E00012808BF81F84E7029D00A88A1F8C5 +:10C2E000BE210A8EA1F8C0218A8EA1F8C2214A8EF1 +:10C2F00001F5CB70A1F8C421C98E018680F82660B3 +:10C30000E078EFF7F7FC13E0606903F005FE16280C +:10C3100005D0606903F000FE172809D113E0E0683A +:10C3200080F8635080F886505FF01A00FFF7C0FA7B +:10C33000E068D0E928134A1C43F10001C0E9282134 +:10C3400003B0BDE8F08FE06890F864102329EFD1C6 +:10C3500080F8645090F88A10491E49B280F88A101B +:10C360000029B8BFFFDFE06880F87B5090F89201A9 +:10C37000002818BF0020DBD0D8E770B5F84E05467E +:10C380000C46F06890F8C300FF2818BFFFDFF26882 +:10C390000020002C82F8C3501CBFA2F8880070BD9A +:10C3A000A2F88200012082F8860070BD10B584B02A +:10C3B00004466846F9F772F8002808BFFFDF0098C6 +:10C3C00003F03DFC0321009803F050FC0098017835 +:10C3D00021F010010170214603F0C5FCA01E1628B3 +:10C3E00073D2DFE800F00BAA4EABAB13AA5CAAAB8A +:10C3F0001B2CAAAAAAAAABAB31734B8DD848C06834 +:10C4000090F8C410009803F035FD97E0D448C06858 +:10C4100090F8C410009803F07DFD8FE0D04CA06828 +:10C420000178009803F060FDA0688188009803F00F +:10C430005DFDA0684188009803F05CFD7EE0062168 +:10C44000009803F063FD79E0C54CE068B0F8441053 +:10C45000009803F06DFDE068B0F84610009803F016 +:10C460006BFDE068B0F84010009803F069FDE068EB +:10C47000B0F84210009803F067FD5FE0B84CE06848 +:10C4800043E0B74CE06800F1E801009803F01CFDC0 +:10C49000E06800F1BC01009803F020FD4EE00020B0 +:10C4A00002900390AE48C06890F8941001F0F50136 +:10C4B0008DF8081090F8950002A900F041008DF861 +:10C4C0000900009803F05DFD38E036E0A44CE06818 +:10C4D000B0F84010009803F033FDE068B0F8421067 +:10C4E000009803F031FDE068B0F84410009803F0C4 +:10C4F0001FFDE068B0F84610009803F01DFD1DE038 +:10C50000974CE06890F8921159B190F89411009806 +:10C5100003F041FDE06890F89511009803F03FFDAD +:10C520000CE090F85110009803F035FDE06890F8A9 +:10C530005210009803F033FD00E0FFDFF8F7C1FF71 +:10C54000002808BFFFDF04B010BD70B50C460546DB +:10C550004FF4F871204605F068FB258070BDF4F7B4 +:10C560005EBB2DE9F0410D4607460721F4F776FA48 +:10C57000040008BFBDE8F08194F896010026C8B118 +:10C580006E700820287094F8960188B1268484F88B +:10C590009661D4F89801C5F80200D4F89C01C5F85A +:10C5A0000600B4F8A001688194F896010028EDD146 +:10C5B000AE7044E094F8A201002837D094F8A201AC +:10C5C0000C2818D00D2818BFFFDF38D12088F4F7C9 +:10C5D0004FFB0746F3F7C4FFA0B96E700D2028701B +:10C5E00094F8A401A8702088A88084F8A261384635 +:10C5F000F3F7B0FF23E02088F4F73AFB0746F3F7A0 +:10C60000AFFF10B10020BDE8F0816E700C202870E3 +:10C6100094F8A401A8702088A88094F8A801A871B3 +:10C6200084F8A2613846F3F795FF08E094F8DA0140 +:10C6300040B16E700F20287084F8DA616F8001209D +:10C64000BDE8F08194F8AA0180B16E7009202870CD +:10C6500020886880D4F8AE01D4F8B2116860A9606F +:10C66000B4F8B601A88184F8AA61E8E794F8B801A3 +:10C6700040B16E7017202870B4F8BA01688084F851 +:10C68000B861DCE794F8D40188B16E701820287086 +:10C6900094F8D4010028D2D084F8D461D4F8D6011B +:10C6A000C5F8020094F8D4010028F5D1C7E794F842 +:10C6B000BC01C8B16E701420287094F8BC01002829 +:10C6C000BDD000BF84F8BC61D4F8BE01C5F802003B +:10C6D000D4F8C201C5F80600B4F8C601688194F820 +:10C6E000BC010028EED1AAE794F8C80180B16E70B1 +:10C6F0001A20287084F8C861D4F8CA01C5F802006D +:10C70000D4F8CE01C5F80600B4F8D201688196E7E6 +:10C7100094F8DC0140B11B20287084F8DC61D4F867 +:10C72000DE01C5F802008AE794F8E201002808BF9C +:10C73000BDE8F0816E701520287094F8E2010028A1 +:10C740003FF47DAF84F8E261D4F8E401C5F802005B +:10C75000B4F8E801E88094F8E2010028F2D16EE72D +:10C7600024010020FA4A9060D1707047002180F8BF +:10C77000631080F8641080F8671090F8D61011B13B +:10C780000221FCF7E8BE0321FCF7E5BE2DE9F047E6 +:10C79000EF4C81460D46E0680088F4F77BFA06000E +:10C7A00008BFFFDF60782843607020794FF00005F4 +:10C7B00010F0200FE0681CBFA0F87C5080F8DC501F +:10C7C00004D1B0F87C10491CA0F87C10E068012767 +:10C7D00090F8691039B990F8642001230621583087 +:10C7E00002F0DFFE48B3A08810F4006F07D0E068C5 +:10C7F00090F86910002918BFA0F874501DD1E068A6 +:10C80000B0F87410491C89B2A0F87410B0F87630F2 +:10C810008B422CBF5A1A0022B4F806C00CF1050C4A +:10C82000624598BF80F87A70994206D3A0F8745098 +:10C8300080F8DA71E078EFF75DFA20794FF0020ABC +:10C8400010F0600F11D0E06890F8671011B1032963 +:10C8500006D00AE080F867700121FCF77CFE04E056 +:10C8600080F867A00121FCF776FEE06890F8671079 +:10C87000012905D1A18811F4807F18BF80F867A035 +:10C880004FF00808B9F1000F40F03281A18811F48F +:10C89000007F18BFA0F8F05004D1B0F8F020521C6F +:10C8A000A0F8F02011F0080F47D06178002944D19A +:10C8B00090F8C300FF2808BFFFDFFF21E06880F881 +:10C8C000C31090F86410192905D0E06890F863103F +:10C8D00020290FD028E080F88B5090F88A10491E4C +:10C8E00049B280F88A100029B8BFFFDFE06880F8FD +:10C8F0006450EAE790F8640002F046FE80B1E06818 +:10C900002621012380F8631090F864200B21583011 +:10C9100002F047FE002804BF2A20FEF7C9FF03E00B +:10C92000E168212081F86300E06890F8661008292A +:10C9300004BF84F800A080F86650FFF733F8207930 +:10C9400010F0040F09D0607838B9E06890F86610EC +:10C95000072904BF277080F8665000F0C5FB2079D6 +:10C9600010F0100F09D0607838B9E06890F86410C2 +:10C970000B2904BF0C2180F86410A07810F0080F78 +:10C9800011D0E0680123052190F86420583002F0AE +:10C9900008FE28B184F80180E06880F8A25102E026 +:10C9A000002001F07CFA00F03CFD01F06EFA002856 +:10C9B000E06818BFA0F8D05004D1B0F8D010491CDE +:10C9C000A0F8D01001F064FA40B1E16891F8DC0001 +:10C9D00002289CBF401C81F8DC0004D8E06890F875 +:10C9E000DC00022806D9E068A0F8D050A0F8D250A8 +:10C9F00080F8DC50E0680123002190F86420583072 +:10CA000002F0CFFD20B9E06890F864000C2859D1FD +:10CA1000E0680123002190F86320583002F0C1FD46 +:10CA200000284FD0E0680123002190F8662058309C +:10CA300002F0B7FDF0B3E06890F86710022904BF78 +:10CA400090F8DC0000283DD13046F3F70FFB88B3A7 +:10CA5000E06890F8C310FF2934D1B0F8CA1001295A +:10CA600030D980F8D570B0F87E10B0F87C208B1EDD +:10CA70009A42AFBF0121891A491E89B2B0F8D0305D +:10CA8000E28893422FBF0122D21A521C92B29142E5 +:10CA900088BF1146012908BF80F8D55090F8612160 +:10CAA000A2B1B0F8D220B0F8620182422CBF0120BE +:10CAB000801A00E006E03CBF401C80B2814288BF83 +:10CAC000014603E0E068012180F8D550E068B0F845 +:10CAD0005820114489B2A0F8CC1090F86730002B90 +:10CAE00018BF012B5FD0022B1CBF032BFFDF09D027 +:10CAF000A088C0F340200028E06818BFA0F8DE50EE +:10CB00005BD153E090F86630082B23D0B0F87C104E +:10CB1000B0F87E2000268B1C9A4206D3511A891E3B +:10CB20000E04360C1CBF711E8EB290F87A1051B1F3 +:10CB300090F8632001230921583002F032FD0028CB +:10CB400008BF00262BD0E06890F8691099B90AE078 +:10CB500024010020B0F87C30032B24D3B0F87E10E1 +:10CB60001144491C1FE090F864200123062158302D +:10CB700002F017FD78B1E1680020B1F87620B1F835 +:10CB800074108B1C9A4203D3501A801E18BF401E8B +:10CB9000B04238BF86B2002E1CBF701E86B2E0685D +:10CBA000B0F8CC103144A0F8C810A1E7B0F8DE10FE +:10CBB000B0F8CE201144A0F8DE10E06890F86611BD +:10CBC00039B990F8662001231946583002F0E9FC83 +:10CBD00038B1E068B0F88010B0F8CE201144A0F869 +:10CBE0008010E06890F8863033B1B0F88210B0F869 +:10CBF000CE201144A0F8821090F98AC0BCF1000F39 +:10CC000006DDB0F88810B0F8CE201144A0F88810E6 +:10CC10003D22B9F1000F18BF80F873204DD1217863 +:10CC2000022910D0012908BF90F8681143D061781B +:10CC300039B380F8727011F0140F18BF1E210CD098 +:10CC400080F8731055E090F8C410062905BF90F8DD +:10CC5000C3100229162106212DE011F0080F18BF7C +:10CC600080F8732045D111F0200F18BF2321E7D1A0 +:10CC700011F0030F08BFFFDF2A20E16881F873007D +:10CC800033E02BB1B0F88210B0F88420914211D279 +:10CC9000BCF1000F05DDB0F88810B0F88420914297 +:10CCA00008D2B0F88020B0F87E108A4208D390F8FD +:10CCB00066212AB1222180F8731080F8727018E082 +:10CCC00090F867203AB1B0F87C208A4228BF80F8FB +:10CCD0007380F2D209E0B0F87C10062905D33E211A +:10CCE00080F8731080F8727003E0E06890F87210BA +:10CCF00079B1E06880F8635080F8645080F867503C +:10CD000090F8D610002914BF02210321FCF723FC60 +:10CD100002E00021FCF71FFCE06880F8D650BDE877 +:10CD2000F047F8F7F0BBF949024648788B7818438A +:10CD30000ED10846C0684AB1097911F0080F03D036 +:10CD400090F86600082803D001207047FCF74FBB1D +:10CD5000002070472DE9F041EC4C05460E46A088B6 +:10CD60002843A08015F0020F04D015F0010F18BF62 +:10CD7000FFDF266115F0010F4FF000084FF00107AB +:10CD80001CD03046666103F01CF8062802D00B2840 +:10CD90000BD013E0E06890F8641017290ED1002141 +:10CDA000C0E9261180F8687008E0E06890F8641027 +:10CDB000112904BF80F8688080F88C7015F0020F8C +:10CDC00018D02069C078052802D00B280BD011E0BC +:10CDD000E06890F8641015290CD10021C0E92811F1 +:10CDE00080F8697006E0E06890F86410102908BFC8 +:10CDF00080F8698015F0800F1CBF0820A070BDE886 +:10CE0000F0812DE9F84FC14C00254FF00108A580B5 +:10CE10006570A5702570E06068F30709074680F823 +:10CE2000D6800088F3F736FF5FEA000A08BFFFDF0D +:10CE3000E0680088F8F72FFBE0680088F8F751FBFE +:10CE4000E068B0F8CA1071B190F8C310FF290FD193 +:10CE500090F8661191B190F8662001231946583078 +:10CE600002F09FFB98B1E06890F8C300FF2805D05E +:10CE7000E06890F8C30000BFFFF798FAD4F80CC040 +:10CE80009CF8D700002818BFE5801ED10FE0E068AD +:10CE9000A0F8805090F8671180F8C410002102209B +:10CEA000FFF76BFAE06880F8D5500220E4E79CF8C1 +:10CEB000960138B9BCF82000BCF80410884288BF3D +:10CEC000E08002D8BCF80400E080BCF8CE00401E30 +:10CED00086B2BCF8D0003044ACF8D0009CF8D40046 +:10CEE00000281CBFACF8D2508CF8D45004D1BCF848 +:10CEF000D2003044ACF8D200BCF87C003044ACF82E +:10CF00007C009CF8690040B99CF86420012306214C +:10CF10000CF1580002F045FB28B1E068B0F874103D +:10CF20003144A0F87410E068B0F8CA1001299CBF21 +:10CF3000491CA0F8CA10002E18BF80F8DC5090F8E9 +:10CF4000D510A1B1B0F8D000E18888420FD2504688 +:10CF5000F3F78CF858B1E06890F8611139B1B0F886 +:10CF6000D210B0F86201814228BF00F094FFE2685D +:10CF700082F8D55092F864000B2818BF0C2817D1FE +:10CF8000B2F85810B2F87C31C91A09B200290FDB87 +:10CF900002F5BF7102F1080004F053FF0221E068BE +:10CFA00001F0FEFEE06880F8645080F8968048E06A +:10CFB000252824D1B2F85800B2F87C11401A00B2EA +:10CFC00000281CDB92F8921192F87E01002808BF1D +:10CFD00092F8510082F8510092F87F01002808BFB2 +:10CFE00092F8520082F8520000291CBF0020FEF780 +:10CFF0005FFCE06880F8645080F87B5021E092F894 +:10D00000630025281DD1B2F85800B2F87C11401AEF +:10D0100000B2002815DB92F87E01002808BF92F8C4 +:10D02000510082F8510092F87F01002808BF92F861 +:10D03000520082F852000020FEF73AFCE06880F8C7 +:10D040006350E16801F15800B1F8CE2002F0B3F866 +:10D05000E06890F86111002918BFA0F8D2502C4860 +:10D0600000902C4B2C4A3946484600F053FEE068AD +:10D070000123052190F86420583002F092FA00282C +:10D0800008BFBDE8F88FBDE8F84F00F014BC00F011 +:10D09000E1BE10B50446B0F882214388B0F884118F +:10D0A000B0F886019A4201BFA3889942E38898426A +:10D0B0000FD02388A4F89A31A4F89C21A4F89E11DB +:10D0C000A4F8A001012084F896011048C078EEF77A +:10D0D00011FE0121204601F063FE002084F8640067 +:10D0E000032084F8670010BD70B5084C207910F05B +:10D0F000020F08BF70BD6078002818BF70BD20699E +:10D10000C178891E162980F06C8107E02401002077 +:10D110008DC7010027CD010055CD0100DFE801F0EA +:10D120000BF969758B1BF942F95BBE80F9F9F9F9C6 +:10D13000FAF7F6F5F4F3E0680123194690F8662053 +:10D14000583002F02EFA002818BF70BD0820E168A0 +:10D1500081F8660070BD02F0DFFEE16891F863209F +:10D160000A2A04BF91F8C220824205D1002081F82A +:10D17000630081F8860070BD91F8650010F0080F1B +:10D1800004BFFFDF70BD20F0080081F8650091F852 +:10D190008A00401E40B281F88A000028A8BF70BDF6 +:10D1A00000F0D8B8E06890F8650010F0010F08BFF3 +:10D1B000FFDFE16891F88A00401E40B281F88A00E2 +:10D1C0000028B8BFFFDFE06890F8651021F001018A +:10D1D00080F8651070BDE06890F86400102818BFF2 +:10D1E000FFDF0121E06880F88B10112180F86410C6 +:10D1F00070BDE06890F86400142818BFFFDF0121BB +:10D20000E06880F88B101521F0E7E06890F8640082 +:10D21000152818BFFFDF1720E16881F8640070BD92 +:10D22000E06890F86400152818BFFFDF1920E16856 +:10D2300081F8640070BDE06890F864001C2818BF95 +:10D24000FFDF0025E06880F88B5090F8A2010028ED +:10D2500018BFFFDFE06890F88C1041B180F88C5067 +:10D260000188A0F8A61180F8A4510D2108E00188DA +:10D27000A0F8A61180F8A451012180F8A8110C2172 +:10D2800080F8A2110088F3F7F3FCF3F753F9E07884 +:10D29000EEF730FDE06880F8645070BDE06890F80B +:10D2A0007A11042915D0E06890F8651011F0020F8A +:10D2B00008BF70BD90F88A10491E49B280F88A10E4 +:10D2C0000029B8BFFFDFE06890F8651021F0020187 +:10D2D0007EE790F8632001230021583002F061F9C5 +:10D2E000002808BFFFDFE06890F88E1011F0020FF1 +:10D2F00007BF062180F86310002180F8861018BF50 +:10D3000080F87A11CFE760E04FE035E024E011E0EB +:10D3100000E066E0E0680123002190F863205830C7 +:10D3200002F03FF9002808BFFFDF0E20E16881F816 +:10D33000630070BDE06890F8651021F0040180F88A +:10D34000651090F88A10491E49B280F88A100029A9 +:10D35000A8BF70BDFFDF70BDE0680123002190F819 +:10D360006320583002F01DF9002808BFFFDF1D20A0 +:10D37000E16881F8630070BDE06890F8650000F036 +:10D380003000102818BFFFDFE06890F8651021F02A +:10D39000100180F8651090F88A10491E49B280F893 +:10D3A0008A100029A8BF70BDD4E7E06801230021DE +:10D3B00090F86320583002F0F4F8002808BFFFDF2F +:10D3C0002020E16881F8630070BDE06890F8640097 +:10D3D00022281CBF0028FFDF2320E16881F86400B9 +:10D3E00070BDFFDF70BD10B5FE4CE16891F86500BF +:10D3F00010F0080F1EBF0120607010BD40F0080043 +:10D4000081F86500606902F0DCFCE16881F8C10028 +:10D410000020A1F8880091F88A00401C81F88A0059 +:10D4200010BD2DE9F041EF4CE06890F8C310FF29E2 +:10D4300006BF61780029BDE8F08190F866200123DD +:10D440001946583002F0ADF8002818BFBDE8F08149 +:10D45000E068002790F8661159B1A0F8807090F844 +:10D46000671180F8C410BDE8F04100210220FEF7EA +:10D4700084BF90F8642001230421583002F091F811 +:10D480005FEA00084FF002054FF001060CD0D4F817 +:10D490000CC09CF8640010287ED014287DD015287C +:10D4A0007CD01C287BD0E1E0E16891F8650010F0A9 +:10D4B000010F05D0BDE8F04101210920FEF75DBF55 +:10D4C00010F0020F0CD001210C20FEF756FFE0688F +:10D4D00090F88E1041F0010180F88E10BDE8F081C7 +:10D4E00010F0040F05D0BDE8F04101211320FEF734 +:10D4F00044BF10F0080F09D091F8C10081F8C400B2 +:10D50000BDE8F04101210720FEF737BF10F0100FF2 +:10D5100002D091F8890120B191F8640022287DD1D0 +:10D520009BE091F8880188B1B1F88A01A1F8400028 +:10D53000B1F88C01A1F84200B1F88E01A1F84400C5 +:10D54000B1F89001A1F8460081F88871FEF7E7F97B +:10D550000521E068FBF7FFFFE06890F84E10012915 +:10D5600008BF80F84E5014D00288A0F8BE21028E69 +:10D57000A0F8C021828EA0F8C221428E00F5CB71A6 +:10D58000A0F8C421C08E088681F82660E078EEF706 +:10D59000B1FB0121152003E006E00BE023E056E09B +:10D5A000BDE8F041FEF7E9BEBDE8F04101210B20E6 +:10D5B000FEF7E3BEF6F7D1FA0C2838BFBDE8F081DC +:10D5C0000821E068E830F6F7C9FA28B1E0680421DC +:10D5D000BC30F6F7C3FA00B9FFDFBDE8F041012126 +:10D5E0000420FEF7CABE9CF86901012817D0022862 +:10D5F00018BFBDE8F0819CF88C0000281CBF0620F5 +:10D600008CF8C4004FF0010114BF02200D20FEF77A +:10D61000B4FEE06880F86971BDE8F08126E09CF80E +:10D62000A201002818BFBDE8F0810CF1A803002278 +:10D630000CF1E0010CF5B57001F03BFF0121052074 +:10D64000FEF79BFEE06880F86971BDE8F081BDE8F7 +:10D65000F04101210620FEF790BE91F87B00C0B991 +:10D6600091F8920110B191F8930190B1E068012313 +:10D67000002190F86320583001F093FFC8B1E068B2 +:10D680000123042190F86420583001F08AFF30B162 +:10D690000FE0BDE8F04101211720FEF76EBEE06803 +:10D6A00090F87A0028B1BDE8F04100211220FEF781 +:10D6B00064BEE06890F863200A2A4DD0B8F1000FEC +:10D6C00018BFBDE8F08101230021583001F069FF47 +:10D6D00048B1E06890F87A11042904BF90F88E00F0 +:10D6E00010F0030F42D0E0680123002190F863207E +:10D6F000583001F056FF002808BFBDE8F081E0680F +:10D7000090F8881111B190F88911E1B390F8921155 +:10D71000002908BFBDE8F08190F89311002918BFD7 +:10D72000BDE8F08190F8642001230B21583001F00E +:10D7300038FF002818BFBDE8F081E06890F851205C +:10D7400090F89411012A71D0022A73D0042A14BFD0 +:10D75000082A042970D082E090F8C21080F8C41022 +:10D76000BDE8F04100210720FEF707BE00210C2094 +:10D77000FEF703FEE06890F88E1041F0010180F89A +:10D780008E10BDE8F081FFE7B0F88A11A0F84010D4 +:10D79000B0F88C11A0F84210B0F88E11A0F8441027 +:10D7A000B0F89011A0F8461080F8887190F86500E4 +:10D7B00010F0200F34D0FEF7B2F80521E068FBF737 +:10D7C000CAFEE06890F84E10012908BF80F84E505C +:10D7D00017D00288A0F8BE21028E00F5CB71A0F808 +:10D7E000C02101E024010020828EA0F8C221428ED7 +:10D7F000A0F8C421C08E088681F82660E078EEF794 +:10D8000079FA01211520FEF7B8FDE06890F865105F +:10D8100021F0200141F0100180F86510BDE8F08191 +:10D82000BDE8F04100211420FEF7A7BD012916D163 +:10D8300002E0FFE7022912D190F8522090F89511EA +:10D84000012A07D0022A08D0042A14BF082A042972 +:10D8500022D004E0012902D11EE002291CD090F858 +:10D86000642001230321583001F09BFE002818BFDB +:10D87000BDE8F081E0680123022190F8642058306F +:10D8800001F08FFE002818BFBDE8F0810021BDE83F +:10D89000F0411620FEF771BDBDE8F0410020FEF713 +:10D8A00007B8000030B5FF4C05462078002818BFA7 +:10D8B000FFDFA57230BDFB49012048727047FA486E +:10D8C00000B502784168406801F1580C91F8633066 +:10D8D00090F85100252B1CBF9CF80CC0BCF1250F03 +:10D8E00017D0202B18BF212B38D0BCF1230F18BF25 +:10D8F00000BD002A08BF00BD91F8942191F8501096 +:10D90000114011F0010F44D0082818BF04284CD052 +:10D910004EE08AB191F87E11002908BF00BD0828A9 +:10D9200018BF042841D0082918BF04293DD0012878 +:10D9300018BF01293CD036E091F8E810002908BF53 +:10D9400000BD082818BF04282FD0082918BF0429B3 +:10D950002BD0012818BF01292AD024E0BCF1230FC5 +:10D96000C7D0002A08BF00BD91F8941111F0010F33 +:10D9700004D0082818BF042817D019E011F0020FAE +:10D9800008BF00BD082818BF04280ED001280FD0FA +:10D9900009E011F0020F08BF00BD082818BF0428D5 +:10D9A00003D0012804D0022000BDFFDF082000BD05 +:10D9B000012000BD2DE9F14FBB4E4FF0010831466B +:10D9C0006FF00E0A4F686FF00D0B97F85210F88E3B +:10D9D00002290CBF0AEB90000BEBD00085B2788EC9 +:10D9E000A84238BF0546AF4C2946606BF2F77AFB78 +:10D9F000DFF8B892E06200281DBF0021A170A0628C +:10DA000084F8028008BFC4F8289030787068014616 +:10DA100000F1580890F86930428E91F85210C08E8B +:10DA200002290CBF0AEB90000BEBD00080B28242BF +:10DA300038BF1046002B1CBF001D80B2F6F756FE03 +:10DA400098F81100002838D008F15001974891E863 +:10DA50000E1000F5027A8AE80E10D8F86010C0F8AF +:10DA60002112D8F86410C0F8251200F58170F7F77C +:10DA7000B6F9307800280CBF0120002080F00101A9 +:10DA80008B480176D8E91212C0E90412C4F8289034 +:10DA90004946A581A0F58372F6F71BFD97F8520061 +:10DAA000012808BF002104D002281ABFFFDF00218F +:10DAB00001210120F6F71BFD04E0A06AF7F78FF9BA +:10DAC000F6F738FD009848B9012297F852309621B0 +:10DAD0001046F7F741F89620F7F7A9F997F82C00C8 +:10DAE000012808BFF7F726FA02202070BDE8F88F5A +:10DAF0002DE9F04FDFF8B08183B0414681464E6892 +:10DB0000A1F11400009096F85D004FF0000A012783 +:10DB100006F15804A1F1380570B3012873D002282A +:10DB200075D0032818BFFFDF7FD0686A082201780C +:10DB300021F008010170A37902EAC302114321F028 +:10DB400004010170E279042303EA8202114321F007 +:10DB50001001017094F805B0286BF2F795FA82462F +:10DB6000F7F7E3FCBBF1020F66D0BBF1010F67D002 +:10DB7000BBF1030F68D06CE0B6F834B0FFF79FFE3E +:10DB8000022819BF6FF00D0000EBDB006FF00E00F4 +:10DB900000EB9B0081B2308E884238BF0146ADF861 +:10DBA0000810A6F84C100098F7F79EFC38B1696A87 +:10DBB000EF70AA694FF48060904703201EE001AA2D +:10DBC00002A9286BF2F743F9686210B194F8331098 +:10DBD00021B10098F7F75CFC6771A6E79DF8041087 +:10DBE00031B9A0F800A080F802A0012102F03EF8AF +:10DBF000BDF80810686A02F01AFA0220607194E712 +:10DC000001E004E011E00098F7F742FC8DE7B6F878 +:10DC10004C00ADF8000001AA6946286BF2F717F92D +:10DC20006862002808BFFFDF7FE70098F7F75CFC19 +:10DC3000002808BFFFDF78E730EA0A0009D106E0D4 +:10DC400030EA0A0005D102E0BAF1000F01D001214B +:10DC500000E00021686A027842EA01110170217C2B +:10DC600000291CBF617901293CD004F150010F4803 +:10DC700091E80E1000F5027A8AE80E10216EC0F8C5 +:10DC80002112616EC0F8251200F58170F7F7A7F830 +:10DC900098F8000000280CBF0121002104480176FB +:10DCA00008E000003C01002074010020C00E0020AC +:10DCB000C8100020D4E91012C0E90412A0F5837145 +:10DCC0006A6AF6F706FC96F85100012808BF0021A1 +:10DCD00004D002281ABFFFDF002101210020F6F73F +:10DCE00006FC03E0F7F77BF8F6F724FCB9F1000F28 +:10DCF00006D196F85130012296210020F6F72CFF2C +:10DD0000AF71686A018829828078A8742F7003B087 +:10DD1000BDE8F08F2DE9F0471E46174681460C46B8 +:10DD2000FE4DDDF82080287828B9002F1CBF002E7A +:10DD3000B8F1000F00D1FFDFC5F82080C5E90E94CF +:10DD4000C5E9067600206872287268712871A8718A +:10DD5000E871F34EE870E881307804F158072088C4 +:10DD6000F2F798FF28632088F2F782FF6863F7F7DD +:10DD70002BF8F6F7DBFC04F11200F7F70EF804F1CC +:10DD80000E00F6F774FD307800280CBF0320012048 +:10DD9000F7F717F8787EF6F772FDF7F70CF830789A +:10DDA0006FF00E056FF00D09002830D0618EE08E07 +:10DDB00094F852407A7C022C0CBF05EB900009EBE2 +:10DDC000D00080B2814238BF0846002A1CBF001D27 +:10DDD00080B22146F6F78AFC3078002831D070688E +:10DDE00090F86001002818BFF6F7F2FC22460021E7 +:10DDF0000120F6F76DFE7068D0F8D800F6F7F2FF54 +:10DE00000120FFF7D7FDBDE8F047F6F7E5BF97F82B +:10DE10001080278EB4F834A0FFF751FD022814BFFC +:10DE200009EBDA0005EB9A0085B2AF4234BF384601 +:10DE30002846B8F1000F1CBF001D80B294F8514075 +:10DE4000C7E7002122460846F6F742FE0120FFF709 +:10DE50004FFED8E7B24810B501783838007831B1B4 +:10DE6000022818BFFFDFBDE81040F6F7ADBF01285C +:10DE700018BFFFDFF7E7A94810B50078022818BFE0 +:10DE8000FFDFBDE8104000F044BAA4488079704735 +:10DE9000A24840797047A1490120C87170472DE917 +:10DEA000F04706009E489D4D4FF0010740684FF037 +:10DEB000000800F15804A86A90F8019018BF012EDC +:10DEC00003D1696B03F0D0FA68706878A0B10128BB +:10DED00031D0022849D003281CBFFFDFBDE8F087FE +:10DEE000012E08BFBDE8F087686BF2F70CFBA87A3B +:10DEF000BDE8F047EDF7FEBE012E08D001224946ED +:10DF0000686BF2F74DF9022E08BFBDE8F087D4E93F +:10DF10001202411C42F10000C4E91210E07901280C +:10DF200003D100BF84F8078000E0E771A87ABDE85C +:10DF3000F047EDF7DFBE012E08D000224946686B9E +:10DF4000F2F72EF9022E08BFBDE8F087D4E91201DE +:10DF5000401C41F10001C4E91201E07901280CBF25 +:10DF600084F80780E771BDE8F087012E06D0686B62 +:10DF7000F2F7C9FA022E08BFBDE8F087D4E9120112 +:10DF8000401C41F10001C4E91201E0790128CCD123 +:10DF9000C8E72DE9F041624F4FF000083846A7F17D +:10DFA00038044068012600F158052078012818BF80 +:10DFB000FFDFA87850B185F80280E670A26941467B +:10DFC000042090473878002818BF2E71606A03211A +:10DFD000007831EA000004BFE878002805D1EE702F +:10DFE000616AE670A269022090470121002000F0DA +:10DFF000B1F918B1BDE8F04100F08BB9BDE8F041CE +:10E000000020D7E42DE9F84F454C83462046A4F183 +:10E0100038054068217800F1580A287800264FF02A +:10E020000109022818BFFFDFE88940F40070E88189 +:10E030002078676800283A48406890F868000090A7 +:10E040003C8EB7F83480FFF73AFC022807BF6FF028 +:10E050000E0000EB98006FF00D0000EBD80080B2CE +:10E06000844238BF2046009900291CBF001D80B2A1 +:10E0700097F85110F6F73AFB9AF81100BBF1000F30 +:10E0800000F0FA80F6F77CFAF6F76AFA90B99AF897 +:10E09000110078B1A86A417861B100789AF8071048 +:10E0A000C0F3C000884205D185F80490BDE8F84F60 +:10E0B00000F02FB9A86A1A4FB0460188A5F81310CE +:10E0C00080786875E88940F02000E8816E713878C2 +:10E0D0007868583000907C6894F82C00012818D19A +:10E0E000F6F71EFF2046009901F023FA88B1387830 +:10E0F000002878680CBF00F5867000F5EA7021886A +:10E1000041800099097A017180F80090A87AEDF7B2 +:10E11000F1FDA86A0078C0F3800003E03C01002014 +:10E12000740100209AF80610884237D03878786851 +:10E1300000F1580490F85D0060B3022848D000BF99 +:10E1400084F80580387840B12079414628B12171A2 +:10E1500085F80390AA6910209047E07898B184F878 +:10E160000380F7F7D0F9002808BFFFDF082085F803 +:10E170000390AA6900219047D4E91002411C42F1A2 +:10E180000000C4E91010A07901280CBF84F80680B3 +:10E1900084F80690E88940F48070E881A86A9AF8CB +:10E1A00007300178C1F3C0029A4252D13A787A68B6 +:10E1B00001F0030102F15804012918BF022935D0EA +:10E1C00003291CBF287A40F0040012D0287240E0D6 +:10E1D000286BF1F776FE002808BFFFDFD4E91002B4 +:10E1E000411C42F10000C4E91010A87AEDF782FD4D +:10E1F000A6E701F05CFDA8B184F80290E9894846E1 +:10E2000041F40061E981A96A85F80390AA69904701 +:10E21000E079012803D100BF84F8078019E084F871 +:10E22000079016E0287A40F01000CFE74078F8B168 +:10E23000E98941F40061E981A97851B9FB28F1D855 +:10E24000687A002808BF4E4603D08020AA690021C2 +:10E2500090475946012000F07DF858B39AF8110014 +:10E26000002818BFBBF1000F1BD0A87868B118E0D8 +:10E27000E0790128D3D1CFE7002818BFF6F7B9F924 +:10E28000E88940F04000E881E3E7A96AAA89487874 +:10E29000904288BF1046C21CE86A03F02DFCE86A71 +:10E2A000A862002E1CBF0020FFF7F9FDBDE8F84F63 +:10E2B00000F02FB8002E1CBF0120FFF7F0FD00205A +:10E2C000FFF716FC9AF81100002818BFBBF1000FE9 +:10E2D0000DD0A87858B9A96AAA894878904288BF11 +:10E2E0001046C21CE86A03F007FCE86AA862002E28 +:10E2F00008BFBDE8F88F0220BDE8F84FCFE5354AEA +:10E300001378526892F851200BB1FBF76ABAFAF70A +:10E310001AB970B52F4900254C68F6F7B7FDF6F726 +:10E32000A9FDF6F7DBFCF6F73EFDF6F703F9F6F785 +:10E3300053FD94F82C00012808BFF6F7F1FD264C98 +:10E340000021A269E0899047226A217A20799047CA +:10E35000257070BD70B5204C0546002908BF012D01 +:10E3600005D16079401CC0B26071012830D8E169E4 +:10E370002846884700282BD0E179184839B1012D6B +:10E3800001BF41780029017811F0100F20D0217AC7 +:10E39000F1B910490978002918BF002102D029439A +:10E3A00004D013E0012D18BF0121F8D10C490978E0 +:10E3B00011F0100F04BF007810F0100F08D0E078B3 +:10E3C00030B9A07810B111F0100F01D0002070BD4D +:10E3D000012070BD740100203C0100204F0100208D +:10E3E0004C01002010B540F2C311F94803F0FBFBCB +:10E3F000FF220821F748E4F7FAFDF74800214170B1 +:10E400004FF46171418010BD2DE9F0410F46064681 +:10E4100000F03FFBEE4C102817D004EBC00191F840 +:10E420004A1111F0010F1CBF0120BDE8F081617895 +:10E4300008291FD2617804EBC000491C61700121DA +:10E4400080F84A110846BDE8F0816178082911D2A8 +:10E450002578681C207004EBC5083868C8F84401AA +:10E46000B888A8F84801102D28BFFFDF88F843615D +:10E470002846DFE70020BDE8F081D5480178491E35 +:10E480004BB2002BB8BF704770B4002500EBC3013E +:10E4900091F84A1111F0010F3BD04278D9B2521EC7 +:10E4A000427000EBC10282F84A5190F802C000228B +:10E4B000BCF1000F0BD9841894F803618E4202D18D +:10E4C000102A26D103E0521CD2B29445F3D8027828 +:10E4D000521ED2B202708A421BD000EBC20200EB85 +:10E4E000C10CD2F84341CCF84341D2F84721CCF8D3 +:10E4F0004721847890F800C00022002C09D98618A2 +:10E5000096F8036166450AD1102A1CBF024482F8BE +:10E510000311591E4BB2002BB8DA70BC7047521C65 +:10E52000D2B29442EBD8F4E72DE9F0471F4690466B +:10E530000E46814600F0ADFAA54C0546102830D0B5 +:10E54000A2780021002A0ED9631893F80331834280 +:10E5500005D110291CBF1220BDE8F08703E0491C3B +:10E56000C9B28A42F0D8082A2FD2102D1CD0A67822 +:10E570001022701CA07004EB061909F1030041463B +:10E5800000F086FF09F183001022394600F080FF79 +:10E59000A019002180F8035180F83B110846BDE81E +:10E5A000F087A278082A10D22578681C207004EB26 +:10E5B000C50A3068CAF84401B088AAF84801102D8D +:10E5C00028BFFFDF8AF84391D1E70720BDE8F08735 +:10E5D00070B47F488178491E4BB2002BBCBF70BC21 +:10E5E000704700BF817803F0FF0C491ECAB28270E9 +:10E5F00050FA83F191F8031194453ED000EB0215D7 +:10E6000000EB0C14D5F80360C4F80360D5F807607C +:10E61000C4F80760D5F80B60C4F80B60D5F80F603C +:10E62000C4F80F60D5F88360C4F88360D5F88760BC +:10E63000C4F88760D5F88B60C4F88B60D5F88F502C +:10E64000C4F88F50851800EB0C0402EB420295F8D9 +:10E6500003610CEB4C0C00EB420284F8036100EB0D +:10E660004C0CD2F80B61CCF80B61B2F80F21ACF86E +:10E670000F2195F83B2184F83B2100EBC10292F871 +:10E680004A2112F0010F33D190F802C00022BCF1F0 +:10E69000000F0BD9841894F803518D4202D1102A2F +:10E6A00026D103E0521CD2B29445F3D80278521E10 +:10E6B000D2B202708A421BD000EBC20200EBC10C46 +:10E6C000D2F84341CCF84341D2F84721CCF8472156 +:10E6D000847890F800C00022002C09D9851895F89C +:10E6E000035165450BD1102A1CBF024482F8031167 +:10E6F000591E4BB2002BBFF675AF70BC7047521C51 +:10E70000D2B29442EAD8F3E73349487070473248AE +:10E710004078704738B14AF2B811884203D82E4980 +:10E72000488001207047002070472B484088704780 +:10E7300010B500F0AEF9102814D0254A014600208B +:10E7400092F802C0BCF1000F0CD9131893F80331F2 +:10E750008B4203D1102818BF10BD03E0401CC0B28B +:10E760008445F2D8082010BD19498A78824286BFB4 +:10E7700001EB001083300020704715498A788242EF +:10E7800086BF01EB0010C01C00207047104B93F8AF +:10E7900002C084459CBF00207047184490F80301D4 +:10E7A00003EBC00090F843310B70D0F844111160B6 +:10E7B000B0F84801908001207047054A114491F853 +:10E7C000032105490A7002684A6080880881704701 +:10E7D000F0100020860100207C01002010B5F5F724 +:10E7E00027FE002804BFFF2010BDBDE81040F5F74C +:10E7F00045BEFE498A7882429CBF0020704708448B +:10E8000090F8030101EBC00090F84A0100F001000C +:10E8100070472DE9F047F54F0026B04638780028BC +:10E8200086BF4FF0080ADFF8C893BDE8F08700BF45 +:10E8300007EBC80505F5A27195F8430100F029F929 +:10E84000102808BF544610D0B978002400290BD9ED +:10E850003A1992F80321824202D1102C05D103E02B +:10E86000621CD4B2A142F3D80824B878A04286BF73 +:10E8700007EB0410C01C002095F84A1111F0010F9D +:10E8800016D050B1082C04D2391991F83B11012946 +:10E8900003D0102100F0D9FD50B109F806403046F0 +:10E8A000731C95F8432105F5A271DEB2F5F7A8FFB8 +:10E8B00008F1010000F0FF0838784045B8D8BDE8FD +:10E8C000F0872DE9F041C94C00263546A078002894 +:10E8D0008CBFC74FBDE8F0816119C0B291F80381C8 +:10E8E000A84286BF04EB0510C01C002091F83B1124 +:10E8F000012903D0102100F0A8FD58B104EBC80095 +:10E90000BD5590F8432100F5A2713046731CDEB26C +:10E91000F5F776FF681CC5B2A078A842DCD8BDE840 +:10E92000F08110B5F5F79BFF002804BF082010BD4B +:10E93000F5F799FFAE49085C10BDAE4910B54978AE +:10E9400041B1AA4B997829B1C21CD81CF5F70DFD2D +:10E95000012010BD002010BDA44A01EB410102EBD3 +:10E9600041010268C1F80B218088A1F80F017047AE +:10E970002DE9F0419D4D07460024A878002898BF56 +:10E98000BDE8F081C0B2A04213D905EB041010F12C +:10E9900083060ED01021304600F057FD48B904EB35 +:10E9A000440005EB400000F20B113A463046F6F702 +:10E9B0003AFE601CC4B2A878A042E3D8BDE8F0815A +:10E9C000014610228C4800F063BD8B48704770B53B +:10E9D000864D0446A878A04206D905EB0410102104 +:10E9E000833000F032FD08B1002070BD04EB44001C +:10E9F00005EB400000F20B1070BD7C498A78824222 +:10EA000006D9084490F83B01002804BF0120704754 +:10EA1000002070472DE9F0410E46074615460621B5 +:10EA2000304600F012FD714C98B1A17871B104F537 +:10EA30009D7011F0010F18BF00F8015FA17849081F +:10EA400004D0457000F8025F491EFAD10120BDE8EC +:10EA5000F0813846314600F01CF8102816D0A37813 +:10EA60000021002B12D9621892F80321824209D1A9 +:10EA7000102918BF082909D0601880F83B510120DF +:10EA8000BDE8F081491CC9B28B42ECD80020BDE83A +:10EA9000F0812DE9F041554D0646002428780F46B7 +:10EAA000002811D905EBC40090F84311B14206D1FA +:10EAB0000622394600F5A27002F0F2FF38B1601C60 +:10EAC000C4B22878A042EDD81020BDE8F0812046DD +:10EAD000BDE8F081454910B44A7801EBC003521EED +:10EAE0004A70002283F84A2191F802C0BCF1000F5D +:10EAF0000DD98B1893F80341844204D1102A1CBF0E +:10EB000010BC704703E0521CD2B29445F1D80A7889 +:10EB1000521ED2B20A70824204BF10BC704701EB91 +:10EB2000C00301EBC202D2F843C1C3F843C1D2F81B +:10EB30004721C3F847218C7891F800C00022002CAF +:10EB40009CBF10BC70478B1893F80331634506D106 +:10EB5000102A1CBF114481F8030110BC7047521CDD +:10EB6000D2B29442EFD810BC704770B41F490D1850 +:10EB70008A78521ED3B28B7095F80321984247D001 +:10EB800001EB001401EB031C00EB4000DCF8036018 +:10EB9000C4F80360DCF80760C4F80760DCF80B60B9 +:10EBA000C4F80B60DCF80F60C4F80F60DCF8836019 +:10EBB000C4F88360DCF88760C4F88760DCF88B6099 +:10EBC000C4F88B60DCF88FC0C4F88FC001EB030C75 +:10EBD00003EB43039CF8034101EB430385F8034136 +:10EBE00001EB4000D3F80B4108E00000F0100020DA +:10EBF000860100207C010020B3120020C0F80B41E8 +:10EC0000B3F80F31A0F80F319CF83B0185F83B01B8 +:10EC100001EBC20090F84A0110F0010F1CBF70BC5C +:10EC2000704700208C78002C0DD90B1893F803C185 +:10EC3000944504D110281CBF70BC704703E0401CF1 +:10EC4000C0B28442F1D80878401EC0B20870904229 +:10EC500004BF70BC704701EBC20301EBC000D0F8E9 +:10EC600043C1C3F843C1D0F84701C3F847018C78CA +:10EC70000B780020002C9CBF70BC704701EB000C8F +:10EC80009CF803C19C4506D110281CBF084480F89D +:10EC9000032170BC7047401CC0B28442EED870BCE7 +:10ECA0007047000010B50A7B02F01F020A730022B1 +:10ECB000C2758B181B7A03F0010C5B0803F001048A +:10ECC000A4445B0803F00104A4445B0803F00104BE +:10ECD000A4445B0803F0010464444FEA530C0CF0B5 +:10ECE000010323444FEA5C0C0CF00104234403EBC2 +:10ECF0005C0300EB020C521C8CF8123090F817C029 +:10ED0000D2B26344C375052AD3D3D8B2252888BFAD +:10ED1000FFDF10BD00238383028401EBC202521E79 +:10ED2000B2FBF1F1C183704770B46FF01F02010CA8 +:10ED300002EA90251F23A1F5AA4054381CBFA1F573 +:10ED4000AA40B0F1550009D0A1F52850AA381EBF3D +:10ED5000A1F52A40B0F1AA00012000D100204FF017 +:10ED6000000C62464FEA0C048CEA0106F643164397 +:10ED7000B6F1FF3F11D005F001064FEA5C0C4CEAFA +:10ED8000C63C03F0010652086D085B08641C42EAA9 +:10ED9000C632162CE8D370BC704770BC0020704798 +:10EDA0002DE9F04701270025044603290FD04FF431 +:10EDB000FA43002972D0012900F0F880022918BF17 +:10EDC000BDE8F0870146BDE8F04758306AE704F136 +:10EDD00058067021304602F028FFB571F571F572C2 +:10EDE0003573B573F573757135767576F52086F8DC +:10EDF0003C00412086F83D00FF2086F86B00A4F817 +:10EE0000C850A4F8CA50A4F8CC50A4F8CE50A4F826 +:10EE1000D050A4F8D25084F8D55084F8D750A4F834 +:10EE2000DE5084F8DC50A4F8F050A4F8F25084F8D6 +:10EE30002C50258484F8517084F852704FF4486047 +:10EE400060801B21218761874FF4A470E087A08731 +:10EE500021866186E086A086A4F84410A4F84600C6 +:10EE6000A4F84010A4F84200A4F84810A4F84A10EE +:10EE7000A4F84C10677384F8885184F8895184F899 +:10EE8000925184F8935184F8615184F8665184F862 +:10EE9000695184F87A51BDE8F087FFE7A4F8DE50A5 +:10EEA00084F8D6506088FE490144B1FBF0F1A4F823 +:10EEB00076104BF68031A4F87810E288A4F87C50E4 +:10EEC000B4F880C0D2000CFB00FCB2FBF0F29CFB5B +:10EED000F0FC521CA4F880C092B202FB00FC04F1CA +:10EEE0005801A4F87E20BCF5C84FC4BF521ECA8486 +:10EEF000B3FBF0F2521C8A8500F5802202F5EE3257 +:10EF0000531EB3FBF0F2CA838B8B03FB00F2B2FB00 +:10EF1000F0F08883214604F15800FFF7C3FED4F8CF +:10EF20000E106FF01F02080C02EA9126A0F5AA410C +:10EF30004FF01F0C54391CBFA0F5AA41B1F1550187 +:10EF40000AD0A0F52851AA391EBFA0F52A41B1F177 +:10EF5000AA014FF0010901D14FF00009002211462A +:10EF60004FEA020382EA00086FEA080848EA01084B +:10EF7000B8F1FF3F16D006F00108520842EAC83245 +:10EF800049080CF0010876085B1C41EAC8314FEAD9 +:10EF90005C0C162BE6D3B9F1000F1CBF84F860514E +:10EFA000BDE8F08784F86071BDE8F087A4F8DE5012 +:10EFB000B4F88221B4F88611B4F802C004F1580004 +:10EFC000A4F87C50B4F88040C90004FB0CF4B1FBF9 +:10EFD000F2F194FBF2F4491C048589B201FB02F4BE +:10EFE000C184B4F5C84FC4BF491EC184B3FBF2F15C +:10EFF000491C8185018C02EBC101491EB1FBF2F174 +:10F00000C183818B01FB0CF1B1FBF2F18183BDE87F +:10F01000F08770B50025044603290DD04FF4FA425D +:10F02000002958D001297DD0022918BF70BD0146A2 +:10F03000BDE87040583035E604F15806702130467E +:10F0400002F0F3FDB571F571F5723573B573F573B3 +:10F05000757135767576F52086F83C00412086F886 +:10F060003D00FF2086F86B00A4F8D050202084F8E3 +:10F07000D20084F8C850C4F8CC50012284F82C5037 +:10F0800084F8512084F852201B20208760874FF499 +:10F09000A471E187A18720866086E186A186A4F815 +:10F0A0004400A4F84610A4F84000A4F84210A4F8C4 +:10F0B0004800A4F84A00A4F84C00627384F8FC509D +:10F0C00084F8FD5084F8065184F8075184F8EC5018 +:10F0D00084F8F85070BD608871490144B1FBF0F1CB +:10F0E000A4F876104BF68031A4F87810E388A4F8E1 +:10F0F0007C50B4F880C0DB000CFB00FCB3FBF0F3E9 +:10F100009CFBF0FC5B1CA4F880C09BB203FB00FCE2 +:10F1100004F15801A4F87E30BCF5C84FC4BF5B1E93 +:10F12000CB8400E017E0B2FBF0F2521C8A8500F5B8 +:10F13000802202F5EE32531EB3FBF0F2CA838B8BB2 +:10F1400003FB00F2B2FBF0F08883214604F1580083 +:10F15000BDE87040A6E5D4F8F030B4F802C004F180 +:10F1600058005989DB89A4F87C50B4F88040DB0052 +:10F1700004FB0CF4B3FBF1F394FBF1F45B1C04858A +:10F180009BB203FB01F4C384B4F5C84FC4BF5B1E3C +:10F19000C384B2FBF1F2521C8285028C01EBC202E5 +:10F1A000521EB2FBF1F2C283828B02FB0CF2B2FB65 +:10F1B000F1F1818370BD2DE9F003C47D0CB1252CE4 +:10F1C00003D9BDE8F00312207047002A02BF0020D7 +:10F1D000BDE8F003704791F80DC01F260123314DA3 +:10F1E0004FF00008BCF1000F7AD0BCF1010F1EBF38 +:10F1F0001F20BDE8F0037047B0F800C00A7C8F7B89 +:10F2000091F80F907A404F7C87EA090742EA07227B +:10F2100082EA0C0C5FF000070CF0FF094FEA1C2C8F +:10F2200099FAA9F99CFAACFC4FEA19694FEA1C6CEF +:10F2300049EA0C2C0CEB0C1C7F1C9444FFB21FFA07 +:10F240008CFC032FE8D38CEA020C164F0022ECFB57 +:10F25000057212096FF0240502FB05C2D2B201EB60 +:10F26000D207027602F007053F7A03FA05F52F422E +:10F2700018BF42767ED104FB0CF2120C521CD2B2A3 +:10F280005FF0000400EB040C9CF812C094453CBFF6 +:10F29000A2EB0C02D2B218D34FF0000C0D1903E010 +:10F2A000FFDB050053E4B36E95F8085003FA0CF742 +:10F2B0003D421CBF521ED2B2002A6AD00CF1010C92 +:10F2C0000CF0FF0CBCF1080FF0D304F1010C0CF0B2 +:10F2D000FF04052CD6D33046BDE8F0037047FFE7A6 +:10F2E00090F818C00C7E474604FB02C2FB4C4FF05E +:10F2F000000CE2FB054C4FEA1C1C6FF024040CFBD5 +:10F300000422D2B201EBD204027602F0070C247A76 +:10F3100003FA0CFC14EA0C0F1FBF42764046BDE80E +:10F32000F003704790F817C0B2FBFCF40CFB1422FA +:10F33000521CD2B25FF0000400EB040C9CF812C027 +:10F3400094453CBFA2EB0C02D2B212D30D194FF080 +:10F35000000C2D7A03FA0CF815EA080F1CBF521E98 +:10F36000D2B27AB10CF1010C0CF0FF0CBCF1080F19 +:10F37000F0D300E010E004F1010C0CF0FF04052CC8 +:10F38000DAD3A8E70CEBC40141763846BDE8F003B8 +:10F3900070470CEBC40141764046BDE8F00370476E +:10F3A000CF4A016812681140CE4A126811430160C9 +:10F3B000704730B4CC49CA4B00244FF0010C0A7896 +:10F3C000521CD2B20A70202A08BF0C700D781A683D +:10F3D0000CFA05F52A42F2D0097802680CFA01F11C +:10F3E0005140016030BC7047017931F01F0113BFFB +:10F3F000002000221146704710B4435C491C03F002 +:10F40000010C5B0803F00104A4445B0803F0010451 +:10F41000A4445B0803F00104A4445B0803F0010466 +:10F42000A4445B0803F001045B08A44403F0010456 +:10F43000A4440CEB53031A44D2B20529DDDB012AA4 +:10F440008CBF0120002010BC704730B40022A1F115 +:10F45000010CBCF1000F11DD431E11F0010F08BFBC +:10F4600013F8012F5C785FEA6C0C07D013F8025F89 +:10F4700022435C782A43BCF1010CF7D1491E5CBFE2 +:10F48000405C0243002A0CBF0120002030BC7047C2 +:10F49000130008BF704710B401EB030CD41A1CF81A +:10F4A00001CC5B1E00F804C013F0FF03F4D110BCC4 +:10F4B0007047F0B58DB0164610251C466A46AC461E +:10F4C00000EB0C03A5EB0C0713F8013CD355ACF192 +:10F4D000010313F0FF0CF3D11546103210208446BF +:10F4E0000B18ACEB000713F8013C401ED35510F08D +:10F4F000FF00F5D1284601F033FA86B1102005F15E +:10F50000200201461318A1EB000C13F8013C401E29 +:10F5100004F80C3010F0FF00F4D10DB0F0BD0898E5 +:10F520002060099860600A98A0600B98E0600DB0B8 +:10F53000F0BD38B505460C466846F5F706FD0028CF +:10F5400008BF38BD9DF90020227294F909100020EF +:10F55000511A48BF494295F82D308B42C8BF38BD7B +:10F56000FF2B08BF38BDA17A491CC9B2A17295F81A +:10F570002E30994203D8617A7F2918BF38BD627254 +:10F580000020A072012038BD0C2818BF0B2806D01F +:10F590000D281CBF2038062884BF0020704701209A +:10F5A00070470C295AD2DFE801F006090E13161B2A +:10F5B000323C4153484E002A52D04FE0072A18BF30 +:10F5C000082A4DD04AE00C2A18BF0B2A48D045E043 +:10F5D0000D2A45D042E0A2F10F000D2840D93DE0B0 +:10F5E00023B1A2F110000C283AD937E0122A18BF33 +:10F5F000112A35D090F8340020B1122A2ED31B2ABC +:10F600002ED92BE0162A29D31B2A29D926E0A2F1CC +:10F610000F01032924D990F83400F8B11C2A1FD90E +:10F620001CE0002B08BF042A18D119E013B1062AE8 +:10F6300016D013E0012A11D112E01D2A1CBF1E2A88 +:10F640001F2A0DD00AE0A2F12000062808D905E003 +:10F6500013B10E2A04D001E0052A01D00020704722 +:10F66000012070472DE9F04187680D460446204689 +:10F67000F3F7CCFB98B1D5B13846A168F3F709FF91 +:10F68000002814DD2844401EB0FBF5F606FB05F10A +:10F690003846F2F7F8FEA0603046BDE8F081F3F797 +:10F6A000E7F94FF4E661F2F7EEFEA060DFE7002035 +:10F6B000BDE8F081904228BF704770B50446101B2A +:10F6C000642838BF642025188D4205D8F3F715FF4C +:10F6D00000281CBF284670BD204670BD53E4B36EA1 +:10F6E00064230200682302008E01002091F851304B +:10F6F0000A8E022B07BF92003C32D200703292B2C7 +:10F700008B8E934238BF1A464B8E91F852C0BCF193 +:10F71000020F07BF9B003C33DB0070339BB2C98EE6 +:10F72000994238BF0B4600280CBF01210021D01898 +:10F730009830002918BF04210844704730B48388EA +:10F74000B0F808C003EB0C049834002A18BF042258 +:10F7500022444C6A944224BF30BC7047121B521C96 +:10F7600052089B1A9BB2ACEB0202838092B20281D8 +:10F7700091F851506FF00E0C6FF00D04022D0CBF7C +:10F780000CEB930304EBD303438091F8521002294E +:10F790000CBF0CEB920104EBD201C18030BC70476E +:10F7A00010F0010F1CBF0120704710F0020F1CBFAA +:10F7B0000220704710F0040018BF082070472DE9A0 +:10F7C000F0410546174688460126084600F001FC30 +:10F7D0000446404600F001FC034610F0010F18BF3C +:10F7E000012008D113F0020F18BF022003D113F03B +:10F7F000040018BF082014F0010F18BF4FF0010CCF +:10F8000021D000BF50EA0C0108BF002613F0030FFF +:10F8100008BF002014F0030F08BF4FF0000C95F84C +:10F820005110814208BF0020387095F85210614590 +:10F8300008BF4FF0000C87F801C0002808BFBCF1DA +:10F84000000F1CD10DE014F0020F18BF4FF0020C96 +:10F85000D8D114F0040F14BF4FF0080C4FF0000C77 +:10F86000D0E7404600F0BFFBB5F85810401A00B290 +:10F8700047F6FE71884201DC002800DC0026304695 +:10F88000BDE8F08101281CBF02280020704718B491 +:10F89000CBB2C1F3072CC1B2C0F30720012B07D0B4 +:10F8A000022B09D0042B08BFBCF1040F23D006E0C3 +:10F8B000BCF1010F03D11EE0BCF1020F1BD00129E6 +:10F8C00006D0022907D0042908BF042813D004E079 +:10F8D000012802D10FE002280DD001EA0C0161F3EA +:10F8E0000702184060F30F22D0B210F0020F18BFC9 +:10F8F00002200BD106E0084003EA0C01084060F347 +:10F900000702EFE710F0010018BF01208DF800009A +:10F91000C2F3072010F0020F18BF022003D110F02D +:10F92000010018BF01208DF80100BDF8000018BCCF +:10F930007047162A10D12A220C2818BF0D280FD084 +:10F940004FF0230C20280DD031B10878012818BFC2 +:10F95000002805D0162805D00020704701207047E8 +:10F960001A70FBE783F800C0F8E70000282102F0D6 +:10F970003AB930B50546007801F00F0220F00F00CB +:10F980001043287007290BD2DFE801F004060406B3 +:10F9900004080400062405E00C2403E0222401E00E +:10F9A0000024FFDF687820F03F002043687030BDFE +:10F9B000007800F00F0070470A68C0F803208988BB +:10F9C000A0F807107047D0F803200A60B0F80700CD +:10F9D000888070470A68C0F809208988A0F80D104F +:10F9E0007047D0F809200A60B0F80D008880704791 +:10F9F0000278202322F0200203EA41111143017012 +:10FA000070470278402322F0400203EA811111433B +:10FA1000017070470078C0F380107047027880232F +:10FA200022F0800203EAC11111430170704700788F +:10FA3000C0097047D0F80320C1F80920B0F80720AA +:10FA4000A1F80D200A7822F080020A70007880095F +:10FA500042EAC0100870704770B515460E4604465D +:10FA60001F2A88BFFFDF2A46314604F1090002F051 +:10FA700043F86078A91D20F03F0001F03F010843E2 +:10FA8000607070BD70B5054640780E4600F03F04CA +:10FA9000062C38BFFFDFA01FC4B21F2C88BF1F2455 +:10FAA000224605F10901304602F026F8204670BDD5 +:10FAB00070B515460E4604461F2A88BFFFDF2A464A +:10FAC000314604F1090002F017F86078A91D20F012 +:10FAD0003F0001F03F010843607070BD70B50546FE +:10FAE00040780E4600F03F04062C38BFFFDFA01F11 +:10FAF000C4B21F2C88BFFFDF224605F10901304642 +:10FB000001F0FAFF204670BD0968C0F80F10704779 +:10FB10000A88A0F813208978417570474176090A50 +:10FB200081767047C176090A017770474177090AE3 +:10FB300081777047C175090A0176704781757047F2 +:10FB400090F8242001F01F0122F01F02114380F8D9 +:10FB500024107047072988BF072190F82420E0234C +:10FB600022F0E00203EA4111114380F824107047AB +:10FB70001F3002F066B94178007801F03F0110F0C3 +:10FB80000F0006D0012808D0022809D006280BD083 +:10FB90000FE0881F1F280AD90BE00C2909D106E0C5 +:10FBA000881F1F2803D904E0881F1F2801D80120BF +:10FBB0007047002070474178007801F03F0100F065 +:10FBC0000F00042805D1062903D325299CBF012055 +:10FBD00070470020704710B4017801F00F0103292D +:10FBE00022D0052925D14478B0F81910B0F81BC0EF +:10FBF000B0F81730827D04F03F04222C19D1062979 +:10FC000017D3B1F5486F98BFBCF5FA7F11D282B116 +:10FC1000082A98BF8A420CD28B429CBFB0F81D00C4 +:10FC2000B0F5486F05D807E0407800F03F000C2899 +:10FC300002D010BC0020704710BC01207047222168 +:10FC400001F0D1BF00B5027801F0030322F00302F6 +:10FC50001A43027000224270012914BF022900BD1C +:10FC6000032912BFFFDF0121417000BD01F0030332 +:10FC700000B5027822F003021A430270002242709B +:10FC8000012914BF022900BD032912BFFFDF012192 +:10FC9000417000BD007800F0030070470278102327 +:10FCA00022F0100203EA01111143017070474178FC +:10FCB000F9B1C078192850D2DFE800F00D10131602 +:10FCC000191C1F2225282B2E31344F4F4F4C373A09 +:10FCD0003D40434649000C2941D042E008293ED02E +:10FCE0003FE002293BD03CE0172938D039E00D290C +:10FCF00035D036E0012932D033E001292FD030E071 +:10FD000002292CD02DE0092929D02AE0092926D062 +:10FD100027E0012923D024E0012920D021E0062971 +:10FD20001DD01EE002291AD01BE0012917D018E0CF +:10FD3000012914D015E0092911D012E009290ED0AB +:10FD40000FE003290BD00CE0032908D009E00529B6 +:10FD500005D006E0032902D003E0FB2901D80120E9 +:10FD600070470020704730B50546C170192924D26C +:10FD7000DFE801F00D0F11131517171119191717D7 +:10FD80001B111921211D171719191D1D1F000C24E6 +:10FD900015E0082413E0022411E017240FE00D24DD +:10FDA0000DE001240BE0092409E0062407E0032408 +:10FDB00005E0052403E0182401E00024FFDF6C7057 +:10FDC00030BDC0787047C171090A01727047B0F840 +:10FDD000070070474172090A81727047B0F8090044 +:10FDE0007047C172090A01737047B0F80B00704781 +:10FDF0004171090A81717047B0F8050070470171BF +:10FE00007047007970474173090A81737047B0F8F1 +:10FE10000D00704730B4B0F80720894DB0F809C024 +:10FE2000B0F805300179941F2D1998BFBCF5FA7F01 +:10FE30000ED269B1082998BF914209D293429FBF5F +:10FE4000B0F80B00B0F5486F012030BC98BF704788 +:10FE5000002030BC7047001D01F0F3BF021D0846B2 +:10FE6000114601F0EEBF4172090A81727047B0F885 +:10FE70000900704701717047007970470A68426055 +:10FE800049688160704742680A60806848607047CE +:10FE90000988818170478089088070470A68C0F8A6 +:10FEA0000E204968C0F812107047D0F80E200A6082 +:10FEB000D0F81200486070470968C0F81610704703 +:10FEC000D0F81600086070470A684260496881608F +:10FED000704742680A608068486070470968C1607E +:10FEE0007047C06808607047017170474171090A26 +:10FEF00081717047C171090A0172704700797047BA +:10FF0000B0F805007047B0F80700704701717047FE +:10FF10000079704701717047007970470A68426044 +:10FF200049688160704742680A608068486070472D +:10FF30000171090A417170478171090AC1717047E5 +:10FF40000172090A417270478172090AC1727047D1 +:10FF500080887047C0887047008970474089704723 +:10FF600001891B2924BF4189B1F5A47F07D381886A +:10FF70001B2921BFC088B0F5A47F01207047002055 +:10FF800070470A68426049688160704742680A6049 +:10FF9000806848607047017170470079704741710F +:10FFA000704740797047017911F0070F1BBF407906 +:10FFB00010F0070F002001207047017911F0070FA2 +:10FFC0001BBF407910F0070F00200120704701711E +:10FFD000704700797047417170474079704781716F +:10FFE000090AC1717047C088704716A282B0D2E971 +:10FFF0000012CDE900120179407901F0070269464B +:020000040002F8 +:100000001DF80220012A07D800F00700085C01282B +:100010009EBF012002B07047002002B070470171FE +:10002000704700797047417170474079704730B52B +:100030000C460546FB2988BFFFDF6C7030BD000011 +:1000400086F3FFFF000101020102020370B50446BE +:10005000C2F11005281901F04FFD15F0FF0108D07D +:10006000491EC9B2802060542046BDE8704001F0AE +:10007000BABD70BD30B505E05B1EDBB2CC5CD55CB3 +:100080006C40C454002BF7D130BD10B5002409E0FA +:100090000B78521E44EA430300F8013B11F8013B80 +:1000A000D2B2DC09002AF3D110BD2DE9F0410C4693 +:1000B00001200978FF4E92B0154602274FF006083E +:1000C0004FF0040C71B101291ED0022945D003293B +:1000D00005D12978042902D105201070002012B022 +:1000E000BDE8F081606850B1CDE9010601202070C3 +:1000F0008DF80080606A05901146684663E02770BD +:1001000085F800C0566026E029780429E7D169689F +:1001100010222069FFF7B9FF6868C07B000606D58A +:10012000E44A2069102310320146FFF7A3FFD4E907 +:1001300004101022FFF7A9FF2069C07B000606D536 +:10014000DC4A6069102310320146FFF793FF2770E5 +:1001500085F800C06E600320C1E729780429BED16C +:10016000A08910280CD9A0F1100080B2A081A1684C +:100170004FF01003014468466A68FFF77BFF18E000 +:1001800004D14FF010032269A16807E0C2B20EA8A3 +:10019000A168FFF75BFF626910230EA90AA8FFF7A9 +:1001A00069FF10230AA968466A68FFF763FF032006 +:1001B000207060680590CDF818D08DF81080606AC6 +:1001C0000990294604A8F1F759FF88E72DE9F04185 +:1001D00007460D4601200B7806213BB1012B04D1C7 +:1001E0001378052B01D11170002079E76C69012685 +:1001F00020226170E8686060686A6062A168287C9B +:100200000870A681A068A968401C01F075FCA0894F +:1002100020222030A081A0686968213001F06CFCA8 +:10022000A08921462030A0812E703846BDE8F041DB +:10023000F1F73BBF2DE9F05F0D46834601200978B9 +:10024000174606464FF00608D1B1DFF868A24FF016 +:100250000009AAF1080A012923D002297ED0032926 +:100260000CD13978052909D179681022E86901F0A3 +:1002700043FC07203870183500207D60BDE8F09FF2 +:100280002C6A8C48202284F8018020306060202075 +:10029000A081686A60626968A06801F02DFC2E7018 +:1002A000D4E039780529E9D12C6A84F80180686A9C +:1002B000606251681022E86901F01EFCE869606024 +:1002C000A0684F4680F80090A681A0684670A0897B +:1002D000401C80B2A081A1680844696951F8012FCF +:1002E000026089888180A089801D80B2A0816969AF +:1002F000A2680978C1F340011154A089401C80B262 +:10030000A081A1680844296951F8012F02608988F9 +:100310008180A089801D80B2A0812969A2680978A6 +:10032000C1F340011154A0891022401C80B2A08169 +:10033000A1680844E96801F0DFFBA08910221030B1 +:1003400080B2A081A1680844A96801F0D5FBA0890A +:10035000103080B2A081A168014400E00DE0DAF81D +:1003600004000860A089001D80B2A081A1680F541C +:10037000A089401CA081022067E03978052992D12C +:1003800051681022A86901F0B7FB2C6A84F801803B +:10039000E8696060686A6062A16881F80090A6817F +:1003A000A0684670A089401C80B2A081A168084462 +:1003B000696951F8012F026089888180A089801DB8 +:1003C00080B2A0816969A2680978C1F34001115423 +:1003D000A089401C80B2A081A1680844296951F815 +:1003E000012F026089888180A089801D80B2A08150 +:1003F0002969A2680978C1F340011154A08910222B +:10040000401C80B2A081A1680844E96801F074FB37 +:10041000A0891022103080B2A081A1680844A96888 +:1004200001F06AFBA089103080B2A081A16801446C +:10043000DAF804000860A089001D80B2A081A168DC +:100440000E54A089401CA0810320287021465846E4 +:10045000BDE8F05FF1F729BE70B50D460646097894 +:10046000012041B1012905D11178052902D10820C7 +:100470001070002070BD2C6A062060706968616091 +:10048000696A6162EA69A16852F8013F0B6092886B +:100490008A80A081E869A1680078C0F34000887173 +:1004A000A089401C80B2A081A1680844A96951F8C4 +:1004B000012F01E074230200026089888180A089F5 +:1004C000801D80B2A081A969A2680978C1F34001AA +:1004D0001154A089401C80B2A081A16808446969B8 +:1004E0000A88028089788170A0891022C01C80B29D +:1004F000A081A1680844296901F0FEFAA0891022B0 +:10050000103080B2A081A1680844E96801F0F4FAD3 +:10051000A0891022103080B2A081A1680844A96887 +:1005200001F0EAFAA08921461030A081012028704C +:100530003046BDE87040F1F7B8BD70B50D460646CF +:100540000978012059B1012908D11178052905D16F +:1005500009201070506800685060002070BD6C6900 +:10056000062010226070E8686060686A606229692D +:10057000A06801F0C1FA1020A081A06820221030EC +:10058000A96801F0B9FAA0892022203080B2A081A8 +:10059000A1680844696801F0AFFAA08921462030BB +:1005A000A081012028703046BDE87040F1F77DBD84 +:1005B00070B50C46012009788EB01546062659B153 +:1005C000012934D0022905D12978042902D10A2031 +:1005D000107000200EB070BD606910236A4600786C +:1005E000C0F340008DF80000A0690078C0F340001F +:1005F0008DF80100E0680168CDF802108188ADF83F +:10060000061080798DF8080020690168CDF809107E +:100610008188ADF80D1080798DF80F006068059025 +:100620000AA80690A168FFF725FD01201DE02978A2 +:100630000429CFD1A06910236A4650F8011F009108 +:100640008088ADF80400606950F8011FCDF80610ED +:100650008088ADF80A0000200390606805900AA821 +:1006600006906968FFF706FD022020708DF8106083 +:10067000606A0990294604A8F1F700FDAAE700B5D1 +:100680000B788BB001204BB1012B05D111780429D7 +:1006900002D10B20107000200BB000BD4868019003 +:1006A00006A80290C86803680693406807908868A7 +:1006B00003680893406809900120087006208DF8AF +:1006C0000000486A059011466846F1F7D7FCE3E759 +:1006D00000B50B788BB0012043B1012BDCD1117830 +:1006E0000429D9D10C2010700020D5E7486801906A +:1006F00006A8029088680368069340680790002067 +:10070000089009900120087006208DF80000486AC2 +:10071000059011466846F1F7B1FCBDE700B50B78CE +:100720008BB0012043B1012BB6D111780429B3D18C +:100730000D2010700020AFE748680590CDF818D064 +:1007400088680088ADF80000C8680088ADF802002D +:1007500000200190029003900120087006208DF87F +:100760001000486A0990114604A8F1F787FC93E746 +:1007700030B403460C7801205CB1012C15D0022C5A +:1007800005D111780C2902D10E201070002030BC48 +:10079000704701200870C868042242704A684260AD +:1007A0000B4A8260921EC2600BE014780D2CEED1D1 +:1007B00002200870C86803244470526842608A6846 +:1007C0008260496A4162014630BC1846F1F76DBC4F +:1007D0006E2302002DE9F0410C4611490D68104AC4 +:1007E000104908321160A0F120012A2901D301200B +:1007F0000CE03E2810D040CC0B4F94E80E0007EBE5 +:100800008000241F50F8807C3046B84720600448A0 +:10081000001D0560BDE8F0812046E0F7E1FCF5E74A +:100820001005024001000001A423020010B5524847 +:1008300000F070FA00B1FFDF4F48401C00F06AFA88 +:10084000002800D0FFDF10BD2DE9F14F4B4ED6F848 +:1008500000B00127484800F065FADFF81C8128B98C +:100860005FF0000708F1010000F072FA444C002527 +:100870004FF0030901206060C4F80051C4F804512E +:10088000009931602060DFF8FCA018E0DAF8000081 +:10089000C00614D50E2000F064F8EFF3108010F0BD +:1008A000010072B600D00120C4F80493D4F80011FE +:1008B00019B9D4F8041101B920BF00B962B6D4F84F +:1008C000000118B9D4F804010028DFD0D4F80401DD +:1008D0000028CFD137B1C6F800B008F1010000F010 +:1008E00021FA11E008F1010000F01CFA0028B9D14A +:1008F000C4F80893C4F80451C4F800510E2000F065 +:1009000030F81D4800F024FA0020BDE8F88F2DE9EA +:10091000F0438DB00D46064600240DF110090DF18F +:10092000200817E004EB4407102255F8271068460A +:1009300001F0E2F805EB870710224846796801F0DC +:10094000DBF86846FFF780FF10224146B86801F0E7 +:10095000D3F8641CB442E5DB0DB00020BDE8F083A1 +:1009600072E700F01F02012191404009800000F170 +:10097000E020C0F8801270478F01002004E500409D +:1009800000E0004010ED00E0D848002101708170C7 +:10099000704770B5D64D01232B60D64B1C68002CD8 +:1009A000FCD0002407E00E6806601E68002EFCD014 +:1009B000001D091D641C9442F5D3002028601868AE +:1009C0000028FCD070BD70B5C84E0446CA4D3078C2 +:1009D000022800D0FFDFAC4200D3FFDF7169C748B7 +:1009E000012903D847F23052944201DD03224271BB +:1009F000491C7161291BC160C0497078F2F782FA05 +:100A0000002800D1FFDF70BD70B5B84C0D4661788D +:100A1000884200D0FFDFB84E082D4ED2DFE805F047 +:100A20004D0421304D4D4D3B2078022800D0FFDF92 +:100A300003202070A078022802D0012804D008E00A +:100A4000A06800F051FD04E004F1080007C8FFF7BA +:100A5000A0FF052020700020A070BDE87040F1F7D5 +:100A600012BFF2F705F801466068F2F712FDB042D6 +:100A700002D2616902290BD30320F2F7E4FF12E0EE +:100A8000F1F7F6FF01466068F2F703FDB042F3D2DA +:100A9000BDE8704097E7207802280AD0052806D0E4 +:100AA000FFDF04202070BDE8704000F014B9022080 +:100AB00000E00320F2F7C7FFF3E7FFDF70BD70B57A +:100AC0000546F1F7D5FF894C60602078012800D0F9 +:100AD000FFDF8A4901200870002008718D60042022 +:100AE00048718548C860022020706078F2F70AFAE1 +:100AF000002800D1FFDF70BD10B57C4CA07808B98C +:100B0000207808B1112010BD7D48F1F737FF6070E3 +:100B10006078202804D0012020700020606110BD82 +:100B2000032010BD0246010B0120B2F5003F02D2A6 +:100B3000884000F071BFB2F5802F03D22039884081 +:100B400000F072BFB2F5C02F03D24039884000F0E8 +:100B500074BFB2F5002F03D26039884000F076BF31 +:100B6000002070472DE9F041144600EB84070E4643 +:100B700005463F1F00F0CBFC4FF080510A695043FF +:100B800006EB8402121FB24201D2012200E00022D1 +:100B90001CB10969B4EB910F02D90920BDE8F081BD +:100BA00058498D4216D3AF4214D3854205D28742AD +:100BB00003D245EA0600800701D01020EEE78E42FE +:100BC00008D33AB92846FFF7ADFF18B93846FFF702 +:100BD000A9FF08B10F20E1E74B484C490068884263 +:100BE00005D0224631462846FFF7D3FE10E0FFF736 +:100BF00083FF0028D2D13D4801218560C0E903640C +:100C000081704FF4A97104FB01F01830FFF757FF12 +:100C10000020C3E770B54FF0805504462869394974 +:100C2000B1FBF0F084420AD300F071FCA04201D87D +:100C3000102070BD28696043FFF774FF08B10F20D2 +:100C400070BD314831490068884204D0286960434A +:100C500000F04AFC0CE0FFF74FFF0028F0D12969B3 +:100C6000224861438160022181702948FFF727FFF4 +:100C7000002070BD2349090BB1EB401F07D940424A +:100C800001EB4011202903D34FF0FF3070470021C2 +:100C900001208840401E704770B505460C46002074 +:100CA000FFF7E8FF28420ED10120FFF7E3FF2042C3 +:100CB00009D10220FFF7DEFF104204D10320FFF725 +:100CC000D9FF184201D00F2070BD21462846BDE84B +:100CD000704000F0C4BE10B5044C6078F1F7A9FE76 +:100CE00000B9FFDF00202070A07010BD940100202B +:100CF00004E5014000E40140105C0C00C412002037 +:100D0000090A020000300200B0000020BEBAFECA8C +:100D10007C5E0100002101700846704701460020FA +:100D200008707047EFF3108101F0010172B602788C +:100D3000012A01D0012200E000220123037001B941 +:100D400062B60AB1002070474FF400507047E9E7DF +:100D5000EFF3108111F0010F72B64FF00002027034 +:100D600000D162B600207047F2E700004C490968E4 +:100D70000160002070474A49086000207047012147 +:100D80008A0720B1012804D042F20400704791671D +:100D900000E0D1670020704742490120086042F21C +:100DA0000600704708B504233E4A1907103230B1D7 +:100DB000C1F80433106840F0010010600BE01068C7 +:100DC00020F001001060C1F808330020C1F80801CC +:100DD000354800680090002008BD011F0B2909D884 +:100DE000304910310A6822F01E0242EA40000860D1 +:100DF0000020704742F205007047000100F180407A +:100E0000C0F8041900207047000100F18040C0F8CC +:100E1000081900207047000100F18040D0F8000957 +:100E2000086000207047012801D9072070471F4A39 +:100E300052F8200002680A4302600020704701282F +:100E400001D907207047194A52F8200002688A43E6 +:100E5000026000207047012801D907207047134A1B +:100E600052F8200000680860002070470200104916 +:100E70004FF0000003D0012A01D0072070470A601C +:100E800070474FF080410020C1F808014FF0E0208A +:100E9000802180F800140121C0F800117047000083 +:100EA0000004004000050040080100404C240200FE +:100EB000780500406249634B0A6863499A420968B1 +:100EC00001D1C1F310010160002070475C495D4B06 +:100ED0000A685D49091D9A4201D1C0F310000860FB +:100EE000002070475649574B0A68574908319A42C3 +:100EF00001D1C0F3100008600020704730B5504B9E +:100F0000504D1C6842F20803AC4202D0142802D2B1 +:100F100003E0112801D3184630BDC3004B481844E4 +:100F2000C0F81015C0F81425002030BD4449454BC9 +:100F30000A6842F209019A4202D0062802D203E06E +:100F4000042801D308467047404A012142F8301076 +:100F5000002070473A493B4B0A6842F209019A4225 +:100F600002D0062802D203E0042801D308467047C5 +:100F7000364A012102EBC00041600020704770B585 +:100F80002F4A304E314C156842F2090304EB8002BF +:100F9000B54204D0062804D2C2F8001807E004289D +:100FA00001D3184670BDC1F31000C2F8000800203C +:100FB00070BD70B5224A234E244C156842F20903D5 +:100FC00004EB8002B54204D0062804D2D2F800080F +:100FD00007E0042801D3184670BDD2F80008C0F31A +:100FE00010000860002070BD174910B5083118487E +:100FF00008601120154A002102EBC003C3F8101548 +:10100000C3F81415401C1428F6D3002006E0042869 +:1010100004D302EB8003C3F8001807E002EB80035F +:10102000D3F80048C4F31004C3F80048401C062855 +:10103000EDD310BD04490648083108607047000030 +:10104000B0000020BEBAFECA00F5014000F0014029 +:101050000000FEFF7D4B1B6803B19847BFF34F8F25 +:101060007B4801687B4A01F4E06111430160BFF3F2 +:101070004F8FFEE710B5EFF3108010F0010F72B63E +:1010800001D0012400E0002400F0D6F850B1E0F7D0 +:1010900041F9F1F7BCFAF2F777FCE1F7C0FE6E49CF +:1010A0000020086004B962B6002010BD70B50C467F +:1010B0000646EFF3108010F0010F72B601D0012543 +:1010C00000E0002500F0B8F818B105B962B60820B4 +:1010D00070BDE0F79BF8E0F71FF9024600204309D6 +:1010E0009B0003F1E02300F01F01D3F80031CB4057 +:1010F000D9071BD0202803D222FA00F1C90722D138 +:1011000041B2002906DA01F00F0101F1E02191F866 +:10111000141D03E001F1E02191F8001449090829A8 +:1011200011D281B101290ED004290CD0401C6428B1 +:10113000D5D3E1F74BFE4849484808602046F3F70D +:101140008FF860B904E005B962B641F2010070BDE4 +:101150003E4804602EB13046F3F7CFF818B11024A2 +:1011600029E03F4E16E03078022802D94FF480542F +:1011700021E007240028707801D0E0B908E0D0B160 +:10118000202818D8B078212815D8012813D001E0DC +:10119000B07880B93349802081F8140DE0F7BCF8AD +:1011A0003146F2F7D7FBF1F7F1F900F0E3F93046F9 +:1011B000E0F782F8044605B962B61CB1FFF75AFFA2 +:1011C000204670BD002070BD10B5044600F034F814 +:1011D00000B101202070002010BD234908600020CC +:1011E000704770B50C4621490D682049204E0831E2 +:1011F0000E60102807D011280CD012280FD0132809 +:1012000011D0012013E0D4E90001FFF74FFF35466C +:1012100020600DE0FFF72EFF0025206008E0206829 +:10122000FFF7D2FF03E0104920680860002020602B +:101230000E48001D056070BD0748084900688842D7 +:1012400001D101207047002070470000AC01002050 +:101250000CED00E00400FA05B0000020BEBAFECAA2 +:10126000542402000BE000E00400002010050240BE +:101270000100000100B5764910F1080F08BFF82001 +:1012800024D014DC10F1280F08BFD8201ED010F194 +:10129000140F08BFEC2019D010F1100F08BFF02078 +:1012A00014D010F10C0F08BFF4200FD00CE010F197 +:1012B000040F08BFFC2009D0002818BF032805D060 +:1012C000042804BF086000BDFFDF00BD086000BD4A +:1012D00000B56049012808BF032004D0022816BFCA +:1012E000FFDF042000BD086000BD5A48016801F01E +:1012F0000F01032904BF01207047006800F00F00B0 +:10130000042804BF0220704700B5FFDF012000BDA4 +:101310005149002808BF086805D0012806BF0868A1 +:1013200040F0010070470860704770B5054601291C +:1013300014D0022A07BF49484FF47A7148484FF445 +:10134000C86144181846F4F759F820444FF47A71EC +:1013500000F27120B0FBF1F0281A70BD022A14BF10 +:101360004FF4C8604FF47A7049F608514418E9E721 +:1013700070B514460546012908BF49F6CA6605D06E +:10138000022B0CBF3748364800F1FA061046F4F736 +:1013900044F8012C0CBF4FF47A714FF4FA71711AB2 +:1013A00008444FF47A7100F28920B0FBF1F0281A5A +:1013B000801E70BD70B51546064601291AD0022B55 +:1013C00007BF26484FF47A7125484FF4C861441886 +:1013D0001046F4F722F8012D0CBF4FF47A714FF448 +:1013E000FA71611A08444FF47A716438B0FBF1F075 +:1013F000301A70BD022B14BF4FF4C8604FF47A70DE +:1014000049F608514418E3E770B505460C46164600 +:101410001046F3F7F3FF05EB4501C1EBC51100EBF7 +:10142000C100012C0CBF4FF47A714FF4FA714518CA +:101430002046F3F7F2FF281A4FF47A7100F60F6096 +:10144000B0FBF1F43046F3F7CDFF2044401D70BDF2 +:101450000C15004010150040501600406836020080 +:10146000A2240200043602002DE9F04184B088462F +:101470000746FEF70FFC05467E786A4601A94046FE +:10148000EFF748F804000ED0012D1EBF032004B072 +:10149000BDE8F08102AA40460199EEF73AFF0298B2 +:1014A000B0F803000AE0022D18D1042E16D3B7F8C5 +:1014B0000300BDF80020011D8A4206D3001D80B242 +:1014C000A119814238BF012004D104B04FF00000BF +:1014D000BDE8F0813CBF04B0BDE8F0814FF00200F0 +:1014E00004B0BDE8F08100000B4A022111600B49F5 +:1014F0000B68002BFCD0084B1B1D186008680028E7 +:10150000FCD00020106008680028FCD070474FF025 +:10151000805040697047000004E5014000E401404C +:1015200002000B464FF00000014620D0012A04D0F3 +:10153000022A04D0032A0DD103E0012002E0022098 +:1015400015E00320072B05D2DFE803F00406080AA4 +:101550000C0E100007207047012108E0022106E070 +:10156000032104E0042102E0052100E00621F1F757 +:1015700022BA0000FC4805218170002101704170F1 +:10158000C17081607047F9490A78012A06D0CA689B +:101590001044C860C8684038F1F748BF8A681044F2 +:1015A00088608868F7E710B5EF4CE078F1F741FA0A +:1015B00000B9FFDF0820F2F746FA0520A0700020EE +:1015C0002070607010BD002819D00378E849E94AFE +:1015D00013B1012B0ED011E00379012B00D06BB9B0 +:1015E00043790BB1012B09D18368643B8B4205D24F +:1015F000C0680EE00379012B02D00BB100207047C8 +:1016000043790BB1012BF9D1C368643B8B42F5D20E +:1016100080689042F2D8012070472DE9F0410446DD +:101620000227F1F72FFE006800B1FFDFCE4D012643 +:101630003CB12078B0B1012805D0022810D0032891 +:1016400013D02E710CE06068C82807D3F1F755FF5E +:1016500020B16068FFF797FF012703E0002701E052 +:1016600000F0CCF93846BDE8F08128780028F7D1A1 +:101670006068FFF7A8FF0028E3D06068DFF8EC821D +:10168000007828B3A878042800D0FFDF0020464661 +:1016900088F8000060680079C8B300203071606885 +:1016A0004079A8B30420707160688168E868F0F739 +:1016B000EAFEB0606068C0685230F0600320A87035 +:1016C000AA49E878F1F71EFC0028C9D1FFDFC7E777 +:1016D000404688F8006061680979D1B10021017144 +:1016E00061684979B9B104214171616889685231F1 +:1016F00081606168C968C160C0689B4C14346060D7 +:10170000F1F7B6F920606E700220A870A8E704E037 +:1017100005E00321E3E70321E6E70120BEE703201C +:10172000C1E72DE9F047904C8846E178884200D027 +:10173000FFDFDFF83492002501278C4E09F11409F0 +:10174000B8F1080F79D2DFE808F0040D2A557E843D +:101750009199A078032803D0A078022800D0FFDF59 +:10176000BDE8F087A078032803D0A078022800D035 +:10177000FFDF0420A0702571207800287AD1FFF7C0 +:1017800002FF3078012806D0B068E06000F07BF9F5 +:101790002061002062E0E078F1F7B0FAF5E7A07888 +:1017A000032803D0A078022800D0FFDF207800288B +:1017B0006FD1A078032816D0F1F75AF901464F46A9 +:1017C000D9F80000F1F765FE00280EDB7968814248 +:1017D0000BDB081AF0606549E078F1F793FB00280D +:1017E000BED1FFDFBCE7042029E00420F2F72BF98B +:1017F000A570B5E7A078032803D0A078022800D010 +:10180000FFDF207888BBA078032817D0F1F730F9E4 +:1018100001464F46D9F80000F1F73BFE0028E4DB13 +:1018200079688142E1DB081AF0605049E078F1F70D +:1018300069FB002894D1FFDF92E740E00520F2F732 +:1018400002F9A7708CE7A078042800D0FFDF0220FF +:1018500004E0A078042800D0FFDF0120A1688847B9 +:10186000FFF7DBFE054630E004E012E0A078042834 +:1018700000D0FFDFBDE8F04700F0C0B8A078042832 +:1018800005D0607810B1A078022800D0FFDF207862 +:1018900010B1BDE8F04786E6207920B10620F2F7C6 +:1018A000D2F82571CDE7607838B13049E078F1F7AA +:1018B00029FB00B9FFDF657052E70720BFE7FFDFB4 +:1018C0004EE73DB1012D03D0FFDF022DF9D147E7EF +:1018D0000420C3E70320C1E770B5050005D0224C02 +:1018E000A078052803D0112070BD102070BD2248BB +:1018F000F1F744F8E070E078202803D0A5600020DC +:10190000A07070BD032070BD174810B5017809B1F3 +:10191000112010BD817805290CD0817801290BD0C8 +:10192000817849B1012101708178012904D0807842 +:1019300010B103E00F2010BDFFF735FE002010BDF1 +:1019400070B5094E0446B07808B101280AD1ACB18F +:101950002046FFF738FE98B12078044D90B1B0785A +:1019600001282AD00F2070BDB0010020D412002021 +:101970003D860100FF1FA107231702001020F2E798 +:101980000720F0E701202870207990B1002028710D +:10199000607980B104206871A0685230A860E06866 +:1019A000E860E8681A4C6060F1F762F82060022095 +:1019B00016E00320EBE70320EDE7002028702079F4 +:1019C000A8B100202871607998B104206871A168DD +:1019D000F068F0F758FDA860E0685230E860032036 +:1019E000B0700C49F078F1F78DFA28B903E00320C4 +:1019F000E8E70320EAE7FFDF0020B4E7044810B57A +:101A00001438006900F037F8BDE81040F0F73BBF2C +:101A1000C4010020D41200201F490968014201D0EE +:101A200001207047002070471B49091D09680142C9 +:101A300001D0012070470020704717491031096814 +:101A4000014201D001207047002070471249143133 +:101A50000968014201D0012070470020704710B58D +:101A60000D4C2060201D01600B4810300260001DED +:101A70000360002010BD09490A6848F202139A4326 +:101A800002430A607047054A116848F2021301EAEE +:101A9000030099431160704700060040C8060240E9 +:101AA00040EA010310B59B070FD1042A0DD310C8DB +:101AB00008C9121F9C42F8D020BA19BA884201D92D +:101AC000012010BD4FF0FF3010BD1AB1D30703D075 +:101AD000521C07E0002010BD10F8013B11F8014B2B +:101AE0001B1B07D110F8013B11F8014B1B1B01D147 +:101AF000921EF1D1184610BD032A40F2308010F03A +:101B0000030C00F0158011F8013BBCF1020F624498 +:101B100098BF11F801CB00F8013B38BF11F8013B29 +:101B2000A2F1040298BF00F801CB38BF00F8013BD6 +:101B300011F0030300F02580083AC0F0088051F846 +:101B4000043B083A51F804CBA0E80810F5E7121D51 +:101B50005CBF51F8043B40F8043BAFF30080D20770 +:101B600024BF11F8013B11F801CB48BF11F8012B3C +:101B700024BF00F8013B00F801CB48BF00F8012B5F +:101B8000704710B5203AC0F00B80B1E81850203AE9 +:101B9000A0E81850B1E81850A0E81850BFF4F5AF0D +:101BA0005FEA027C24BFB1E81850A0E8185044BF97 +:101BB00018C918C0BDE810405FEA827C24BF51F804 +:101BC000043B40F8043B08BF7047D20728BF31F8F8 +:101BD000023B48BF11F8012B28BF20F8023B48BF49 +:101BE00000F8012B70474FF000020429C0F012806A +:101BF00010F0030C00F01B80CCF1040CBCF1020FC0 +:101C000018BF00F8012BA8BF20F8022BA1EB0C0194 +:101C100000F00DB85FEAC17C24BF00F8012B00F88A +:101C2000012B48BF00F8012B70474FF0000200B5B0 +:101C3000134694469646203922BFA0E80C50A0E8EF +:101C40000C50B1F12001BFF4F7AF090728BFA0E89D +:101C50000C5048BF0CC05DF804EB890028BF40F869 +:101C6000042B08BF704748BF20F8022B11F0804FAB +:101C700018BF00F8012B704770477047704700008D +:101C8000FEDF04207146084219D10699124A91429A +:101C900015DC069902394878DF2810D10878FE282B +:101CA00007D0FF280BD14FF001004FF000020B4B83 +:101CB000184741F201000099019A084B1847084B58 +:101CC000002B02D01B68DB6818474FF0FF307146CD +:101CD0004FF00002014B184700300200551002007F +:101CE00004000020184819497047FFF7FBFFDFF791 +:101CF00065FA00BD4FF4805015490968884203D148 +:101D0000144A13605B68184700BD000020BFFDE760 +:101D10004FF480500E490968884210D10E4B186864 +:101D20004FF0FF318842F1D080F308884FF0202136 +:101D3000884204DD0948026802210A43026008481B +:101D4000804708488047FFDFE8120020E8120020A3 +:101D500000000020040000200030020024050040A4 +:101D600039430100F51C020004207146084202D0EC +:101D7000EFF3098101E0EFF3088188690238007808 +:101D8000102813DB20280FDB2B280BDB0A4A1268F4 +:101D90000A4B9A4203D1602804DB094A104702200B +:101DA00008607047074A1047074A1047074A1268F9 +:101DB0002C32126810470000B0000020BEBAFECAE4 +:101DC0001D130000D5070200E311020004000020EB +:101DD0000D4B0E4908470E4B0C4908470D4B0B495C +:101DE00008470D4B094908470C4B084908470C4B5D +:101DF000064908470B4B054908470B4B0349084761 +:101E00000A4B024908470000F9BA0000092F0000F8 +:101E1000812C00001D2B0000AB2A0000232D0000A8 +:101E2000391300006728000029BD0000C911000017 +:101E300000210160818070470021016041600172D2 +:101E400070470A6802600B7903717047599500006A +:101E50001B970000779800009B980000D598000021 +:101E6000099900004399000081990000D39900006E +:101E700031960000A7120000A7120000C140000028 +:101E80000541000025410000E1410000274300001A +:101E90000144000031440000F5440000153D0000FD +:101EA000274700001948000039480000DD150000F0 +:101EB00001160000311500008515000033160000E2 +:101EC000C716000003600000B561000073650000E4 +:101ED000896600000D67000087670000F967000051 +:101EE00015690000E3690000616A000053480000C2 +:101EF0005948000063480000D73C00001F4900001B +:101F0000A13C00005F4A0000B74A00001F4B0000E0 +:101F1000A7120000A7120000A7120000A7240000CB +:101F20002D2500004925000065250000F32600004E +:101F30008F25000099250000DB250000FD2500000D +:101F4000D92600001B270000A7120000CF82000046 +:101F5000F7820000F98200003383000061830000F3 +:101F60004F840000DB840000EF8400003D8500000A +:101F70002D860000D1870000F9880000D172000092 +:101F800011890000A7120000A712000049B4000048 +:101F9000B3B5000007B6000073B6000023B7000019 +:101FA00051000000000000000000000000000000E0 +:101FB0000000000000000000000000000000000021 +:101FC0000000000000000000000000003E000000D3 +:101FD0000000000000000000000000000000000001 +:101FE00000000000000000000000000000000000F1 +:101FF0000000000000000000500000000000000091 +:1020000000000000000000000000000000000000D0 +:1020100000000000000000000000000000000000C0 +:1020200000000000100110013A0200001A02000432 +:102030000506000013900000F38F0000FFFFFFFF74 +:102040000000FFFF3BAC00003D39000041200000D4 +:102050001B730000EB8D0000000000000000020078 +:10206000000000000002000000000000000100006D +:10207000000000006F8000004F800000BD80000065 +:1020800029240000EB2300000B240000A7A7000078 +:10209000D3A70000DBA9000021590000DD8000006B +:1020A000000000000D810000772400000000000007 +:1020B0000000000000000000BDA8000000000000BB +:1020C000B359000000000000000000000000000004 +:1020D0000000000000000000000000000000000000 +:1020E000000000000000000000000000D5E5000036 +:1020F00059E60000000000000000000000000000A1 +:1021000059E700000000000000000000000000008F +:1021100049F800000000000000000000000000007E +:1021200005E900005DF4000000000000DDF400009F +:1021300051F500000000000037EE0000D5EE000071 +:102140000000000017F50000D1EF0000C9F1000009 +:102150003DF2000041F30000A5EA0000000000008D +:1021600000000000BFE90000000000001FE80000C0 +:1021700095E70000BDF300007BF60000E9F60000E3 +:1021800000000000A7E60000D7E6000007E6000018 +:102190000000000021E70000000000000000000037 +:1021A000000000004BF700000000000000000000ED +:1021B000000000000000000000000000EFEC000044 +:1021C000000000000000000000000000C3E8000064 +:1021D000C1E700008BE800000000000053E80000A9 +:1021E0000000000000000000B3F7000097F80000B6 +:1021F0009BFA000017F900003DE9000051FA0000C9 +:10220000000000004FEB000021EC000061F900002D +:10221000ABF9000007F80000E5F90000F1ED00005F +:1022200093560000935600009D400000E7AA00006E +:102230009F750000531F000087AA01004BC50100D5 +:10224000D9560000D9560000BF40000049AB00003D +:1022500023760000C51F0000B5AA01005FC501007C +:10226000D001D001400038005C0024004001F001A2 +:1022700001000000010000000001020304120F1021 +:102280001100000013000000B10502007F060200EB +:10229000D10602001D07020071070200AB00020018 +:1022A000CD01020035020200590402003B05020084 +:1022B000750D01008B1E01000000000006000000EB +:1022C0000A0000003200000073000000B4000000AB +:1022D000B197010045850100235F010077DE010011 +:1022E000F772010077DE01007D5F010005E001006B +:1022F000876B010005E001007B5E010093DF0100B8 +:10230000C971010093DF01004D630100FFE201008C +:102310007F730100FFE20100555555D6BE898E003E +:102320000000A606340DC21300004A03EE05920811 +:10233000000096041409920D555555252627D6BE42 +:10234000898EF401FA00960064004B0032001E00F2 +:1023500014000A00050002000100000025410000F1 +:1023600000000000AAAED7AB15412010000003000A +:10237000656C7462000000000000000000000000B6 +:1023800000000000870000000000000000000000C6 +:1023900000000000BE83605ADB0B376038A5F5AA49 +:1023A0009183886CB50E0200CD0E0200E50E02008E +:1023B000FD0E02002D0F0200550F02007F0F0200DC +:1023C000B30F0200150C0200650B0200990C02000D +:1023D000150D0200250D0200510D0200A33B010066 +:1023E000AB3B0100B93B01007F0D0200990D0200DB +:1023F0006D0D0200770D0200A50D0200DB0D02003D +:10240000FB0D0200090E0200170E0200270E02004B +:102410003F0E0200570E02006D0E02000000000089 +:10242000F7B800004DB9000063B9000021150200A3 +:10243000490802000F090200D91802000919020018 +:1024400041190200E93901000D3E01001C05004060 +:10245000200500400010020078240200080000203F +:10246000C401000044110000A8240200CC01002097 +:102470001C110000A01100000118136813024C2069 +:102480001A010222782720FB349B5F801280021EF3 +:1024900010139F0A1B205C041AE2040128237F0109 +:0824A00002A329091DFB013113 +:00000001FF diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json new file mode 100644 index 0000000000..55ecb9abc4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json @@ -0,0 +1,48 @@ +{ + "name": "softdevice", + "config": { + }, + "macros": [ + "SOFTDEVICE_PRESENT=1", + "S132", + "BLE_STACK_SUPPORT_REQD", + "NRF_SDH_CLOCK_LF_SRC=1", + "NRF_SDH_CLOCK_LF_RC_CTIV=0", + "NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0", + "NRF_SDH_CLOCK_LF_XTAL_ACCURACY=7", + "NRF_SD_BLE_API_VERSION=5", + "NRF_SDH_ENABLED=1", + "NRF_SDH_BLE_ENABLED=1", + "PEER_MANAGER_ENABLED=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", + "NRF_SDH_BLE_SERVICE_CHANGED=1", + "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23", + "NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE=0x600", + "NRF_SDH_BLE_VS_UUID_COUNT=4", + "NRF_SDH_BLE_OBSERVER_PRIO_LEVELS=4", + "NRF_SDH_BLE_GAP_EVENT_LENGTH=3", + "BLE_ADV_BLE_OBSERVER_PRIO=1", + "BLE_CONN_STATE_BLE_OBSERVER_PRIO=0", + "BLE_CONN_PARAMS_BLE_OBSERVER_PRIO=1", + "NRF_BLE_GATT_BLE_OBSERVER_PRIO=1", + "NRF_SDH_DISPATCH_MODEL=2", + "NRF_SDH_SOC_ENABLED=1", + "NRF_SDH_STACK_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_STATE_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_SOC_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_REQ_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_BLE_STACK_OBSERVER_PRIO=0", + "NRF_SDH_SOC_STACK_OBSERVER_PRIO=0", + "FDS_BACKEND=2", + "SWI_DISABLE1=1", + "NRF_LOG_ENABLED=0" + ], + "target_overrides": { + "*": { + "target.features_add": ["BLE"], + "target.bootloader_img": "hex/s132_nrf52_5.0.0_softdevice.hex" + } + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.pdf new file mode 100644 index 0000000000..1a1a731d3a Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt new file mode 100644 index 0000000000..b8d26c9a84 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt @@ -0,0 +1,96 @@ +S110/S120/S130/S132/S140 license agreement + + +NORDIC SEMICONDUCTOR ASA SOFTDEVICE LICENSE AGREEMENT + +License Agreement for the Nordic Semiconductor ASA ("Nordic") S110, S120, S130, S132, and S140 Bluetooth SoftDevice software packages +("SoftDevice"). + +You ("You" "Licensee") must carefully and thoroughly read this License Agreement ("Agreement"), and accept to adhere to this Agreement before +downloading, installing and/or using any software or content in the SoftDevice provided herewith. + +YOU ACCEPT THIS LICENSE AGREEMENT BY (A) CLICKING ACCEPT OR AGREE TO THIS LICENSE AGREEMENT, WHERE THIS +OPTION IS MADE AVAILABLE TO YOU; OR (B) BY ACTUALLY USING THE SOFTDEVICE, IN THIS CASE YOU AGREE THAT THE USE OF +THE SOFTDEVICE CONSTITUTES ACCEPTANCE OF THE LICENSING AGREEMENT FROM THAT POINT ONWARDS. + +IF YOU DO NOT AGREE TO BE BOUND BY THE TERMS OF THIS AGREEMENT, THEN DO NOT DOWNLOAD, INSTALL/COMPLETE +INSTALLATION OF, OR IN ANY OTHER WAY MAKE USE OF THE SOFTDEVICE. + +1. Grant of License +Subject to the terms in this Agreement Nordic grants Licensee a limited, non-exclusive, non-transferable, non-sub licensable, revocable license +("License"): (a) to use the SoftDevice solely in connection with a Nordic integrated circuit, and (b) to distribute the SoftDevice solely as integrated +in Licensee Product. Licensee shall not use the SoftDevice for any purpose other than specifically authorized herein. It is a material breach of this +agreement to use or modify the SoftDevice for use on any wireless connectivity integrated circuit other than a Nordic integrated circuit. + +2. Title +Nordic retains full rights, title, and ownership to the SoftDevice and any and all patents, copyrights, trade secrets, trade names, trademarks, and +other intellectual property rights in and to the SoftDevice. + +3. No Modifications or Reverse Engineering +Licensee shall not, modify, reverse engineer, disassemble, decompile or otherwise attempt to discover the source code of any non-source code +parts of the SoftDevice including, but not limited to pre-compiled hex files, binaries and object code. + +4. Distribution Restrictions +Except as set forward in Section 1 above, the Licensee may not disclose or distribute any or all parts of the SoftDevice to any third party. +Licensee agrees to provide reasonable security precautions to prevent unauthorized access to or use of the SoftDevice as proscribed herein. +Licensee also agrees that use of and access to the SoftDevice will be strictly limited to the employees and subcontractors of the Licensee +necessary for the performance of development, verification and production tasks under this Agreement. The Licensee is responsible for making +such employees and subcontractors comply with the obligations concerning use and non-disclosure of the SoftDevice. + +5. No Other Rights +Licensee shall use the SoftDevice only in compliance with this Agreement and shall refrain from using the SoftDevice in any way that may be +contrary to this Agreement. + +6. Fees +Nordic grants the License to the Licensee free of charge provided that the Licensee undertakes the obligations in the Agreement and warrants to +comply with the Agreement. + +7. DISCLAIMER OF WARRANTY +THE SOFTDEVICE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EXPRESS OR IMPLIED AND NEITHER NORDIC, ITS +LICENSORS OR AFFILIATES NOR THE COPYRIGHT HOLDERS MAKE ANY REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR +THAT THE SOFTDEVICE WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. THERE +IS NO WARRANTY BY NORDIC OR BY ANY OTHER PARTY THAT THE FUNCTIONS CONTAINED IN THE SOFTDEVICE WILL MEET THE +REQUIREMENTS OF LICENSEE OR THAT THE OPERATION OF THE SOFTDEVICE WILL BE UNINTERRUPTED OR ERROR-FREE. +LICENSEE ASSUMES ALL RESPONSIBILITY AND RISK FOR THE SELECTION OF THE SOFTDEVICE TO ACHIEVE LICENSEES +INTENDED RESULTS AND FOR THE INSTALLATION, USE AND RESULTS OBTAINED FROM IT. + + +8. No Support +Nordic is not obligated to furnish or make available to Licensee any further information, software, technical information, know-how, show-how, +bug-fixes or support. Nordic reserves the right to make changes to the SoftDevice without further notice. + +9. Limitation of Liability +In no event shall Nordic, its employees or suppliers, licensors or affiliates be liable for any lost profits, revenue, sales, data or costs of +procurement of substitute goods or services, property damage, personal injury, interruption of business, loss of business information or for any +special, direct, indirect, incidental, economic, punitive, special or consequential damages, however caused and whether arising under contract, +tort, negligence, or other theory of liability arising out of the use of or inability to use the SoftDevice, even if Nordic or its employees or suppliers, +licensors or affiliates are advised of the possibility of such damages. Because some countries/states/jurisdictions do not allow the exclusion or +limitation of liability, but may allow liability to be limited, in such cases, Nordic, its employees or licensors or affiliates liability shall be limited to +USD 50. + +10. Breach of Contract +Upon a breach of contract by the Licensee, Nordic and its licensor are entitled to damages in respect of any direct loss which can be reasonably +attributed to the breach by the Licensee. If the Licensee has acted with gross negligence or willful misconduct, the Licensee shall cover both +direct and indirect costs for Nordic and its licensors. + +11. Indemnity +Licensee undertakes to indemnify, hold harmless and defend Nordic and its directors, officers, affiliates, shareholders, licensors, employees and +agents from and against any claims or lawsuits, including attorney's fees, that arise or result of the Licensees execution of the License and which +is not due to causes for which Nordic is responsible. + +12. Governing Law +This Agreement shall be construed according to the laws of Norway, and hereby submits to the exclusive jurisdiction of the Oslo tingrett. + +13. Assignment +Licensee shall not assign this Agreement or any rights or obligations hereunder without the prior written consent of Nordic. + +14. Termination +Without prejudice to any other rights, Nordic may cancel this Agreement if Licensee does not abide by the terms and conditions of this +Agreement. Upon termination Licensee must promptly cease the use of the License and destroy all copies of the Licensed Technology and any +other material provided by Nordic or its affiliate, or produced by the Licensee in connection with the Agreement or the Licensed Technology. + +15. Third party beneficiaries +Nordics licensors are intended third party beneficiaries under this Agreement. + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_migration-document.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_migration-document.pdf new file mode 100644 index 0000000000..8026762196 Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_migration-document.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_readme.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_readme.txt new file mode 100644 index 0000000000..2cce458228 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_readme.txt @@ -0,0 +1,10 @@ +s140_nrf52840_5.0.0-2.alpha + +This release consists of the following: + +- This readme file +- The s140_nrf52840_5.0.0-2.alpha API (SoftDevice header files) +- The s140_nrf52840_5.0.0-2.alpha license agreement +- The s140_nrf52840_5.0.0-2.alpha release notes +- The s140_nrf52840_5.0.0-2.alpha SoftDevice (binary hex file) +- The s140_nrf52840_5.0.0-2.alpha Migration Document diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_release-notes-update-1.pdf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_release-notes-update-1.pdf new file mode 100644 index 0000000000..9ffceb9b56 Binary files /dev/null and b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/doc/s140_nrf52840_5.0.0-2.alpha_release-notes-update-1.pdf differ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_err.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_err.h new file mode 100644 index 0000000000..36d54a0dc0 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_err.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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_.h or ble_error_.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 + + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gap.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gap.h new file mode 100644 index 0000000000..339db01fd1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gap.h @@ -0,0 +1,2211 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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_GAP Generic Access Profile (GAP) + @{ + @brief Definitions and prototypes for the GAP interface. + */ + +#ifndef BLE_GAP_H__ +#define BLE_GAP_H__ + + +#include "ble_types.h" +#include "ble_ranges.h" +#include "nrf_svc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@addtogroup BLE_GAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GAP API SVC numbers. + */ +enum BLE_GAP_SVCS +{ + SD_BLE_GAP_ADDR_SET = BLE_GAP_SVC_BASE, /**< Set own Bluetooth Address. */ + SD_BLE_GAP_ADDR_GET, /**< Get own Bluetooth Address. */ + SD_BLE_GAP_WHITELIST_SET, /**< Set active whitelist. */ + SD_BLE_GAP_DEVICE_IDENTITIES_SET, /**< Set device identity list. */ + SD_BLE_GAP_PRIVACY_SET, /**< Set Privacy settings*/ + SD_BLE_GAP_PRIVACY_GET, /**< Get Privacy settings*/ + SD_BLE_GAP_ADV_DATA_SET, /**< Set Advertising Data. */ + SD_BLE_GAP_ADV_START, /**< Start Advertising. */ + SD_BLE_GAP_ADV_STOP, /**< Stop Advertising. */ + SD_BLE_GAP_CONN_PARAM_UPDATE, /**< Connection Parameter Update. */ + SD_BLE_GAP_DISCONNECT, /**< Disconnect. */ + SD_BLE_GAP_TX_POWER_SET, /**< Set TX Power. */ + SD_BLE_GAP_APPEARANCE_SET, /**< Set Appearance. */ + SD_BLE_GAP_APPEARANCE_GET, /**< Get Appearance. */ + SD_BLE_GAP_PPCP_SET, /**< Set PPCP. */ + SD_BLE_GAP_PPCP_GET, /**< Get PPCP. */ + SD_BLE_GAP_DEVICE_NAME_SET, /**< Set Device Name. */ + SD_BLE_GAP_DEVICE_NAME_GET, /**< Get Device Name. */ + SD_BLE_GAP_AUTHENTICATE, /**< Initiate Pairing/Bonding. */ + SD_BLE_GAP_SEC_PARAMS_REPLY, /**< Reply with Security Parameters. */ + SD_BLE_GAP_AUTH_KEY_REPLY, /**< Reply with an authentication key. */ + SD_BLE_GAP_LESC_DHKEY_REPLY, /**< Reply with an LE Secure Connections DHKey. */ + SD_BLE_GAP_KEYPRESS_NOTIFY, /**< Notify of a keypress during an authentication procedure. */ + SD_BLE_GAP_LESC_OOB_DATA_GET, /**< Get the local LE Secure Connections OOB data. */ + SD_BLE_GAP_LESC_OOB_DATA_SET, /**< Set the remote LE Secure Connections OOB data. */ + SD_BLE_GAP_ENCRYPT, /**< Initiate encryption procedure. */ + SD_BLE_GAP_SEC_INFO_REPLY, /**< Reply with Security Information. */ + SD_BLE_GAP_CONN_SEC_GET, /**< Obtain connection security level. */ + SD_BLE_GAP_RSSI_START, /**< Start reporting of changes in RSSI. */ + SD_BLE_GAP_RSSI_STOP, /**< Stop reporting of changes in RSSI. */ + SD_BLE_GAP_SCAN_START, /**< Start Scanning. */ + SD_BLE_GAP_SCAN_STOP, /**< Stop Scanning. */ + SD_BLE_GAP_CONNECT, /**< Connect. */ + SD_BLE_GAP_CONNECT_CANCEL, /**< Cancel ongoing connection procedure. */ + SD_BLE_GAP_RSSI_GET, /**< Get the last RSSI sample. */ + SD_BLE_GAP_PHY_REQUEST, /**< Initiate PHY Update procedure. */ + SD_BLE_GAP_DATA_LENGTH_UPDATE, /**< Initiate or respond to a Data Length Update Procedure. */ +}; + +/**@brief GAP Event IDs. + * IDs that uniquely identify an event coming from the stack to the application. + */ +enum BLE_GAP_EVTS +{ + BLE_GAP_EVT_CONNECTED = BLE_GAP_EVT_BASE, /**< Connection established. \n See @ref ble_gap_evt_connected_t. */ + BLE_GAP_EVT_DISCONNECTED, /**< Disconnected from peer. \n See @ref ble_gap_evt_disconnected_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE, /**< Connection Parameters updated. \n See @ref ble_gap_evt_conn_param_update_t. */ + BLE_GAP_EVT_SEC_PARAMS_REQUEST, /**< Request to provide security parameters. \n Reply with @ref sd_ble_gap_sec_params_reply. \n See @ref ble_gap_evt_sec_params_request_t. */ + BLE_GAP_EVT_SEC_INFO_REQUEST, /**< Request to provide security information. \n Reply with @ref sd_ble_gap_sec_info_reply. \n See @ref ble_gap_evt_sec_info_request_t. */ + BLE_GAP_EVT_PASSKEY_DISPLAY, /**< Request to display a passkey to the user. \n In LESC Numeric Comparison, reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_passkey_display_t. */ + BLE_GAP_EVT_KEY_PRESSED, /**< Notification of a keypress on the remote device.\n See @ref ble_gap_evt_key_pressed_t */ + BLE_GAP_EVT_AUTH_KEY_REQUEST, /**< Request to provide an authentication key. \n Reply with @ref sd_ble_gap_auth_key_reply. \n See @ref ble_gap_evt_auth_key_request_t. */ + BLE_GAP_EVT_LESC_DHKEY_REQUEST, /**< Request to calculate an LE Secure Connections DHKey. \n Reply with @ref sd_ble_gap_lesc_dhkey_reply. \n See @ref ble_gap_evt_lesc_dhkey_request_t */ + BLE_GAP_EVT_AUTH_STATUS, /**< Authentication procedure completed with status. \n See @ref ble_gap_evt_auth_status_t. */ + BLE_GAP_EVT_CONN_SEC_UPDATE, /**< Connection security updated. \n See @ref ble_gap_evt_conn_sec_update_t. */ + BLE_GAP_EVT_TIMEOUT, /**< Timeout expired. \n See @ref ble_gap_evt_timeout_t. */ + BLE_GAP_EVT_RSSI_CHANGED, /**< RSSI report. \n See @ref ble_gap_evt_rssi_changed_t. */ + BLE_GAP_EVT_ADV_REPORT, /**< Advertising report. \n See @ref ble_gap_evt_adv_report_t. */ + BLE_GAP_EVT_SEC_REQUEST, /**< Security Request. \n See @ref ble_gap_evt_sec_request_t. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, /**< Connection Parameter Update Request. \n Reply with @ref sd_ble_gap_conn_param_update. \n See @ref ble_gap_evt_conn_param_update_request_t. */ + BLE_GAP_EVT_SCAN_REQ_REPORT, /**< Scan request report. \n See @ref ble_gap_evt_scan_req_report_t. */ + BLE_GAP_EVT_PHY_UPDATE, /**< PHY have been updated \n See @ref ble_gap_evt_phy_update_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST, /**< Data Length Update request. \n Reply with @ref sd_ble_gap_data_length_update.\n See @ref ble_gap_evt_data_length_update_request_t. */ + BLE_GAP_EVT_DATA_LENGTH_UPDATE, /**< LL Data Channel PDU payload length updated. \n See @ref ble_gap_evt_data_length_update_t. */ +}; + +/**@brief GAP Option IDs. + * IDs that uniquely identify a GAP option. + */ +enum BLE_GAP_OPTS +{ + BLE_GAP_OPT_CH_MAP = BLE_GAP_OPT_BASE, /**< Channel Map. @ref ble_gap_opt_ch_map_t */ + BLE_GAP_OPT_LOCAL_CONN_LATENCY, /**< Local connection latency. @ref ble_gap_opt_local_conn_latency_t */ + BLE_GAP_OPT_PASSKEY, /**< Set passkey. @ref ble_gap_opt_passkey_t */ + BLE_GAP_OPT_SCAN_REQ_REPORT, /**< Scan request report. @ref ble_gap_opt_scan_req_report_t */ + BLE_GAP_OPT_COMPAT_MODE_1, /**< Compatibility mode. @ref ble_gap_opt_compat_mode_1_t */ + BLE_GAP_OPT_COMPAT_MODE_2, /**< Compatibility mode. @ref ble_gap_opt_compat_mode_2_t */ + BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, /**< Set Authenticated payload timeout. @ref ble_gap_opt_auth_payload_timeout_t */ + BLE_GAP_OPT_PREFERRED_PHYS_SET, /**< Set the preferred PHYs for all new connections. @ref ble_gap_opt_preferred_phys_t */ + BLE_GAP_OPT_SLAVE_LATENCY_DISABLE, /**< Disable slave latency. @ref ble_gap_opt_slave_latency_disable_t */ +}; + +/**@brief GAP Configuration IDs. + * + * IDs that uniquely identify a GAP configuration. + */ +enum BLE_GAP_CFGS +{ + BLE_GAP_CFG_ROLE_COUNT = BLE_GAP_CFG_BASE, /**< Role count configuration. */ + BLE_GAP_CFG_DEVICE_NAME, /**< Device name configuration. */ +}; + +/** @} */ + +/**@addtogroup BLE_GAP_DEFINES Defines + * @{ */ + +/**@defgroup BLE_ERRORS_GAP SVC return values specific to GAP + * @{ */ +#define BLE_ERROR_GAP_UUID_LIST_MISMATCH (NRF_GAP_ERR_BASE + 0x000) /**< UUID list does not contain an integral number of UUIDs. */ +#define BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST (NRF_GAP_ERR_BASE + 0x001) /**< Use of Whitelist not permitted with discoverable advertising. */ +#define BLE_ERROR_GAP_INVALID_BLE_ADDR (NRF_GAP_ERR_BASE + 0x002) /**< The upper two bits of the address do not correspond to the specified address type. */ +#define BLE_ERROR_GAP_WHITELIST_IN_USE (NRF_GAP_ERR_BASE + 0x003) /**< Attempt to modify the whitelist while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE (NRF_GAP_ERR_BASE + 0x004) /**< Attempt to modify the device identity list while already in use by another operation. */ +#define BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE (NRF_GAP_ERR_BASE + 0x005) /**< The device identity list contains entries with duplicate identity addresses. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLES GAP Roles + * @note Not explicitly used in peripheral API, but will be relevant for central API. + * @{ */ +#define BLE_GAP_ROLE_INVALID 0x0 /**< Invalid Role. */ +#define BLE_GAP_ROLE_PERIPH 0x1 /**< Peripheral Role. */ +#define BLE_GAP_ROLE_CENTRAL 0x2 /**< Central Role. */ +/**@} */ + + +/**@defgroup BLE_GAP_TIMEOUT_SOURCES GAP Timeout sources + * @{ */ +#define BLE_GAP_TIMEOUT_SRC_ADVERTISING 0x00 /**< Advertising timeout. */ +#define BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST 0x01 /**< Security request timeout. */ +#define BLE_GAP_TIMEOUT_SRC_SCAN 0x02 /**< Scanning timeout. */ +#define BLE_GAP_TIMEOUT_SRC_CONN 0x03 /**< Connection timeout. */ +#define BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD 0x04 /**< Authenticated payload timeout. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADDR_TYPES GAP Address types + * @{ */ +#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00 /**< Public address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01 /**< Random static address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02 /**< Random private resolvable address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03 /**< Random private non-resolvable address. */ +/**@} */ + + +/**@brief The default interval in seconds at which a private address is refreshed. */ +#define BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S (900) /* 15 minutes. */ +/**@brief The maximum interval in seconds at which a private address can be refreshed. */ +#define BLE_GAP_MAX_PRIVATE_ADDR_CYCLE_INTERVAL_S (41400) /* 11 hours 30 minutes. */ + + +/** @brief BLE address length. */ +#define BLE_GAP_ADDR_LEN (6) + + +/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes + * @{ */ +#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ +#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ +/**@} */ + + +/**@defgroup BLE_GAP_AD_TYPE_DEFINITIONS GAP Advertising and Scan Response Data format + * @note Found at https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm + * @{ */ +#define BLE_GAP_AD_TYPE_FLAGS 0x01 /**< Flags for discoverability. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE 0x02 /**< Partial list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE 0x03 /**< Complete list of 16 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE 0x04 /**< Partial list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE 0x05 /**< Complete list of 32 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE 0x06 /**< Partial list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE 0x07 /**< Complete list of 128 bit service UUIDs. */ +#define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME 0x08 /**< Short local device name. */ +#define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME 0x09 /**< Complete local device name. */ +#define BLE_GAP_AD_TYPE_TX_POWER_LEVEL 0x0A /**< Transmit power level. */ +#define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE 0x0D /**< Class of device. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C 0x0E /**< Simple Pairing Hash C. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F /**< Simple Pairing Randomizer R. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 /**< Security Manager TK Value. */ +#define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS 0x11 /**< Security Manager Out Of Band Flags. */ +#define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 /**< Slave Connection Interval Range. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT 0x14 /**< List of 16-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT 0x15 /**< List of 128-bit Service Solicitation UUIDs. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA 0x16 /**< Service Data - 16-bit UUID. */ +#define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS 0x17 /**< Public Target Address. */ +#define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS 0x18 /**< Random Target Address. */ +#define BLE_GAP_AD_TYPE_APPEARANCE 0x19 /**< Appearance. */ +#define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL 0x1A /**< Advertising Interval. */ +#define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B /**< LE Bluetooth Device Address. */ +#define BLE_GAP_AD_TYPE_LE_ROLE 0x1C /**< LE Role. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256 0x1D /**< Simple Pairing Hash C-256. */ +#define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256 0x1E /**< Simple Pairing Randomizer R-256. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID 0x20 /**< Service Data - 32-bit UUID. */ +#define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID 0x21 /**< Service Data - 128-bit UUID. */ +#define BLE_GAP_AD_TYPE_LESC_CONFIRMATION_VALUE 0x22 /**< LE Secure Connections Confirmation Value */ +#define BLE_GAP_AD_TYPE_LESC_RANDOM_VALUE 0x23 /**< LE Secure Connections Random Value */ +#define BLE_GAP_AD_TYPE_URI 0x24 /**< URI */ +#define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA 0x3D /**< 3D Information Data. */ +#define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF /**< Manufacturer Specific Data. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FLAGS GAP Advertisement Flags + * @{ */ +#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ +#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ +#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ +#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_INTERVALS GAP Advertising interval max and min + * @{ */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 /**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_NONCON_INTERVAL_MIN 0x00A0 /**< Minimum Advertising interval in 625 us units for non connectable mode, i.e. 100 ms. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 /**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ + /**@} */ + + +/**@defgroup BLE_GAP_SCAN_INTERVALS GAP Scan interval max and min + * @{ */ +#define BLE_GAP_SCAN_INTERVAL_MIN 0x0004 /**< Minimum Scan interval in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_INTERVAL_MAX 0x4000 /**< Maximum Scan interval in 625 us units, i.e. 10.24 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_WINDOW GAP Scan window max and min + * @{ */ +#define BLE_GAP_SCAN_WINDOW_MIN 0x0004 /**< Minimum Scan window in 625 us units, i.e. 2.5 ms. */ +#define BLE_GAP_SCAN_WINDOW_MAX 0x4000 /**< Maximum Scan window in 625 us units, i.e. 10.24 s. */ + /** @} */ + + +/**@defgroup BLE_GAP_SCAN_TIMEOUT GAP Scan timeout max and min + * @{ */ +#define BLE_GAP_SCAN_TIMEOUT_MIN 0x0001 /**< Minimum Scan timeout in seconds. */ +#define BLE_GAP_SCAN_TIMEOUT_MAX 0xFFFF /**< Maximum Scan timeout in seconds. */ + /** @} */ + + +/**@brief Maximum size of advertising data in octets. */ +#define BLE_GAP_ADV_MAX_SIZE (31) + + +/**@defgroup BLE_GAP_ADV_TYPES GAP Advertising types + * @{ */ +#define BLE_GAP_ADV_TYPE_ADV_IND 0x00 /**< Connectable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01 /**< Connectable directed. */ +#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02 /**< Scannable undirected. */ +#define BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03 /**< Non connectable undirected. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_FILTER_POLICIES GAP Advertising filter policies + * @{ */ +#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ +#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01 /**< Filter scan requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02 /**< Filter connect requests with whitelist. */ +#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03 /**< Filter both scan and connect requests with whitelist. */ +/**@} */ + + +/**@defgroup BLE_GAP_ADV_TIMEOUT_VALUES GAP Advertising timeout values + * @{ */ +#define BLE_GAP_ADV_TIMEOUT_LIMITED_MAX (180) /**< Maximum advertising time in limited discoverable mode (TGAP(lim_adv_timeout) = 180 s). */ +#define BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED (0) /**< Unlimited advertising in general discoverable mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_DISC_MODES GAP Discovery modes + * @{ */ +#define BLE_GAP_DISC_MODE_NOT_DISCOVERABLE 0x00 /**< Not discoverable discovery Mode. */ +#define BLE_GAP_DISC_MODE_LIMITED 0x01 /**< Limited Discovery Mode. */ +#define BLE_GAP_DISC_MODE_GENERAL 0x02 /**< General Discovery Mode. */ +/**@} */ + + +/**@defgroup BLE_GAP_IO_CAPS GAP IO Capabilities + * @{ */ +#define BLE_GAP_IO_CAPS_DISPLAY_ONLY 0x00 /**< Display Only. */ +#define BLE_GAP_IO_CAPS_DISPLAY_YESNO 0x01 /**< Display and Yes/No entry. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_ONLY 0x02 /**< Keyboard Only. */ +#define BLE_GAP_IO_CAPS_NONE 0x03 /**< No I/O capabilities. */ +#define BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY 0x04 /**< Keyboard and Display. */ +/**@} */ + + +/**@defgroup BLE_GAP_AUTH_KEY_TYPES GAP Authentication Key Types + * @{ */ +#define BLE_GAP_AUTH_KEY_TYPE_NONE 0x00 /**< No key (may be used to reject). */ +#define BLE_GAP_AUTH_KEY_TYPE_PASSKEY 0x01 /**< 6-digit Passkey. */ +#define BLE_GAP_AUTH_KEY_TYPE_OOB 0x02 /**< Out Of Band data. */ +/**@} */ + + +/**@defgroup BLE_GAP_KP_NOT_TYPES GAP Keypress Notification Types + * @{ */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_START 0x00 /**< Passkey entry started. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_IN 0x01 /**< Passkey digit entered. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_DIGIT_OUT 0x02 /**< Passkey digit erased. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_CLEAR 0x03 /**< Passkey cleared. */ +#define BLE_GAP_KP_NOT_TYPE_PASSKEY_END 0x04 /**< Passkey entry completed. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS GAP Security status + * @{ */ +#define BLE_GAP_SEC_STATUS_SUCCESS 0x00 /**< Procedure completed with success. */ +#define BLE_GAP_SEC_STATUS_TIMEOUT 0x01 /**< Procedure timed out. */ +#define BLE_GAP_SEC_STATUS_PDU_INVALID 0x02 /**< Invalid PDU received. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_BEGIN 0x03 /**< Reserved for Future Use range #1 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE1_END 0x80 /**< Reserved for Future Use range #1 end. */ +#define BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user canceled or other). */ +#define BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE 0x82 /**< Out of Band Key not available. */ +#define BLE_GAP_SEC_STATUS_AUTH_REQ 0x83 /**< Authentication requirements not met. */ +#define BLE_GAP_SEC_STATUS_CONFIRM_VALUE 0x84 /**< Confirm value failed. */ +#define BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP 0x85 /**< Pairing not supported. */ +#define BLE_GAP_SEC_STATUS_ENC_KEY_SIZE 0x86 /**< Encryption key size. */ +#define BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED 0x87 /**< Unsupported SMP command. */ +#define BLE_GAP_SEC_STATUS_UNSPECIFIED 0x88 /**< Unspecified reason. */ +#define BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS 0x89 /**< Too little time elapsed since last attempt. */ +#define BLE_GAP_SEC_STATUS_INVALID_PARAMS 0x8A /**< Invalid parameters. */ +#define BLE_GAP_SEC_STATUS_DHKEY_FAILURE 0x8B /**< DHKey check failure. */ +#define BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE 0x8C /**< Numeric Comparison failure. */ +#define BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG 0x8D /**< BR/EDR pairing in progress. */ +#define BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED 0x8E /**< BR/EDR Link Key cannot be used for LE keys. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_BEGIN 0x8F /**< Reserved for Future Use range #2 begin. */ +#define BLE_GAP_SEC_STATUS_RFU_RANGE2_END 0xFF /**< Reserved for Future Use range #2 end. */ +/**@} */ + + +/**@defgroup BLE_GAP_SEC_STATUS_SOURCES GAP Security status sources + * @{ */ +#define BLE_GAP_SEC_STATUS_SOURCE_LOCAL 0x00 /**< Local failure. */ +#define BLE_GAP_SEC_STATUS_SOURCE_REMOTE 0x01 /**< Remote failure. */ +/**@} */ + + +/**@defgroup BLE_GAP_CP_LIMITS GAP Connection Parameters Limits + * @{ */ +#define BLE_GAP_CP_MIN_CONN_INTVL_NONE 0xFFFF /**< No new minimum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 /**< Lowest minimum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MAX 0x0C80 /**< Highest minimum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_NONE 0xFFFF /**< No new maximum connection interval specified in connect parameters. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MIN 0x0006 /**< Lowest maximum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. */ +#define BLE_GAP_CP_MAX_CONN_INTVL_MAX 0x0C80 /**< Highest maximum connection interval permitted, in units of 1.25 ms, i.e. 4 s. */ +#define BLE_GAP_CP_SLAVE_LATENCY_MAX 0x01F3 /**< Highest slave latency permitted, in connection events. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE 0xFFFF /**< No new supervision timeout specified in connect parameters. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN 0x000A /**< Lowest supervision timeout permitted, in units of 10 ms, i.e. 100 ms. */ +#define BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 0x0C80 /**< Highest supervision timeout permitted, in units of 10 ms, i.e. 32 s. */ +/**@} */ + + +/**@defgroup BLE_GAP_DEVNAME GAP device name defines. + * @{ */ +#define BLE_GAP_DEVNAME_DEFAULT "nRF5x" /**< Default device name value. */ +#define BLE_GAP_DEVNAME_DEFAULT_LEN 31 /**< Default number of octets in device name. */ +#define BLE_GAP_DEVNAME_MAX_LEN 248 /**< Maximum number of octets in device name. */ +/**@} */ + + +/**@brief Disable RSSI events for connections */ +#define BLE_GAP_RSSI_THRESHOLD_INVALID 0xFF + +/**@defgroup BLE_GAP_PHYS GAP PHYs + * @{ */ +#define BLE_GAP_PHY_1MBPS 0x01 /**< 1 Mbps PHY. */ +#define BLE_GAP_PHY_2MBPS 0x02 /**< 2 Mbps PHY. */ +#define BLE_GAP_PHY_CODED 0x04 /**< Coded PHY. */ +/**@} */ + +/**@defgroup BLE_GAP_CONN_SEC_MODE_SET_MACROS GAP attribute security requirement setters + * + * See @ref ble_gap_conn_sec_mode_t. + * @{ */ +/**@brief Set sec_mode pointed to by ptr to have no access rights.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(ptr) do {(ptr)->sm = 0; (ptr)->lv = 0;} while(0) +/**@brief Set sec_mode pointed to by ptr to require no protection, open link.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_OPEN(ptr) do {(ptr)->sm = 1; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption, but no MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 2;} while(0) +/**@brief Set sec_mode pointed to by ptr to require encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 3;} while(0) +/**@brief Set sec_mode pointed to by ptr to require LESC encryption and MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(ptr) do {(ptr)->sm = 1; (ptr)->lv = 4;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption, no MITM protection needed.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 1;} while(0) +/**@brief Set sec_mode pointed to by ptr to require signing or encryption with MITM protection.*/ +#define BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(ptr) do {(ptr)->sm = 2; (ptr)->lv = 2;} while(0) +/**@} */ + + +/**@brief GAP Security Random Number Length. */ +#define BLE_GAP_SEC_RAND_LEN 8 + + +/**@brief GAP Security Key Length. */ +#define BLE_GAP_SEC_KEY_LEN 16 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key Length. */ +#define BLE_GAP_LESC_P256_PK_LEN 64 + + +/**@brief GAP LE Secure Connections Elliptic Curve Diffie-Hellman DHKey Length. */ +#define BLE_GAP_LESC_DHKEY_LEN 32 + + +/**@brief GAP Passkey Length. */ +#define BLE_GAP_PASSKEY_LEN 6 + + +/**@brief Maximum amount of addresses in the whitelist. */ +#define BLE_GAP_WHITELIST_ADDR_MAX_COUNT (8) + + +/**@brief Maximum amount of identities in the device identities list. */ +#define BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT (8) + + +/**@brief Default connection count for a configuration. */ +#define BLE_GAP_CONN_COUNT_DEFAULT (1) + + +/**@defgroup BLE_GAP_EVENT_LENGTH GAP event length defines. + * @{ */ +#define BLE_GAP_EVENT_LENGTH_MIN (2) /**< Minimum event length, in 1.25 ms units. */ +#define BLE_GAP_EVENT_LENGTH_DEFAULT (3) /**< Default event length, in 1.25 ms units. */ +/**@} */ + + +/**@defgroup BLE_GAP_ROLE_COUNT GAP concurrent connection count defines. + * @{ */ +#define BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT (1) /**< Default maximum number of connections concurrently acting as peripherals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT (3) /**< Default maximum number of connections concurrently acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT (1) /**< Default number of SMP instances shared between all connections acting as centrals. */ +#define BLE_GAP_ROLE_COUNT_COMBINED_MAX (20) /**< Maximum supported number of concurrent connections in the peripheral and central roles combined. */ +/**@} */ + + + + +/**@brief Automatic data length parameter. */ +#define BLE_GAP_DATA_LENGTH_AUTO 0 + + +/**@defgroup GAP_SEC_MODES GAP Security Modes + * @{ */ +#define BLE_GAP_SEC_MODE 0x00 /**< No key (may be used to reject). */ +/**@} */ +/** @} */ + + +/**@addtogroup BLE_GAP_STRUCTURES Structures + * @{ */ + +/**@brief Bluetooth Low Energy address. */ +typedef struct +{ + uint8_t addr_id_peer : 1; /**< Only valid for peer addresses. + Reference to peer in device identities list (as set with @ref sd_ble_gap_device_identities_set) when peer is using privacy. */ + uint8_t addr_type : 7; /**< See @ref BLE_GAP_ADDR_TYPES. */ + uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format. */ +} ble_gap_addr_t; + + +/**@brief GAP connection parameters. + * + * @note When ble_conn_params_t is received in an event, both min_conn_interval and + * max_conn_interval will be equal to the connection interval set by the central. + * + * @note If both conn_sup_timeout and max_conn_interval are specified, then the following constraint applies: + * conn_sup_timeout * 4 > (1 + slave_latency) * max_conn_interval + * that corresponds to the following Bluetooth Spec requirement: + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, where Conn_Interval_Max is given in milliseconds. + */ +typedef struct +{ + uint16_t min_conn_interval; /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t max_conn_interval; /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t slave_latency; /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/ + uint16_t conn_sup_timeout; /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/ +} ble_gap_conn_params_t; + + +/**@brief GAP connection security modes. + * + * Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\n + * Security Mode 1 Level 1: No security is needed (aka open link).\n + * Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\n + * Security Mode 1 Level 3: MITM protected encrypted link required.\n + * Security Mode 1 Level 4: LESC MITM protected encrypted link required.\n + * Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\n + * Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\n + */ +typedef struct +{ + uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */ + uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */ + +} ble_gap_conn_sec_mode_t; + + +/**@brief GAP connection security status.*/ +typedef struct +{ + ble_gap_conn_sec_mode_t sec_mode; /**< Currently active security mode for this connection.*/ + uint8_t encr_key_size; /**< Length of currently active encryption key, 7 to 16 octets (only applicable for bonding procedures). */ +} ble_gap_conn_sec_t; + +/**@brief Identity Resolving Key. */ +typedef struct +{ + uint8_t irk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing IRK. */ +} ble_gap_irk_t; + + +/**@brief Channel mask for RF channels used in advertising. */ +typedef struct +{ + uint8_t ch_37_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 37 */ + uint8_t ch_38_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 38 */ + uint8_t ch_39_off : 1; /**< Setting this bit to 1 will turn off advertising on channel 39 */ +} ble_gap_adv_ch_mask_t; + + +/**@brief GAP advertising parameters. */ +typedef struct +{ + uint8_t type; /**< See @ref BLE_GAP_ADV_TYPES. */ + ble_gap_addr_t const *p_peer_addr; /**< Address of a known peer. + - When privacy is enabled and the local device use @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE addresses, the device identity list is searched for a matching + entry. If the local IRK for that device identity is set, the local IRK for that device will be used to generate the advertiser address field in the advertise packet. + - If type is @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this must be set to the targeted initiator. If the initiator is in the device identity list, + the peer IRK for that device will be used to generate the initiator address field in the ADV_DIRECT_IND packet. */ + uint8_t fp; /**< Filter Policy, see @ref BLE_GAP_ADV_FILTER_POLICIES. */ + uint16_t interval; /**< Advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20 ms to 10.24 s), see @ref BLE_GAP_ADV_INTERVALS. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for high duty cycle directed advertising. + - If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, set @ref BLE_GAP_ADV_INTERVAL_MIN <= interval <= @ref BLE_GAP_ADV_INTERVAL_MAX for low duty cycle advertising.*/ + uint16_t timeout; /**< Advertising timeout between 0x0001 and 0x3FFF in seconds, 0x0000 disables timeout. See also @ref BLE_GAP_ADV_TIMEOUT_VALUES. If type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND, this parameter must be set to 0 for High duty cycle directed advertising. */ + ble_gap_adv_ch_mask_t channel_mask; /**< Advertising channel mask. See @ref ble_gap_adv_ch_mask_t. */ +} ble_gap_adv_params_t; + + +/**@brief GAP scanning parameters. */ +typedef struct +{ + uint8_t active : 1; /**< If 1, perform active scanning (scan requests). */ + uint8_t use_whitelist : 1; /**< If 1, filter advertisers using current active whitelist. */ + uint8_t adv_dir_report : 1; /**< If 1, also report directed advertisements where the initiator field is set to a private resolvable address, + even if the address did not resolve to an entry in the device identity list. A report will be generated + even if the peer is not in the whitelist. */ + uint16_t interval; /**< Scan interval between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */ + uint16_t window; /**< Scan window between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */ + uint16_t timeout; /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ +} ble_gap_scan_params_t; + + +/**@brief Device Privacy. + * + * The privacy feature provides a way for the device to avoid being tracked over a period of time. + * The privacy feature, when enabled, hides the local device identity and replaces it with a private address + * that is automatically refreshed at a specified interval. + * + * If a device still wants to be recognized by other peers, it needs to share it's Identity Resolving Key (IRK). + * With this key, a device can generate a random private address that can only be recognized by peers in possession of that key, + * and devices can establish connections without revealing their real identities. + * + * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all + * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. + * The IRK distributed during bonding procedure is the device IRK that is active when @ref sd_ble_gap_sec_params_reply is called. + */ +typedef struct +{ + uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ + uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ + uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ + ble_gap_irk_t *p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. + When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. + By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ +} ble_gap_privacy_params_t; + + +/**@brief Physical Layer configuration + * @note tx_phys and rx_phys are bitfields, to indicate multiple preferred PHYs for each direction they can be ORed together. + * @code + * p_gap_phys->tx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * p_gap_phys->rx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * @endcode + * + */ +typedef struct +{ + uint8_t tx_phys; /**< Preferred transmit PHYs, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phys; /**< Preferred receive PHYs, see @ref BLE_GAP_PHYS. */ +} ble_gap_phys_t; + +/** @brief Keys that can be exchanged during a bonding procedure. */ +typedef struct +{ + uint8_t enc : 1; /**< Long Term Key and Master Identification. */ + uint8_t id : 1; /**< Identity Resolving Key and Identity Address Information. */ + uint8_t sign : 1; /**< Connection Signature Resolving Key. */ + uint8_t link : 1; /**< Derive the Link Key from the LTK. */ +} ble_gap_sec_kdist_t; + + +/**@brief GAP security parameters. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Enable Man In The Middle protection. */ + uint8_t lesc : 1; /**< Enable LE Secure Connection pairing. */ + uint8_t keypress : 1; /**< Enable generation of keypress notifications. */ + uint8_t io_caps : 3; /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ + uint8_t oob : 1; /**< The OOB data flag. + - In LE legacy pairing, this flag is set if a device has out of band authentication data. + The OOB method is used if both of the devices have out of band authentication data. + - In LE Secure Connections pairing, this flag is set if a device has the peer device's out of band authentication data. + The OOB method is used if at least one device has the peer device's OOB data available. */ + uint8_t min_key_size; /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ + uint8_t max_key_size; /**< Maximum encryption key size in octets between min_key_size and 16. */ + ble_gap_sec_kdist_t kdist_own; /**< Key distribution bitmap: keys that the local device will distribute. */ + ble_gap_sec_kdist_t kdist_peer; /**< Key distribution bitmap: keys that the remote device will distribute. */ +} ble_gap_sec_params_t; + + +/**@brief GAP Encryption Information. */ +typedef struct +{ + uint8_t ltk[BLE_GAP_SEC_KEY_LEN]; /**< Long Term Key. */ + uint8_t lesc : 1; /**< Key generated using LE Secure Connections. */ + uint8_t auth : 1; /**< Authenticated Key. */ + uint8_t ltk_len : 6; /**< LTK length in octets. */ +} ble_gap_enc_info_t; + + +/**@brief GAP Master Identification. */ +typedef struct +{ + uint16_t ediv; /**< Encrypted Diversifier. */ + uint8_t rand[BLE_GAP_SEC_RAND_LEN]; /**< Random Number. */ +} ble_gap_master_id_t; + + +/**@brief GAP Signing Information. */ +typedef struct +{ + uint8_t csrk[BLE_GAP_SEC_KEY_LEN]; /**< Connection Signature Resolving Key. */ +} ble_gap_sign_info_t; + + +/**@brief GAP LE Secure Connections P-256 Public Key. */ +typedef struct +{ + uint8_t pk[BLE_GAP_LESC_P256_PK_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman P-256 Public Key. Stored in the standard SMP protocol format: {X,Y} both in little-endian. */ +} ble_gap_lesc_p256_pk_t; + + +/**@brief GAP LE Secure Connections DHKey. */ +typedef struct +{ + uint8_t key[BLE_GAP_LESC_DHKEY_LEN]; /**< LE Secure Connections Elliptic Curve Diffie-Hellman Key. Stored in little-endian. */ +} ble_gap_lesc_dhkey_t; + + +/**@brief GAP LE Secure Connections OOB data. */ +typedef struct +{ + ble_gap_addr_t addr; /**< Bluetooth address of the device. */ + uint8_t r[BLE_GAP_SEC_KEY_LEN]; /**< Random Number. */ + uint8_t c[BLE_GAP_SEC_KEY_LEN]; /**< Confirm Value. */ +} ble_gap_lesc_oob_data_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONNECTED. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + uint8_t role; /**< BLE role for this connection, see @ref BLE_GAP_ROLES */ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_connected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_DISCONNECTED. */ +typedef struct +{ + uint8_t reason; /**< HCI error code, see @ref BLE_HCI_STATUS_CODES. */ +} ble_gap_evt_disconnected_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_t; + +/**@brief Event Structure for @ref BLE_GAP_EVT_PHY_UPDATE. */ +typedef struct +{ + uint8_t status; /**< Status of the procedure, see @ref BLE_HCI_STATUS_CODES */ + uint8_t tx_phy; /**< TX PHY for this connection, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phy; /**< RX PHY for this connection, see @ref BLE_GAP_PHYS. */ +} ble_gap_evt_phy_update_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. */ +typedef struct +{ + ble_gap_sec_params_t peer_params; /**< Initiator Security Parameters. */ +} ble_gap_evt_sec_params_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_INFO_REQUEST. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + ble_gap_master_id_t master_id; /**< Master Identification for LTK lookup. */ + uint8_t enc_info : 1; /**< If 1, Encryption Information required. */ + uint8_t id_info : 1; /**< If 1, Identity Information required. */ + uint8_t sign_info : 1; /**< If 1, Signing Information required. */ +} ble_gap_evt_sec_info_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_PASSKEY_DISPLAY. */ +typedef struct +{ + uint8_t passkey[BLE_GAP_PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ + uint8_t match_request : 1; /**< If 1 requires the application to report the match using @ref sd_ble_gap_auth_key_reply + with either @ref BLE_GAP_AUTH_KEY_TYPE_NONE if there is no match or + @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY if there is a match. */ +} ble_gap_evt_passkey_display_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_KEY_PRESSED. */ +typedef struct +{ + uint8_t kp_not; /**< Keypress notification type, see @ref BLE_GAP_KP_NOT_TYPES. */ +} ble_gap_evt_key_pressed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_KEY_REQUEST. */ +typedef struct +{ + uint8_t key_type; /**< See @ref BLE_GAP_AUTH_KEY_TYPES. */ +} ble_gap_evt_auth_key_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST. */ +typedef struct +{ + ble_gap_lesc_p256_pk_t *p_pk_peer; /**< LE Secure Connections remote P-256 Public Key. This will point to the application-supplied memory + inside the keyset during the call to @ref sd_ble_gap_sec_params_reply. */ + uint8_t oobd_req :1; /**< LESC OOB data required. A call to @ref sd_ble_gap_lesc_oob_data_set is required to complete the procedure. */ +} ble_gap_evt_lesc_dhkey_request_t; + + +/**@brief Security levels supported. + * @note See Bluetooth Specification Version 4.2 Volume 3, Part C, Chapter 10, Section 10.2.1. +*/ +typedef struct +{ + uint8_t lv1 : 1; /**< If 1: Level 1 is supported. */ + uint8_t lv2 : 1; /**< If 1: Level 2 is supported. */ + uint8_t lv3 : 1; /**< If 1: Level 3 is supported. */ + uint8_t lv4 : 1; /**< If 1: Level 4 is supported. */ +} ble_gap_sec_levels_t; + + +/**@brief Encryption Key. */ +typedef struct +{ + ble_gap_enc_info_t enc_info; /**< Encryption Information. */ + ble_gap_master_id_t master_id; /**< Master Identification. */ +} ble_gap_enc_key_t; + + +/**@brief Identity Key. */ +typedef struct +{ + ble_gap_irk_t id_info; /**< Identity Resolving Key. */ + ble_gap_addr_t id_addr_info; /**< Identity Address. */ +} ble_gap_id_key_t; + + +/**@brief Security Keys. */ +typedef struct +{ + ble_gap_enc_key_t *p_enc_key; /**< Encryption Key, or NULL. */ + ble_gap_id_key_t *p_id_key; /**< Identity Key, or NULL. */ + ble_gap_sign_info_t *p_sign_key; /**< Signing Key, or NULL. */ + ble_gap_lesc_p256_pk_t *p_pk; /**< LE Secure Connections P-256 Public Key. When in debug mode the application must use the value defined + in the Core Bluetooth Specification v4.2 Vol.3, Part H, Section 2.3.5.6.1 */ +} ble_gap_sec_keys_t; + + +/**@brief Security key set for both local and peer keys. */ +typedef struct +{ + ble_gap_sec_keys_t keys_own; /**< Keys distributed by the local device. For LE Secure Connections the encryption key will be generated locally and will always be stored if bonding. */ + ble_gap_sec_keys_t keys_peer; /**< Keys distributed by the remote device. For LE Secure Connections, p_enc_key must always be NULL. */ +} ble_gap_sec_keyset_t; + + +/**@brief Data Length Update Procedure parameters. */ +typedef struct +{ + uint16_t max_tx_octets; /**< Maximum number of payload octets that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_octets; /**< Maximum number of payload octets that a Controller supports for reception of a single Link Layer Data Channel PDU. */ + uint16_t max_tx_time_us; /**< Maximum time, in microseconds, that a Controller supports for transmission of a single Link Layer Data Channel PDU. */ + uint16_t max_rx_time_us; /**< Maximum time, in microseconds, that a Controller supports for reception of a single Link Layer Data Channel PDU. */ +} ble_gap_data_length_params_t; + + +/**@brief Data Length Update Procedure local limitation. */ +typedef struct +{ + uint16_t tx_payload_limited_octets; /**< If > 0, the requested TX packet length is too long by this many octets. */ + uint16_t rx_payload_limited_octets; /**< If > 0, the requested RX packet length is too long by this many octets. */ + uint16_t tx_rx_time_limited_us; /**< If > 0, the requested combination of TX and RX packet lengths is too long by this many microseconds. */ +} ble_gap_data_length_limitation_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_AUTH_STATUS. */ +typedef struct +{ + uint8_t auth_status; /**< Authentication status, see @ref BLE_GAP_SEC_STATUS. */ + uint8_t error_src : 2; /**< On error, source that caused the failure, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ + uint8_t bonded : 1; /**< Procedure resulted in a bond. */ + ble_gap_sec_levels_t sm1_levels; /**< Levels supported in Security Mode 1. */ + ble_gap_sec_levels_t sm2_levels; /**< Levels supported in Security Mode 2. */ + ble_gap_sec_kdist_t kdist_own; /**< Bitmap stating which keys were exchanged (distributed) by the local device. If bonding with LE Secure Connections, the enc bit will be always set. */ + ble_gap_sec_kdist_t kdist_peer; /**< Bitmap stating which keys were exchanged (distributed) by the remote device. If bonding with LE Secure Connections, the enc bit will never be set. */ +} ble_gap_evt_auth_status_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_SEC_UPDATE. */ +typedef struct +{ + ble_gap_conn_sec_t conn_sec; /**< Connection security level. */ +} ble_gap_evt_conn_sec_update_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Source of timeout event, see @ref BLE_GAP_TIMEOUT_SOURCES. */ +} ble_gap_evt_timeout_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_RSSI_CHANGED. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ +} ble_gap_evt_rssi_changed_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_ADV_REPORT. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ + ble_gap_addr_t direct_addr; /**< Set when the scanner is unable to resolve the private resolvable address of the initiator + field of a directed advertisement packet and the scanner has been enabled to report this in @ref ble_gap_scan_params_t::adv_dir_report. */ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ + uint8_t scan_rsp : 1; /**< If 1, the report corresponds to a scan response and the type field may be ignored. */ + uint8_t type : 2; /**< See @ref BLE_GAP_ADV_TYPES. Only valid if the scan_rsp field is 0. */ + uint8_t dlen : 5; /**< Advertising or scan response data length. */ + uint8_t data[BLE_GAP_ADV_MAX_SIZE]; /**< Advertising or scan response data. */ +} ble_gap_evt_adv_report_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SEC_REQUEST. */ +typedef struct +{ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Man In The Middle protection requested. */ + uint8_t lesc : 1; /**< LE Secure Connections requested. */ + uint8_t keypress : 1; /**< Generation of keypress notifications requested. */ +} ble_gap_evt_sec_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_request_t; + + +/**@brief Event structure for @ref BLE_GAP_EVT_SCAN_REQ_REPORT. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1 + and the address is the device's identity address. */ +} ble_gap_evt_scan_req_report_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST. */ +typedef struct +{ + ble_gap_data_length_params_t peer_params; /**< Peer data length parameters. */ +} ble_gap_evt_data_length_update_request_t; + +/**@brief Event structure for @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE. */ +typedef struct +{ + ble_gap_data_length_params_t effective_params; /**< The effective data length parameters. */ +} ble_gap_evt_data_length_update_t; + + +/**@brief GAP event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + union /**< union alternative identified by evt_id in enclosing struct. */ + { + ble_gap_evt_connected_t connected; /**< Connected Event Parameters. */ + ble_gap_evt_disconnected_t disconnected; /**< Disconnected Event Parameters. */ + ble_gap_evt_conn_param_update_t conn_param_update; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_sec_params_request_t sec_params_request; /**< Security Parameters Request Event Parameters. */ + ble_gap_evt_sec_info_request_t sec_info_request; /**< Security Information Request Event Parameters. */ + ble_gap_evt_passkey_display_t passkey_display; /**< Passkey Display Event Parameters. */ + ble_gap_evt_key_pressed_t key_pressed; /**< Key Pressed Event Parameters. */ + ble_gap_evt_auth_key_request_t auth_key_request; /**< Authentication Key Request Event Parameters. */ + ble_gap_evt_lesc_dhkey_request_t lesc_dhkey_request; /**< LE Secure Connections DHKey calculation request. */ + ble_gap_evt_auth_status_t auth_status; /**< Authentication Status Event Parameters. */ + ble_gap_evt_conn_sec_update_t conn_sec_update; /**< Connection Security Update Event Parameters. */ + ble_gap_evt_timeout_t timeout; /**< Timeout Event Parameters. */ + ble_gap_evt_rssi_changed_t rssi_changed; /**< RSSI Event Parameters. */ + ble_gap_evt_adv_report_t adv_report; /**< Advertising Report Event Parameters. */ + ble_gap_evt_sec_request_t sec_request; /**< Security Request Event Parameters. */ + ble_gap_evt_conn_param_update_request_t conn_param_update_request; /**< Connection Parameter Update Parameters. */ + ble_gap_evt_scan_req_report_t scan_req_report; /**< Scan Request Report Parameters. */ + ble_gap_evt_phy_update_t phy_update; /**< PHY Update Parameters. */ + ble_gap_evt_data_length_update_request_t data_length_update_request; /**< Data Length Update Request Event Parameters. */ + ble_gap_evt_data_length_update_t data_length_update; /**< Data Length Update Event Parameters. */ + } params; /**< Event Parameters. */ +} ble_gap_evt_t; + + +/** + * @brief BLE GAP connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The connection count for the connection configurations is zero. + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - The sum of conn_count for all connection configurations combined exceeds UINT8_MAX. + * - The event length is smaller than @ref BLE_GAP_EVENT_LENGTH_MIN. + */ +typedef struct +{ + uint8_t conn_count; /**< The number of concurrent connections the application can create with this configuration. + The default and minimum value is @ref BLE_GAP_CONN_COUNT_DEFAULT. */ + uint16_t event_length; /**< The time set aside for this connection on every connection interval in 1.25 ms units. + The default value is @ref BLE_GAP_EVENT_LENGTH_DEFAULT, the minimum value is @ref BLE_GAP_EVENT_LENGTH_MIN. + The event length and the connection interval are the primary parameters + for setting the throughput of a connection. + See the SoftDevice Specification for details on throughput. */ +} ble_gap_conn_cfg_t; + + +/** + * @brief Configuration of maximum concurrent connections in the different connected roles, set with + * @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_CONN_COUNT The sum of periph_role_count and central_role_count is too + * large. The maximum supported sum of concurrent connections is + * @ref BLE_GAP_ROLE_COUNT_COMBINED_MAX. + * @retval ::NRF_ERROR_INVALID_PARAM central_sec_count is larger than central_role_count. + */ +typedef struct +{ + uint8_t periph_role_count; /**< Maximum number of connections concurrently acting as a peripheral. Default value is @ref BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT. */ + uint8_t central_role_count; /**< Maximum number of connections concurrently acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_DEFAULT. */ + uint8_t central_sec_count; /**< Number of SMP instances shared between all connections acting as a central. Default value is @ref BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT. */ +} ble_gap_cfg_role_count_t; + + +/** + * @brief Device name and its properties, set with @ref sd_ble_cfg_set. + * + * @note If the device name is not configured, the default device name will be @ref + * BLE_GAP_DEVNAME_DEFAULT, the maximum device name length will be @ref + * BLE_GAP_DEVNAME_DEFAULT_LEN, vloc will be set to @ref BLE_GATTS_VLOC_STACK and the device name + * will have no write access. + * + * @note If @ref max_len is more than @ref BLE_GAP_DEVNAME_DEFAULT_LEN and vloc is set to @ref BLE_GATTS_VLOC_STACK, + * the attribute table size must be increased to have room for the longer device name (see + * @ref sd_ble_cfg_set and @ref ble_gatts_cfg_attr_tab_size_t). + * + * @note If vloc is @ref BLE_GATTS_VLOC_STACK : + * - p_value must point to non-volatile memory (flash) or be NULL. + * - If p_value is NULL, the device name will initially be empty. + * + * @note If vloc is @ref BLE_GATTS_VLOC_USER : + * - p_value cannot be NULL. + * - If the device name is writable, p_value must point to volatile memory (RAM). + * + * @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true: + * - Invalid device name location (vloc). + * - Invalid device name security mode. + * @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true: + * - 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_NOT_SUPPORTED Device name security mode is not supported. + */ +typedef struct +{ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vloc:2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t *p_value; /**< Pointer to where the value (device name) is stored or will be stored. */ + uint16_t current_len; /**< Current length in bytes of the memory pointed to by p_value.*/ + uint16_t max_len; /**< Maximum length in bytes of the memory pointed to by p_value.*/ +} ble_gap_cfg_device_name_t; + + +/**@brief Configuration structure for GAP configurations. */ +typedef union +{ + ble_gap_cfg_role_count_t role_count_cfg; /**< Role count configuration, cfg_id is @ref BLE_GAP_CFG_ROLE_COUNT. */ + ble_gap_cfg_device_name_t device_name_cfg; /**< Device name configuration, cfg_id is @ref BLE_GAP_CFG_DEVICE_NAME. */ +} ble_gap_cfg_t; + + +/**@brief Channel Map option. + * Used with @ref sd_ble_opt_get to get the current channel map + * or @ref sd_ble_opt_set to set a new channel map. When setting the + * channel map, it applies to all current and future connections. When getting the + * current channel map, it applies to a single connection and the connection handle + * must be supplied. + * + * @note Setting the channel map may take some time, depending on connection parameters. + * The time taken may be different for each connection and the get operation will + * return the previous channel map until the new one has taken effect. + * + * @note After setting the channel map, by spec it can not be set again until at least 1 s has passed. + * See Bluetooth Specification Version 4.1 Volume 2, Part E, Section 7.3.46. + * + * @retval ::NRF_SUCCESS Get or set successful. + * @retval ::NRF_ERROR_BUSY Channel map was set again before enough time had passed. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied for get. + * @retval ::NRF_ERROR_NOT_SUPPORTED Returned by sd_ble_opt_set in peripheral-only SoftDevices. + * + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle (only applicable for get) */ + uint8_t ch_map[5]; /**< Channel Map (37-bit). */ +} ble_gap_opt_ch_map_t; + + +/**@brief Local connection latency option. + * + * Local connection latency is a feature which enables the slave to improve + * current consumption by ignoring the slave latency set by the peer. The + * local connection latency can only be set to a multiple of the slave latency, + * and cannot be longer than half of the supervision timeout. + * + * Used with @ref sd_ble_opt_set to set the local connection latency. The + * @ref sd_ble_opt_get is not supported for this option, but the actual + * local connection latency (unless set to NULL) is set as a return parameter + * when setting the option. + * + * @note The latency set will be truncated down to the closest slave latency event + * multiple, or the nearest multiple before half of the supervision timeout. + * + * @note The local connection latency is disabled by default, and needs to be enabled for new + * connections and whenever the connection is updated. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t requested_latency; /**< Requested local connection latency. */ + uint16_t * p_actual_latency; /**< Pointer to storage for the actual local connection latency (can be set to NULL to skip return value). */ +} ble_gap_opt_local_conn_latency_t; + +/**@brief Disable slave latency + * + * Used with @ref sd_ble_opt_set to temporarily disable slave latency of a peripheral connection (see @ref ble_gap_conn_params_t::slave_latency). And to re-enable it again. + * When disabled, the peripheral will ignore the slave_latency set by the central. + * + * @note Shall only be called on peripheral links. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_NOT_SUPPORTED Get is not supported. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint8_t disable : 1; /**< Set to 1 to disable slave latency. Set to 0 enable it again.*/ +} ble_gap_opt_slave_latency_disable_t; + +/**@brief Passkey Option. + * + * Structure containing the passkey to be used during pairing. This can be used with @ref + * sd_ble_opt_set to make the SoftDevice use a preprogrammed passkey for authentication + * instead of generating a random one. + * + * @note Repeated pairing attempts using the same preprogrammed passkey makes pairing vulnerable to MITM attacks. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + */ +typedef struct +{ + uint8_t const * p_passkey; /**< Pointer to 6-digit ASCII string (digit 0..9 only, no NULL termination) passkey to be used during pairing. If this is NULL, the SoftDevice will generate a random passkey if required.*/ +} ble_gap_opt_passkey_t; + + +/**@brief Scan request report option. + * + * This can be used with @ref sd_ble_opt_set to make the SoftDevice send + * @ref BLE_GAP_EVT_SCAN_REQ_REPORT events. + * + * @note Due to the limited space reserved for scan request report events, + * not all received scan requests will be reported. + * + * @note If whitelisting is used, only whitelisted requests are reported. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When advertising is ongoing while the option is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable scan request reports. */ +} ble_gap_opt_scan_req_report_t; + +/**@brief Compatibility mode 1 option. + * + * This can be used with @ref sd_ble_opt_set to enable and disable + * compatibility mode 1. Compatibility mode 1 is disabled by default. + * + * @note Compatibility mode 1 enables interoperability with devices that do not support + * a value of 0 for the WinOffset parameter in the Link Layer CONNECT_REQ packet. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_STATE When connection creation is ongoing while mode 1 is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable compatibility mode 1.*/ +} ble_gap_opt_compat_mode_1_t; + +/**@brief Compatibility mode 2 option. + * + * This can be used with @ref sd_ble_opt_set to enable compatibility mode 2. + * Compatibility mode 2 is disabled by default. + * + * @note Compatibility mode 2 enables interoperability with devices that initiate Feature exchange + * and version exchange procedure in parallel. + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM if enable bit is not set to 1. Currently only enabling is supported. + * @retval ::NRF_ERROR_INVALID_STATE When any role is running while mode 2 is set. + */ +typedef struct +{ + uint8_t enable : 1; /**< Enable compatibility mode 2.*/ +} ble_gap_opt_compat_mode_2_t; + + +/**@brief Authenticated payload timeout option. + * + * This can be used with @ref sd_ble_opt_set to change the Authenticated payload timeout to a value other than the default of 8 minutes. + * + * @note The authenticated payload timeout event ::BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD will be generated + * if auth_payload_timeout time has elapsed without receiving a packet with a valid MIC on an encrypted + * link. + * + * @note The LE ping procedure will be initiated before the timer expires to give the peer a chance + * to reset the timer. In addition the stack will try to prioritize running of LE ping over other + * activities to increase chances of finishing LE ping before timer expires. To avoid side-effects + * on other activities, it is recommended to use high timeout values. + * Recommended timeout > 2*(connInterval * (6 + connSlaveLatency)). + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. auth_payload_timeout was outside of allowed range. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter. + */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle */ + uint16_t auth_payload_timeout; /**< Requested timeout in 10 ms unit. Maximum is 48 000 (=480 000 ms =8 min). Minimum is 1 (=10 ms). */ +} ble_gap_opt_auth_payload_timeout_t; + +/**@brief Preferred PHY option + * + * @details This can be used with @ref sd_ble_opt_set to change the preferred PHYs. Before this function is called the PHYs + * for peer initiated PHY Update procedure is @ref BLE_GAP_PHY_1MBPS. If @ref ble_gap_opt_preferred_phys_t::tx_phys or + * @ref ble_gap_opt_preferred_phys_t::rx_phys is 0, then the stack will select PHYs based on the peer requirements on that specific direction. + * + * @note The preferred PHYs are only valid for newly created connections after this option is called. If the PHYs should be + * changed for an existing link the @ref sd_ble_gap_phy_request would have to be called, and that would try to update the + * PHYs for the given link. + * + * @note tx_phys and rx_phys are bitfields, to indicate multiple preferred PHYs for each direction they can be ORed together. + * @code + * tx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * rx_phys = BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_2MBPS; + * @endcode + * + * @events + * @event{@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update if initiated by peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_PHY_REQUEST} + * @mmsc{@ref BLE_GAP_PERIPHERAL_PHY_REQUEST} + * @endmscs + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +typedef struct +{ + uint8_t tx_phys; /**< Preferred transmit PHYs, see @ref BLE_GAP_PHYS. */ + uint8_t rx_phys; /**< Preferred receive PHYs, see @ref BLE_GAP_PHYS. */ +} ble_gap_opt_preferred_phys_t; + +/**@brief Option structure for GAP options. */ +typedef union +{ + ble_gap_opt_ch_map_t ch_map; /**< Parameters for the Channel Map option. */ + ble_gap_opt_local_conn_latency_t local_conn_latency; /**< Parameters for the Local connection latency option */ + ble_gap_opt_passkey_t passkey; /**< Parameters for the Passkey option.*/ + ble_gap_opt_scan_req_report_t scan_req_report; /**< Parameters for the scan request report option.*/ + ble_gap_opt_compat_mode_1_t compat_mode_1; /**< Parameters for the compatibility mode 1 option.*/ + ble_gap_opt_compat_mode_2_t compat_mode_2; /**< Parameters for the compatibility mode 2 option.*/ + ble_gap_opt_auth_payload_timeout_t auth_payload_timeout; /**< Parameters for the authenticated payload timeout option.*/ + ble_gap_opt_preferred_phys_t preferred_phys; /**< Parameters for the preferred PHYs option. */ + ble_gap_opt_slave_latency_disable_t slave_latency_disable; /**< Parameters for the Disable slave latency option */ +} ble_gap_opt_t; +/**@} */ + + +/**@addtogroup BLE_GAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set the local Bluetooth identity address. + * + * The local Bluetooth identity address is the address that identifies this device to other peers. + * The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * The identity address cannot be changed while roles are running. + * + * @note This address will be distributed to the peer during bonding. + * If the address changes, the address stored in the peer device will not be valid and the ability to + * reconnect using the old address will be lost. + * + * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC upon being + * enabled. The address is a random number populated during the IC manufacturing process and remains unchanged + * for the lifetime of each IC. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @endmscs + * + * @param[in] p_addr Pointer to address structure. + * + * @retval ::NRF_SUCCESS Address successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_INVALID_STATE The identity address cannot be changed while the roles are running. + */ +SVCALL(SD_BLE_GAP_ADDR_SET, uint32_t, sd_ble_gap_addr_set(ble_gap_addr_t const *p_addr)); + + +/**@brief Get local Bluetooth identity address. + * + * @note This will always return the identity address irrespective of the privacy settings, + * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC. + * + * @param[out] p_addr Pointer to address structure to be filled in. + * + * @retval ::NRF_SUCCESS Address successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied. + */ +SVCALL(SD_BLE_GAP_ADDR_GET, uint32_t, sd_ble_gap_addr_get(ble_gap_addr_t *p_addr)); + + +/**@brief Set the active whitelist in the SoftDevice. + * + * @note Only one whitelist can be used at a time and the whitelist is shared between the BLE roles. + * The whitelist cannot be set if a BLE role is using the whitelist. + * + * @note If an address is resolved using the information in the device identity list, then the whitelist + * filter policy applies to the peer identity address and not the resolvable address sent on air. + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @endmscs + * + * @param[in] pp_wl_addrs Pointer to a whitelist of peer addresses, if NULL the whitelist will be cleared. + * @param[in] len Length of the whitelist, maximum @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. + * + * @retval ::NRF_SUCCESS The whitelist is successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The whitelist (or one of its entries) provided is invalid. + * @retval ::BLE_ERROR_GAP_WHITELIST_IN_USE The whitelist is in use by a BLE role and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given whitelist size is invalid (zero or too large); this can only return when + * pp_wl_addrs is not NULL. + */ +SVCALL(SD_BLE_GAP_WHITELIST_SET, uint32_t, sd_ble_gap_whitelist_set(ble_gap_addr_t const * const * pp_wl_addrs, uint8_t len)); + + +/**@brief Set device identity list. + * + * @note Only one device identity list can be used at a time and the list is shared between the BLE roles. + * The device identity list cannot be set if a BLE role is using the list. + * + * @param[in] pp_id_keys Pointer to an array of peer identity addresses and peer IRKs, if NULL the device identity list will be cleared. + * @param[in] pp_local_irks Pointer to an array of local IRKs. Each entry in the array maps to the entry in pp_id_keys at the same index. + * To fill in the list with the currently set device IRK for all peers, set to NULL. + * @param[in] len Length of the device identity list, maximum @ref BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_PRIVATE_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The device identity list successfully set/cleared. + * @retval ::NRF_ERROR_INVALID_ADDR The device identity list (or one of its entries) provided is invalid. + * This code may be returned if the local IRK list also has an invalid entry. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE The device identity list is in use and cannot be set or cleared. + * @retval ::BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE The device identity list contains multiple entries with the same identity address. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_DATA_SIZE The given device identity list size invalid (zero or too large); this can + * only return when pp_id_keys is not NULL. + */ +SVCALL(SD_BLE_GAP_DEVICE_IDENTITIES_SET, uint32_t, sd_ble_gap_device_identities_set(ble_gap_id_key_t const * const * pp_id_keys, ble_gap_irk_t const * const * pp_local_irks, uint8_t len)); + + +/**@brief Set privacy settings. + * + * @note Privacy settings cannot be set while BLE roles are running. + * + * @param[in] p_privacy_params Privacy settings. + * + * @mscs + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Set successfully. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer to privacy settings is NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + * @retval ::NRF_ERROR_INVALID_PARAM Out of range parameters are provided. + * @retval ::NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while BLE roles using privacy are enabled. + */ +SVCALL(SD_BLE_GAP_PRIVACY_SET, uint32_t, sd_ble_gap_privacy_set(ble_gap_privacy_params_t const *p_privacy_params)); + + +/**@brief Get privacy settings. + * + * @note The privacy settings returned include the current device irk as well. + * + * @param[in] p_privacy_params Privacy settings. + * + * @retval ::NRF_SUCCESS Privacy settings read. + * @retval ::NRF_ERROR_INVALID_ADDR The pointer given for returning the privacy settings may be NULL or invalid. + * Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer. + */ +SVCALL(SD_BLE_GAP_PRIVACY_GET, uint32_t, sd_ble_gap_privacy_get(ble_gap_privacy_params_t *p_privacy_params)); + + +/**@brief Set, clear or update advertising and scan response data. + * + * @note The format of the advertising data will be checked by this call to ensure interoperability. + * Limitations imposed by this API call to the data provided include having a flags data type in the scan response data and + * duplicating the local name in the advertising data and scan response data. + * + * @note To clear the advertising data and set it to a 0-length packet, simply provide a valid pointer (p_data/p_sr_data) with its corresponding + * length (dlen/srdlen) set to 0. + * + * @note The call will fail if p_data and p_sr_data are both NULL since this would have no effect. + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_data Raw data to be placed in advertising packet. If NULL, no changes are made to the current advertising packet data. + * @param[in] dlen Data length for p_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_data is NULL, can be 0 if p_data is not NULL. + * @param[in] p_sr_data Raw data to be placed in scan response packet. If NULL, no changes are made to the current scan response packet data. + * @param[in] srdlen Data length for p_sr_data. Max size: @ref BLE_GAP_ADV_MAX_SIZE octets. Should be 0 if p_sr_data is NULL, can be 0 if p_data is not NULL. + * + * @retval ::NRF_SUCCESS Advertising data successfully updated or cleared. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, both p_data and p_sr_data cannot be NULL. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_FLAGS Invalid combination of advertising flags supplied. + * @retval ::NRF_ERROR_INVALID_DATA Invalid data type(s) supplied, check the advertising data format specification. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid data length(s) supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported data type. + * @retval ::BLE_ERROR_GAP_UUID_LIST_MISMATCH Invalid UUID list supplied. + */ +SVCALL(SD_BLE_GAP_ADV_DATA_SET, uint32_t, sd_ble_gap_adv_data_set(uint8_t const *p_data, uint8_t dlen, uint8_t const *p_sr_data, uint8_t srdlen)); + + +/**@brief Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @note An application can start an advertising procedure for broadcasting purposes while a connection + * is active. After a @ref BLE_GAP_EVT_CONNECTED event is received, this function may therefore + * be called to start a broadcast advertising procedure. The advertising procedure + * cannot however be connectable (it must be of type @ref BLE_GAP_ADV_TYPE_ADV_SCAN_IND or + * @ref BLE_GAP_ADV_TYPE_ADV_NONCONN_IND). @note Only one advertiser may be active at any time. + * + * @events + * @event{@ref BLE_GAP_EVT_CONNECTED, Generated after connection has been established through connectable advertising.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Advertisement has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_adv_params Pointer to advertising parameters structure. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or @ref + * BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. + * + * @retval ::NRF_SUCCESS The BLE stack has started advertising. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections has been reached; connectable advertiser cannot be started. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check the accepted ranges and limits. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Bluetooth address supplied. + * @retval ::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST Discoverable mode and whitelist incompatible. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Observer) and try again + */ +SVCALL(SD_BLE_GAP_ADV_START, uint32_t, sd_ble_gap_adv_start(ble_gap_adv_params_t const *p_adv_params, uint8_t conn_cfg_tag)); + + +/**@brief Stop advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_ADV_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS The BLE stack has stopped advertising. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (most probably not in advertising state). + */ +SVCALL(SD_BLE_GAP_ADV_STOP, uint32_t, sd_ble_gap_adv_stop(void)); + + + +/**@brief Update connection parameters. + * + * @details In the central role this will initiate a Link Layer connection parameter update procedure, + * otherwise in the peripheral role, this will send the corresponding L2CAP request and wait for + * the central to perform the procedure. In both cases, and regardless of success or failure, the application + * will be informed of the result with a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE event. + * + * @details This function can be used as a central both to reply to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST or to start the procedure unrequested. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_PARAM_UPDATE, Result of the connection parameter update procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CPU_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CPU_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CPU_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_conn_params Pointer to desired connection parameters. If NULL is provided on a peripheral role, + * the parameters in the PPCP characteristic of the GAP service will be used instead. + * If NULL is provided on a central role and in response to a @ref BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request will be rejected + * + * @retval ::NRF_SUCCESS The Connection Update procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY Procedure already in progress or not allowed at this time, process pending events and wait for pending procedures to complete and retry. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_GAP_CONN_PARAM_UPDATE, uint32_t, sd_ble_gap_conn_param_update(uint16_t conn_handle, ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Disconnect (GAP Link Termination). + * + * @details This call initiates the disconnection procedure, and its completion will be communicated to the application + * with a @ref BLE_GAP_EVT_DISCONNECTED event. + * + * @events + * @event{@ref BLE_GAP_EVT_DISCONNECTED, Generated when disconnection procedure is complete.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CONN_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] hci_status_code HCI status code, see @ref BLE_HCI_STATUS_CODES (accepted values are @ref BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION and @ref BLE_HCI_CONN_INTERVAL_UNACCEPTABLE). + * + * @retval ::NRF_SUCCESS The disconnection procedure has been started successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (disconnection is already in progress). + */ +SVCALL(SD_BLE_GAP_DISCONNECT, uint32_t, sd_ble_gap_disconnect(uint16_t conn_handle, uint8_t hci_status_code)); + + +/**@brief Set the radio's transmit power. + * + * @param[in] tx_power Radio transmit power in dBm (accepted values are -40, -20, -16, -12, -8, -4, 0, 2, 3, 4, 5, 6, 7, 8 and 9 dBm). + * + * @note The -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +2dBm, +3dBm, +4dBm, +5dBm, +6dBm, +7dBm, +8dBm and +9dBm settings are available on nRF52840 series ICs. + * @note The -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, +3dBm and +4dBm settings are available on nRF52 series ICs. + * + * @retval ::NRF_SUCCESS Successfully changed the transmit power. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_TX_POWER_SET, uint32_t, sd_ble_gap_tx_power_set(int8_t tx_power)); + + +/**@brief Set GAP Appearance value. + * + * @param[in] appearance Appearance (16-bit), see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value set successfully. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_SET, uint32_t, sd_ble_gap_appearance_set(uint16_t appearance)); + + +/**@brief Get GAP Appearance value. + * + * @param[out] p_appearance Pointer to appearance (16-bit) to be filled in, see @ref BLE_APPEARANCES. + * + * @retval ::NRF_SUCCESS Appearance value retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_GET, uint32_t, sd_ble_gap_appearance_get(uint16_t *p_appearance)); + + +/**@brief Set GAP Peripheral Preferred Connection Parameters. + * + * @param[in] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure with the desired parameters. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters set successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_SET, uint32_t, sd_ble_gap_ppcp_set(ble_gap_conn_params_t const *p_conn_params)); + + +/**@brief Get GAP Peripheral Preferred Connection Parameters. + * + * @param[out] p_conn_params Pointer to a @ref ble_gap_conn_params_t structure where the parameters will be stored. + * + * @retval ::NRF_SUCCESS Peripheral Preferred Connection Parameters retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_PPCP_GET, uint32_t, sd_ble_gap_ppcp_get(ble_gap_conn_params_t *p_conn_params)); + + +/**@brief Set GAP device name. + * + * @note If the device name is located in application flash memory (see @ref ble_gap_cfg_device_name_t), + * it cannot be changed. Then @ref NRF_ERROR_FORBIDDEN will be returned. + * + * @param[in] p_write_perm Write permissions for the Device Name characteristic, see @ref ble_gap_conn_sec_mode_t. + * @param[in] p_dev_name Pointer to a UTF-8 encoded, non NULL-terminated string. + * @param[in] len Length of the UTF-8, non NULL-terminated string pointed to by p_dev_name in octets (must be smaller or equal than @ref BLE_GAP_DEVNAME_MAX_LEN). + * + * @retval ::NRF_SUCCESS GAP device name and permissions set successfully. + * @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_FORBIDDEN Device name is not writable. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len)); + + +/**@brief Get GAP device name. + * + * @note If the device name is longer than the size of the supplied buffer, + * p_len will return the complete device name length, + * and not the number of bytes actually returned in p_dev_name. + * The application may use this information to allocate a suitable buffer size. + * + * @param[out] p_dev_name Pointer to an empty buffer where the UTF-8 non NULL-terminated string will be placed. Set to NULL to obtain the complete device name length. + * @param[in,out] p_len Length of the buffer pointed by p_dev_name, complete device name length on output. + * + * @retval ::NRF_SUCCESS GAP device name retrieved successfully. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_GET, uint32_t, sd_ble_gap_device_name_get(uint8_t *p_dev_name, uint16_t *p_len)); + + +/**@brief Initiate the GAP Authentication procedure. + * + * @details In the central role, this function will send an SMP Pairing Request (or an SMP Pairing Failed if rejected), + * otherwise in the peripheral role, an SMP Security Request will be sent. + * + * @events + * @event{Depending on the security parameters set and the packet exchanges with the peer\, the following events may be generated:} + * @event{@ref BLE_GAP_EVT_SEC_PARAMS_REQUEST} + * @event{@ref BLE_GAP_EVT_SEC_INFO_REQUEST} + * @event{@ref BLE_GAP_EVT_PASSKEY_DISPLAY} + * @event{@ref BLE_GAP_EVT_KEY_PRESSED} + * @event{@ref BLE_GAP_EVT_AUTH_KEY_REQUEST} + * @event{@ref BLE_GAP_EVT_LESC_DHKEY_REQUEST} + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE} + * @event{@ref BLE_GAP_EVT_AUTH_STATUS} + * @event{@ref BLE_GAP_EVT_TIMEOUT} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_sec_params Pointer to the @ref ble_gap_sec_params_t structure with the security parameters to be used during the pairing or bonding procedure. + * In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. + * In the central role, this pointer may be NULL to reject a Security Request. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_NO_MEM The maximum number of authentication procedures that can run in parallel for the given role is reached. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + * @retval ::NRF_ERROR_TIMEOUT A SMP timeout has occurred, and further SMP operations on this link is prohibited. + */ +SVCALL(SD_BLE_GAP_AUTHENTICATE, uint32_t, sd_ble_gap_authenticate(uint16_t conn_handle, ble_gap_sec_params_t const *p_sec_params)); + + +/**@brief Reply with GAP security parameters. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_CONFIRM_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_KS_TOO_SMALL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_APP_ERROR_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_REMOTE_PAIRING_FAIL_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_PAIRING_TIMEOUT_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] sec_status Security status, see @ref BLE_GAP_SEC_STATUS. + * @param[in] p_sec_params Pointer to a @ref ble_gap_sec_params_t security parameters structure. In the central role this must be set to NULL, as the parameters have + * already been provided during a previous call to @ref sd_ble_gap_authenticate. + * @param[in,out] p_sec_keyset Pointer to a @ref ble_gap_sec_keyset_t security keyset structure. Any keys generated and/or distributed as a result of the ongoing security procedure + * will be stored into the memory referenced by the pointers inside this structure. The keys will be stored and available to the application + * upon reception of a @ref BLE_GAP_EVT_AUTH_STATUS event. + * Note that the SoftDevice expects the application to provide memory for storing the + * peer's keys. So it must be ensured that the relevant pointers inside this structure are not NULL. The pointers to the local key + * can, however, be NULL, in which case, the local key data will not be available to the application upon reception of the + * @ref BLE_GAP_EVT_AUTH_STATUS event. + * + * @retval ::NRF_SUCCESS Successfully accepted security parameter from the application. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED Setting of sign or link fields in @ref ble_gap_sec_kdist_t not supported. + */ +SVCALL(SD_BLE_GAP_SEC_PARAMS_REPLY, uint32_t, sd_ble_gap_sec_params_reply(uint16_t conn_handle, uint8_t sec_status, ble_gap_sec_params_t const *p_sec_params, ble_gap_sec_keyset_t const *p_sec_keyset)); + + +/**@brief Reply with an authentication key. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_AUTH_KEY_REQUEST or a @ref BLE_GAP_EVT_PASSKEY_DISPLAY, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_BONDING_PK_CENTRAL_OOB_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_BONDING_PK_PERIPH_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] key_type See @ref BLE_GAP_AUTH_KEY_TYPES. + * @param[in] p_key If key type is @ref BLE_GAP_AUTH_KEY_TYPE_NONE, then NULL. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY, then a 6-byte ASCII string (digit 0..9 only, no NULL termination) + * or NULL when confirming LE Secure Connections Numeric Comparison. + * If key type is @ref BLE_GAP_AUTH_KEY_TYPE_OOB, then a 16-byte OOB key value in little-endian format. + * + * @retval ::NRF_SUCCESS Authentication key successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_AUTH_KEY_REPLY, uint32_t, sd_ble_gap_auth_key_reply(uint16_t conn_handle, uint8_t key_type, uint8_t const *p_key)); + +/**@brief Reply with an LE Secure connections DHKey. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST, calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_PAIRING_JW_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_NC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_PD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dhkey LE Secure Connections DHKey. + * + * @retval ::NRF_SUCCESS DHKey successfully set. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_DHKEY_REPLY, uint32_t, sd_ble_gap_lesc_dhkey_reply(uint16_t conn_handle, ble_gap_lesc_dhkey_t const *p_dhkey)); + +/**@brief Notify the peer of a local keypress. + * + * @details This function can only be used when an authentication procedure using LE Secure Connection is in progress. Calling it at other times will result in an @ref NRF_ERROR_INVALID_STATE. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_PKE_CD_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_PKE_CD_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] kp_not See @ref BLE_GAP_KP_NOT_TYPES. + * + * @retval ::NRF_SUCCESS Keypress notification successfully queued for transmission. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. Either not entering a passkey or keypresses have not been enabled by both peers. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_BUSY The BLE stack is busy. Retry at later time. + */ +SVCALL(SD_BLE_GAP_KEYPRESS_NOTIFY, uint32_t, sd_ble_gap_keypress_notify(uint16_t conn_handle, uint8_t kp_not)); + +/**@brief Generate a set of OOB data to send to a peer out of band. + * + * @note The @ref ble_gap_addr_t included in the OOB data returned will be the currently active one (or, if a connection has already been established, + * the one used during connection setup). The application may manually overwrite it with an updated value. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. Can be BLE_CONN_HANDLE_INVALID if a BLE connection has not been established yet. + * @param[in] p_pk_own LE Secure Connections local P-256 Public Key. + * @param[out] p_oobd_own The OOB data to be sent out of band to a peer. + * + * @retval ::NRF_SUCCESS OOB data successfully generated. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_GET, uint32_t, sd_ble_gap_lesc_oob_data_get(uint16_t conn_handle, ble_gap_lesc_p256_pk_t const *p_pk_own, ble_gap_lesc_oob_data_t *p_oobd_own)); + +/**@brief Provide the OOB data sent/received out of band. + * + * @note An authentication procedure with OOB selected as an algorithm must be in progress when calling this function. + * @note A @ref BLE_GAP_EVT_LESC_DHKEY_REQUEST event with the oobd_req set to 1 must have been received prior to calling this function. + * + * @events + * @event{This function is used during authentication procedures\, see the list of events in the documentation of @ref sd_ble_gap_authenticate.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_LESC_BONDING_OOB_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_LESC_BONDING_OOB_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_oobd_own The OOB data sent out of band to a peer or NULL if the peer has not received OOB data. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST. + * @param[in] p_oobd_peer The OOB data received out of band from a peer or NULL if none received. + * Must correspond to @ref ble_gap_sec_params_t::oob flag in @ref sd_ble_gap_authenticate in the central role + * or @ref sd_ble_gap_sec_params_reply in the peripheral role. + * + * @retval ::NRF_SUCCESS OOB data accepted. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_LESC_OOB_DATA_SET, uint32_t, sd_ble_gap_lesc_oob_data_set(uint16_t conn_handle, ble_gap_lesc_oob_data_t const *p_oobd_own, ble_gap_lesc_oob_data_t const *p_oobd_peer)); + +/**@brief Initiate GAP Encryption procedure. + * + * @details In the central role, this function will initiate the encryption procedure using the encryption information provided. + * + * @events + * @event{@ref BLE_GAP_EVT_CONN_SEC_UPDATE, The connection security has been updated.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_AUTH_MUTEX_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_ENC_MSC} + * @mmsc{@ref BLE_GAP_MULTILINK_CTRL_PROC_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_SEC_REQ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_master_id Pointer to a @ref ble_gap_master_id_t master identification structure. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. + * + * @retval ::NRF_SUCCESS Successfully initiated authentication procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::BLE_ERROR_INVALID_ROLE Operation is not supported in the Peripheral role. + * @retval ::NRF_ERROR_BUSY Procedure already in progress or not allowed at this time, wait for pending procedures to complete and retry. + */ +SVCALL(SD_BLE_GAP_ENCRYPT, uint32_t, sd_ble_gap_encrypt(uint16_t conn_handle, ble_gap_master_id_t const *p_master_id, ble_gap_enc_info_t const *p_enc_info)); + + +/**@brief Reply with GAP security information. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_SEC_INFO_REQUEST, calling it at other times will result in @ref NRF_ERROR_INVALID_STATE. + * @note If the call returns an error code, the request is still pending, and the reply call may be repeated with corrected parameters. + * @note Data signing is not yet supported, and p_sign_info must therefore be NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_PERIPH_ENC_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] p_enc_info Pointer to a @ref ble_gap_enc_info_t encryption information structure. May be NULL to signal none is available. + * @param[in] p_id_info Pointer to a @ref ble_gap_irk_t identity information structure. May be NULL to signal none is available. + * @param[in] p_sign_info Pointer to a @ref ble_gap_sign_info_t signing information structure. May be NULL to signal none is available. + * + * @retval ::NRF_SUCCESS Successfully accepted security information. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_SEC_INFO_REPLY, uint32_t, sd_ble_gap_sec_info_reply(uint16_t conn_handle, ble_gap_enc_info_t const *p_enc_info, ble_gap_irk_t const *p_id_info, ble_gap_sign_info_t const *p_sign_info)); + + +/**@brief Get the current connection security. + * + * @param[in] conn_handle Connection handle. + * @param[out] p_conn_sec Pointer to a @ref ble_gap_conn_sec_t structure to be filled in. + * + * @retval ::NRF_SUCCESS Current connection security successfully retrieved. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_CONN_SEC_GET, uint32_t, sd_ble_gap_conn_sec_get(uint16_t conn_handle, ble_gap_conn_sec_t *p_conn_sec)); + + +/**@brief Start reporting the received signal strength to the application. + * + * A new event is reported whenever the RSSI value changes, until @ref sd_ble_gap_rssi_stop is called. + * + * @events + * @event{@ref BLE_GAP_EVT_RSSI_CHANGED, New RSSI data available. How often the event is generated is + * dependent on the settings of the threshold_dbm + * and skip_count input parameters.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[in] threshold_dbm Minimum change in dBm before triggering the @ref BLE_GAP_EVT_RSSI_CHANGED event. Events are disabled if threshold_dbm equals @ref BLE_GAP_RSSI_THRESHOLD_INVALID. + * @param[in] skip_count Number of RSSI samples with a change of threshold_dbm or more before sending a new @ref BLE_GAP_EVT_RSSI_CHANGED event. + * + * @retval ::NRF_SUCCESS Successfully activated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Disconnection in progress. Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_START, uint32_t, sd_ble_gap_rssi_start(uint16_t conn_handle, uint8_t threshold_dbm, uint8_t skip_count)); + + +/**@brief Stop reporting the received signal strength. + * + * @note An RSSI change detected before the call but not yet received by the application + * may be reported after @ref sd_ble_gap_rssi_stop has been called. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @mmsc{@ref BLE_GAP_RSSI_FILT_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * + * @retval ::NRF_SUCCESS Successfully deactivated RSSI reporting. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +SVCALL(SD_BLE_GAP_RSSI_STOP, uint32_t, sd_ble_gap_rssi_stop(uint16_t conn_handle)); + + +/**@brief Get the received signal strength for the last connection event. + * + * @ref sd_ble_gap_rssi_start must be called to start reporting RSSI before using this function. @ref NRF_ERROR_NOT_FOUND + * will be returned until RSSI was sampled for the first time after calling @ref sd_ble_gap_rssi_start. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_RSSI_READ_MSC} + * @endmscs + * + * @param[in] conn_handle Connection handle. + * @param[out] p_rssi Pointer to the location where the RSSI measurement shall be stored. + * + * @retval ::NRF_SUCCESS Successfully read the RSSI. + * @retval ::NRF_ERROR_NOT_FOUND No sample is available. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_STATE RSSI reporting is not ongoing, or disconnection in progress. + */ +SVCALL(SD_BLE_GAP_RSSI_GET, uint32_t, sd_ble_gap_rssi_get(uint16_t conn_handle, int8_t *p_rssi)); + + +/**@brief Start scanning (GAP Discovery procedure, Observer Procedure). + * + * @events + * @event{@ref BLE_GAP_EVT_ADV_REPORT, An advertising or scan response packet has been received.} + * @event{@ref BLE_GAP_EVT_TIMEOUT, Scanner has timed out.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @param[in] p_scan_params Pointer to scan parameters structure. + * + * @retval ::NRF_SUCCESS Successfully initiated scanning procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_SCAN_START, uint32_t, sd_ble_gap_scan_start(ble_gap_scan_params_t const *p_scan_params)); + + +/**@brief Stop scanning (GAP Discovery procedure, Observer Procedure). + * + * @mscs + * @mmsc{@ref BLE_GAP_SCAN_MSC} + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully stopped scanning procedure. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation (most probably not in scanning state). + */ +SVCALL(SD_BLE_GAP_SCAN_STOP, uint32_t, sd_ble_gap_scan_stop(void)); + + +/**@brief Create a connection (GAP Link Establishment). + * + * @note If a scanning procedure is currently in progress it will be automatically stopped when calling this function. + * The scanning procedure will be stopped even if the function returns an error. + * + * @mscs + * @mmsc{@ref BLE_GAP_WL_SHARE_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC} + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @param[in] p_peer_addr Pointer to peer address. If the use_whitelist bit is set in @ref ble_gap_scan_params_t, then this is ignored. + * If @ref ble_gap_addr_t::addr_id_peer is set then p_peer_addr must be present in the device identity list + * see @ref sd_ble_gap_device_identities_set. + * @param[in] p_scan_params Pointer to scan parameters structure. + * @param[in] p_conn_params Pointer to desired connection parameters. + * @param[in] conn_cfg_tag Tag identifying a configuration set by @ref sd_ble_cfg_set or @ref + * BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. + * + * @retval ::NRF_SUCCESS Successfully initiated connection procedure. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid parameter(s) pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * - Invalid parameter(s) in p_scan_params or p_conn_params. + * - Use of whitelist requested but whitelist has not been set, see @ref sd_ble_gap_whitelist_set. + * - Peer address was not present in the device identity list, see @ref sd_ble_gap_device_identities_set. + * @retval ::NRF_ERROR_INVALID_STATE The SoftDevice is in an invalid state to perform this operation. This may be due to an + * existing locally initiated connect procedure, which must complete before initiating again. + * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Peer address. + * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections has been reached. + * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry. If another connection is being established + * wait for the corresponding @ref BLE_GAP_EVT_CONNECTED event before calling again. + * @retval ::NRF_ERROR_RESOURCES Not enough BLE role slots available. + * Stop one or more currently active roles (Central, Peripheral or Broadcaster) and try again + */ +SVCALL(SD_BLE_GAP_CONNECT, uint32_t, sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params, uint8_t conn_cfg_tag)); + + +/**@brief Cancel a connection establishment. + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_CONN_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully canceled an ongoing connection procedure. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + */ +SVCALL(SD_BLE_GAP_CONNECT_CANCEL, uint32_t, sd_ble_gap_connect_cancel(void)); + + +/**@brief PHY Update Request + * + * @details This function is used to request a new PHY configuration for a central or a peripheral connection. It will always generate a + * @ref BLE_GAP_EVT_PHY_UPDATE event if successfully executed. If @ref ble_gap_phys_t::tx_phys or @ref ble_gap_phys_t::rx_phys + * is 0, then the stack will select PHYs based on the peer requirements on that specific direction. If the peer does not support + * the PHY Update procedure, then the resulting @ref BLE_GAP_EVT_PHY_UPDATE event will have a status different from + * @ref BLE_HCI_STATUS_CODE_SUCCESS. + * + * @note The requested PHYs does not have to be within the set of the preferred PHYs. + * + * @note If the @ref ble_gap_opt_preferred_phys_t have not been configured with @ref BLE_GAP_PHY_CODED, then this call might return + * @ref BLE_ERROR_BLOCKED_BY_OTHER_LINKS if there are multiple devices connected. + * + * + * @events + * @event{@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update procedure procedure.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GAP_CENTRAL_PHY_REQUEST} + * @mmsc{@ref BLE_GAP_PERIPHERAL_PHY_REQUEST} + * @endmscs + * + * @param[in] conn_handle Connection handle to indicate the connection for which the PHY Update is requested. + * @param[in] p_gap_phys Pointer to PHY structure. + * + * @retval ::NRF_SUCCESS Successfully requested a PHY Update. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Unsupported PHYs supplied to the call. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::BLE_ERROR_BLOCKED_BY_OTHER_LINKS Other connections may block the scheduling of the current link. + * @retval ::NRF_ERROR_BUSY Procedure is already in progress or not allowed at this time. Process pending events and wait for the pending procedure to complete and retry. + * + */ +SVCALL(SD_BLE_GAP_PHY_REQUEST, uint32_t, sd_ble_gap_phy_request(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys)); + +/**@brief Initiate or respond to a Data Length Update Procedure. + * + * @note Only symmetric input parameters for the Data Length Update is supported. Only @ref + * BLE_GAP_DATA_LENGTH_AUTO for max_tx_time_us and max_rx_time_us is supported. + * + * @note If the application uses @ref BLE_GAP_DATA_LENGTH_AUTO for one or more members of + * p_dl_params, the SoftDevice will choose the highest value supported in current + * configuration and connection parameters. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_dl_params Pointer to local parameters to be used in Data Length Update + * Procedure. Set any member to @ref BLE_GAP_DATA_LENGTH_AUTO to let + * the SoftDevice automatically decide the value for that member. + * Set to NULL to use automatic values for all members. + * @param[out] p_dl_limitation Pointer to limitation to be written when local device does not + * have enough resources to accommodate the requested Data Length + * Update parameters. Ignored if NULL. + * + * @mscs + * @mmsc{@ref BLE_GAP_DATA_LENGTH_UPDATE_PROCEDURE_MSC} + * @endmscs + * + * @retval ::NRF_SUCCESS Successfully set Data Length Extension initiation/response parameters. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle parameter supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. + * @retval ::NRF_ERROR_NOT_SUPPORTED The requested parameters are not supported by the SoftDevice. + * @retval ::NRF_ERROR_RESOURCES The requested parameters can not be accommodated. Inspect + * p_dl_limitation so see where the limitation is. + * @retval ::NRF_ERROR_BUSY Peer has already initiated a Data Length Update Procedure. Process the + * pending @ref BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event to respond. + */ +SVCALL(SD_BLE_GAP_DATA_LENGTH_UPDATE, uint32_t, sd_ble_gap_data_length_update(uint16_t conn_handle, ble_gap_data_length_params_t const *p_dl_params, ble_gap_data_length_limitation_t *p_dl_limitation)); + + + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_GAP_H__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatt.h new file mode 100644 index 0000000000..f6e7ee8563 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatt.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 ATT MTU, in bytes. */ +#define BLE_GATT_ATT_MTU_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 Authorization. */ +#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 connection configuration parameters, set with @ref sd_ble_cfg_set. + * + * @retval NRF_ERROR_INVALID_PARAM att_mtu is smaller than @ref BLE_GATT_ATT_MTU_DEFAULT. + */ +typedef struct +{ + uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive. + The default and minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT. + @mscs + @mmsc{@ref BLE_GATTC_MTU_EXCHANGE} + @mmsc{@ref BLE_GATTS_MTU_EXCHANGE} + @endmscs + */ +} ble_gatt_conn_cfg_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; /**< Notification 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gattc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gattc.h new file mode 100644 index 0000000000..b6a75ece77 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gattc.h @@ -0,0 +1,700 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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. */ + BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE /**< Write without Response transmission complete. \n See @ref ble_gattc_evt_write_cmd_tx_complete_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. */ +/** @} */ + +/** @defgroup BLE_GATTC_DEFAULTS GATT Client defaults + * @{ */ +#define BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Write without Response that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTC_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTC connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t write_cmd_tx_queue_size; /**< The guaranteed minimum number of Write without Response that can be queued for transmission. + The default value is @ref BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT */ +} ble_gattc_conn_cfg_t; + +/**@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 Event structure for @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of write without response transmissions completed. */ +} ble_gattc_evt_write_cmd_tx_complete_t; + +/**@brief GATTC event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occurred. */ + 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. */ + ble_gattc_evt_write_cmd_tx_complete_t write_cmd_tx_complete; /**< Write without Response transmission complete 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 Only one write with response procedure can be ongoing per connection at a time. + * If the application tries to write with response while another write with response procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTC_EVT_WRITE_RSP event will be issued as soon as the write response arrives from the peer. + * + * @note The number of Write without Response that can be queued is configured by @ref ble_gattc_conn_cfg_t::write_cmd_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event will be issued as soon as the transmission of the write without response is complete. + * + * @note The application can keep track of the available queue element count for writes without responses by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE, Write without response transmission complete.} + * @event{@ref BLE_GATTC_EVT_WRITE_RSP, Write response received from the peer.} + * @endevents + * + * @mscs + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_WITHOUT_RESP_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC} + * @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_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 For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry. + * @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued. + * Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry. + */ +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_ATT_MTU_DEFAULT. + * + * @events + * @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP} + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - 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__ */ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatts.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatts.h new file mode 100644 index 0000000000..6bb24831d8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_gatts.h @@ -0,0 +1,832 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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. \n 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 respond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */ + BLE_GATTS_EVT_HVN_TX_COMPLETE /**< Handle Value Notification transmission complete. \n See @ref ble_gatts_evt_hvn_tx_complete_t. */ +}; + +/**@brief GATTS Configuration IDs. + * + * IDs that uniquely identify a GATTS configuration. + */ +enum BLE_GATTS_CFGS +{ + BLE_GATTS_CFG_SERVICE_CHANGED = BLE_GATTS_CFG_BASE, /**< Service changed configuration. */ + BLE_GATTS_CFG_ATTR_TAB_SIZE, /**< Attribute table size configuration. */ +}; + +/** @} */ + +/** @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_SERVICE_CHANGED Service Changed Inclusion Values + * @{ + */ +#define BLE_GATTS_SERVICE_CHANGED_DEFAULT (1) /**< Default is to include the Service Changed characteristic in the Attribute Table. */ +/** @} */ + +/** @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 (1408) /**< Default Attribute Table size. */ +/** @} */ + +/** @defgroup BLE_GATTS_DEFAULTS GATT Server defaults + * @{ + */ +#define BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Handle Value Notifications that can be queued for transmission. */ +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATTS_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTS connection configuration parameters, set with @ref sd_ble_cfg_set. + */ +typedef struct +{ + uint8_t hvn_tx_queue_size; /**< Minimum guaranteed number of Handle Value Notifications that can be queued for transmission. + The default value is @ref BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT */ +} ble_gatts_conn_cfg_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 const *p_uuid; /**< Pointer to the attribute UUID. */ + ble_gatts_attr_md_t const *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 const *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 const *p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */ + ble_gatts_attr_md_t const *p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */ + ble_gatts_attr_md_t const *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 const *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. */ + uint8_t const *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 Service Changed Inclusion configuration parameters, set with @ref sd_ble_cfg_set. */ +typedef struct +{ + uint8_t service_changed : 1; /**< If 1, include the Service Changed characteristic in the Attribute Table. Default is @ref BLE_GATTS_SERVICE_CHANGED_DEFAULT. */ +} ble_gatts_cfg_service_changed_t; + +/**@brief Attribute table size configuration parameters, set with @ref sd_ble_cfg_set. + * + * @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. + */ +typedef struct +{ + uint32_t attr_tab_size; /**< Attribute table size. Default is @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, minimum is @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. */ +} ble_gatts_cfg_attr_tab_size_t; + +/**@brief Config structure for GATTS configurations. */ +typedef union +{ + ble_gatts_cfg_service_changed_t service_changed; /**< Include service changed characteristic, cfg_id is @ref BLE_GATTS_CFG_SERVICE_CHANGED. */ + ble_gatts_cfg_attr_tab_size_t attr_tab_size; /**< Attribute table size, cfg_id is @ref BLE_GATTS_CFG_ATTR_TAB_SIZE. */ +} ble_gatts_cfg_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 finalize 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 Event structure for @ref BLE_GATTS_EVT_HVN_TX_COMPLETE. */ +typedef struct +{ + uint8_t count; /**< Number of notification transmissions completed. */ +} ble_gatts_evt_hvn_tx_complete_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. */ + ble_gatts_evt_hvn_tx_complete_t hvn_tx_complete; /**< Handle Value Notification transmission complete Event Parameters. */ + } 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 writable auxiliaries bits, + * readable (no security) and writable (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 whether 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. + * + * @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 NRF_ERROR_RESOURCES. + * The caller can check whether the value has been updated by looking at the contents of *(p_hvx_params->p_len). + * + * @note Only one indication procedure can be ongoing per connection at a time. + * If the application tries to indicate an attribute value while another indication procedure is ongoing, + * the function call will return @ref NRF_ERROR_BUSY. + * A @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from the peer. + * + * @note The number of Handle Value Notifications that can be queued is configured by @ref ble_gatts_conn_cfg_t::hvn_tx_queue_size + * When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES. + * A @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event will be issued as soon as the transmission of the notification is complete. + * + * @note The application can keep track of the available queue element count for notifications by following the procedure below: + * - Store initial queue element count in a variable. + * - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS. + * - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event. + * + * @events + * @event{@ref BLE_GATTS_EVT_HVN_TX_COMPLETE, Notification transmission complete.} + * @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from the 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} + * @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 For @ref BLE_GATT_HVX_INDICATION Procedure already in progress. Wait for a @ref BLE_GATTS_EVT_HVC event and retry. + * @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 ::NRF_ERROR_RESOURCES Too many notifications queued. + * Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry. + */ +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_cfg_set and @ref ble_gatts_cfg_service_changed_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. + */ +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. + */ +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 persistently 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. Unconditionally 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_ATT_MTU_DEFAULT. + * + * @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_ATT_MTU_DEFAULT. + * - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration + used for this connection. + * - 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. + */ +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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_hci.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_hci.h new file mode 100644 index 0000000000..21293e8efc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_hci.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 Advertisement 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__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_l2cap.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_l2cap.h new file mode 100644 index 0000000000..90cce565d8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_l2cap.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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_DEFINES Defines + * @{ */ + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif // BLE_L2CAP_H__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_ranges.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_ranges.h new file mode 100644 index 0000000000..f9c6af76b8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_ranges.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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__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_.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_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */ +#define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */ + +#define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */ +#define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */ + +#define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */ +#define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */ + +#define BLE_L2CAP_OPT_BASE 0xA0 /**< L2CAP BLE Option base. */ +#define BLE_L2CAP_OPT_LAST 0xBF /**< L2CAP BLE Option last. */ + + +#define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */ + +#define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */ +#define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */ + +#define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */ +#define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */ + +#define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */ +#define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */ + +#define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */ +#define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */ + +#define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */ +#define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */ + +#define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */ +#define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */ + +#define BLE_L2CAP_CFG_BASE 0xC0 /**< L2CAP BLE configuration base. */ +#define BLE_L2CAP_CFG_LAST 0xDF /**< L2CAP BLE configuration last. */ + + + + + +#ifdef __cplusplus +} +#endif +#endif /* BLE_RANGES_H__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_types.h new file mode 100644 index 0000000000..e24be0b574 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/ble_types.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 + +#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 /**< Joystick (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__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf52/nrf_mbr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf52/nrf_mbr.h new file mode 100644 index 0000000000..ccbe96bd59 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf52/nrf_mbr.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 + +*/ + +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + +#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, /**< Initialize 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 SoftDevice Specification 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 SoftDevice Specification 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 return values, 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_ble.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_ble.h new file mode 100644 index 0000000000..c4835fa6ef --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_ble.h @@ -0,0 +1,615 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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_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. */ + SD_BLE_CFG_SET, /**< Add a configuration to the BLE stack. */ +}; + +/** + * @brief BLE Module Independent Event IDs. + */ +enum BLE_COMMON_EVTS +{ + BLE_EVT_USER_MEM_REQUEST = BLE_EVT_BASE, /**< 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 */ +}; + +/**@brief BLE Connection Configuration IDs. + * + * IDs that uniquely identify a connection configuration. + */ +enum BLE_CONN_CFGS +{ + BLE_CONN_CFG_GAP = BLE_CONN_CFG_BASE, /**< BLE GAP specific connection configuration. */ + BLE_CONN_CFG_GATTC, /**< BLE GATTC specific connection configuration. */ + BLE_CONN_CFG_GATTS, /**< BLE GATTS specific connection configuration. */ + BLE_CONN_CFG_GATT, /**< BLE GATT specific connection configuration. */ +}; + +/**@brief BLE Common Configuration IDs. + * + * IDs that uniquely identify a common configuration. + */ +enum BLE_COMMON_CFGS +{ + BLE_COMMON_CFG_VS_UUID = BLE_CFG_BASE, /**< Vendor specific UUID configuration */ +}; + +/**@brief Common Option IDs. + * IDs that uniquely identify a common option. + */ +enum BLE_COMMON_OPTS +{ + BLE_COMMON_OPT_PA_LNA = BLE_OPT_BASE, /**< 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 The highest value used for @ref ble_gatt_conn_cfg_t::att_mtu in any connection configuration shall be used as a parameter. + * If that value has not been configured for any connections then @ref BLE_GATT_ATT_MTU_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_DEFAULT 10 /**< Default VS UUID count. */ +#define BLE_UUID_VS_COUNT_MAX 254 /**< Maximum VS UUID count. */ +/** @} */ + +/** @defgroup BLE_COMMON_CFG_DEFAULTS Configuration defaults. + * @{ + */ +#define BLE_CONN_CFG_TAG_DEFAULT 0 /**< Default configuration tag, SoftDevice default connection configuration. */ + +/** @} */ + +/** @} */ + +/** @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_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 events not associated with a specific function module. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which this event occurred. */ + union + { + 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. */ + } params; /**< Event parameter union. */ +} ble_common_evt_t; + +/**@brief BLE Event header. */ +typedef struct +{ + uint16_t evt_id; /**< Value from a BLE__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_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 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 connection configuration as set by @ref ble_gap_conn_cfg_t::event_length. + * 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_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 connection configuration type, wrapping the module specific configurations, set with + * @ref sd_ble_cfg_set. + * + * @note Connection configurations don't have to be set. + * In the case that no configurations has been set, or fewer connection configurations has been set than enabled connections, + * the default connection configuration will be automatically added for the remaining connections. + * When creating connections with the default configuration, @ref BLE_CONN_CFG_TAG_DEFAULT should be used in + * place of @ref ble_conn_cfg_t::conn_cfg_tag. See @ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect()" + * + * @mscs + * @mmsc{@ref BLE_CONN_CFG} + * @endmscs + + */ +typedef struct +{ + uint8_t conn_cfg_tag; /**< The application chosen tag it can use with the @ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect() + calls to select this configuration when creating a connection. + Must be different for all connection configurations added and not @ref BLE_CONN_CFG_TAG_DEFAULT. */ + union { + ble_gap_conn_cfg_t gap_conn_cfg; /**< GAP connection configuration, cfg_id is @ref BLE_CONN_CFG_GAP. */ + ble_gattc_conn_cfg_t gattc_conn_cfg; /**< GATTC connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTC. */ + ble_gatts_conn_cfg_t gatts_conn_cfg; /**< GATTS this connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTS. */ + ble_gatt_conn_cfg_t gatt_conn_cfg; /**< GATT this connection configuration, cfg_id is @ref BLE_CONN_CFG_GATT. */ + } params; /**< Connection configuration union. */ +} ble_conn_cfg_t; + +/** + * @brief Configuration of Vendor Specific UUIDs, set with @ref sd_ble_cfg_set. + * + * @retval ::NRF_ERROR_INVALID_PARAM Too many UUIDs configured. + */ +typedef struct +{ + uint8_t vs_uuid_count; /**< Number of 128-bit Vendor Specific UUID bases to allocate memory for. + Default value is @ref BLE_UUID_VS_COUNT_DEFAULT. Maximum value is + @ref BLE_UUID_VS_COUNT_MAX. */ +} ble_common_cfg_vs_uuid_t; + +/**@brief Common BLE Configuration type, wrapping the common configurations. */ +typedef union +{ + ble_common_cfg_vs_uuid_t vs_uuid_cfg; /**< Vendor specific UUID configuration, cfg_id is @ref BLE_COMMON_CFG_VS_UUID. */ +} ble_common_cfg_t; + +/**@brief BLE Configuration type, wrapping the module specific configurations. */ +typedef union +{ + ble_conn_cfg_t conn_cfg; /**< Connection specific configurations, cfg_id in @ref BLE_CONN_CFGS series. */ + ble_common_cfg_t common_cfg; /**< Global common configurations, cfg_id in @ref BLE_COMMON_CFGS series. */ + ble_gap_cfg_t gap_cfg; /**< Global GAP configurations, cfg_id in @ref BLE_GAP_CFGS series. */ + ble_gatts_cfg_t gatts_cfg; /**< Global GATTS configuration, cfg_id in @ref BLE_GATTS_CFGS series. */ +} ble_cfg_t; + +/** @} */ + +/** @addtogroup BLE_COMMON_FUNCTIONS Functions + * @{ */ + +/**@brief Enable the BLE stack + * + * @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. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note The value of *p_app_ram_base when the app has done no custom configuration of the + * SoftDevice, i.e. the app has not called @ref sd_ble_cfg_set before @ref sd_ble_enable, can + * be found in the release notes. + * + * @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 BLE related function other than @ref + * sd_ble_cfg_set 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_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. + */ +SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base)); + +/**@brief Add configurations for the BLE stack + * + * @param[in] cfg_id Config ID, see @ref BLE_CONN_CFGS, @ref BLE_COMMON_CFGS, @ref + * BLE_GAP_CFGS or @ref BLE_GATTS_CFGS. + * @param[in] p_cfg Pointer to a ble_cfg_t structure containing the configuration value. + * @param[in] app_ram_base The start address of the application RAM region (APP_RAM_BASE). + * See @ref sd_ble_enable for details about APP_RAM_BASE. + * + * @note The memory requirement for a specific configuration will not increase between SoftDevices + * with the same major version number. + * + * @note If a configuration is set more than once, the last one set is the one that takes effect on + * @ref sd_ble_enable. + * + * @note Any part of the BLE stack that is NOT configured with @ref sd_ble_cfg_set will have default + * configuration. + * + * @note @ref sd_ble_cfg_set may be called at any time when the SoftDevice is enabled (see @ref + * sd_softdevice_enable) while the BLE part of the SoftDevice is not enabled (see @ref + * sd_ble_enable). + * + * @note Error codes for the configurations are described in the configuration structs. + * + * @mscs + * @mmsc{@ref BLE_COMMON_ENABLE} + * @endmscs + * + * @retval ::NRF_SUCCESS The configuration has been added successfully. + * @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized. + * @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @retval ::NRF_ERROR_INVALID_PARAM Invalid cfg_id supplied. + * @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by app_ram_base is not + * large enough to fit this configuration's memory requirement. + */ +SVCALL(SD_BLE_CFG_SET, uint32_t, sd_ble_cfg_set(uint32_t cfg_id, ble_cfg_t const * p_cfg, uint32_t 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 must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT. + * 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 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 indexes 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] p_block Pointer to a user memory block structure or NULL if memory is managed by the application. + * + * @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 ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @retval ::NRF_ERROR_INVALID_LENGTH Invalid user memory block length supplied. + * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no user memory request pending. + */ +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} + * @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__ */ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error.h new file mode 100644 index 0000000000..43c091630b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_sdm.h new file mode 100644 index 0000000000..103659a913 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_sdm.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 erroneous SoftDevice flashing). + +#ifdef __cplusplus +} +#endif +#endif // NRF_ERROR_SDM_H__ + +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_soc.h new file mode 100644 index 0000000000..e31d8c9c97 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_error_soc.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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__ +/** + @} + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_nvic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_nvic.h new file mode 100644 index 0000000000..f4e3808071 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_nvic.h @@ -0,0 +1,517 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 +#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)SWI5_IRQn) \ + )) + + /**@brief Interrupts available for to application. */ + #define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0) +#endif + +#if defined(NRF52) || defined(NRF52840_XXAA) + #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)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<= (1 << __NVIC_PRIO_BITS)) + { + return 0; + } +#ifdef NRF51 + if( priority == 0 + || priority == 2 + ) + { + return 0; + } +#endif +#if defined(NRF52) || defined(NRF52840_XXAA) + 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; + #if defined(NRF52) || defined(NRF52840_XXAA) + 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]; + #if defined(NRF52) || defined(NRF52840_XXAA) + 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__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sd_def.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sd_def.h new file mode 100644 index 0000000000..0b4d221d6a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sd_def.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#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__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sdm.h new file mode 100644 index 0000000000..57ffe13358 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_sdm.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 (0) + +/** @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 retrieving 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 retrieving 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 retrieving 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 retrieving 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 retrieving 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 disallowed + 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 */ +#define NRF_CLOCK_LF_XTAL_ACCURACY_10_PPM (8) /**< 10 ppm */ +#define NRF_CLOCK_LF_XTAL_ACCURACY_5_PPM (9) /**< 5 ppm */ +#define NRF_CLOCK_LF_XTAL_ACCURACY_2_PPM (10) /**< 2 ppm */ +#define NRF_CLOCK_LF_XTAL_ACCURACY_1_PPM (11) /**< 1 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 +/-250 ppm 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, see @ref NRF_CLOCK_LF_XTAL_ACCURACY. + + @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__ + +/** + @} +*/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_soc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_soc.h new file mode 100644 index 0000000000..875f9bb63f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_soc.h @@ -0,0 +1,926 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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 +#include +#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 Guaranteed 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 +#if defined(NRF52) || defined(NRF52840_XXAA) +#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. + The default interrupt priority for this handler is set to 4 */ +#define RADIO_NOTIFICATION_IRQn (SWI1_EGU1_IRQn) /**< The radio notification IRQ number. */ +#define RADIO_NOTIFICATION_IRQHandler (SWI1_EGU1_IRQHandler) /**< The radio notification IRQ handler. + The default interrupt priority for this handler is set to 4 */ +#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_RAM_POWER_SET, + SD_POWER_RAM_POWER_CLR, + SD_POWER_RAM_POWER_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_V17 = 4UL, /**< 1.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V18, /**< 1.8 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V19, /**< 1.9 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V20, /**< 2.0 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V22, /**< 2.2 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V24, /**< 2.4 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V26, /**< 2.6 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V27, /**< 2.7 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V28 /**< 2.8 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. + @note The SoftDevice will automatically turn on and off the external crystal, + at the beginning and end of the timeslot, respectively. The crystal may also + intentionally be left running after the timeslot, in cases where it is needed + by the SoftDevice shortly after the end of the timeslot. */ + 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 activities 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 const * p_key; /**< Pointer to the Encryption key. */ + soc_ecb_cleartext_t const * 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 Writes the NRF_POWER->RAM[index].POWERSET register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERSET register to write to. + * @param[in] ram_powerset Contains the word to write to the NRF_POWER->RAM[index].POWERSET register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_SET, uint32_t, sd_power_ram_power_set(uint8_t index, uint32_t ram_powerset)); + +/**@brief Writes the NRF_POWER->RAM[index].POWERCLR register. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWERCLR register to write to. + * @param[in] ram_powerclr Contains the word to write to the NRF_POWER->RAM[index].POWERCLR register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_CLR, uint32_t, sd_power_ram_power_clr(uint8_t index, uint32_t ram_powerclr)); + +/**@brief Get contents of NRF_POWER->RAM[index].POWER register, indicates power status of RAM[index] blocks. + * + * @param[in] index Contains the index in the NRF_POWER->RAM[index].POWER register to read from. + * @param[out] p_ram_power Content of NRF_POWER->RAM[index].POWER register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAM_POWER_GET, uint32_t, sd_power_ram_power_get(uint8_t index, uint32_t * p_ram_power)); + +/**@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 + * main thread. 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, the radio + * notifications must be configured 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_ERROR_INVALID_STATE A protocol stack or other SoftDevice is running. Stop all + * running activities and retry. + * @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 50 us 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 * p_dst, uint32_t 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 Page number 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 100 ms 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 const * p_request)); + +/**@} */ + +#ifdef __cplusplus +} +#endif +#endif // NRF_SOC_H__ + +/**@} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_svc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_svc.h new file mode 100644 index 0000000000..31ea671529 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/headers/nrf_svc.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 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 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 other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. This software must only be used in a processor manufactured by Nordic + * Semiconductor ASA, or in a processor manufactured by a third party that + * is used in combination with a processor manufactured by Nordic Semiconductor. + * + * + * 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__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt new file mode 100644 index 0000000000..b8d26c9a84 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_licence-agreement.txt @@ -0,0 +1,96 @@ +S110/S120/S130/S132/S140 license agreement + + +NORDIC SEMICONDUCTOR ASA SOFTDEVICE LICENSE AGREEMENT + +License Agreement for the Nordic Semiconductor ASA ("Nordic") S110, S120, S130, S132, and S140 Bluetooth SoftDevice software packages +("SoftDevice"). + +You ("You" "Licensee") must carefully and thoroughly read this License Agreement ("Agreement"), and accept to adhere to this Agreement before +downloading, installing and/or using any software or content in the SoftDevice provided herewith. + +YOU ACCEPT THIS LICENSE AGREEMENT BY (A) CLICKING ACCEPT OR AGREE TO THIS LICENSE AGREEMENT, WHERE THIS +OPTION IS MADE AVAILABLE TO YOU; OR (B) BY ACTUALLY USING THE SOFTDEVICE, IN THIS CASE YOU AGREE THAT THE USE OF +THE SOFTDEVICE CONSTITUTES ACCEPTANCE OF THE LICENSING AGREEMENT FROM THAT POINT ONWARDS. + +IF YOU DO NOT AGREE TO BE BOUND BY THE TERMS OF THIS AGREEMENT, THEN DO NOT DOWNLOAD, INSTALL/COMPLETE +INSTALLATION OF, OR IN ANY OTHER WAY MAKE USE OF THE SOFTDEVICE. + +1. Grant of License +Subject to the terms in this Agreement Nordic grants Licensee a limited, non-exclusive, non-transferable, non-sub licensable, revocable license +("License"): (a) to use the SoftDevice solely in connection with a Nordic integrated circuit, and (b) to distribute the SoftDevice solely as integrated +in Licensee Product. Licensee shall not use the SoftDevice for any purpose other than specifically authorized herein. It is a material breach of this +agreement to use or modify the SoftDevice for use on any wireless connectivity integrated circuit other than a Nordic integrated circuit. + +2. Title +Nordic retains full rights, title, and ownership to the SoftDevice and any and all patents, copyrights, trade secrets, trade names, trademarks, and +other intellectual property rights in and to the SoftDevice. + +3. No Modifications or Reverse Engineering +Licensee shall not, modify, reverse engineer, disassemble, decompile or otherwise attempt to discover the source code of any non-source code +parts of the SoftDevice including, but not limited to pre-compiled hex files, binaries and object code. + +4. Distribution Restrictions +Except as set forward in Section 1 above, the Licensee may not disclose or distribute any or all parts of the SoftDevice to any third party. +Licensee agrees to provide reasonable security precautions to prevent unauthorized access to or use of the SoftDevice as proscribed herein. +Licensee also agrees that use of and access to the SoftDevice will be strictly limited to the employees and subcontractors of the Licensee +necessary for the performance of development, verification and production tasks under this Agreement. The Licensee is responsible for making +such employees and subcontractors comply with the obligations concerning use and non-disclosure of the SoftDevice. + +5. No Other Rights +Licensee shall use the SoftDevice only in compliance with this Agreement and shall refrain from using the SoftDevice in any way that may be +contrary to this Agreement. + +6. Fees +Nordic grants the License to the Licensee free of charge provided that the Licensee undertakes the obligations in the Agreement and warrants to +comply with the Agreement. + +7. DISCLAIMER OF WARRANTY +THE SOFTDEVICE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EXPRESS OR IMPLIED AND NEITHER NORDIC, ITS +LICENSORS OR AFFILIATES NOR THE COPYRIGHT HOLDERS MAKE ANY REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR +THAT THE SOFTDEVICE WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. THERE +IS NO WARRANTY BY NORDIC OR BY ANY OTHER PARTY THAT THE FUNCTIONS CONTAINED IN THE SOFTDEVICE WILL MEET THE +REQUIREMENTS OF LICENSEE OR THAT THE OPERATION OF THE SOFTDEVICE WILL BE UNINTERRUPTED OR ERROR-FREE. +LICENSEE ASSUMES ALL RESPONSIBILITY AND RISK FOR THE SELECTION OF THE SOFTDEVICE TO ACHIEVE LICENSEES +INTENDED RESULTS AND FOR THE INSTALLATION, USE AND RESULTS OBTAINED FROM IT. + + +8. No Support +Nordic is not obligated to furnish or make available to Licensee any further information, software, technical information, know-how, show-how, +bug-fixes or support. Nordic reserves the right to make changes to the SoftDevice without further notice. + +9. Limitation of Liability +In no event shall Nordic, its employees or suppliers, licensors or affiliates be liable for any lost profits, revenue, sales, data or costs of +procurement of substitute goods or services, property damage, personal injury, interruption of business, loss of business information or for any +special, direct, indirect, incidental, economic, punitive, special or consequential damages, however caused and whether arising under contract, +tort, negligence, or other theory of liability arising out of the use of or inability to use the SoftDevice, even if Nordic or its employees or suppliers, +licensors or affiliates are advised of the possibility of such damages. Because some countries/states/jurisdictions do not allow the exclusion or +limitation of liability, but may allow liability to be limited, in such cases, Nordic, its employees or licensors or affiliates liability shall be limited to +USD 50. + +10. Breach of Contract +Upon a breach of contract by the Licensee, Nordic and its licensor are entitled to damages in respect of any direct loss which can be reasonably +attributed to the breach by the Licensee. If the Licensee has acted with gross negligence or willful misconduct, the Licensee shall cover both +direct and indirect costs for Nordic and its licensors. + +11. Indemnity +Licensee undertakes to indemnify, hold harmless and defend Nordic and its directors, officers, affiliates, shareholders, licensors, employees and +agents from and against any claims or lawsuits, including attorney's fees, that arise or result of the Licensees execution of the License and which +is not due to causes for which Nordic is responsible. + +12. Governing Law +This Agreement shall be construed according to the laws of Norway, and hereby submits to the exclusive jurisdiction of the Oslo tingrett. + +13. Assignment +Licensee shall not assign this Agreement or any rights or obligations hereunder without the prior written consent of Nordic. + +14. Termination +Without prejudice to any other rights, Nordic may cancel this Agreement if Licensee does not abide by the terms and conditions of this +Agreement. Upon termination Licensee must promptly cease the use of the License and destroy all copies of the Licensed Technology and any +other material provided by Nordic or its affiliate, or produced by the Licensee in connection with the Agreement or the Licensed Technology. + +15. Third party beneficiaries +Nordics licensors are intended third party beneficiaries under this Agreement. + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_softdevice.hex b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_softdevice.hex new file mode 100644 index 0000000000..a45fac6daa --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/hex/s140_nrf52840_5.0.0-2.alpha_softdevice.hex @@ -0,0 +1,8363 @@ +:020000040000FA +:1000000000040020E508000079050000C508000094 +:10001000830500008D05000097050000000000002A +:1000200000000000000000000000000009090000BE +:10003000A105000000000000AB050000B5050000B0 +:10004000BF050000C9050000D3050000DD05000064 +:10005000E7050000F1050000FB05000005060000B3 +:100060000F06000019060000230600002D06000000 +:1000700037060000410600004B0600005506000050 +:100080005F06000069060000730600007D060000A0 +:1000900087060000910600009B060000A5060000F0 +:1000A000AF060000B9060000C3060000CD06000040 +:1000B000D7060000E1060000EB060000F506000090 +:1000C000FF06000009070000130700001D070000DD +:1000D00027070000310700003B070000450700002C +:1000E0004F07000059070000630700006D0700007C +:1000F00077070000810700008B07000095070000CC +:100100009F0700001FB500F003F88DE80F001FBD2A +:1001100000F0DEBB1FB56FF00100009040100390AF +:10012000029001904FF010208069000B420900F00E +:100130001F045DF822300120A04083434DF8223097 +:10014000684600F044F91FBDF0B54FF6FF734FF459 +:10015000B4751A466E1E11E0A94201D3344600E080 +:100160000C46091B30F8027B641E3B441A44F9D14B +:100170009CB204EB134394B204EB12420029EBD17E +:1001800098B200EB134002EB124140EA0140F0BD8F +:10019000DD4992B00446D1E90001CDE91001FF220A +:1001A0004021684600F03AFB94E80F008DE80F000C +:1001B000684610A902E004C841F8042D8842FAD12B +:1001C00010216846FFF7C0FF1090AA208DF8440068 +:1001D000FFF7A0FF00F0F2F84FF01024A069102202 +:1001E0006946803000F001F9A069082210A900F0EA +:1001F000FCF800F0D7F84FF080510A6949690068AF +:100200004A43824201D8102070470020704710B541 +:10021000D0E900214FF0805002EB8103026944696C +:100220006243934209D84FF01022536903EB8103D4 +:100230000169406941438B4201D9092010BD5069D1 +:10024000401C01D0002010BD0F2010BD70B501680A +:100250000446AE4D4FF01020062951D2DFE801F0E0 +:10026000320318283B1DD4E90265646829463046EC +:1002700000F0CDF82A462146304600F0B6F8AA0034 +:100280002146304600F09EFA002800D0032070BDC1 +:1002900000F050FB4FF4805007E0201DFFF7ABFF4C +:1002A0000028F4D100F046FB60682860002070BD93 +:1002B000241D94E80700920000F084FA0028F6D08C +:1002C0000E2070BD8069401C12D0201DFFF79FFFDB +:1002D0000028F6D109E08069401C09D0201DFFF7F5 +:1002E0008AFF0028EDD1606820B12046FFF750FF5B +:1002F000042070BDFFF70EFF00F060F800F052F828 +:10030000072070BD10B50C46182802D001200860E7 +:1003100010BD2068FFF79AFF206010BD4FF0102439 +:10032000A069401C05D0A569A66980353079AA2846 +:1003300008D06069401C2DD060690068401C29D03D +:1003400060692CE010212846FFF7FEFE31688142EB +:100350001CD1A16901F18002C03105E030B108CAA9 +:1003600051F8040D984201D1012000E000208A429A +:10037000F4D158B1286810B1042803D0FEE728460C +:1003800000F057F861496868086008E000F016F866 +:1003900000F008F84FF480500168491C01D000F0CB +:1003A000A3FAFEE7BFF34F8F59480168594A01F499 +:1003B000E06111430160BFF34F8FFEE74FF0102063 +:1003C0008169491C02D0806900F0ADB87047524A7B +:1003D00001681160121D416811604F4A8168103236 +:1003E0001160111DC068086070472DE9F041174683 +:1003F0000D460646002406E03046296800F0A6F8BF +:10040000641C2D1D361DBC42F6D3BDE8F08170B5CD +:100410000C4605464FF4806608E0284600F083F855 +:10042000B44205D3A4F5806405F58055002CF4D1C1 +:1004300070BD4168044609B1012500E000254FF078 +:1004400010267069A268920000F0BCF9C8B120467D +:1004500000F01AF89DB17669A56864684FF4002031 +:1004600084420AD2854208D229463046FFF7CFFFA0 +:100470002A4621463046FFF7B8FFFFF79FFFFFF7F8 +:1004800091FFFFF747FEF8E72DE9FF414FF01024F9 +:10049000616980680D0B01EB800000F6FF70010BB5 +:1004A00000200090019002900246039068460123CC +:1004B0000BE0560902F01F0C50F8267003FA0CFCF2 +:1004C00047EA0C0740F82670521CAA42F1D30AE012 +:1004D0004A0901F01F0650F8225003FA06F6354388 +:1004E00040F82250491C8029F2D3A169090B4A091E +:1004F00001F01F0150F822408B409C4340F82240FD +:10050000FFF765FFBDE8FF815809000000000020EB +:100510000CED00E00400FA050006004014480168F4 +:100520000029FCD07047134A0221116010490B6862 +:10053000002BFCD00F4B1B1D186008680028FCD056 +:100540000020106008680028FCD07047094B10B5E7 +:1005500001221A60064A1468002CFCD00160106861 +:100560000028FCD00020186010680028FCD010BDC6 +:1005700000E4014004E5014008208F49096809585A +:10058000084710208C4909680958084714208A49EF +:100590000968095808471820874909680958084711 +:1005A0003020854909680958084738208249096878 +:1005B000095808473C2080490968095808474020E5 +:1005C0007D4909680958084744207B49096809584A +:1005D0000847482078490968095808474C20764957 +:1005E000096809580847502073490968095808479D +:1005F0005420714909680958084758206E4909680C +:10060000095808475C206C49096809580847602068 +:100610006949096809580847642067490968095801 +:100620000847682064490968095808476C206249EE +:1006300009680958084770205F4909680958084740 +:1006400074205D4909680958084778205A490968A3 +:10065000095808477C2058490968095808478020EC +:1006600055490968095808478420534909680958B9 +:100670000847882050490968095808478C204E4986 +:1006800009680958084790204B49096809580847E4 +:10069000942049490968095808479820464909683B +:1006A000095808479C204449096809580847A02070 +:1006B0004149096809580847A4203F490968095871 +:1006C0000847A8203C49096809580847AC203A491E +:1006D000096809580847B020374909680958084788 +:1006E000B4203549096809580847B82032490968D3 +:1006F00009580847BC203049096809580847C020F4 +:100700002D49096809580847C4202B490968095828 +:100710000847C8202849096809580847CC202649B5 +:10072000096809580847D02023490968095808472B +:10073000D4202149096809580847D8201E4909686A +:1007400009580847DC201C49096809580847E02077 +:100750001949096809580847E420174909680958E0 +:100760000847E8201449096809580847EC2012494D +:10077000096809580847F0200F49096809580847CF +:10078000F4200D49096809580847F8200A49096802 +:1007900009580847FC2008490968095808475FF4C8 +:1007A0008070054909680958084700000348044952 +:1007B000024A034B70470000000000206809000057 +:1007C0006809000040EA010310B59B070FD1042A15 +:1007D0000DD310C808C9121F9C42F8D020BA19BA0C +:1007E000884201D9012010BD4FF0FF3010BD1AB171 +:1007F000D30703D0521C07E0002010BD10F8013BC6 +:1008000011F8014B1B1B07D110F8013B11F8014BEC +:100810001B1B01D1921EF1D1184610BD02F0FF033F +:1008200043EA032242EA024200F005B870477047EB +:1008300070474FF000020429C0F0128010F0030C42 +:1008400000F01B80CCF1040CBCF1020F18BF00F8C3 +:10085000012BA8BF20F8022BA1EB0C0100F00DB872 +:100860005FEAC17C24BF00F8012B00F8012B48BFD0 +:1008700000F8012B70474FF0000200B51346944674 +:100880009646203922BFA0E80C50A0E80C50B1F1E8 +:100890002001BFF4F7AF090728BFA0E80C5048BFFC +:1008A0000CC05DF804EB890028BF40F8042B08BF9A +:1008B000704748BF20F8022B11F0804F18BF00F896 +:1008C000012B7047014B1B68DB68184700000020B4 +:1008D00009480A497047FFF7FBFFFFF713FC00BD0B +:1008E00020BFFDE7064B1847064A1060016881F3F8 +:1008F0000888406800470000680900006809000097 +:100900001D030000000000201EF0040F0CBFEFF3D9 +:100910000881EFF30981886902380078182803D12B +:1009200000E00000074A1047074A12682C3212689C +:100930001047000000B5054B1B68054A9B589847B7 +:1009400000BD000005030000000000205409000065 +:1009500004000000001000000000000000FFFFFF86 +:040960000090D00330 +:101000009012002091090200452F0000FF08020005 +:10101000452F0000452F0000452F00000000000074 +:10102000000000000000000000000000E9090200CC +:10103000452F000000000000452F0000452F000054 +:10104000510A0200570A0200452F0000452F0000F8 +:10105000452F0000452F0000452F0000452F0000C0 +:101060005D0A0200452F0000452F0000630A0200C0 +:10107000452F0000690A02006F0A0200750A02008B +:10108000452F0000452F0000452F0000452F000090 +:10109000452F0000452F0000452F0000452F000080 +:1010A000452F00007B0A0200452F0000452F00005D +:1010B000452F0000452F0000452F0000452F000060 +:1010C000810A0200452F0000452F0000452F000037 +:1010D000452F0000452F0000452F0000452F000040 +:1010E000452F0000452F0000452F0000452F000030 +:1010F000452F0000452F0000452F0000452F000020 +:10110000452F0000452F000000F002F81FF02DFCD5 +:101110000AA090E8000C82448344AAF10107DA4552 +:1011200001D11FF022FCAFF2090EBAE80F0013F054 +:10113000010F18BFFB1A43F0010318476CFF0100B1 +:101140008CFF01000A4410F8014B14F00F0508BF92 +:1011500010F8015B240908BF10F8014B6D1E05D083 +:1011600010F8013B6D1E01F8013BF9D1641E03D05C +:10117000641E01F8015BFBD19142E4D3704700008B +:101180000023002400250026103A28BF78C1FBD890 +:10119000520728BF30C148BF0B6070471FB500F031 +:1011A0003DF88DE80F001FBD1EF0040F0CBFEFF3DC +:1011B0000880EFF30980014A104700009F2E0000CD +:1011C0008269034981614FF00100104470470000BB +:1011D000D511000001B41EB400B511F0BFFC01B47C +:1011E0000198864601BC01B01EBD0000F0B4404627 +:1011F000494652465B460FB402A0013001B506488D +:10120000004700BF01BC86460FBC80468946924617 +:101210009B46F0BC70470000091100001FF0A2BB04 +:1012200070B51A4C054609202070A01C00F05FF82C +:101230005920A08029462046BDE8704008F0B2B889 +:1012400008F0BBB870B50C461149097829B1A0F176 +:101250006001512908D3012013E0602804D06928D7 +:1012600002D043F201000CE020CC0A4E94E80E00BC +:1012700006EB8000A0F58050241FD0F8806E284631 +:10128000B047206070BD01207047000008000020BA +:101290001C000020CC0A020010B5044600210120E9 +:1012A00000F03BF800210B2000F037F80421192052 +:1012B00000F033F804210D2000F02FF804210E2057 +:1012C00000F02BF804210F2000F027F80421C84378 +:1012D00000F023F80721162000F01FF80721152041 +:1012E00000F01BF82046FFF79BFF002010BD962161 +:1012F00001807047FFF7A4BF10487047104A10B52F +:1013000014680F4B0F4A08331A60FFF79BFF0C4815 +:10131000001D046010BD704770474907090E002882 +:1013200006DA00F00F0000F1E02080F8141D70478D +:1013300000F1E02080F800147047000003F900423B +:101340001005024001000001FE48002101604160DB +:10135000018170472DE9F743044692B091464068F9 +:1013600011F0B0FE40B1606811F0B5FE20B96078B0 +:1013700000F00300022801D0012000E00020F14E1F +:101380004D463072484611F059FE18B1102015B084 +:10139000BDE8F0832946012001F02EFF0028F6D198 +:1013A00001258DF842504FF4C050ADF840000022A6 +:1013B00010A9284606F09BFC0028E8D18DF8425081 +:1013C0004FF428504FF00008ADF8400047461C216C +:1013D0006846CDF81C801FF06AFA9DF81C0008AA28 +:1013E00020F00F00401C20F0F00010308DF81C00A1 +:1013F00020788DF81D0061789DF81E0061F3420091 +:1014000040F001008DF81E009DF800000AA940F090 +:1014100002008DF800002089ADF83000ADF8327080 +:10142000608907AFADF834000B97606810AC0E9080 +:101430000A94684606F04EFA0028A8D1BDF82000AC +:1014400030808DF8425042F60120ADF840009DF802 +:101450001E0008AA20F00600801C20F001008DF874 +:101460001E000220ADF83000ADF8340013A80E9035 +:101470000AA9684606F02EFA002888D1BDF8200097 +:101480007080311D484600F033F9002887D18DF86F +:10149000425042F6A620ADF840001C216846CDF827 +:1014A0001C801FF004FA9DF81C00ADF8345020F0A9 +:1014B0000F00401C20F0F00010308DF81C009DF84B +:1014C0001D0008AA20F0FF008DF81D009DF81E00E9 +:1014D0000AA920F0060040F00100801C8DF81E00D3 +:1014E0009DF800008DF8445040F002008DF8000097 +:1014F000CDE90A4711A80E90ADF83050684606F0C5 +:10150000E9F9002899D1BDF82000F08000203EE7DD +:101510003EB504460820ADF80000204611F08EFDCF +:1015200008B110203EBD2146012001F065FE0028D3 +:10153000F8D12088ADF804006088ADF80600A088D6 +:10154000ADF80800E088ADF80A007E4801AB6A46B5 +:101550008088002106F0C8FDBDF800100829E1D000 +:1015600003203EBD1FB50446002002900820ADF8C0 +:101570000800CDF80CD0204611F060FD10B110200D +:1015800004B010BD6F4802AA81884FF6FF7007F0C3 +:1015900047F80028F4D1BDF80810082901D003202D +:1015A000EEE7BDF800102180BDF802106180BDF8A3 +:1015B0000410A180BDF80610E180E1E701B582B01A +:1015C0000220ADF800005F4802AB6A464088002167 +:1015D00006F08AFDBDF80010022900D003200EBDE0 +:1015E0001CB5002100910221ADF80010019011F00E +:1015F0004BFD08B110201CBD52486A4641884FF689 +:10160000FF7007F00DF8BDF800100229F3D0032099 +:101610001CBDFEB54B4C06461546207A0F46C0074A +:1016200005D0084611F00AFD18B11020FEBD0F20AC +:10163000FEBDF82D01D90C20FEBD304611F0FEFC98 +:1016400018BB208801A905F04AFE0028F4D13078A3 +:101650008DF80500208801A906F024FD0028EBD1B3 +:1016600000909DF800009DF8051040F002008DF8F4 +:101670000000090703D040F008008DF80000208822 +:10168000694606F0ACFC0028D6D1ADF80850208899 +:101690003B4602AA002106F027FDBDF80810A9422A +:1016A000CAD00320FEBD7CB5054600200090019005 +:1016B0000888ADF800000C462846019511F002FD9F +:1016C00018B9204611F0E0FC08B110207CBD15B11E +:1016D000BDF8000050B11B486A4601884FF6FF7004 +:1016E00006F09EFFBDF8001021807CBD0C207CBD63 +:1016F00030B593B0044600200D460090142101A897 +:101700001FF0D5F81C2108A81FF0D1F89DF80000A3 +:10171000CDF808D020F00F00401C20F0F000103071 +:101720008DF800009DF8010020F0FF008DF8010009 +:101730009DF8200040F002008DF8200001208DF877 +:10174000460001E0CE01002042F60420ADF844003E +:1017500011A801902088ADF83C006088ADF83E00EB +:10176000A088ADF84000E088ADF842009DF8020086 +:1017700006AA20F00600801C20F001008DF802006F +:101780000820ADF80C00ADF810000FA8059001A9D5 +:1017900008A806F09FF8002803D1BDF8180028809B +:1017A000002013B030BD0000F0B5007B059F1E4641 +:1017B00014460D46012800D0FFDF0C2030803A206F +:1017C0003880002C08D0287A052806D0287B0128EC +:1017D00000D0FFDF17206081F0BDA889FBE72DE96D +:1017E000F04786B0144691F80C900E9A0D46B9F168 +:1017F000010F0BD01021007B2E8A8846052807D0C8 +:10180000062833D0FFDF06B0BDE8F0870221F2E7FB +:10181000E8890C2100EB400001EB400018803320E8 +:101820001080002CEFD0E889608100271AE0009634 +:10183000688808F1020301AA696900F0B2FF06EBAB +:101840000800801C07EB470186B204EB4102BDF89B +:10185000040090810DF1060140460E320FF09AFD12 +:101860007F1CBFB26089B842E1D8CCE73420108039 +:10187000E889B9F1010F11D0122148430E301880C8 +:10188000002CC0D0E88960814846B9F1010F00D032 +:101890000220207300270DF1040A1FE00621ECE767 +:1018A0000096688808F1020301AA696900F079FFCF +:1018B00006EB0800801C86B2B9F1010F12D007EBCD +:1018C000C70004EB4000BDF80410C18110220AF1EA +:1018D000020110301EF052FF7F1CBFB26089B84277 +:1018E000DED890E707EB470104EB4102BDF80400A6 +:1018F000D0810AF10201404610320FF04BFDEBE7B8 +:101900002DE9F0470E4688B090F80CC096F80C8090 +:10191000378AF5890C20109902F10C044FF0000A67 +:10192000BCF1030F08D0BCF1040F3ED0BCF1070F8F +:101930007DD0FFDF08B067E705EB850C00EB4C00BE +:10194000188031200880002AF4D0A8F1060000F0A9 +:10195000FF09558125E0182101A81EF0A8FF009776 +:101960007088434601AA716900F01BFFBDF80400AE +:101970002080BDF80600E080BDF808002081A21C90 +:101980000DF10A0148460FF005FDB9F1000F00D036 +:1019900018B184F804A0A4F802A007EB080087B2ED +:1019A0000A346D1EADB2D6D2C4E705EB850C00EB50 +:1019B0004C00188032200880002ABBD0A8F1050016 +:1019C00000F0FF09558137E000977088434601AA6F +:1019D000716900F0E6FE9DF80600BDF80410E18094 +:1019E0002179420860F3000162F34101820862F349 +:1019F0008201C20862F3C301020962F304114209C1 +:101A000062F34511820962F386112171C009607188 +:101A1000BDF80700208122460DF1090148460FF06C +:101A2000B9FC18B184F802A0A4F800A000E007E017 +:101A300007EB080087B20A346D1EADB2C4D279E755 +:101A4000A8F1020084B205FB08F000F10E0CA3F827 +:101A500000C035230B80002AA6D0558194810097C1 +:101A600083B270880E32716900F09BFE62E72DE947 +:101A7000F84F1E460A9D0C4681462AB1607A00F551 +:101A80008070D080E089108199F80C000C274FF00D +:101A900000084FF00E0A0D2873D2DFE800F09E0711 +:101AA0000E1C28303846556A737373002146484629 +:101AB0000095FFF779FEBDE8F88F207B9146082856 +:101AC00002D0032800D0FFDF378030200AE000BFBB +:101AD000A9F80A80EFE7207B9146042800D0FFDFB9 +:101AE000378031202880B9F1000FF1D1E3E7207B66 +:101AF0009146042800D0FFDF37803220F2E7207BB8 +:101B00009146022800D0FFDF37803320EAE7207BB0 +:101B10001746022800D0FFDF3420A6F800A0288056 +:101B2000002FC8D0A7F80A80C5E7207B17460428F5 +:101B300000D0FFDF3520A6F800A02880002FBAD003 +:101B40004046A7F80A8012E0207B1746052802D0FD +:101B5000062800D0FFDF1020308036202880002F9C +:101B6000A9D0E0897881A7F80E80B9F80E00B88175 +:101B7000A1E7207B9146072800D0FFDF3780372080 +:101B8000B0E72AE04FF0120018804FF0380017003D +:101B9000288090D0E0897881A7F80E80A7F810807F +:101BA00099F80C000A2805D00B2809D00C280DD074 +:101BB000FFDF80E7207B0C2800D0FFDF01200AE058 +:101BC000207B0D2800D0FFDF042004E0207B0E28BE +:101BD00000D0FFDF052038736DE7FFDF6BE770B5DE +:101BE0000C46054601F07BFA20B10078222804D289 +:101BF000082070BD43F2020070BD052128460DF09B +:101C000059FF206008B1002070BD032070BD38B5B9 +:101C10000546DDE905011446049A72B10B460090B1 +:101C20000422214628460AF0CFFE032C06D1214685 +:101C30002846BDE838400BF097B8198038BD2DE92B +:101C4000FF4F85B0002003900898904689461230D7 +:101C500008F061FB401D20F00306089828B908A988 +:101C60000598FFF7BCFF002861D1B9F1000F06D03D +:101C70000898017B00295FD10525046829E098F8C0 +:101C80000000092803D00F2820D0FFDF54E0089A75 +:101C900003255168527B48887243824246D901F13C +:101CA000040B098897B20C181FFA86FABC4200D3BD +:101CB000E41B5044B84200D9FFDF04EB0A00B842ED +:101CC00000D9FFDF5C440020208002E0089C04254E +:101CD00008340CB1208810B1032D27D02CE00898CF +:101CE0000121123008F04FFBADF81000024603ABA3 +:101CF000294605980AF059FD070001D1A01C039060 +:101D000008983A461230C8F804000598A8F802006E +:101D100004A94046039B08F043FBC0B1072814D236 +:101D2000DFE800F0080A1313110C0E00132009B0AD +:101D3000BDE8F08F0020FAE71120F8E70820F6E769 +:101D400043F20300F3E70720F1E70320EFE7BDF8D4 +:101D5000100003990097CDE9011023462A460899FF +:101D60000598FFF754FFC7B9032D16D10898B7B2ED +:101D70004568407B704384B2298868880E18A64263 +:101D800000D3361B3844A04200D9FFDFF019A0422F +:101D900000D9FFDF688838446880B9F1000FC9D0E6 +:101DA000089981F80C90C5E72DE9FF4791461A88FC +:101DB0001C468A4680460AB303AB49460AF0F5FC46 +:101DC00005001BD04046A61C27880DF090FF324628 +:101DD000072629463B4600960DF016FC20880399FD +:101DE0000095CDE9011023464A4651464046FFF78B +:101DF0000EFF00202080012004B005E50020FBE755 +:101E000010B586B01C46AAB104238DF800301388A3 +:101E1000ADF808305288ADF80A208A788DF80E2087 +:101E20000988ADF80C1000236A462146FFF707FF2A +:101E300006B010BD1020FBE770B50D4605210DF072 +:101E400039FE040000D1FFDF294604F11200BDE88D +:101E5000704008F081BA2DE9F8430D46804600260F +:101E600007F053FB0446287812287BD2DFE800F005 +:101E70007A54543C355632321332323209323232CD +:101E800032322879001FC0B2022801D0102810D1A8 +:101E900014BBFFDF35E004B9FFDF052140460DF03C +:101EA00009FE007B032806D004280BD0072828D081 +:101EB000FFDF072657E02879801FC0B2022820D014 +:101EC00050B1F6E72879401FC0B2022819D0102877 +:101ED00017D0EEE704B9FFDF13E004B9FFDF28797C +:101EE00001280ED1172139E0052140460DF0E2FD11 +:101EF000070000D1FFDF07F11201404608F003FAA6 +:101F00002CB12A462146404600F05BFC2BE0132111 +:101F1000404602F08AFC26E0FFDF24E004B9FFDF40 +:101F2000052140460DF0C6FD060000D1FFDF6946E1 +:101F300006F1120008F0F1F9060000D0FFDFA988D1 +:101F4000172901D2172200E00A46BDF8000082429C +:101F500002D9014602E005E01729C3D3404600F04C +:101F600046FCCEE7FFDF3046BDE8F883401D20F099 +:101F70000300021D01FB0020704708B1FE4A1060FB +:101F80000CF041BF2DE9F0470E461546242130469E +:101F90001EF08DFC05B9FFDFA87870732888DFF884 +:101FA000D8A3401D20F0030195F802900C46DAF802 +:101FB00000000CF03FFF070000D1FFDF4FF00008EA +:101FC0003760A7F8008004FB09F4211DDAF800004F +:101FD0000CF030FF040000D1FFDF7460C4F8008013 +:101FE000298806F11200BDE8F04708F07EB92DE916 +:101FF000F047804601F112000D46814608F08BF94A +:10200000401DDD4E20F003046F7B224629683068B6 +:102010000CF039FF7C43221D696830680CF033FFF7 +:1020200005200DF0F1FC044605200DF0F5FC201A0A +:10203000012802D130680CF0EEFE49464046BDE86A +:10204000F04708F067B970B5054605210DF032FD7F +:10205000040000D1FFDF04F112012846BDE8704002 +:1020600008F051B92DE9F04F91B04FF0000BADF8E9 +:1020700034B0ADF804B047880C46054692460521B9 +:1020800038460DF017FD060000D1FFDF24B1A78010 +:10209000A4F806B0A4F808B0297809220B20B2EB06 +:1020A000111F297A7DD104F110023827C91E4FF083 +:1020B0000C094FF0010803920F2973D2DFE801F0F9 +:1020C000F4F3F28108D48A8FA13DDDF5F0B8B800B1 +:1020D000307B022800D0FFDFA88909EBC001ADF8F2 +:1020E00004103021ADF83410002C25D06081B5F8F3 +:1020F0000E9000271DE004EBC708317C88F80E1015 +:10210000F189A8F80C10CDF800906888042304AA7F +:10211000296900F046FBBDF81010A8F8101009F16D +:102120000400BDF812107F1C1FFA80F9A8F81210E5 +:10213000BFB26089B842DED80CE1307B022800D003 +:10214000FFDFE98909EBC100ADF804003020ADF8EC +:102150003400287B0A90001FC0B20F90002CEBD0F7 +:102160006181B5F81090002727E000BFCDF80090FE +:102170006888696903AA0A9B00F013FB0A9904EBBB +:10218000C70809EB01001FFA80F908F10C0204A945 +:102190000F980FF0FFF818B188F80EB0A8F80CB03F +:1021A00001E0D4E0D1E0BDF80C10A8F81010BDF8A3 +:1021B0000E107F1CA8F81210BFB26089B842D5D8A3 +:1021C000C8E00DA8009001AB224629463046FFF733 +:1021D00006FBBFE0307B082805D0FFDF03E0307B43 +:1021E000082800D0FFDFE8891030ADF80400362061 +:1021F000ADF83400002C3FD0A9896181F189A1811B +:1022000027E0307B092800D0FFDFA88900F10C010E +:10221000ADF804103721ADF83410002C2CD06081BB +:10222000E8890090AB89688804F10C02296956E0BE +:10223000E8893921103080B2ADF80400ADF83410CF +:10224000002C74D0A9896181287A10280AD0022133 +:102250002173E989E181288A0090EB89688869699E +:10226000039A3CE00121F3E70DA8009001AB224660 +:1022700029463046FFF744FB6CE0307B0A2800D04B +:10228000FFDF1220ADF80400ADF834704CB3A9891B +:102290006181A4F810B0A4F80EB084F80C8059E065 +:1022A00020E002E031E039E042E0307B0B2800D052 +:1022B000FFDF288AADF834701230ADF8040084B125 +:1022C00004212173A9896181E989E181298A218217 +:1022D000688A00902B8A688804F11202696900F00C +:1022E00060FA37E0307B0C2800D0FFDF1220ADF819 +:1022F0000400ADF834703CB305212173A4F80AB092 +:10230000A4F80EB0A4F810B024E00DA8009001AB22 +:10231000224629463046FFF747FA1BE00DA80090F9 +:1023200001AB224629463046FFF7A1FB12E035E01B +:102330003B21ADF80400ADF834107CB3A4F806805E +:10234000A4F808B084F80AB004E0FFDF02E0012935 +:102350001BD0FFDFBDF80400AAF8000094B1BDF85F +:1023600034002080BDF804006080BDF834003928B6 +:1023700008D03B2806D001E0100000203C2801D006 +:1023800086F80CB0002011B0D2E43C21ADF8040076 +:10239000ADF8341014B1697AA172DBE7FFE7AAF84F +:1023A0000000EFE72DE9F84356880F4680461546B2 +:1023B000052130460DF07EFB040000D1FFDF123412 +:1023C00000943B46414630466A6808F0A3F9CBE5E5 +:1023D00070B50D4605210DF06DFB040000D1FFDF47 +:1023E000294604F11200BDE8704007F0A1BF70B5A6 +:1023F0000D4605210DF05EFB040000D1FFDF2946EC +:1024000004F11200BDE8704007F0C5BF70B5054685 +:1024100005210DF04FFB040000D1FFDF04F108039C +:1024200021462846BDE870400422BDE470B505464B +:1024300005210DF03FFB040000D1FFDF21462846B7 +:102440002368BDE870400522AEE42DE9F0478246DE +:1024500005210DF02FFB040000D1FFDF04F1120075 +:1024600007F059FF401D20F0030626E0011D0088FB +:102470000322431821465046FFF796FC002820D03F +:10248000607B656870431FFA80F82888B7B2814680 +:1024900010FA86F080B22880404502D3A0EB0800F5 +:1024A00028806888B84200D2FFDF09EB0701414568 +:1024B00000D9FFDF6888C01B6880606841880029F8 +:1024C000D4D1BDE8F08770B50E46054607F01DF87B +:1024D000040000D1FFDF0120207266726580207841 +:1024E00020F00F00C01C20F0F00030302070BDE85C +:1024F000704007F00DB82DE9F0438BB00D4614463F +:10250000814606A9FFF76BFB002814D14FF6FF7632 +:1025100001274FF420588CB103208DF800001020C3 +:10252000ADF8100007A8059007AA204604A90EF0F0 +:1025300050FF78B107200BB0BDE8F0830820ADF85C +:1025400008508DF80E708DF80000ADF80A60ADF8F7 +:102550000C800CE00698A17801742188C1818DF867 +:102560000E70ADF80850ADF80C80ADF80A606A4600 +:1025700002214846069BFFF762FBDCE708B5012213 +:102580008DF8022042F60202ADF800200A4603232D +:102590006946FFF735FC08BD08B501228DF8022019 +:1025A00042F60302ADF800200A4604236946FFF70D +:1025B00027FC08BD00B587B079B102228DF8002054 +:1025C0000A88ADF808204988ADF80A1000236A4649 +:1025D0000521FFF734FB07B000BD1020FBE709B170 +:1025E00007230DE40720704770B588B00D461446E8 +:1025F000064606A9FFF7F3FA00280ED17CB10620A3 +:10260000ADF808508DF80000ADF80A40069B6A4608 +:102610000821DC813046FFF712FB08B070BD0520B1 +:102620008DF80000ADF80850F0E700B587B059B15B +:1026300007238DF80030ADF80820039100236A4687 +:102640000921FFF7FCFAC6E71020C4E770B588B08F +:102650000C460646002506A9FFF7C1FA0028DCD182 +:1026600006980121123007F08EFE9CB121780629D0 +:1026700021D2DFE801F0200505160318801E80B284 +:10268000C01EE28880B20AB1A3681BB1824203D99E +:102690000C20C2E71020C0E7042904D0A08850B95C +:1026A00001E00620B9E7012913D0022905D0042949 +:1026B0001CD005292AD00720AFE709208DF800009B +:1026C0006088ADF80800E088ADF80A00A0680390C3 +:1026D00023E00C208DF800006088ADF80800E08849 +:1026E000ADF80A00A0680A25039016E00D208DF8C9 +:1026F00000006088ADF80800A088ADF80A00E08806 +:10270000ADF80C00A0680B25049006E00E208DF8B3 +:10271000000060788DF808000C256A46294630468E +:10272000069BFFF78CFA78E700B587B00F228DF88B +:102730000020ADF8081000236A461946FFF77FFA1B +:1027400049E700B587B071B102228DF800200A88F0 +:10275000ADF808204988ADF80A1000236A46062122 +:10276000FFF76DFA37E7102035E770B586B00646FB +:1027700001200D46ADF808108DF800000146002339 +:102780006A463046FFF75BFA040008D12946304616 +:1027900005F0C4FC0021304605F0DEFC204606B002 +:1027A00070BDF8B51C4615460E46069F0DF08DFA15 +:1027B0002346FF1DBCB231462A4600940CF0EBFEC6 +:1027C000F8BD10B548800878144620F00F00C01CF2 +:1027D00020F0F00090300B4608701822214603F1DB +:1027E00008001EF010F8BDE8104006F091BE70B56C +:1027F0000C460546FFF720FB2146284605F09DFCC8 +:102800002846BDE87040012105F0A6BC4FF0E0224B +:102810004FF400410020C2F880112049087020497F +:1028200090020860704730B51C4D04462878A042DD +:1028300018BF002C02D0002818BFFFDF2878A04264 +:1028400008BF30BD2C701749154A0020ECB1164D59 +:10285000DFF858C0131F012C0DD0022C1CBFFFDF66 +:1028600030BD086003200860CCF800504FF4000031 +:102870001060186030BD086002200860CCF800507D +:102880004FF040701060186030BD086008604FF075 +:102890006070106030BD00B5FFDF00BD1800002083 +:1028A00008F5014000F500401C03002014F500402D +:1028B00070B50B2000F0B5F9082000F0B2F9002146 +:1028C0000B2000F0C4F90021082000F0C0F9EC4C06 +:1028D00001256560A5600020C4F84001C4F84401EA +:1028E000C4F848010B2000F0A7F9082000F0A4F973 +:1028F0000B2000F08BF9256070BD10B50B2000F0A7 +:1029000090F9082000F08DF9DD48012141608160D7 +:10291000DC490A68002AFCD10021C0F84011C0F847 +:102920004411C0F848110B2000F086F9BDE81040B2 +:10293000082000F081B910B50B2000F07DF9BDE84A +:102940001040082000F078B900B530B1012806D059 +:10295000022806D0FFDF002000BDCB4800BDCB48D9 +:1029600000BDCA48001D00BD70B5C9494FF0004008 +:102970000860C84DC00BC5F80803C74800240460B0 +:10298000C5F840410820C43500F04BF9C5F83C417A +:10299000C248047070BD08B5B94A002128B10128A9 +:1029A00011D002281CD0FFDF08BD4FF48030C2F8E0 +:1029B0000803C2F84803B3483C300160C2F8401134 +:1029C000BDE80840D0E74FF40030C2F80803C2F871 +:1029D0004803AC4840300160C2F84411AB480CE0F9 +:1029E0004FF48020C2F80803C2F84803A5484430D9 +:1029F0000160C2F84811A548001D0068009008BD9C +:102A000070B516460D460446022800D9FFDF0022A5 +:102A10009B48012304F110018B4000EB8401C1F8B5 +:102A2000405526B1C1F84021C0F8043303E0C0F896 +:102A30000833C1F84021C0F8443370BD2DE9F0419E +:102A40001C46154630B1012834D0022839D0FFDFAA +:102A5000BDE8F081891E002221F07F411046FFF77A +:102A6000CFFF012C24D000208C4E8A4F012470709F +:102A70003C61894900203C3908600220091D08603A +:102A8000854904203039086083483D350560C7F822 +:102A90000042082000F0D0F82004C7F80403082002 +:102AA00000F0B4F87A49E007091F08603470CFE7F6 +:102AB0000120D9E7012B02D00022012005E00122EC +:102AC000FBE7012B04D000220220BDE8F04197E78C +:102AD0000122F9E76B480068704770B500F0C7F84D +:102AE000674C0546D4F840010026012809D1D4F8E6 +:102AF0000803C00305D54FF48030C4F80803C4F8B8 +:102B00004061D4F8440101280CD1D4F808038003B3 +:102B100008D54FF40030C4F80803C4F8446101201C +:102B20000FF0E6FAD4F8480101280CD1D4F80803D4 +:102B3000400308D54FF48020C4F80803C4F8486166 +:102B400002200FF0D5FA5648056070BD70B500F050 +:102B50008EF8524D0446287858B1FFF705FF687883 +:102B600020B1002085F801000FF0C2FA4C48046043 +:102B700070BD0320F8E74FF0E0214FF40010C1F8DA +:102B800000027047152000F057B842490120086143 +:102B9000082000F051B83F494FF47C10C1F80803F9 +:102BA0000020024601EB8003C3F84025C3F8402112 +:102BB000401CC0B20628F5D37047410A43F60952BB +:102BC0005143C0F3080010FB02F000F5807001EBE8 +:102BD0005020704710B5430B48F2376463431B0C19 +:102BE0005C020C602F4C03FB04002F4B4CF2F724CB +:102BF00043435B0D13FB04F404EB402000F58070AD +:102C00004012107008681844086010BD00F01F02E0 +:102C1000012191404009800000F1E020C0F800113E +:102C2000704700F01F02012191404009800000F12F +:102C3000E020C0F88011704700F01F020121914090 +:102C40004009800000F1E020C0F880127047490779 +:102C5000090E002806DA00F00F0000F1E02080F8ED +:102C6000141D704700F1E02080F8001470470C48F4 +:102C7000001F00680A4A0D49121D116070470000CC +:102C800000B0004004B500404081004044B1004025 +:102C900008F5014000800040408500402C000020E5 +:102CA00014050240F7C2FFFF6F0C01000100000194 +:102CB0000A4810B5046809490948083108600FF04E +:102CC000B4FA0648001D046010BD064900200860E3 +:102CD0004FF0E0210220C1F8800270471005024049 +:102CE00001000001FC1F004010B50D2000F06FF83E +:102CF000C4B26FF0040000F06AF8C0B2844200D0A1 +:102D0000FFDF3A490120086010BD70B50D2000F0CA +:102D100048F8374C0020C4F800010125C4F80453DA +:102D20000D2000F049F825604FF0E0216014C1F853 +:102D3000000170BD10B50D2000F033F82C480121C2 +:102D400041600021C0F80011BDE810400D2000F0E6 +:102D500033B8284810B50468264927480831086068 +:102D60002349D1F80001012804D0FFDF2148001DCC +:102D7000046010BD1D48001D00680022C0B2C1F8EB +:102D800000210FF024FEF1E710B51948D0F800112A +:102D90000029FBD0FFF7DDFFBDE810400D2000F05B +:102DA0000BB800F01F02012191404009800000F1A2 +:102DB000E020C0F88011704700F01F02012191400F +:102DC0004009800000F1E020C0F880127047002820 +:102DD00006DA00F00F0000F1E02090F8140D03E097 +:102DE00000F1E02090F800044009704704D500404D +:102DF00000D00040100502400100000110B5202065 +:102E000000F075F8202000F07DF84449202081F87A +:102E10000004434900060860091D42480860FEF7A7 +:102E20006BFA3F49C83108603F48D0F8041341F0BD +:102E30000101C0F80413D0F8041341F08071C0F808 +:102E40000413364901201C39C1F8000110BD10B52A +:102E5000202000F04CF8324800210160001D016084 +:102E60002F4A481EE83A10602F4AC2F808032C4B3C +:102E7000C8331960C2F80001C2F860012B4908602C +:102E8000BDE81040202000F03DB825492848EC3925 +:102E90000860704722492648E8390860704770B5D5 +:102EA0001F4A8069E83A224911601F49D1F8006140 +:102EB0000023204D1D4A5C1E1EB1A84206D30021EE +:102EC0000FE0D1F8606186B1A84209D2C1F80031A3 +:102ED000C1F860311460BDE87040202000F012B8E5 +:102EE0001168BDE870401DF009BDFFDF70BD00F046 +:102EF0001F02012191404009800000F1E020C0F84C +:102F00008011704700F01F020121914040098000AC +:102F100000F1E020C0F880127047000020E000E0DF +:102F2000000602400C130020000002400004024092 +:102F300001000001002002000F4A12680D498A4278 +:102F40000CD118470C4A12680A4B9A4206D101B5B7 +:102F50000FF0F6FDFFF799FFBDE80140074909684A +:102F60000958084706480749054A064B70470000BC +:102F700000000000BEBAFECAA0000020040000202D +:102F8000901200209012002070B50C46054607F004 +:102F90005EFD21462846BDE8704008F050BE10B5E1 +:102FA00010F01CFAFFF732FC10F0B4F8BDE8104046 +:102FB00010F066B90548064A0168914201D1002126 +:102FC000016004490120086070470000A000002053 +:102FD000BEBAFECA40E5014070477047704770476F +:102FE000704702F0FF0343EA032242EA02421DF067 +:102FF0003EBC7047704770477047000405060100EB +:1030000018FFFFFFDBE5B151002002009600FFFF33 +:10301000840000000000000030B5FE4D044610287A +:103020000AD0112C06D02846122CC17806D0132CB9 +:1030300008D0FFDFEC7030BDFFDFFBE71129F9D0CE +:10304000FFDFF7E71129F5D0FFDFF3E770B50EF0EA +:103050002BFB04460FF04AFB201AC4B206200CF0EA +:10306000D3FC054606200CF0D7FC2E1A07200CF0E6 +:10307000CBFC054607200CF0CFFCE649281A321895 +:10308000C87812280DD000231A4413280BD0002032 +:1030900002440878022808D000201044201AC0B248 +:1030A00070BD0123F0E70120F2E70120F5E7D948E0 +:1030B00000B58079D74942089BB051F8070F89883D +:1030C0000BD017220190ADF808108DF800200BA945 +:1030D000684609F053FA1BB000BD4622F2E7022110 +:1030E0000CF0E8BC2DE9F0419AB01D4690460E4622 +:1030F0000746FFF7F4FF04000BD02078222804D302 +:10310000A07FC0F34010A84206D108201AB0BDE845 +:10311000F08143F20200F9E74B208DF80000ADF892 +:1031200004703DB101208DF806008DF807608DF820 +:10313000088002E000208DF806000BA9684609F01F +:103140001DFAA07F65F34510A0770020DEE730B5BB +:103150000446A1F120000D460A284AD2DFE800F01B +:1031600005070C1C2328353A3F44FFDF42E0207856 +:1031700020283FD1FFDF3DE0A6480178032939D060 +:10318000C078132836D02078242833D0252831D091 +:1031900023282FD0FFDF2DE0207822282AD02328D3 +:1031A00028D8FFDF26E02078222823D0FFDF21E087 +:1031B000207822281ED024281CD026281AD0272880 +:1031C00018D0292816D0FFDF14E02078252811D048 +:1031D000FFDF0FE0207825280CD0FFDF0AE0207801 +:1031E000252807D0FFDF05E02078282802D0FFDF60 +:1031F00000E0FFDF257030BD30B50B8840F67B4422 +:103200004FF6FF72022801D0934204D09D1FA542C1 +:1032100024D2022802D04D88954203D04D88AD1F9C +:10322000A5421BD24C88A34218D88B88B3F5FA7FED +:1032300014D2022802D0C888904205D0C88840F62F +:1032400077450A38A84209D2C888904208D09442EB +:1032500006D05B1C6343B3EB800F01DB072030BD5E +:10326000002030BD70B514460D4606460FF0E6FE50 +:1032700058B90DB1A54201D90C2070BD002408E059 +:1032800056F824000FF0DAFE08B1102070BD641C5F +:10329000E4B2AC42F4D3002070BDF0B50024059D2B +:1032A00010B1A94203D850E009B90020F0BD0920AF +:1032B000F0BD055DD5B1071997F801C0BCF1150F38 +:1032C0002DD03BDCBCF1150F38D2DFE80CF0371203 +:1032D0002020262628282F2F3737373737373737FC +:1032E00037372000025D22BB641CE4B28C42F9D364 +:1032F000DBE7022DDBD1BD781D70072D01D26D07F4 +:1033000001D40A20F0BD157845F0010515E0EF4322 +:10331000FF0707E0012D07D010E00620F0BD2F07C2 +:10332000A7F18057002FF5D03046F0BD1578AF07D4 +:1033300001D50B20F0BD45F002051570055D641C3C +:103340002C44E4B28C4202D9B1E74FF448568C4287 +:10335000AFD3AAE710B50278540809D0012243F28E +:103360000223012C07D0022C0DD0032C13D10FE027 +:103370000020087005E080790324B4EB901F0AD187 +:103380000A70002010BD8079B2EB901F03D1F7E7DF +:1033900080798009F4D0184610BD1E4A117C39B1DD +:1033A000517C022908D0032908D043F2022070473B +:1033B0000146901D01F01EBD032100E001210170B6 +:1033C0000020704738B50C460546694601F012FDED +:1033D00000280DD19DF80010207861F3470020707F +:1033E00055F8010FC4F80100A888A4F805000020D2 +:1033F00038BD38B51378E8B102281BD006A46D4655 +:10340000246800944C7905EB9414247864F3470302 +:10341000137003E0B80100200302FF0103280ED05F +:1034200003F0FE0010700868C2F801008888A2F856 +:10343000050038BD23F0FE0313700228E9D1D8B28D +:1034400040F00100EEE730B50C4609789BB0222928 +:1034500002D208201BB030BD28218DF80010ADF835 +:103460000400132A03D03B2A01D00720F2E78DF88D +:1034700006200BA9684609F081F8050003D1212137 +:103480002046FFF764FE2846E4E700B59BB0232101 +:103490008DF80010ADF804001088ADF806005088D3 +:1034A000ADF80800D088ADF80C009088ADF80A009F +:1034B0000020ADF80E00ADF810000BA9684609F029 +:1034C0005DF808E62DE9FF470220FB4E8DF8040069 +:1034D0000027B08AADF80600B84643F202094DE075 +:1034E00001A80CF050FA050006D0B08AA8B3A6F8DF +:1034F0001480ADF806803FE0039CA07F01072DD526 +:1035000004F124000090A28EBDF80800214604F1C9 +:10351000360301F084FE050005D04D452BD0112D5A +:103520003DD0FFDF3BE0A07F20F00800A077E07FE8 +:10353000810861F30000C10861F34100E07794F86D +:10354000210000F01F0084F820002078282827D1CF +:1035500029212046FFF7FBFD22E015E040070BD5AF +:10356000BDF80800214604F10E02FFF78EFF0500AA +:103570000DD04D4510D100257F1CFFB202200CF06C +:1035800043FA401CB842ABD8052D12D008E0A07F0A +:1035900020F00400A07703E0112D00D0FFDF00250C +:1035A000BDF80600B082052D05D0284604B0BDE860 +:1035B000F087A6F814800020F8E72DE9FE43040008 +:1035C00000D1FFDF2078002720F00F00801C20F0C2 +:1035D000F000703020706068B74E0178091F17291D +:1035E0000ED2DFE801F0FD0D0C0D4AFC0D0FFCFCC6 +:1035F00037FD0D0DFD6CFDFD0D0DFDFDFB00FFDF2D +:10360000BDE8FE8385882846FFF769FD040000D1E8 +:10361000FFDF05F07DFFB07C212140F00400B07495 +:103620002046FFF794FD284609F09CF92846FEF74E +:103630000AFD284604F078F8294602200FF0BAFC6B +:10364000A07F20F01000A077FFF73CFF0028D7D024 +:10365000FFDFD5E785882846FFF741FD00B9FFDF8A +:1036600060688078012800D0FFDF6068817903B04E +:103670002846BDE8F04309F0D9BA86883046FFF7FE +:103680002EFD050000D1FFDF05F042FF60683146E6 +:10369000C088288160680089688160684089A88145 +:1036A00002200FF087FCAF75A87F00F0030002280E +:1036B000A6D1FFF707FF0028A2D0FFDFA0E78078A0 +:1036C0003C281BD0002502280ED08DF8007000B1D8 +:1036D000FFDF05F01DFFB07C40F00800B0748DB135 +:1036E000B07801F046FB01208DF800009DF8000045 +:1036F000012876D0022875D0FFDF81E701258DF8FB +:103700000070E6E76568B5F80490A879AD1C01285B +:1037100006D03079804605F0ADFC070003D101E00A +:10372000B078F7E7FFDF0022022148460CF0B9F934 +:10373000040000D1FFDF22212046FFF708FD287991 +:10374000012800D002208DF80000A17F6A4660F3B6 +:103750000101A177288B2081688B6081A88BA081D3 +:1037600084F82280032148460CF09BF900B9FFDF62 +:10377000B888ADF80800B8788DF80A0002AA0521CB +:1037800048460CF08EF900B9FFDFB888ADF80400A8 +:10379000F8788DF8060001AA042148460CF081F95A +:1037A00000B9FFDF062105F1120001F05AFB30B32A +:1037B0006879800700D5FFDF6979E07D61F3470014 +:1037C000E075D5F80600A0616889A083062105F19F +:1037D0000C0001F046FBE0B1B07904E041E03BE0D1 +:1037E00046E021E02CE04108607861F3470060701A +:1037F000D6F80700C4F80200B6F80B0012E0E07D2E +:1038000020F0FE00801CE075D5F81200A061E88A67 +:10381000DBE7607820F0FE00801C6070E868C4F888 +:103820000200288AE08061E73078032800D0FFDFBB +:10383000002108460FF0BEFB012001F065FADFE62B +:10384000F078132800D0FFDF002107200FF0B2FB33 +:103850001120FFF7E1FBD3E62046BDE8FE4301F06F +:103860009FBF05F055FEB07C40F04000B074C7E645 +:10387000BDE8FE4305F04CBE2DE9F05F054600783B +:103880000C4600270109DFF830A091463E46012989 +:103890006FD000234FF6FF7002296BD007290DD09F +:1038A0000A2968D0FFDF00BFA9F800600CB12780AB +:1038B00066800020BDE8F09FB8010020D5F804C064 +:1038C00004F108029CF80010132973D00EDC04F1F7 +:1038D00018080B2913D004DC042969D0082968D101 +:1038E0004AE00F295AD01229F9D1C2E01439072928 +:1038F0005FD2DFE801F0F2F35E5E49DFF0001127EE +:103900000926002C7DD0BCF804804046FFF7E7FB79 +:1039100090F822B0A4F804806868807920729AF840 +:103920001210404621F004018AF8121004210CF014 +:10393000D3F8052140460CF0CFF8002140460CF0AA +:10394000CBF8012140460CF0C7F8032140460CF0AB +:10395000C3F8022140460CF0BFF8062140460CF0A7 +:10396000BBF8072140460CF0B7F8584601F001FAC1 +:103970009AE70AE135E102E112271026BCF80400BB +:10398000214601F04FFA8FE71C270926B4B3BCF893 +:103990000200A08068680079207285E71B2709264D +:1039A00064B30420207268684088A0807CE701E04E +:1039B00034E0E3E09CF802003C2825D010271826CC +:1039C0000CF1020CD4B1BCF80200A080BCF81800C5 +:1039D0006082BCF818002082BCF81A00A082BCF8F3 +:1039E0001C00E0829CF805000CF10601FFF701FDC8 +:1039F0009CF8040018B10120E0730AE001E0022005 +:103A0000FAE7A9F8006054E71B270926002CF8D034 +:103A100023729AF8121021F00801F5E01D273726CD +:103A2000002CEED0A0806968081DCB7801461846AE +:103A3000FFF7DFFC6868C07AA0756868007B04281F +:103A4000E07D13D020F00100E07569681F22097B3A +:103A500061F34200E0756968897A61F3C700E07537 +:103A6000696840460D311CF089FE1DE740F00100F9 +:103A7000EAE71D273726002CC3D0A08069680879A3 +:103A8000491DFFF7B6FC696804F10F02C87A0C31D2 +:103A9000FFF7AFFC6868807CA0756868C178E07D3E +:103AA00061F3420020F0F900E0751F2140461CF050 +:103AB000FEFEF9E620271026002CA2D0A080686820 +:103AC00004F10902807A207269680B1DC8781946D2 +:103AD000FFF78FFCE8E63AE000E024E021270B2620 +:103AE000002C8ED0BCF80400A0806868807820721A +:103AF00068688079012805D0022803D003280ED0F9 +:103B0000FFDF002060726868C079012805D00228B4 +:103B100003D0032805D0FFDF0020A072C4E60420F4 +:103B2000F0E70420F9E723271026002CA4D0BCF8E6 +:103B30000200A0806868007920816868007A60814E +:103B40006868C088A08168684089E081ACE6222767 +:103B50001026002C90D06888A0806868808820811A +:103B60006868C088608168680089A0816868408949 +:103B7000E0819AF8121021F0400145E04A462146C2 +:103B80002846BDE8F05F01F0A9BF287A012803D0DC +:103B9000022814D0FFDF87E61F271026002C8CD0C8 +:103BA0006888A08068892081A8896081E889A081CF +:103BB000288AE0819AF8121021F0200124E01227CF +:103BC00010266888214601F02DF9002C89D06878EC +:103BD00000F007000528A1D19AF8121021F0020187 +:103BE00012E0297A062923D2DFE801F0041111033B +:103BF0000303C3E71B270926002C97D0A08023725C +:103C00009AF8121021F001018AF812104CE61B27D5 +:103C10000926002C8AD0A080287A012806D003200B +:103C200020729AF8121021F01001EDE70220F7E758 +:103C3000FFDF39E630B5F84D9BB0E878132801D0A6 +:103C4000082007E422208DF83C0069460FA808F000 +:103C500095FC040002D1287901F08BF8002107209F +:103C60000FF0A8F920460FE400B5EB489BB0C078F0 +:103C7000122801D0082024E41E208DF80000002026 +:103C80008DF804008DF805000BA9684608F076FC55 +:103C90000028F0D1002107200FF08CF91120FFF748 +:103CA000BBF900200DE410B5DB4C9AB02078012858 +:103CB00013D01B208DF8000000208DF804000BA904 +:103CC000684608F05BFC002808D1002108460FF088 +:103CD00071F92078032803D005E008201AB010BD40 +:103CE000A07801F046F8012001F00EF80020F5E779 +:103CF0002DE9F041C84C002740B102281DD007280B +:103D000042D0082800D0FFDFBDE8F081FFF7CBFFED +:103D10000028F9D105F0F9FB0028F5D0017821F051 +:103D20000F01891C21F0F00120310170077205F0AC +:103D3000EFFBA07C40F001001DE08EB23046FFF7A3 +:103D4000CEF9050000D1FFDF28782128DCD005F06E +:103D5000DCFB90B1017821F00F01891C21F0F0010A +:103D600010310170022101724680AF7505F0D0FB61 +:103D7000A07C40F00200A074C6E729463046BDE8AA +:103D8000F0411322FFF75FBBE578122D03D0132D0E +:103D900004D0FFDFB8E7FFF767FF01E0FFF74AFF56 +:103DA0000028B1D105F0B1FB0028ADD0017821F099 +:103DB0000F01891C21F0F00120310170122D07D074 +:103DC0000221017205F0A4FBA07C40F01000D2E7B4 +:103DD0000121F6E72DE9F04116460C00074600D117 +:103DE000FFDF307820F00F00801C20F0F000103052 +:103DF00030702078012803D0022817D0FFDF83E736 +:103E00003846FFF76CF9050000D1FFDF0220A875E6 +:103E100005F07EFB2068B0606068F0602089308229 +:103E20007D48817C41F0200181746DE73846FFF7C1 +:103E300056F9050000D1FFDF61884FF6FF7081421F +:103E400009D1A288824206D129463846BDE8F04110 +:103E50001322FFF7F8BA814201D1A08848B105F0DA +:103E600057FB2068B0606068F060208930820020D5 +:103E700006E078230022394602200EF0FBFF0120E5 +:103E8000A87541E730B505469BB00C4608460FF0D3 +:103E9000D5F878BB00210120203D092D6BD2DFE849 +:103EA00005F005254C505A616D7B4000002108202B +:103EB0000FF056F808B11120C3E624208DF8000059 +:103EC000D4F802000190A0798DF808000BA968468B +:103ED00008F054FB05004FD1082300221146184674 +:103EE0000EF0C8FF082847D0FFDF45E060680FF0FC +:103EF000E9F808B11020A4E64C208DF800002088D5 +:103F0000ADF804006088ADF806000BA9684608F01B +:103F100035FB050030D1606860B3BDF8301001801A +:103F20002AE04E208DF800002088ADF80400A0782B +:103F300000F001008DF8060029E0206802F06FF81B +:103F400017E04D2208E000BF8DF804001FE000BF1D +:103F50008DF804101BE048228DF800202278D2074B +:103F6000F6D0F1E72178C90705D057218DF8001068 +:103F7000EAE7054600E00725284662E638208DF886 +:103F800000002088ADF804006088ADF806000BA999 +:103F9000684608F0F3FAECE72078C00802D16078B0 +:103FA000C00801D007204CE63F208DF800002078A3 +:103FB0008DF8050060788DF80600207830B100207B +:103FC0008DF80400617819B1002102E00120F7E7C3 +:103FD00002210843B8E730B505469BB00C460846B9 +:103FE0000FF052F808B110202BE6203D092D2BD2FE +:103FF000DFE805F0052828282A2A2A2A2800208810 +:10400000FFF76DF820B10078222807D2082018E6C3 +:1040100043F2020015E60000B801002025208DF8CB +:1040200000002088ADF804000BA9684608F0A6FA45 +:104030000028D9D1DDF83210C4F802109DF83610EE +:10404000A171FEE50620FCE50720FAE5F748704778 +:1040500038B5F6481621801F1CF007FC012000F03F +:1040600053FE1120FEF7D8FFF04C6846A41FE11D57 +:1040700005F0ACF99DF80010A07961F3470020F03D +:104080000100A071002020744FF46170E0810220D3 +:104090006074FFF70CF800B1FFDFFDF755F901F090 +:1040A0003AFB38BD10B50C463E2120461CF0DDFB26 +:1040B000A07F20F00300A077202020700020A075B2 +:1040C00084F8230010BD70477CB505460EF0B6FF9E +:1040D00008B110207CBDD54CA41FA11DD4F806004A +:1040E0000090D4F80A0001902846FFF76BF90028E9 +:1040F000F0D1FEF7DCFF0028ECD00099C4F80610E0 +:10410000BDF8041061819DF8061021737CBD10B5C7 +:1041100004460EF0B9FF08B1102010BDC349224675 +:10412000891F8879C91D4008FFF763F9002010BD79 +:104130002DE9F047A0B00D4604004FF0000812D062 +:104140000822FFF78FF800281CD1002609E000BFE5 +:1041500054F8260004A9FFF7FDF8002812D1761CB8 +:10416000F6B2AE42F4D32F460A2006AD0DF1440A52 +:104170008DF8180026465146284608F0FFF920B170 +:1041800043F2032020B0BDE8F0874046DFF89C8270 +:10419000A8F1060888F805002EB300244FF00B099B +:1041A0001DE000BF56F8240005A9FFF7D3F800B1C1 +:1041B000FFDF9DF81400287156F8240050F8011F05 +:1041C000C5F805108088A5F8090085F800905146CB +:1041D000284608F0D3F900B1FFDF641CE4B2BC420A +:1041E000E0D388F805700020CCE72DE9F047A2B0B5 +:1041F0001546894604001ED00F4608222946FFF7BF +:1042000031F8002811D1002613E000BF54F8260031 +:1042100005A9103000F0EEFD002806D13FB157F897 +:1042200026000EF00BFF10B1102022B0ABE7761C79 +:10423000F6B2AE42EAD30026A5F101081CE000BFA9 +:1042400006F1010A0AF0FF0712E000BF54F8260049 +:10425000017C4A0854F827100B7CB2EB530F05D1B0 +:104260000622113011311CF05DFAC0B17F1CFFB283 +:10427000AF42EBD30AF0FF064645E1DBC8462F46C6 +:10428000342007AD0DF148098DF81C00264649463B +:10429000284608F073F928B143F20420C5E743F239 +:1042A0000520C2E796B300242CE000BF56F8240096 +:1042B000291D103000F09EFD00B1FFDF56F82400EC +:1042C000102250F8111FC5F805108088A5F80900C4 +:1042D00056F8241005F10B001CF050FAB8F1000F4D +:1042E00015D058F82410102205F11B001CF046FAD6 +:1042F000322028704946284608F040F900B1FFDF17 +:10430000641CE4B2BC42D1D3012206E004E005F112 +:104310001B0001F078FEEBE700224946284600F03A +:1043200094FD002081E770B59AB004460EF086FE39 +:1043300018B960680EF0CFFE10B110201AB070BD31 +:1043400060884AF2B811884206D8384D20786E4607 +:10435000AD1F18B1012804D00720EFE7FEF7A7FE34 +:1043600019E06078022804D0032802D043F202202A +:10437000E4E7687417208DF80000697C0020019044 +:10438000ADF80800022932D003292DD0FFDF0BA998 +:10439000684608F0F3F80028D0D1606801F026FEE6 +:1043A000207870B101208DF80400701D01F02BFE03 +:1043B00050208DF800000BA9684608F0DFF800B126 +:1043C000FFDF6088A8B1E88180B2ADF8040030203A +:1043D0008DF800000BA9684608F0D0F800B1FFDFA7 +:1043E000207828740020A9E78DF80900CFE7402045 +:1043F000FAE74FF46170E6E710B504460EF044FEAC +:1044000020B9606838B10EF05DFE08B1102010BD13 +:10441000606801F0F8FD0548801FC1896180417C1A +:104420006170007C2070002010BD0000BE010020E3 +:104430002DE9F041A0B0054600208DF874008DF8FC +:1044400070008DF86C008DF878001E461446884682 +:1044500028460EF040FE18B920460EF03CFE10B182 +:10446000102020B050E455EA040018D01F271BABE1 +:104470001DAA414628460097FEF70FFF0028F0D1FD +:104480001EAB1CAA314620460097FEF706FF002807 +:10449000E7D19DF87000C00703D00A20E1E70720AC +:1044A000DFE701AF7DB11A208DF804008DF8088098 +:1044B00042462946781D1CF061F90CA901A808F0B4 +:1044C0005DF80028CDD17CB120208DF804008DF856 +:1044D000086032462146781D1CF050F90CA901A84D +:1044E00008F04CF80028BCD1FF499DF86C004870DA +:1044F0000020B6E72DE9F0479EB08A464FF000084D +:10450000FAA104468DF86880D1E90001CDE91B01CC +:1045100020460EF093FD90B92078012803D1606801 +:104520000EF08CFD58B9F04D4FF00109287C48B1D0 +:10453000687C022806D160680EF0CDFD10B1102015 +:104540001EB020E62878012801D00820F8E70720CF +:104550000BF062FA18B9207848B1012807D0FEF7AD +:1045600075FD30B1A87C10F00C0F08D103E01220CB +:10457000E6E71320E4E7C10701D1800701D5112048 +:10458000DEE7608943F6E172A0F1200191422178D3 +:1045900007D301297ED100287CD1A189002979D1B6 +:1045A0000FE0022901D0032901D1A02872D30129EB +:1045B00007D06978C90704D0A18900296AD0B42935 +:1045C00068D8217831B1012908D0022904D0032903 +:1045D00060D10AE0002609E0022607E008B9A089B8 +:1045E00008B1042609E0012607E00326287C50B123 +:1045F000687C022807D1606828B11AA96068FEF7B4 +:10460000A9FE00289CD1207A30B1012806D00228CA +:1046100006D0032878D105E0002704E0012702E056 +:10462000022700E003270EB1022E0ED16FB1687988 +:1046300080B36878800702D043F2012080E7022E21 +:1046400003D1022F60D0032F5ED0207808B101285B +:1046500006D1504600F06CFB002889D185F802A0F5 +:1046600018208DF83C006089ADF840006089ADF8F5 +:1046700042008DF844600DF14500FEF78EFE00B15A +:10468000FFDF9DF868008DF846002078012808D0EB +:10469000287C00E038E058B1687C022808D16068C6 +:1046A00030B1606850F8011FCDF84710808802E0F3 +:1046B0004046CDF84780ADF84B008DF84E70A07B9A +:1046C000C0F34002014662F35F01C0F3800041EA9B +:1046D00080001BA9085C8DF84D00A8B169460FA8A1 +:1046E00007F04CFF0028A9D11B208DF83C008DF865 +:1046F000409069460FA807F041FF00289ED19DF821 +:1047000001001B281CD101E0072019E7052E0CD25F +:10471000DFE806F0030308080300A87800F01CFB9C +:10472000032000E0022000F0EFFA012E0AD0A08959 +:1047300040B100228300114610460EF09BFB08B1E9 +:104740000320FDE60020FBE62DE9FC4107460D466F +:10475000032608460EF0BFFC002864D13846FEF759 +:10476000BEFC040005D02078222805D20820BDE830 +:10477000FC8143F20200FAE7A07F00F0030C2DB1A8 +:1047800029466046FEF738FD0600F0D15648BCF1D8 +:10479000010F05D0BCF1020F17D0FFDF3046E6E76E +:1047A000A27D2946012A02D0807C800701D51120F4 +:1047B000DDE729B96846FCF7D5FE0028D7D1694660 +:1047C000384608F0E1F90646E8E7A17D022914D150 +:1047D000807C800611D425B1A07F40070BD4002136 +:1047E00000E00121384608F0FAF90600D6D1A0759C +:1047F000002DD3D002E01126D0E7A5B12A462146EC +:104800003846FEF742FE06461128C7D1A07F410771 +:10481000C4D4296844F80E1F6968616040F0040040 +:1048200020740026BAE71020A1E770B50C460546B3 +:10483000FEF755FC010005D022462846BDE8704031 +:10484000FEF701BE43F2020070BD00B59BB04521EA +:104850008DF800108DF804000BA9684607F08EFE55 +:104860001BB000BD0123FEF73DBC00231A461946CC +:10487000FEF738BC30B59BB004460EF0DFFB10B13C +:1048800010201BB030BD204600F0A2FA0028F8D15D +:10489000154DE878112801D00820F2E7FEF7D6FB85 +:1048A00020B1A87CC00603D51120EAE71320E8E771 +:1048B0002078800701D56879F0B31D208DF80000BD +:1048C0002078022200F001008DF804006088ADF825 +:1048D0000600A088ADF808002078C0F3400102EA85 +:1048E0005000014306E00000B8010020070605045F +:1048F000030201008DF80B100DF10A00FEF74DFDCB +:1049000000B1FFDF0BA9684607F038FE0028B8D1D8 +:104910001E208DF8000001208DF8040000208DF885 +:1049200005000BA9684607F029FE0028A9D1E088F8 +:1049300000F06AFA040000E005E0A2D11220FEF7C0 +:104940006BFB20469DE707209BE72DE9F041FE4CDD +:1049500007469AB0E078984616460D46122803D1CD +:10496000FFF782F900280ED128460EF067FB70BBD6 +:1049700030460EF063FB50BBA07C10F0180F01D145 +:10498000400703D511201AB0BDE8F081284600F099 +:104990001FFA0028F7D131460220FEF72DFC00282F +:1049A000F1D1E078112801D00820ECE706200BF0C7 +:1049B00033F850B12878800701D5607940B1FEF70F +:1049C00045FB022806D21320DDE71220DBE716E0C4 +:1049D0000720D8E721208DF800006888ADF8040092 +:1049E000A888ADF806002878C0F340008DF80800CC +:1049F000287880071DD438460EF020FB08B110201F +:104A0000C1E73878420808D0012A18D043F20221C1 +:104A1000022A18D0032A18D115E0C00700D00220BE +:104A20008DF8090057F8010FCDF80A00B888ADF8E5 +:104A30000E0004A8FEF7B1FC58B10320A3E7C0079D +:104A400005D00320ECE7C00701D008469BE7012012 +:104A5000E6E73088ADF812007088ADF81400B08831 +:104A6000ADF81600F088ADF818000020ADF81A0077 +:104A7000ADF81C00404600F05BF9002883D184F8B3 +:104A800004800BA9684607F079FD00288DD12079B4 +:104A900000F062F9E88800F0B7F9040085D113202E +:104AA000FEF7BAFA20466EE730B505469BB00C46D5 +:104AB00008460EF0E9FA08B11020E2E62846FEF7B3 +:104AC0000EFB38B10178222902D3807F800604D4FE +:104AD0000820D6E643F20200D3E613208DF800004A +:104AE000ADF804500BA9684607F048FD0028E4D152 +:104AF0009DF932107F2901D02170C2E60520C0E661 +:104B000030B505469BB00C4608460EF097FA08B142 +:104B10001020B6E62846FEF7E2FA20B100782228F7 +:104B200004D20820ADE643F20200AAE62078C008CD +:104B300002D16078C00801D00720A2E656208DF887 +:104B40000000ADF8045020788DF8070060788DF8EB +:104B50000800207830B100208DF80600617819B186 +:104B6000002102E00120F7E7022108438DF806004A +:104B70000020ADF80A000BA9684607F0FFFC80E6AC +:104B80002DE9F041B8B0144688460546FEF7A7FA6D +:104B9000060005D03078222805D2082038B0F3E688 +:104BA00043F20200FAE740460EF095FA28B90027D2 +:104BB0003CB120460EF086FA08B11020EEE72760DF +:104BC000A7806148807C400601D51120E6E796F871 +:104BD000220004F04FFA8088011DFB2901D2001D3C +:104BE00000E0FB20C0B26A46414600F0CCF82C221F +:104BF000564913A81BF007FEADF85050BDF802004F +:104C0000ADF85200BDF80600ADF85400BDF8000044 +:104C1000ADF85600BDF80400ADF8580004A913A87B +:104C200007F0ACFC00B1FFDFBDF81400ADF80800E0 +:104C3000BDF81600ADF80A00BDF81800BDF81A104E +:104C4000BDF800200844ADF80C0007201B2AA5D3AE +:104C5000BDF802101B29A1D3FB2A9FD8FB299DD8A0 +:104C600006268A4210D10121104600F03DF8BDF819 +:104C70000410884208D1BDF80200012100F034F888 +:104C8000BDF80610884201D0304687E7BDF808001D +:104C900028B9BDF80A0010B9BDF80C0038B124B12C +:104CA00002982060BDF80C00A080132076E7274909 +:104CB0002C222C311EA81BF0A6FDADF87C50BDF8AF +:104CC0000200ADF87E00BDF80600ADF88000BDF82A +:104CD0000000ADF88200BDF80400ADF8840029A9F9 +:104CE0001EA807F04BFC59E7032904D0022907D07E +:104CF000C000703006E04FF4747101EB801001E0E9 +:104D000080003C3080B2704730B50F4D040008D0B1 +:104D1000012C04D0022C06D0032C04D0FFDF2C7011 +:104D200030BDFFDFFBE728780128F8D0FFDFF6E78A +:104D300010B5044604F09EF950B1407850B12046B9 +:104D400004F09FFC002010BDB8010020100C0200F0 +:104D50000720F8E71220F6E710B504F08BF90400FD +:104D600000D1FFDF607800B9FFDF6078401E60701F +:104D7000E9E710B504F07EF9040000D1FFDF6078A8 +:104D8000401C6070DFE710B5144631B10A6822603C +:104D900049686160218839B107E020806080012185 +:104DA000FFF7A2FFA0800DE02080618801B960803C +:104DB000A08820B920880121FFF796FFA080E08815 +:104DC0000028C0D160880121FFF78EFFE080BAE79C +:104DD000418843F6FD730A1F9A4209D2808804284D +:104DE00006D3B0F5804F03D8884201D80020704721 +:104DF000072070470278520804D0012A02D043F2FB +:104E000002207047FEF7A6BA10B548B18300002211 +:104E1000114607200EF02EF8072801D0032092E754 +:104E2000002090E770B50C0006460DD0FEF757F94C +:104E3000050000D1FFDFA6802889208128896081B4 +:104E40006889A081A889E08170BD10B502F00102D7 +:104E500002713122027007F091FB002800D0FFDFC1 +:104E600071E710B500231A4603E0845C2343521C0B +:104E7000D2B28A42F9D30BB1002064E7012062E785 +:104E80002DE9F041884606460188408815460C18F1 +:104E90001F46AC4200D3641B3844A84200D9FFDF50 +:104EA000E019A84200D9FFDF70883844708008EB11 +:104EB0000400BDE8F08110B504460EF0BFF808B15B +:104EC000102010BD2078C0F30210042807D86078A5 +:104ED000072804D3A178102901D8814201D20720E4 +:104EE00010BDE078410706D421794A0703D40007B2 +:104EF00001D4080701D5062010BD002010BD10B553 +:104F000013785C08C37F64F30003C3771478A408A4 +:104F100064F34103C3771078C309487863F3410011 +:104F2000487013781C090B7864F347130B701378DF +:104F3000DB0863F3000048705078487110BD10B56D +:104F4000C4780B7864F300030B70C478640864F3CE +:104F500041030B70C478A40864F382030B70C47817 +:104F6000E40864F3C3030B700379117863F3000161 +:104F7000117003795B0863F34101117003799B0899 +:104F800063F3820111700079C00860F3C3011170EE +:104F900010BD70B514460D46064604F0B6FA80B151 +:104FA0000178142221F00F01891C21F0F001A031B9 +:104FB00000F8081B21461BF026FCBDE8704004F0F9 +:104FC000A7BA29463046BDE870401322FEF73BBA27 +:104FD00070B514460E46054604F097FA70B1017894 +:104FE00021F00F01891C21F0F00120310170458072 +:104FF00021688160BDE8704004F08ABA31462846D5 +:10500000BDE870401322FEF71EBA10B5FE4C94F8AE +:10501000300000280CD104F120014FF6FF72A1F1FD +:1050200010000CF03EF900B1FFDF012084F83000E1 +:1050300010BD2DE9F047064608A8894690E83004DF +:105040001F469046142128461BF031FC0021CAF867 +:105050000010B8F1000F03D0B9F1000F03D114E034 +:105060003878C00711D020680EF00EF8F0BBB8F108 +:10507000000F07D120681230286020681430686063 +:105080002068A8602168CAF800103878800728D501 +:1050900060680EF017F848BBB9F1000F2DD0FEF78D +:1050A000D5FF0168C6F8C8118188A6F8CC118079AF +:1050B00086F8CE01FFF7A9FFDFF84C8308F120083E +:1050C000C5F80C80626862B196F8C80106F2C91191 +:1050D00040081032FEF78DF91022414660681BF03F +:1050E0004DFB3878400712D5A06800E002E00DF0D3 +:1050F000CBFF50B11020BDE8F08760680028F9D0E0 +:10510000E8606068C6F8C401EBE7A0682861002089 +:10511000F1E730B5054608780C4620F00F00401C3A +:1051200020F0F001103121700020607095F823000C +:1051300030B104280FD0052811D0062814D0FFDF85 +:1051400020780121B1EB101F04D295F8200000F067 +:105150001F00607030BD21F0F000203002E021F02F +:10516000F00030302070EBE721F0F0004030F9E73C +:1051700010B510B190F8BD4044B1A34890F8354047 +:10518000002064B108601060186010BD00F1BC041C +:105190000C6000F1E40100F586701160F4E79A4CB0 +:1051A00034340C60EFE700B58BB00723CDE9021271 +:1051B0008DF80130019194490023643105910993E0 +:1051C00001468DF8103068460CF043F8002800D0F6 +:1051D000FFDF0BB000BD70B590B015460C46022243 +:1051E0000646ADF80820082103AB07F0DEFA04906C +:1051F000002812D00C208DF8010004208DF8040046 +:1052000004F59A74099605948DF818500AA9684611 +:105210000CF01FF800B1FFDF012010B070BD30B5F9 +:105220009BB00C462C251E998DF80050ADF804005B +:10523000C3B11868CDF80600D3F80400CDF80A0011 +:10524000ADF80E20102204A81BF098FA0BA96846AE +:1052500007F094F9002803D1A17F41F01001A17754 +:105260001BB030BD0020CDF80600E7E72DE9F04780 +:105270000646008A8CB080B20D468246FDF72FFFAD +:105280000446614F3078383FDFF87C814FF00009E9 +:10529000122873D2DFE800F072F8350936777E966F +:1052A000A3E7F7F6F5F4F35BF3F3A07F00F0030058 +:1052B000012806D0002150460AF0FCFB050003D16E +:1052C00001E00121F7E7FFDF98F85C10090602D53D +:1052D000D8F860000BE0032105F121000DF058FB28 +:1052E000D5F821004949B0FBF1F201FB1200C5F8E5 +:1052F00021007068A867B068E8672078252800D08A +:10530000FFDFE7E0A07F00F00300012806D00021C6 +:1053100050460AF0CFFB060003D101E00121F7E778 +:10532000FFDF3078810702D52178252904D040F0AD +:10533000010030700CB0DEE60220287096F82000E4 +:10534000287106F121003136C5E90206F2E7A07F97 +:1053500000F00300012806D0002150460AF0AAFB05 +:10536000040003D101E00121F7E7FFDF2078C10647 +:1053700005D51320287041346C60DBE7C9E140F0AB +:1053800008002070D6E72048082138380DF000FBCF +:10539000032014E02A208DF80000102201A8716873 +:1053A0001BF0ECF9102205A8B1681BF0E7F91649CB +:1053B00068463C3907F0E2F800B1FFDF04202870AE +:1053C0006F60B7E7E07FC00600D5FFDFB0680090F0 +:1053D000B38806220821504607F0F6FAAAE704B976 +:1053E000FFDF716821B1102204F124001BF0C6F91F +:1053F00028212046FDF7ABFEA07F00F00300022825 +:1054000013D104F1240003E01402002040420F00F5 +:10541000002300901A4621465046FFF700FF11284E +:1054200007D029212046FDF792FE307A84F820002B +:1054300080E7A07F000700D5FFDF14F81E0F40F0C3 +:1054400008002070A4F81690C4F81890C4F81C90B6 +:105450006178084661F38200410861F3C30060701F +:10546000307AE07066E7A07F00F0030001280CD0DE +:10547000002150460AF01EFB040009D107E01BE0A2 +:1054800043E17FE075E04DE02BE00121F1E7FFDF34 +:10549000022104F189000DF07BFA1020287004F538 +:1054A000E4706860B4F88910298204F18000FE4934 +:1054B0006861C5E902813DE7A07F00F00300012893 +:1054C00005D0002150460AF0F5FA18B901E0012193 +:1054D000F8E7FFDF0CB0324621465046BDE8F04702 +:1054E00057E504B9FFDF20782128A1D930790128B8 +:1054F00002D002280AD103E0E07F40F01000E077FC +:1055000098F85C1041F0010188F85C1032462146A1 +:105510005046FFF73EFD0CB02046BDE8F047232182 +:10552000FDF715BE3279AA8005F10803082150461F +:1055300007F03BF9E86008B1112021E0A07F00F0FE +:105540000300012806D0002150460AF0B3FA0400F7 +:1055500003D101E00121F7E7FFDF04F16601022337 +:105560001022081FFFF78CFC80F800903179417001 +:10557000E0E60821504607F0F7FB00289BD11220F7 +:105580002870D7E6A07F00F00300012806D0002194 +:1055900050460AF08FFA050003D101E00121F7E738 +:1055A000FFDF95F8880000F00300012878D1A07F84 +:1055B00000F00307E07FC0F3400616B1012F04D0CE +:1055C0002BE095F8A400C0072AD0D5F8C01119B374 +:1055D00095F88720087C62F387000874E27FD5F88D +:1055E000C01162F341000874D5F8C01166F30000E1 +:1055F0000874AEB1D5F8C001102204F124018C3535 +:105600001BF0BCF8287E40F001002876287820F0B6 +:10561000010005F88C0900E016B1022F04D02CE03F +:1056200095F88C00C00726D0D5F8BC1119B395F8B1 +:105630008720087C62F387000874E27FD5F8BC11EC +:1056400062F341000874D5F8BC1166F300000874D9 +:105650008EB1D5F8BC01102204F124018C351BF069 +:105660008DF8287840F0010005F8180B287820F014 +:10567000010005F8A409022F43D0002000EB4000F0 +:1056800005EBC00090F88C00800709D595F88000E4 +:10569000D5F8C421400805F181011032FDF7A9FEBB +:1056A00005208DF8000095F888006A4600F0030098 +:1056B0008DF8010095F88C108DF8021095F8A40073 +:1056C0008DF8030021465046FFF782FC20782528FC +:1056D00005D0212807D0FFDF2078222803D92221F6 +:1056E0002046FDF734FDA07F00F0030001280AD01A +:1056F000002150460AF0F0F900283FF427AEFFDF02 +:1057000018E60120BAE70121F3E7716881F80190FA +:1057100010E6FFDF0EE670B5634C0025103C14F870 +:105720005C0F20F08000207065600BF05AFD5E4930 +:10573000A1F1100003F07CFE04F82C5C06206072DE +:1057400059487C3020615030A0611030E06170BD5C +:1057500070B50D46FDF7C3FC040000D1FFDF4FF428 +:10576000E87128461BF0A3F84F485430686104F1F3 +:1057700024002861A07F00F00300012808D0022146 +:1057800005F59A700BF02EFD002800D0FFDF70BDEC +:105790000121F5E70A46014602F59A700BF042BD79 +:1057A00070B505464068A0B00178092906D00C29DB +:1057B00038D00D2934D0FFDF20B070BD4688304688 +:1057C000FDF78DFC040000D1FFDF20782128F3D005 +:1057D000282822D1686802210C3001F0D1F9E0B10B +:1057E00068680821001D01F0CBF9B0B12D208DF8BB +:1057F0000000ADF80460102204F124010DF1060050 +:105800001AF0BCFF0BA9684606F0B8FE00B1FFDF36 +:1058100029212046FDF79BFCCEE703F079FECBE77C +:1058200001218171686886883046FDF758FC0400C4 +:1058300000D1FFDFA07F00F00301022902D120F098 +:105840001000A077207821280AD06868817909B1F2 +:10585000807880B1A07F00F0030002285AD0FFDFDB +:10586000A07F00F003000228A6D1FDF72BFE002840 +:10587000A2D0FFDFA0E703F04BFEE07FC10724D0FA +:10588000800701D5062000E0052084F82300207859 +:1058900029281CD02428E3D1314606200DF08AFBAC +:1058A0002221204602E0000024020020FDF74FFCE8 +:1058B000A07F00F0030001282AD0002130460AF022 +:1058C0000BF90028CCD0FFDFCAE70420DDE7A07F7A +:1058D00000F00300012806D0002130460AF0EAF863 +:1058E000050003D101E00121F7E7FFDF2521204674 +:1058F000FDF72DFC0F208DF868001AA905F59A70A8 +:105900000BF087FC0228ABD00028A9D0FFDFA7E767 +:105910000121D3E703F0FCFDA2E72DE9F0438BB0B2 +:105920009946154688460646FDF7D9FB04004FD038 +:10593000207822284CD323284AD0E07FC00647D4C1 +:10594000A07F00F00300012806D0002130460AF0B5 +:10595000B1F8070002D00CE00121F7E7A07F00F0CA +:105960000300012805D10121002230460AF099F8F0 +:10597000074601AB02AA03A93846FFF7F9FB0398D3 +:1059800000B9FFDF4FB1039807F59A778761207858 +:10599000222806D0242804D007E00399002088613B +:1059A00003E025212046FDF7D2FB03980B2141702F +:1059B00046628580C0E902890299016101994161CD +:1059C00004A90BF046FC022802D0002800D0FFDF1B +:1059D0000BB0BDE8F083F0B587B00746FDF77FFB5D +:1059E000017822291DD9807F00F00300012806D00C +:1059F000002138460AF05EF804003FD101E00121A1 +:105A0000F7E7FFDF3AE000BFB4F8621004F1660088 +:105A100008440178427831B121463846FFF7DBFB74 +:105A2000B8B907B0F0BDADF804200821384602AB84 +:105A300006F0BBFE03900028F3D011208DF8000083 +:105A4000694604F59A700BF0E4FB022801D000B11E +:105A5000FFDF04F162052E88B01C80B22880102878 +:105A600001D3103828806888022800D2FFDFB61CD6 +:105A7000102E00D9FFDF6888801E6880B4F86400AB +:105A80000028C1D1CDE730B587B00546FDF727FB2B +:105A90000446007822281FD90821284607F064F917 +:105AA000002819D1A07F00F00300012806D00021B2 +:105AB000284609F0FFFF040003D101E00121F7E7C8 +:105AC000FFDF12208DF80000694604F59A700BF094 +:105AD000A0FB002800D0FFDF07B030BD2DE9F05F4C +:105AE00005460C4600270078904601093E46BB4615 +:105AF00004F1080A02297CD0072902D00A2909D119 +:105B000042E068680178092905D00C292CD00D29BC +:105B10002AD0FFDFC6E114271C26002C6AD040885B +:105B2000A080FDF7DCFA5FEA000900D1FFDF99F8F9 +:105B300017005246400809F11801FDF75AFC686841 +:105B40008089208268684168C4F812108068C4F8AF +:105B50001600A07E20F0060040F00100A07699F823 +:105B60001E0040F040014DE01A270A26002CD5D037 +:105B70008088A080FDF7B3FA050000D1FFDF514611 +:105B80002846FFF7C6FA8DE10CB1288BA080287A51 +:105B90000E287CD006DC01287AD0022808D0032801 +:105BA00004D135E0102874D0112873D0FFDF79E1DB +:105BB0001E270926002CB1D0A088FDF790FA5FEAD5 +:105BC000000900D1FFDF287B00F003000128207AC4 +:105BD0001BD020F001002072297B890861F341006D +:105BE0002072297BC90861F382002072297B090990 +:105BF00001E04CE119E161F3C300207299F81E0045 +:105C000040F0800189F81E104CE140F00100E2E70D +:105C100013270D26002CAAD0A088FDF760FA814634 +:105C2000807F00F00300012806D00021A08809F041 +:105C300041FF050003D101E00121F7E7FFDF99F8FB +:105C40001E0000F00302012A59D0E86F817801F0AC +:105C500003010129217A54D021F0010121728378B6 +:105C60009B0863F3410121728378DB0863F38201AF +:105C7000217283781B0963F3C3012172037863F3F4 +:105C800006112172437863F3C711217203E060E0CB +:105C9000A6E08EE09EE084F809B0C178A172012AE6 +:105CA00032D04279E17A62F30001E172427952081E +:105CB00062F34101E1724279920862F38201E1727A +:105CC0004279D20862F3C301E1720279217B62F367 +:105CD000000121730279520862F3410121730279B4 +:105CE000920862F3820121730079C00860F3C30156 +:105CF000217399F8000023285AD9262168E0A86F5B +:105D0000A4E741F00101A9E70279E17A62F3000119 +:105D1000E1720279520862F34101E172027992085C +:105D200062F38201E1720279D20862F3C301E17287 +:105D30004279217B62F3000121734279520862F3B8 +:105D4000410121734279920862F382012173407903 +:105D5000CBE718271026002C67D0A088FDF7BFF9E5 +:105D60008246807F00F00300012807D00021A08830 +:105D700009F0A0FE5FEA000903D101E00121F6E786 +:105D8000FFDFE868A06099F8000040F0040189F89E +:105D9000001099F80100800708D5012020739AF8B7 +:105DA000000023287ED92721504663E084F80CB0F8 +:105DB00078E015270F26C4B3A088FDF790F9814637 +:105DC00006225146E86806F041FC0120A073AEE0CF +:105DD00048464FE0162709263CB3287B207261E035 +:105DE000297BFE4802290CD019270E26ECB1012987 +:105DF0000DD003291AD004291BD0052919D0FFDFA3 +:105E000023E01B270926BCB30121217205E00121F3 +:105E10002172617A21F00301617210F85C1F4A0857 +:105E2000520062F3060101700FE02BE002202072A5 +:105E300007E0687B052900F00F0040F08000207229 +:105E40001BD0607A20F003006072A088FDF747F94C +:105E500005460078212825D0232800D0FFDFA87F21 +:105E600000F00300012810D00021A08809F034FEC2 +:105E700022212846FDF76BF914E0607A20F0030038 +:105E8000401CE1E7A8F8006011E00121EDE70CB14A +:105E90006888A080287A03282BD004280AD00528F7 +:105EA0004BD0FFDFA8F800600CB12780668000208F +:105EB000BDE8F09F15270F26002CE3D0A088FDF742 +:105EC0000EF9807F00F00300012806D00021A08891 +:105ED00009F0F0FD050003D101E00121F7E7FFDF44 +:105EE000D5F821000622514606F0B0FB84F80EB02A +:105EF000D8E717270926002CC4D0A088FDF7EFF8B3 +:105F00008146807F00F00300012806D00021A08890 +:105F100009F0D0FD050003D101E00121F7E7FFDF23 +:105F20006878800701D5022000E00120207299F8EE +:105F300000002328B6D927214AE719270E26002C6E +:105F4000A0D0A088FDF7CBF85FEA000900D1FFDF01 +:105F5000C4F808B0A4F80CB084F808B0A07A40F0F7 +:105F60000300A07299F81F1061F38200A07299F8E3 +:105F70001F1001EA510161F3C300A072687A00F0BA +:105F8000030001288ED1607A40F00400607299F815 +:105F90001E00E97A00F00300012813D0607B61F352 +:105FA00000006073AA7A217B62F300012173EA7A10 +:105FB000520862F341006073A87A400860F341011F +:105FC00021736FE7207B61F300002073AA7A617B65 +:105FD00062F300016173EA7A520862F341002073B0 +:105FE000A87A400860F3410161735BE710B57B4C10 +:105FF00030B10146102204F120001AF0BFFB01204D +:1060000084F8300010BD10B50446FEF7FEFF73495A +:1060100020461022BDE8104020311AF0AFBB70B509 +:106020006E4C06004FF0000514D00DF007F808B1D3 +:1060300010250DE00621304606F0EFFA411C06D08F +:10604000206614F85C0F40F08000207000E0072507 +:10605000284670BD14F85C0F20F08000F5E700784A +:1060600010F00F0204D0012A05D0022A0CD110E052 +:10607000000909D10AE00009012807D0022805D04B +:10608000032803D0042801D007207047087000209F +:1060900070470620704705282AD2DFE800F0030782 +:1060A0000F171F00087820F0FF001EE0087820F08E +:1060B0000F00401C20F0F000103016E0087820F0AF +:1060C0000F00401C20F0F00020300EE0087820F097 +:1060D0000F00401C20F0F000303006E0087820F07F +:1060E0000F00401C20F0F000403008700020704786 +:1060F000072070472DE9F041804688B00D46002703 +:1061000008460CF0E8FFA8B94046FCF7E8FF040099 +:1061100003D02078222815D104E043F2020008B011 +:10612000BDE8F08145B9A07F010603D500F003006A +:10613000022801D01020F2E7A07FC10601D4010798 +:1061400002D50DB10820EAE7244991F85C10C9078F +:1061500001D01120E3E7E17FC90601D50D20DEE77C +:1061600000F00300022805D125B12846FEF7A3FE62 +:106170000700D4D1A07F00F00300012806D0002141 +:10618000404609F097FC060002D00DE00121F7E738 +:10619000A07F00F0030001280CD00021002240461F +:1061A00009F07FFC060007D0A07F00F00300022862 +:1061B00004D009E00121F1E70420B0E725B12A4627 +:1061C00031462046FEF79BFE07AB1A46694630462D +:1061D000FEF7CEFF009800B9FFDF01E014020020B7 +:1061E00000990C20487006F59A70C1F82480486127 +:1061F00000200881A07F00F00300012828D0EDB323 +:1062000002200871301D8861307840090877707865 +:10621000C0F340004877287800F00102887F62F3DD +:1062200001008877E27F62F382008877E27F52087C +:1062300062F3C3008877727862F304108877A878D5 +:10624000C87701F1210228462031FEF778FE22E0CE +:1062500001200871287800F00102087E62F3010035 +:1062600008762A78520862F3820008762A78920823 +:1062700062F3C30008762A78D20800E007E062F3F0 +:106280000410087624212046FCF761FF0BE0032070 +:1062900008710520087625212046FCF758FFA07FCD +:1062A00020F08000A07701A900980AF0D2FF022810 +:1062B00001D000B1FFDF384631E72DE9FF4FF94A41 +:1062C0000D4699B09A4607CA14AB002783E8070029 +:1062D0001998FCF704FF060006D03078262806D06F +:1062E00008201DB0BDE8F08F43F20200F9E7B07F4F +:1062F00000F00309B9F1010F03D0B9F1020F07D083 +:1063000008E03DB91B98FEF7D6FD0028E9D101E071 +:106310001B9878BBB07F00F00300012806D0002155 +:10632000199809F0C7FB040003D101E00121F7E748 +:10633000FFDF852D25D007DCD5B1812D1BD0822D27 +:106340001BD0832D08D11AE0862D1CD0882D1CD09F +:10635000892D1CD08A2D1CD00F2020710F281AD017 +:1063600001208DF83400201D0E902079A8B158E14D +:106370000020F2E70FE00120EFE70220EDE7032025 +:10638000EBE70520E9E70620E7E70820E5E7092035 +:10639000E3E70A20E1E70720A3E7B9F1010F17D0EF +:1063A000D4E91E5080460220019001200090A87878 +:1063B00098F80210C0F3C000C1F3C00108405FEAC2 +:1063C000000B5DD050460CF039FE00286CD12DE05A +:1063D000D4E91E850120019002200090214630461C +:1063E0001B9AFEF78CFD1B98007800F00101A8783D +:1063F00061F30100A870F17F61F38200A870F17F62 +:10640000490861F3C300A870617861F30410A870B3 +:106410002078400928706078C0F3400068701B98AD +:106420008078E870002068712871C0E7DAF80C0005 +:106430000CF004FEC0BBDAF81C000CF0FFFD98BBAA +:10644000DAF80C00A060DAF81C00E06098F80100AF +:10645000617800F0010041EA4000607098F8021095 +:10646000C0B2C1F30011891E08406070002084F89A +:106470002000009906F1170002290BD001210AE043 +:1064800098F80110607801F00101FD2242EA410113 +:106490000840E2E7002104EB810188610199701C4A +:1064A000022902D0012101E028E0002104EB810152 +:1064B0008861A87800F00300012849D198F802000B +:1064C00000F00300012843D1B9F1010F04D12A1DC6 +:1064D000691D1B98FEF733FD297998F804000140E7 +:1064E0008DF82C10687998F8052010408DF8300050 +:1064F00001432DD050460CF0A1FD08B11020F0E66C +:106500000AF1100004F5DE7104F190020490B9F173 +:10651000020F3CD00090CDE9012100210BAB5A467F +:106520002046FEF786FD0028E9D104F5E07104F16C +:10653000A802B9F1010F30D004980090CDE90121F3 +:1065400000210CAB5A462046FEF773FD0028D6D139 +:106550006078800740D4A87898F80210C0F38000D3 +:10656000C1F38001084337D0297898F8000014AAB5 +:10657000B9F1010F17D032F810204B00DA4012F0B9 +:10658000030718D0012F1ED0022F12D11DE0CDF825 +:1065900000A0CDE901210121C0E7CDF800A0CDE99F +:1065A00001210121CDE732F811204300DA4002F049 +:1065B0000307032F07D0BBF1000F0DD0012906D030 +:1065C000042904D008E00227F5E70127F3E70128B2 +:1065D00001D0042800D10427F07F40F001006BF3C4 +:1065E0004100F077607881074FF003000CD5A0716F +:1065F000BBF1000F15D100BF8DF85C0017AA314622 +:106600001998FEF7E5FC0CE00221022F18D0012FAB +:1066100018D0042F22D00020A071F07F20F00100BC +:10662000F07725213046FCF792FD0DA904F59A700C +:106630000AF0EFFD10B1022800D0FFDF002050E685 +:10664000A171D9E7A1710D2104F124001AF02FF9ED +:10665000207840F0020020700420CDE70120A071D6 +:10666000DFE72DE9F04387B09046894604460025D0 +:10667000FCF735FD060006D03078272806D0082024 +:1066800007B0BDE8F08343F20200F9E7B07F00F005 +:106690000300012808D00021204609F00BFA04006D +:1066A00005D103E0680C02000121F5E7FFDFA779BF +:1066B0005FEA090005D0012821D0B9F1020F26D1E7 +:1066C00010E0B8F1000F22D1012F05D0022F05D024 +:1066D000032F05D0FFDF2DE00C252BE0012529E05D +:1066E000022527E040460CF0A9FCB0B9032F0ED1DB +:1066F0001022414604F121001AF040F81AE0012F5F +:1067000002D0022F03D104E0B8F1000F12D007200D +:10671000B6E740460CF092FC08B11020B0E710211B +:1067200004F121001AF0A1F80621404605F075FF9A +:10673000C4F821002078252140F002002070304666 +:10674000FCF705FD2078C10714D020F0010020706F +:1067500002208DF8000004F1210002908DF8045011 +:10676000694604F59A700AF054FD022804D018B165 +:10677000FFDF01E084F82050002081E730B587B0CA +:106780000D460446FCF7ABFC88B1807F00F00300A7 +:1067900001280FD00021204609F08CF904000ED00A +:1067A00028460CF04BFC38B1102007B030BD43F246 +:1067B0000200FAE70121EEE72078400701D4082023 +:1067C000F3E7294604F141002022054619F0D6FFDF +:1067D000207840F01000207001070FD520F008004D +:1067E000207013208DF80000694604F59A70019519 +:1067F0000AF00FFD022801D000B1FFDF0020D4E72E +:1068000070B50D460646FCF76AFC18B101782729D9 +:106810001FD102E043F2020070BD807F00F0030050 +:10682000012806D00021304609F044F9040003D1C4 +:1068300001E00121F7E7FFDFA079022809D16078A4 +:10684000C00706D02A4621463046FEF7C4FC10B1E8 +:106850000FE0082070BDB4F864000E280BD204F1DC +:10686000660102231022081FFEF70AFB01210170B6 +:106870004570002070BD112070BD70B5064686B011 +:1068800014460D4608460CF0D9FB18B920460CF00A +:10689000FBFB10B1102006B070BDA6F57F40FF389D +:1068A0000ED03046FCF71BFC38B1417822464B082D +:1068B000811C1846FCF79DFD07E043F20200EAE761 +:1068C0002046FDF724FC0028E5D11021E01D0CF046 +:1068D0005FF8E21D29466846FEF765FC102204F1C8 +:1068E0001700019919F04AFF0020D4E72DE9F04183 +:1068F000044686B015468846002708460CF0EBFB98 +:1069000018B928460CF0E7FB10B1102006B007E4D8 +:106910002046FCF7E4FB060003D03078272818D186 +:1069200002E043F20200F1E7B07F00F0030001282B +:1069300006D00021204609F0BDF8040003D101E093 +:106940000121F7E7FFDF2078400702D56078800754 +:1069500001D40820DAE7B07F00F00300012818D046 +:10696000D4E91E01407800B1B5B1487810B1B8F152 +:10697000000F11D0C5B1EA1D6846E168FEF713FCAF +:10698000102205F11700019919F0CCFE30B104274F +:106990000AE0D4E91E10E5E70720B7E71022E91D59 +:1069A00004F1310019F0EAFEB8F1000F06D0102210 +:1069B00008F1070104F1210019F0E0FE20782521FB +:1069C00040F0020020703046FCF7C1FB2078C10780 +:1069D00016D020F00100207002208DF8000004F194 +:1069E00021000290103003908DF80470694604F580 +:1069F0009A700AF00EFC022804D018B1FFDF01E003 +:106A000084F82070002081E7F8B515460E46074649 +:106A1000FCF765FB040004D02078222804D008206D +:106A2000F8BD43F20200F8BDA07F00F00300022889 +:106A300002D043F20500F8BD30460CF0FFFA18B959 +:106A400028460CF0FBFA08B11020F8BD00953288FA +:106A5000B31C21463846FEF7E2FB112814D000286B +:106A6000F3D1297C4A08E17F62F30001E1772A7CB7 +:106A700062F34101E177297C890884F82010A17F25 +:106A800021F08001A177F8BDA17F0907FBD4D6F8DA +:106A90000200C4F83600D6F80600C4F83A00308880 +:106AA000A0861022294604F1240019F067FE287CF4 +:106AB0004108E07F61F38200E077297C61F3C30045 +:106AC000E077287C800884F82100A07F40F008004F +:106AD000A0770020D3E770B59AB00D46064613B1F3 +:106AE00007201AB070BDFCF7FAFA040007D020782E +:106AF000222802D3A07F400604D40820F1E743F205 +:106B00000200EEE7CDB12D208DF80000ADF8046055 +:106B1000102229460DF1060019F030FE287C4108AC +:106B2000E07F61F30000E077297C61F34100E077CA +:106B3000287C800884F8200004E02E208DF80000D6 +:106B4000ADF804600BA9684605F018FDA17F21F09F +:106B50004001A177C5E770B50D46FCF7C0FA040007 +:106B600005D028460CF090FA20B1102070BD43F2F9 +:106B7000020070BD29462046FEF7CBFA002070BD0A +:106B800005E000BF10F8012B0AB100207047491E34 +:106B900089B2F7D20120704718B18178012938D124 +:106BA00001E010207047018842F60112881A9142D4 +:106BB00031D018DC42F60102A1EB020091422AD04A +:106BC0000CDC41B3B1F5C05F25D06FF4C05008189C +:106BD00021D0A0F57060FF381BD11CE001281AD02D +:106BE00002280AD117E0B0F5807F14D008DC012814 +:106BF00011D002280FD003280DD0FF2809D10AE0B8 +:106C0000B0F5817F07D0A0F58070033803D001284C +:106C100001D0002070470F2070470B2826D008DCD9 +:106C20001BD2DFE800F01C2025251A252923252763 +:106C30001E0011281CD008DC0C2817D00D281DD0F0 +:106C40000F2815D0102808D110E0822809D08428F8 +:106C500010D0852810D0872812D00320704700203C +:106C600070470520704743F20300704707207047C4 +:106C70000F20704704207047062070470C20704793 +:106C800043F20200704708280DD2DFE800F0040646 +:106C9000040C0C080A0A00207047112070470720D6 +:106CA0007047082070470320704738B50C46050030 +:106CB00041D06946FFF7D3F9002819D19DF800109B +:106CC000607861F3020060706946681CFFF7C7F9DD +:106CD00000280DD19DF80010607861F3C500607048 +:106CE000A978C1F34101012903D0022905D0072069 +:106CF00038BD217821F0200102E0217841F0200107 +:106D00002170410704D0A978C90861F3861060702A +:106D1000607810F0380F07D0A978090961F3C7101F +:106D2000607010F0380F02D16078400603D52078EB +:106D300040F040002070002038BD70B504460020AF +:106D4000088015466068FFF7B0FF002816D120893B +:106D5000A189884211D860688078C0070AD0B1F54F +:106D6000007F0AD840F20120B1FBF0F200FB1210C4 +:106D7000288007E0B1F5FF7F01D90C2070BD01F23A +:106D800001212980002070BD10B50478137864F3C8 +:106D9000000313700478640864F3410313700478EB +:106DA000A40864F3820313700478E40864F3C30353 +:106DB00013700478240964F30413137004786409CD +:106DC00064F3451313700078800960F38613137021 +:106DD00031B10878C10701D1800701D5012000E059 +:106DE000002060F3C713137010BD4278530702D020 +:106DF00002F0070306E012F0380F02D0C2F3C2031C +:106E000000E001234A7863F302024A70407810F0F0 +:106E1000380F02D0C0F3C20005E0430702D000F0F3 +:106E2000070000E0012060F3C5024A7070472DE9B9 +:106E3000F04F95B00D00804615D0B8F1000F16D078 +:106E40001221284619F011FD4FF6FF7B05AA0121FA +:106E5000584605F0DDF90024264637464FF4205900 +:106E60006FF4205A75E0102015B0BDE8F08F0720B0 +:106E7000FAE700BF9DF81E0001280AD1BDF81C00EA +:106E800048450BD010EB0A000AD001280CD002288C +:106E90000CD0042C0ED0052C0FD10DE0012400E005 +:106EA0000224BDF81A6008E0032406E00424BDF8BB +:106EB0001A7002E0052400E00624BDF81A104145CE +:106EC00047D12C74BEB34FF0000810AA4FF0070A48 +:106ED000CDE90282CDE900A80DF13C091023CDF8DF +:106EE000109042463146584605F045FA08BBBDF8B9 +:106EF0003C002A46C0B210A90AF04CFAC8B9AE81CB +:106F0000CFB1CDE900A80DF1080C0AAE40468CE8DF +:106F10004102132300223946584605F02CFA40B9A5 +:106F2000BDF83C00F11CC01EC0B22A1D0AF032FAA6 +:106F300010B1032098E70AE0BDF82900E881062C8B +:106F400005D19DF81E00A872BDF81C002881002004 +:106F50008AE705A805F068F900288BD0FFF75DFEE9 +:106F600082E72DE9F0471C46DDE90978DDF820903D +:106F700015460E00824600D1FFDF0CB1208818B103 +:106F8000D5B11120BDE8F087022D01D0012100E02C +:106F9000002106F1140004F013F8A8F800000246DE +:106FA0003B462946504605F000FCC9F8000008B9E8 +:106FB000A41C3C600020E5E71320E3E7F8B50D468C +:106FC00006461446DDE90710069ACAB10346009149 +:106FD00004222146304605F0F7FC5CB1022C08D1B2 +:106FE000A87CC00705D02146304605F0BDFE002034 +:106FF000A874F8BD21463046BDE8F84005F0B4BE9F +:107000001880F8BD2DE9FF4791461A881C468A462C +:1070100080460AB303AB494605F0C7FB05001BD009 +:107020004046A61C278808F062FE324607262946FD +:107030003B46009608F0E8FA208803990095CDE9D0 +:10704000011023464A4651464046FFF7B7FF00204D +:107050002080012004B095E70020FBE72DE9F047F0 +:107060008CB00D46DDE9149882461C461746022670 +:10707000142103A819F01BFC012002218DF8101027 +:107080008DF80C008DF81180ADF8147064B1A17802 +:10709000C90709D08DF81600E088ADF81A00A0885D +:1070A000ADF81800A06807900AAA09A908A88DE8F9 +:1070B00007003246294650466B68FFF752FF00280A +:1070C0000ED1DDE9080105F114028DE807000AABD5 +:1070D0004A4603A9504604F037FB18B1FFF7D3FD29 +:1070E0000CB04FE7DDE90801BDF828208DE8070066 +:1070F0003246294650466B68FFF760FF0020EFE7F5 +:10710000F0B58BB000240646069407940727089430 +:1071100005A80994019400970294CDE903400D4617 +:1071200010232246304605F026F978B90AA806A9A8 +:10713000019400970294CDE90310BDF814300022A9 +:107140002946304604F0EEFE002801D0FFF765FD29 +:107150000BB0F0BD04F080BD2DE9FC410C4680462B +:10716000002602F0D2F9054620780D287ED2DFE80D +:1071700000F0B2070BA918B33C5C6C8FA5949A0081 +:10718000404602F0F1F9A7E00421404608F092FCE5 +:10719000070000D1FFDF07F11401404603F0A4FE11 +:1071A0006AE00421404608F085FC070000D1FFDFBB +:1071B000E088ADF800000020B8819DF800000107CC +:1071C00004D5C00602D5A088B88105E09DF801006D +:1071D000400609D5A088F88105B9FFDF2246294677 +:1071E000404601F017FD022676E0A088694605F0CA +:1071F000A5F900B1FFDF9DF8020001280BD1BDF811 +:10720000000042F6011188420BD0A0F5245102394A +:1072100007D0491E05D0E079000600D5022635BB0F +:1072200001E0042658E0FFDF27E0E079000609D5F9 +:107230000421404608F03EFC060000D1FFDFA08894 +:10724000F08102269DB9FFDF17E00421404608F0D7 +:1072500031FC070000D1FFDF07F1140004F033FD1B +:1072600090F0010F05D1E079000601E033E004E081 +:1072700032D50226A7F810802DB122462946404675 +:1072800001F0C8FC28E013214046FDF7CEFA23E0C8 +:107290000226002DF1D1FFDFEFE702260121404653 +:1072A00002F0AEF918E0606800902089ADF80400A3 +:1072B00001226946404602F0C4F90DE0002DDCD100 +:1072C000FFDFDAE7022600214046FBF790F8002DA9 +:1072D000D3D1FFDFD1E7FFDF3046BDE8FC813EB50B +:1072E0000C0009D001466B4601AA002005F0C5F844 +:1072F00020B1FFF792FC3EBD10203EBD0020208053 +:10730000A0709DF8050002A900F00700FEF7C3FE7B +:1073100050B99DF8080020709DF8050002A9C0F33F +:10732000C200FEF7B8FE08B103203EBD9DF808007C +:1073300060709DF80500C109A07861F30410A07089 +:107340009DF80510890961F3C300A0709DF8041031 +:10735000890601D5022100E0012161F342009DF878 +:10736000001061F30000A07000203EBD70B514460F +:1073700006460D4651EA040005D075B108460BF0EB +:10738000A1FE78B901E0072070BD2946304605F01E +:10739000D5F810B1BDE870403FE454B120460BF081 +:1073A00091FE08B1102070BD21463046BDE8704006 +:1073B00095E7002070BD2DE9FE4F0C46904605462E +:1073C000002701780822007A3E46B2EB111F7DD1DA +:1073D00004F10A010091891E02910C31821E4FF0C6 +:1073E000020B4FF0010A0191092A70D2DFE802F086 +:1073F000F5F4056F252579B8F6006888042108F0B2 +:1074000059FB060000D1FFDFB08910B152270726D3 +:10741000EBE051271026002C7ED06888A08084F8ED +:1074200006A0A88900220099FFF7A0FF002874D1C8 +:10743000A8892081288AE081FDE0B5F8129007280C +:1074400025D1E87B000622D5512709F1140086B228 +:10745000002CE1D0A88900220099FFF787FF0028BF +:107460007CD16888A08084F806B0A889208184F83F +:107470000EA0288A2082A4F81290A88A009068881A +:107480004B46A969DDF8042001F0A1FBD3E05027A9 +:1074900009F1120086B2002C3ED0A8890022029980 +:1074A000FFF764FF002859D16888A080A889E08090 +:1074B000287A072813D002202073288AE081E87BED +:1074C000C0096073A4F81090A88A01E0B0E0ADE0B4 +:1074D000009068884B4604F11202A969D4E70120A4 +:1074E000EAE76888042108F0E5FAB5F812A05FEA37 +:1074F000000900D1FFDF09F1140004F0E4FB90F073 +:10750000010F02D1E87B000627D50AF114005127AC +:1075100086B2002C7FD001E072E01FE06888A08076 +:10752000A88900220099FFF721FF002816D184F8CE +:1075300006B0A88920810420A073288A2082A4F89C +:1075400012A0A88A009068885346A969019A01F0A0 +:107550003EFBA989A9F80E106DE00320BDE8FE8F5F +:107560006888FBF7BCFD82466888042108F0A2FA0F +:107570008146BAF1000F00D1FFDFB9F1000F00D151 +:10758000FFDFB9F81010A1F57F40FF3802D0512776 +:10759000142601E05027122694B36888A080502F4B +:1075A00006D084F806B0287B029901F020FB42E067 +:1075B000287BA11D01F01BFB00219AF82300CDE9D7 +:1075C00000010B46B9F80E2068884946FFF746FDD2 +:1075D0000028C3D12FE001E013E01FE0FB49A88998 +:1075E000C988814205D1542706264CB16888A080FD +:1075F00021E053270CE06888A080A889E0801AE089 +:1076000009E06888042108F055FA00B9FFDF552722 +:107610000826002CEFD1A8F8006011E056270726B5 +:10762000002CF8D06888A080002012E0FFDF02E084 +:10763000012807D0FFDFA8F800600CB12780668022 +:1076400000208BE757270726002CE4D06888A0800D +:10765000687AA071EFE7401D20F00300042202EBDE +:10766000400201FB00207047D84B00221A7008B17D +:10767000D74A106007F0C7BB70B50C46064686B007 +:1076800015465C21204619F012F905B9FFDFA878EC +:10769000E074AA782988204601F0D2FA0020A0815F +:1076A000E0814FF6FF7020822A8804F114013046F1 +:1076B00003F0FFFB6A460121304604F0A9FD19E002 +:1076C0009DF80300000715D5BDF806103046FFF7FA +:1076D00017FD9DF80300BDF8061040F010008DF86E +:1076E0000300BDF80300ADF81400FF233046059AEF +:1076F00004F0EFFE684604F097FD0028E0D006B0E5 +:1077000070BD70B5064601F114000C46054603F045 +:1077100007FC0146E27C204601F0BEFA29463046CD +:10772000BDE8704003F0E7BB70B50546042108F0E2 +:10773000C1F9040000D1FFDF04F114012846BDE8BF +:10774000704003F0D1BB2DE9F0418CB00C4680466F +:107750000226FBF7C4FC050014D02878222829D380 +:107760000CB1A08898B101208DF8180003208DF885 +:107770001C0000208DF81D005CB1A088ADF824002D +:10778000206808E043F202000CB0BDE8F081092057 +:10779000FAE7ADF8240008900421404608F08AF981 +:1077A000040000D1FFDF04F11400074603F0CFFB13 +:1077B000C00601D40820E7E705AA04A903A88DE8BC +:1077C00007003246214640466368FFF7CAFB00B116 +:1077D000FFDFDDE903018DE8830095F8232005AB89 +:1077E00006A9404603F0B0FF10B1FFF74CFACBE713 +:1077F000BDF81420DDE903018DE80700324621467B +:1078000040466368FFF7DAFB4FF6FF7020820020E6 +:10781000BAE72DE9F047B2F80290824688B01546E3 +:1078200088464846FBF75BFC06460421484608F0BC +:1078300041F904460020059002270690ADF81C008F +:1078400006B9FFDF04B9FFDF3946484605F0A2FA62 +:1078500060B907AA06A905A88DE807003A4621469F +:1078600048466368FFF77DFB00B1FFDFDDE90512E5 +:1078700004F11400CDF80080CDE9032007ABCDE979 +:10788000013196F82320514648466B6803F0A8FB67 +:1078900006000AD0022E04D0032E16D0042E00D0EB +:1078A000FFDF08B03046BDE8F087BDF81C000028B7 +:1078B000F7D0DDE905120091CDE901203A462146D5 +:1078C00048466368FFF77AFBEBE7687840F008000A +:1078D0006870E6E72DE9F04F9BB004464FF00008D2 +:1078E0003A48ADF85480ADF83080ADF85080A0F83B +:1078F0000480ADF81480ADF81880ADF82080ADF8A4 +:107900001C80007816460D464746012809D00228FB +:1079100007D0032805D0042803D008201BB0BDE8F9 +:10792000F08F20460BF08AFBD0BB28460BF086FB7D +:10793000B0BB60680BF0CFFB90BB606848B160895A +:107940002189884202D8B1F5007F01D90C20E5E7F2 +:1079500080460BAA06A92846FFF7EFF90028DDD1DB +:1079600068688078C0F34100022808D19DF81900AA +:1079700010F0380F03D028690BF0A4FB80B905A9DB +:107980002069FFF792F90028C8D1206950B16078CA +:1079900080079DF8150000F0380002D5F0B301E033 +:1079A00011E0D8BB9DF81400800613D59DF8150092 +:1079B00010F0380F03D060680BF084FB18B96068D2 +:1079C0000BF089FB30B11020A8E700001003002065 +:1079D0001400002007A96069FFF767F900289DD10E +:1079E000606940B19DF81D0000F0070101293BD1FD +:1079F00010F0380F38D008A9A069FFF756F9002811 +:107A00008CD19DF81C0080062ED49DF820008006A5 +:107A10002AD4A06950B19DF8210000E024E000F0D4 +:107A20000701012920D110F0380F1DD0E06818B1EE +:107A30000078C8B11C2817D20EAA611C2046FFF797 +:107A4000A3F90120B94660F30F27BA4607468DF81F +:107A50004E0042F60300ADF84C000DF13B0217A9B1 +:107A6000286809F0B6FC08B1072057E79DF85C00CC +:107A700016A9CDF80090C01CCDE9019100F0FF0BD4 +:107A800000230BF20122514613A804F005FBE8BBCA +:107A9000BDF858000990FE482A8929690092CDE96D +:107AA00001106B89BDF82C202868069904F0F4FABF +:107AB00001007DD120784FF0020AC10601D4800672 +:107AC0002BD5ADF80C90606950B907A906A8FFF74F +:107AD0008CF99DF81D0020F00700401C8DF81D005A +:107AE0009DF81C008DF84E7040F0C8008DF81C0009 +:107AF00042F60210ADF84C000CA903AACDF800A084 +:107B0000CDE90121002340F2032200E01FE013A889 +:107B1000079904F0C1FA01004AD1DD484D46001F23 +:107B20005B468088ADF839000EA8CDE90290CDF80B +:107B30000490CDF810904FF007090022CDF8009086 +:107B4000BDF858104FF6FF7004F0ECF910B1FFF7D4 +:107B500064F8E3E69DF83800000625D529460120A3 +:107B600060F30F218DF84E704FF42450ADF84C00A7 +:107B7000ADF8105062789DF81000002362F3000009 +:107B80008DF810006278CDF800A0520862F3410031 +:107B90008DF8100004AACDE9012540F2032213A8B4 +:107BA00004F07AFA010003D1606888B3206900E02C +:107BB00087E098B905A906A8FFF717F9607880074C +:107BC00006D49DF8150020F038008DF8150005E06A +:107BD0009DF8140040F040008DF814008DF84E70B0 +:107BE00042F60110ADF84C00208940F20121B0FBB3 +:107BF000F1F201FB1202606814ABCDF80080CDE910 +:107C00000103002313A8059904F046FA010058D196 +:107C10002078C00729D0ADF80C50A06950B908A948 +:107C200006A8FFF7E2F89DF8210020F00700401CAD +:107C30008DF821009DF820008DF84E7040F0400036 +:107C40008DF8200042F60310ADF84C0015A903AAE8 +:107C5000CDF800A0CDE90121002340F2032213A8B2 +:107C6000089904F019FA01002BD1E06868B329469D +:107C7000012060F30F218DF84E7042F60410ADF82C +:107C80004C00E068002302788DF8602040788DF881 +:107C90006100E06818AA4088ADF86200E0680079E9 +:107CA0008DF86400E068C088ADF86500CDF80090FC +:107CB000CDE901254FF4027213A804F0EDF901009B +:107CC00003D0099801F011F828E671480321001F3C +:107CD000017056B180883080BDF850007080BDF8CA +:107CE0003000B080BDF85400F080002016E670B57A +:107CF00001258AB016460B46012802D0022816D16B +:107D000004E08DF80E504FF4205003E08DF80E5033 +:107D100042F60100ADF80C0063B10024601C60F372 +:107D20000F2404AA08A9184609F053FB20B1072024 +:107D30000AB070BD1020FBE704A99DF8202054482C +:107D4000CDE90021801E02900023214603A802F203 +:107D5000012204F0A1F910B1FEF75FFFE8E74C48FB +:107D6000001F0EB14188318005700020E0E7F0B5BA +:107D700093B0074601268DF83E6041F60100ADF84C +:107D80003C0012AA0FA93046FFF7B1FF002848D1E6 +:107D90003F4C0025241FE7B31C2102A818F087FDE3 +:107DA0009DF808008DF83E6040F020008DF8080036 +:107DB00042F60520ADF83C000E959DF83A0011956D +:107DC00020F00600801C8DF83A009DF838006A46C5 +:107DD00020F0FF008DF838009DF8390009A920F047 +:107DE000FF008DF839000420ADF82C00ADF830000C +:107DF0000EA80A9011A80D900FA80990ADF82E506A +:107E000002A8FFF767FD00280BD1BDF80000E08055 +:107E100000E008E0BDF804002081401C608125706E +:107E2000002013B0F0BDE5802581BDF84800F4E7DF +:107E30002DE9F74F1649A0B00024091F17940A78BE +:107E4000A146012A04D0022A02D0082023B066E508 +:107E50004A88824201D00620F8E721988A46824269 +:107E600001D10720F2E701202146ADF848004FF686 +:107E7000FF788DF86E0042F6020B60F30F21ADF82B +:107E80004A80ADF86CB006918DF8724002E00000B7 +:107E9000140300201CA9ADF870401391ADF8508078 +:107EA00012A804F0E5F900252E462F460DAB072257 +:107EB00012A9404604F0DFF978B182285DD195B36C +:107EC0008EB3ADF86450ADF866609DF85E008DF835 +:107ED000144019AC012864D06BE09DF83A001FB340 +:107EE000012859D1BDF8381059451FD118A809A942 +:107EF00001940294CDE9031007200090BDF83610DC +:107F000010230022404604F036FAB0BBBDF86000F2 +:107F1000042801D006284AD1BDF8241021988142B6 +:107F20003AD10F2092E73AE0012835D1BDF8380068 +:107F3000B0F5205F03D042F6010188422CD1BAF897 +:107F40000200BDF83610884201D1012700E0002769 +:107F500005B19EB1219881421ED118A809AA0194A9 +:107F60000294CDE90320072000900D461023002243 +:107F7000404604F000FA00B902E02DE04E460BE066 +:107F8000BDF86000022801D0102810D1C0B217AA95 +:107F900009A909F0FFF950B9BDF8369086E7052028 +:107FA00054E705A917A8221D09F013FA08B1032008 +:107FB0004CE79DF814000023001DC2B28DF8142078 +:107FC00022980092CDE901401BA8069904F064F8BC +:107FD00010B902228AF80020FEF71FFE36E710B51E +:107FE0000B46401E88B084B205AA00211846FEF751 +:107FF000CBFE00200DF1080C06AA05A901908CE823 +:108000000700072000900123002221464FF6FF7051 +:1080100003F088FF0446BDF81800012800D0FFDFF8 +:108020002046FEF7FAFD08B010BDF0B5FF4F04463C +:1080300087B038780E46032804D0042802D00820E0 +:1080400007B0F0BD04AA03A92046FEF776FE05009E +:10805000F6D160688078C0F3410002280AD19DF80B +:108060000D0010F0380F05D020690BF02BF808B187 +:108070001020E5E7208905AA21698DE807006389BA +:10808000BDF810202068039904F006F810B1FEF73F +:10809000C4FDD5E716B1BDF8140030800420387057 +:1080A0002846CDE7F8B50C0006460CD001464FF641 +:1080B000FF7500236A46284604F0DFF928B100BFA7 +:1080C000FEF7ABFDF8BD1020F8BD69462046FEF76F +:1080D000ECFD0028F8D1A078314600F001032846D5 +:1080E000009A04F0F6F9EBE730B587B014460022A9 +:1080F0000DF1080C05AD01928CE82C0007220092CE +:108100000A46014623884FF6FF7003F00BFFBDF8C7 +:1081100014102180FEF781FD07B030BD70B50D460B +:10812000042107F0C7FC040000D1FFDF294604F159 +:108130001400BDE8704002F003BF70B50D46042185 +:1081400007F0B8FC040000D1FFDF294604F1140059 +:10815000BDE8704002F017BF70B50D46042107F06E +:10816000A9FC040000D1FFDF294604F11400BDE89A +:10817000704002F02FBF70B50546042107F09AFC4D +:10818000040000D1FFDF214628462368BDE8704087 +:108190000122FEF737BF2DE9F0478246042107F0A0 +:1081A00089FC040000D1FFDF04F1140002F0B8FEE6 +:1081B000401D20F0030626E0011D00880022431820 +:1081C00021465046FEF71EFF002820D0E07CA5681F +:1081D00070431FFA80F82888B7B2814610FA86F0FB +:1081E00080B22880404502D3A0EB08002880688830 +:1081F000B84200D2FFDF09EB0701414500D9FFDF9C +:108200006888C01B6880A06841880029D4D1BDE877 +:10821000F08770B50546042107F04CFC040000D13E +:10822000FFDF214628466368BDE870400222FEF762 +:10823000E9BE70B50E46054601F067F9040000D1AD +:10824000FFDF0120207266726580207820F00F0029 +:10825000001D20F0F00040302070BDE8704001F0BB +:1082600057B910B50446012900D0FFDF2046BDE80C +:1082700010400121FAF7BBB82DE9F34F9BB04FF046 +:10828000000B0C00ADF81CB05E461BD0E06830B1AE +:10829000A068B8B10188ADF81C10A0F800B01B9818 +:1082A000FAF71DFF5FEA000943F2020769D099F867 +:1082B0000000222863D304211B9807F0FBFB050074 +:1082C00005D103E010201DB0BDE8F08FFFDF05F100 +:1082D0001400109002F024FE401D20F00308A07846 +:1082E000012803D0022801D00720ECE7208878B1CC +:1082F000401C81B20BAA1B9803F08AFF0BA803F065 +:1083000093FF9DF836204FF45051012A0DD102E021 +:1083100043F20300D7E7BDF83420A2F52453023B13 +:1083200003D1822801D0A0B901E00846CBE7E0687C +:10833000B0B1CDE902B0072007AA0090CDF804B093 +:108340000492A2882188BDF81C301B9803F0EAFD36 +:1083500010B1FEF762FCB6E7A168BDF81C0008800A +:108360009DF82F00C00602D543F20140ABE70F98FD +:1083700038B1A1780078012905D080072AD40820D7 +:10838000A1E738469FE7C007F9D0002003900220FC +:108390008DF84C00A868EA7C418802FB08F28A420A +:1083A0001ED9031D0A93008896B247181FFA88FA4F +:1083B000B74200D3BF1B01EB0A00B04200D9FFDF78 +:1083C00007EB0A00B04200D9FFDF0A98C619A6F8E9 +:1083D00000B005E00120039003208DF84C002E68CA +:1083E0009DF8300010F0380F00D1FFDF9DF830000D +:1083F0000F49C0F3C200084410F8011C99F823008B +:10840000814201D90F205EE72088ADF8500008AA0C +:1084100006A905A88DE8070033462946039A1B984C +:10842000FEF79FFD002896D104E000001003002015 +:10843000FA2F0000DDE90501109A8DE8070008AB6E +:10844000072213A91B9803F07FF910B1FEF71BFC5C +:1084500039E7BDF82020DDE905018DE80700334646 +:108460002946039A1B98FEF7A9FD0598D0B9A07874 +:10847000012817D1E87CAC6800FB08F086B221889F +:1084800060881FFA88F70D18B54200D3AD1B384439 +:10849000B04200D9FFDFE819B04200D9FFDF6088A1 +:1084A0003844608000200EE770B5064615460C463D +:1084B0000846FEF771FB002805D12A4621463046C2 +:1084C000BDE8704013E470BDB2E470B51E461446BA +:1084D0000D0009D044B1616831B138B1FE49498815 +:1084E000814203D0072070BD102070BD2068FEF7C8 +:1084F00053FB0028F9D1324621462846BDE870409A +:10850000FFF7E8B970B515460C0006D038B1F2494E +:108510008988814203D0072070BD102070BD20687B +:10852000FEF73AFB0028F9D129462046BDE8704005 +:108530007BE570B5064686B00D46144610460AF037 +:10854000A3FDD0BB60680AF0C6FDB0BBA6F57F40B6 +:10855000FF3803D03046FAF7C2FD80B1284669469D +:10856000FEF765FC00280CD19DF810100F2008299B +:108570003CD2DFE801F008060606060A0A0843F2C4 +:10858000020006B070BD0320FBE79DF80210012930 +:1085900008D1BDF80010B1F5C05FF2D06FF4C05241 +:1085A000D142EED09DF8061001290DD1BDF804107E +:1085B000A1F52851062907D200E028E0DFE801F004 +:1085C000030304030303DCE79DF80A1001290ED11D +:1085D000BDF80810B1F5245FD3D0A1F524510239BC +:1085E000CFD00129CDD0022901D1CAE7FFDF6068D1 +:1085F00078B9002305AA2946304603F03EFF10B1A2 +:10860000FEF70BFBBDE79DF81400800601D4102097 +:10861000B7E76188224628466368FFF765FDB0E743 +:108620002DE9F043814687B08846144610460AF08B +:108630002BFD18B1102007B0BDE8F083002306AA77 +:108640004146484603F019FF18B100BFFEF7E5FAAE +:10865000F1E79DF81800C00602D543F20140EAE7B1 +:108660000025072705A8019500970295CDE903503D +:1086700062884FF6FF734146484603F07CFE0600D1 +:1086800013D160680AF000FD60B960680195CDE91A +:10869000025000970495238862884146484603F0BB +:1086A0006AFE0646BDF8140020803046CEE739B198 +:1086B000894B0A881B899A4202D843F2030070470B +:1086C000DAE510B586B0844C0423ADF81430E388A5 +:1086D00043B124898C4201D2914205D943F203006F +:1086E00006B010BD0620FBE7ADF810100021009188 +:1086F0000191ADF8003002218DF8021005A9029118 +:1087000004A90391ADF812206946FFF7B5FDE7E72C +:108710002DE9FC4781460F4608460AF08FFC88BBCE +:108720004846FAF7DCFC5FEA00080AD098F8000037 +:10873000222829D30421484607F0BCF9060005D1B8 +:1087400003E043F20200BDE8FC87FFDF06F11400FE +:1087500002F0FDFB05463878012803D0022804D03A +:108760000720F0E7A8070FD502E015F0340F0BD073 +:10877000B8793C1DC00709D0E08838B1A0680AF07C +:108780005DFC18B11020DEE70820DCE73A7820888D +:10879000002128B3A0F201130721112B18D20CD20B +:1087A000DFE803F00B090D0B1D0B121D100B0B1D49 +:1087B0001D1D1D0B1D00022A11D10846C3E7012A09 +:1087C000FBD00CE0EA0600E0AA06002AF5DA06E093 +:1087D000A0F5C0721F2A02D97D3A022AEDD8C1B293 +:1087E00098F82300CDE90001F28923463146484636 +:1087F000FEF734FCA7E72DE9F04F8BB01F46154676 +:108800000C4683460026FAF76AFC28B10078222835 +:1088100005D208200BB057E543F20200FAE7B8088A +:1088200001D00720F6E7032F00D100274FF6FF798C +:10883000CCB1022D71D320460AF04DFC30B904EBC7 +:108840000508A8F101000AF046FC08B11020E1E794 +:10885000AD1EAAB22146484603F009FF38F8021CB3 +:1088600088425AD1ADB21C49B80702D50889401CCC +:1088700000E001201FFA80F8F80701D00F8900E01E +:108880004F4605AA4146584603F0C2FC4FF0070A7E +:108890004FF00009FCB1204608E0408810283CD881 +:1088A000361D304486B2AE4237D2A0190288424506 +:1088B000F3D352E09DF8170002074ED57CB304EBCA +:1088C0000608361DB8F80230B6B2102B25D89A1912 +:1088D000AA4222D802E040E010030020B8F80020AD +:1088E00091421AD1C0061BD5CDE900A90DF1080CA3 +:1088F0000AAAA11948468CE80700B8F8001000221F +:10890000584603F00FFB10B1FEF787F982E7B8F87D +:108910000200BDF82810884202D00B207AE704E05C +:10892000B8F80200304486B206E0C00604D55846C6 +:10893000FEF7E6FB00288AD19DF81700BDF81A1053 +:1089400020F010008DF81700BDF81700ADF80000FA +:10895000FF235846009A03F0BCFD05A803F064FC11 +:1089600018B9BDF81A10B942A4D90421584607F025 +:10897000A1F8040000D1FFDFA2895AB1CDE900A916 +:108980004D46002321465846FEF768FB0028BDD11E +:10899000A5813FE700203DE72DE9FF4F8BB01E4644 +:1089A00017000D464FF0000412D0B00802D0072087 +:1089B0000FB089E4032E00D100265DB108460AF00D +:1089C00081FB28B93888691E08440AF07BFB08B18E +:1089D0001020EDE7CA4AB00701D5518900E0012116 +:1089E000F0074FF6FF7802D05089401E00E0404665 +:1089F00086B206AA0B9803F00BFC4FF000094FF06B +:108A0000070B0DF1140A38E09DF81B00000734D560 +:108A1000CDF80490CDF800B0CDF80890CDE9039AD8 +:108A2000434600220B9803F0A6FC60BB05B3BDF8DB +:108A300014103A8821442819091D8A4230D3BDF800 +:108A40001E2020F8022BBDF8142020F8022BCDE9BF +:108A500000B9CDE90290CDF810A0BDF81E10BDF808 +:108A6000143000220B9803F086FC08B103209FE726 +:108A7000BDF814002044001D84B206A803F0D4FB06 +:108A800020B1822806D0FEF7C8F891E7BDF81E1085 +:108A9000B142B9D934B17DB13888A11C884203D222 +:108AA0000C2085E7052083E722462946404603F04F +:108AB000DEFD014628190180A41C3C80002077E7D8 +:108AC00010B504460AF0E0FA08B1102010BD8C4839 +:108AD00040892080002010BD2DE9F0438DB00D4667 +:108AE00081464FF00208142106A817F0E0FE012687 +:108AF0008DF81C6000208DF81D008DF81860ADF811 +:108B000020504846FAF7EBFA48B10078222812D3F1 +:108B10000421484606F0CEFF040005D103E043F2ED +:108B200002000DB088E5FFDF04F11400074602F0F3 +:108B30000EFA400601D40820F3E705AA04A903A809 +:108B40008DE807004246214648466368FEF709FA69 +:108B500000B1FFDFDDE903018DE8830005AB0722EB +:108B600006A9484602F0F0FD10B1FEF78CF8D8E7F0 +:108B7000A674BDF81420DDE903018DE80700424624 +:108B8000214648466368FEF719FA29464846F9F730 +:108B90001FFC0BA9384602F0C9F900B1FFDFBDF890 +:108BA0002C40172C01D2172000E02046A84201D902 +:108BB0002C4602E0172C00D2172421464846FFF726 +:108BC000BCFA21464846F9F737F90020A9E7F8B57D +:108BD0001C4615460E46069F07F077F82346FF1DF4 +:108BE000BCB231462A46009406F0D5FCF8BD70B5FB +:108BF0000C4605460E21204617F037FE0020208047 +:108C00002DB1012D01D0FFDF70BD062000E0052051 +:108C1000A07170BD10B548800878144620F00F0090 +:108C2000001D20F0F00080300B4608701422214611 +:108C300003F1080017F0E7FDBDE8104000F068BC44 +:108C40002DE9F0472F4F491D064621F003019146BB +:108C50000C46386806F0EEF8050000D1FFDF4FF053 +:108C600000083560A5F800802146386806F0E2F873 +:108C7000050000D1FFDF7560A5F8008004FB09F155 +:108C8000091D386806F0D6F8040000D1FFDFB46093 +:108C9000C4F80080BDE8F0872DE9F041491D21F0BE +:108CA0000304184D1746064601682246286806F058 +:108CB000EAF822467168286806F0E5F87C43221D30 +:108CC000B168286806F0DFF8042006F09DFE04462F +:108CD000042006F0A1FE201A012804D12868BDE86E +:108CE000F04106F098B8BDE8F08110B50C4603F0ED +:108CF0005CFA00B1FFDF2046BDE81040FDF78DBFF4 +:108D00001003002014000020F0B59BB00546592048 +:108D10008DF80000281DADF80400ADF806101E46C1 +:108D200017460BA9684603F029FC00B1FFDFBDF828 +:108D30003040032C01D2204600E00320C1B2284677 +:108D400000F07EFF3870022C00D30224E1B22846E6 +:108D500000F076FF401C30701BB0F0BD2DE9F04FE5 +:108D60000C00FC499DB08246D1E90201FA4ECDE9E2 +:108D70000C010AF10300717A327A1144CDB220F06D +:108D800003010091377E07F1010704D1F8B208F022 +:108D9000A7FA00B1FFDF00982A4600EB0710C01CBD +:108DA00020F00301F7694FF00009009134B981F810 +:108DB0000090B8B203F081F800B1FFDF00982346BD +:108DC00038440090B07A317A2A460844C1B26846E5 +:108DD00000F0FEFE0098C01C20F003000090737AA3 +:108DE000327AB17A04B1002006F056FD00990844A9 +:108DF00000902146684600F02EFF00273D46B3460E +:108E000096F801800CE0284600F0C5FE0646817801 +:108E10008088F9F7ABF871786D1C00FB0177EDB233 +:108E20004545F0D10098C01C20F00300009004B12B +:108E300000203946F9F7A1F800990027084400906E +:108E40003D469BF801800CE0284600F0A4FE064653 +:108E5000C1788088FEF7FFFB71786D1C00FB0177FD +:108E6000EDB24545F0D10098C01C20F00300009001 +:108E700004B100203946FEF7F7FB00990844C01DF5 +:108E800020F007000090ECBBB54AB4491160111DF9 +:108E9000401E086001223C21B24806F08EFCFAF721 +:108EA0007EF8B1484178806804F00FF9AE4801249B +:108EB0000C300178012915D144218DF80410C078B7 +:108EC0008DF8080010B1012803D004E08DF80840A7 +:108ED00001E08DF8089001A805F047FE10B10EA83A +:108EE00004F0B3F900211E22084601F0F7F9FBF760 +:108EF000AFF803F018FD98480CAA00210C30F8F7E1 +:108F000029FA00E01DE000B1FFDF9BF81900FEF731 +:108F10002EFF00B1FFDF90484FF4B871443017F0D6 +:108F2000C6FC8D480221443080F8694180F86A11FE +:108F300080F86B1180F86C91062180F86D11052185 +:108F4000017100991DB0A1EB0A00BDE8F08F70B56A +:108F5000814D06464435287805EB4014E8780834FE +:108F6000A0B9A81990F86801002810D0A8780B289B +:108F700000D3FFDF207820F0FF002070607866F3D8 +:108F8000020020F0080060700120E870204670BDEB +:108F90002DE9F04105460C46002700780521904652 +:108FA0003E46B1EB101F00D0FFDF287A50B10128F8 +:108FB0000ED0FFDFA8F800600CB12780668000208B +:108FC000BDE8F0810127092674B16888A08008E017 +:108FD0000227142644B16888A0802869E060A88A26 +:108FE0002082287B2072E5E7A8F80060E7E710B54B +:108FF0005D4C6068C11D21F00701814200D0FFDF98 +:10900000554801210022017042700172032343720E +:1090100081720273052282821F22C282417353A28F +:1090200002610A22027641764FF4B061C161616843 +:10903000416010BD30B54C4C1568636808339D42E3 +:1090400002D20420136030BD434B5D785A6802EBB6 +:10905000C502107051700320D0801720908001202D +:10906000D07090705878401C58706068083060600C +:10907000002030BD70B5064637480024457807E02B +:10908000204600F088FD0178B14204D0641CE4B2AF +:10909000AC42F5D1002070BDF7B5064608780C4605 +:1090A00050B1FFF7E7FF0546202E07D0232E17D03B +:1090B000212E18D0222E16D00720FEBD00F076FDFE +:1090C0000DB1697800E00021401A81B2A078014416 +:1090D000FF29F1D80028EFD0A088022803D2EBE7BF +:1090E00060881728E8D365B9207802AA0121FFF724 +:1090F000A1FF0028E1D12078FFF7BCFF050000D1D7 +:10910000FFDF202E08D0212E0ED0222E0FD0232EAE +:1091100007D0FFDF0020FEBDA0786870A088E8803F +:10912000F8E76088A880F5E7A078A870F2E7A07853 +:10913000E870EFE700B59BB055218DF8001000787E +:109140000BA900F001008DF80400684603F016FA40 +:109150001BB000BD740C0200280400200000002099 +:1091600000060240DC0500201C0000206E5246353F +:109170007800000000B501789BB001F001018DF886 +:109180000410417801F001018DF805100178C1F358 +:1091900040018DF806104178C1F340018DF80710A9 +:1091A000017889088DF80810417889088DF8091030 +:1091B00081788DF80A10C1788DF80B1000798DF840 +:1091C0000C004F208DF800000BA9684603F0D6F97B +:1091D000BEE700B59BB058218DF80010ADF8040033 +:1091E0000BA9684603F0CAF900B1FFDF9DF8300013 +:1091F00000F00100ACE72DE9F84FDFF8F483FD4CF7 +:1092000000271BE0022000F066FD0120FFF79FFE13 +:109210000546F94806F0FAFA686000B9FFDF6868A9 +:1092200003F0F9F9A0B12846FAF7C7F9284600F08B +:1092300058FD18B9F048696806F0F1FA94F8690128 +:109240000028DFD1022006F0DFFB064600259AE069 +:10925000E948696806F0E3FAF4E7B8F80210404616 +:10926000491C89B2A8F80210B14201D30021418003 +:109270000221B8F8020006F01DFC00285DD0B8F805 +:109280000200FFF7A6FF78B1B8F8020006F02FFD44 +:109290005FEA000900D1FFDF484605F0E2FF18B1A0 +:1092A000B8F8020003F04FFDB8F8020006F00DFD1B +:1092B0005FEA000900D1FFDF484605F0CBFFE0BBC5 +:1092C0000321B8F8020006F0F5FB5FEA000B47D176 +:1092D000FFDF45E0DBF8040010B10078FF2848D03C +:1092E000042000F0F8FC0320FFF731FE82464846D8 +:1092F00006F0E2F8CAF8040000B9FFDFDAF804006B +:1093000006F0BCF9002100900170B8F80210504638 +:10931000AAF8021003F094FB484606F0B1F900B930 +:10932000FFDF504600F0DDFC18B99AF80100000795 +:1093300004D50099CBF8041012E022E0DBF8040019 +:1093400038B10178491C11F0FF01017008D1FFDF2D +:1093500006E000221146484600F01BFC00B9FFDF82 +:1093600094F86B0128B1B8F8020003F044FB002820 +:10937000B0D194F8690120B1484606F0F7F900B180 +:1093800001276D1CEDB2B54204D294F86B010028A0 +:109390007FF463AF002F7FF433AFBDE8F84F0520B3 +:1093A00000F099BC10B5924CA0600868E060AFF284 +:1093B000B91000F006FF607010BD8E4800214438DF +:1093C00001708B4801708D494160704730B505468A +:1093D0004FF080500C46D0F8A4109BB0491C05D12A +:1093E000D0F8A810C9430904090C08D050F8A01FF0 +:1093F00001F0010129704168216080680EE02B2096 +:109400008DF800000BA9684603F0B8F800B1FFDF43 +:10941000012028700C982060BDF83400A0802878C6 +:10942000002803D0607940F0C00060711BB030BDEF +:10943000F0B54FF080540746D4F880009BB00D463D +:109440002B26401C0BD1D4F88400401C07D1D4F843 +:109450008800401C03D1D4F88C00401C0BD0D4F8F9 +:1094600080003860D4F884007860D4F88800B86050 +:10947000D4F88C0016E08DF83C6069460FA803F024 +:109480007DF800B1FFDF01983860029878608DF8B0 +:109490003C6069460FA803F071F800B1FFDF019846 +:1094A000B8600298F860D4F89000401C0BD1D4F852 +:1094B0009400401C07D1D4F89800401C03D1D4F884 +:1094C0009C00401C08D054F8900F286060686860C9 +:1094D000A068A860E06816E08DF800600BA96846F7 +:1094E00003F04CF800B1FFDF0C9828600D9868601D +:1094F0008DF800600BA9684603F040F800B1FFDF6B +:109500000C98A8600D98E86026E43A4800791EE5BA +:1095100070B5384CE07828B3207804EB4010407ADE +:1095200000F00700204490F8680100B9FFDF2078C0 +:10953000002504EB4010407A00F00700011991F873 +:109540006801401E81F868012078401CC0B220707C +:109550000B2800D12570A078401CA07009F007F9F5 +:10956000E57070BDFFDF70BD3EB50546032106F016 +:10957000A1FA0446284606F0A8FB054604B9FFDF19 +:10958000606818B10078FF2800D1FFDF01AA6946A2 +:10959000284600F0FEFA60B9FFDF0AE0002202A9C7 +:1095A000284600F0F6FA00B9FFDF9DF8080000B188 +:1095B000FFDF9DF80000411E8DF80010EED26068BC +:1095C0000199884201D1002060600A4C94F86B0137 +:1095D000022800D3FFDF94F86B0118B904484078E3 +:1095E00000F00EFE94F86B01401C84F86B013EBD48 +:1095F0001C0000206C040020DC050020101300205B +:1096000070B50546A0F57F400C46FF3800D1FFDF5E +:10961000012C01D0FFDF70BDFFF777FF040000D100 +:10962000FFDF207820F00F00401D20F0F0005030C8 +:10963000207065800020207201202073BDE87040FA +:1096400066E770B515460C460646FFF75EFF90B11B +:10965000017821F00F01491D21F0F0015031017016 +:1096600046800121017221680161A1888182057310 +:10967000BDE870404CE73046BDE870401321FBF771 +:10968000D4B830B59DB0FFF7F5FC040000D1FFDF82 +:10969000A588E1880BAB0CAA2846FFF735FB5420C0 +:1096A0008DF800009DF830008DF804009DF82C0026 +:1096B0002D1D8DF80500ADF80650ADF80850E08876 +:1096C000ADF80A000DA9684602F058FF002800D046 +:1096D000FFDF1DB030BD2DE9F84FF94E05464FF0C4 +:1096E000000A307810B10820BDE8F88F284609F04C +:1096F000CBFC08B11020F7E7F24C207808B9FFF74F +:1097000076FC617A207A0844C4B200F04FFAA04295 +:1097100008D2201AC1B22A460020FFF78BFC5FEA6C +:10972000000AE1D1E6484FF00009C84641684F46BB +:10973000C91C21F003014160E248CDF800904E467B +:109740004C4690F801B00EE0204600F024FA417833 +:10975000827809F10109884412FB0177C07810FB77 +:109760000166641CE4B25C45EED10098D54C00EB78 +:10977000890000EBC80000EB8700217A00EB86002F +:1097800000EBC100617ADFF8388300EBC100A17AF9 +:1097900000EBC100D8F80410471801213846FFF744 +:1097A000DDFA064629683844884202D8B6F5803F7B +:1097B00013D328600020FFF75DFC60B1D8F80410D7 +:1097C00045460839814200D0FFDF6078401E607056 +:1097D000686808386860042086E700213846FFF78B +:1097E000BDFA0446A64200D0FFDFE119C8F8041014 +:1097F00029604FF6FF71A8F80210012188F80010C7 +:10980000504671E72DE9F0410446AD4817460D4634 +:10981000007810B10820BDE8F081084609F00EFC80 +:1098200008B11020F7E7A74E307808B9FFF7DFFB43 +:10983000601E1E2807D8012C3FD12878FE283CD86E +:1098400030760020E7E7A4F120001F2805D8E0B219 +:109850003A462946BDE8F0411EE4A4F140004FF02D +:1098600000081F2821D8402C02D0412C25D117E018 +:10987000687829784418A97881421ED8FF2C08D826 +:1098800007F012FF074608F031FF381A801EA04289 +:1098900001DA1220BFE728883081A878B07224E06E +:1098A0002846BDE8F04100F042BAA4F1A0001F280C +:1098B00003D8A02C03D0A12C06D00720ABE7287832 +:1098C00000F00100707610E029680920F829A2D381 +:1098D0008A07A0D1727B02F00302012A04D1F28A26 +:1098E000D73293B28B4296D8F161404693E72DE987 +:1098F000F04707460C46084609F0C6FB40B9384613 +:1099000009F0E0FB20B9F81C20F00300B84202D0B7 +:109910001020BDE8F0876B484FF000084430817894 +:1099200089B14178824600EB4115B4F8009015F8F2 +:10993000080F234600F00F000022294600F0DFF94F +:10994000060004D013E0A4F800800520E1E797B1F9 +:109950002188494501D90C260DE02878234600F0DE +:109960000F003A46294600F0CAF9060005D00C2E31 +:1099700001D0A4F800803046CBE79AF801005446A5 +:10998000401CC0B28AF801000B2801D184F8018084 +:10999000A078401EA070697801F00700062827D241 +:1099A000DFE800F026091E031E1E0807E3D46888BE +:1099B000FFF7DAFDDFE74448696805F030FF94F807 +:1099C000690130B93E48407800F01AFC94F869010A +:1099D00000B1FFDF94F86901401C84F86901CAE70F +:1099E00000EB0A0191F86801401C81F86801C2E7A8 +:1099F000FFDFC0E770B50D46044609F01FFB18B93C +:109A0000284609F041FB08B1102070BD29462046C8 +:109A1000BDE8704007F09BBC70B5044615460E4685 +:109A2000084609F00BFB18B9284609F02DFB08B1D0 +:109A3000102070BD022C03D0102C01D0092070BD65 +:109A40002A463146204607F0A5FC0028F7D005201D +:109A500070BD70B514460D46064609F0EFFA38B9E8 +:109A6000284609F011FB18B9204609F02BFB08B174 +:109A7000102070BD22462946304607F0AAFC002877 +:109A8000F7D0072070BD10B59AB0044609F0FCFA73 +:109A900010B110201AB010BD0F208DF800000BA9D6 +:109AA000684602F06BFD0028F4D19DF83400207068 +:109AB000BDF836006080BDF83800A0800020E9E7DE +:109AC0001C00002028040020DC05002070B505469D +:109AD0000C46084609F0F6FA20B93CB1206809F0B6 +:109AE000D3FA08B1102070BDA08828B121462846BD +:109AF000BDE87040FDF727BE092070BD70B5044673 +:109B00000D46084609F09AFA30B9601E1E2814D88E +:109B1000284609F093FA08B1102070BD022C01D933 +:109B2000072070BD04B9FFDFA64800EB840050F8A1 +:109B3000041C2846BDE870400847A4F120001F28F7 +:109B4000EED829462046BDE87040FAF79BB970B5BB +:109B500004460D46084609F097FA30B9601E1E28E3 +:109B60000DD8284609F06AFA08B1102070BD012C02 +:109B700001D0022C01D1062070BD072070BDA4F1D8 +:109B800020001F28F9D829462046BDE87040FAF782 +:109B900022BA05F01ABB30B58B4D04466878A04256 +:109BA00000D8FFDF686800EBC40030BD70B58648A0 +:109BB00000252C46467807E02046FFF7ECFF40786A +:109BC000641C2844C5B2E4B2B442F5D1284670BD45 +:109BD0002DE9F0410646022012B101EB4200401D82 +:109BE000C7B23068C01C20F0030232601BBB76484D +:109BF0003B460921203009F00DF9002408E0092C2A +:109C000011D2DFE804F005070509090B0B05050073 +:109C10006E4804E06E4802E06E4800E06E4809F0CD +:109C200019F9054600E0FFDFA54200D0FFDF641C04 +:109C3000E4B2092CE3D3306800EB07103060EAE5AA +:109C4000001D4143452900D24521491EB1FBF0F0DA +:109C5000401CC0B270472DE9FC5F06465A484FF0E1 +:109C600000088B464746454690F801901FE028467D +:109C7000FFF791FF040000D1FFDFB4F804A0E188F2 +:109C800001AB6A465046FFF73FF860789DF8043014 +:109C90003844C7B20AF1040081B280B29DF80020B6 +:109CA00005F05EFF62786D1C00FB0288EDB24D4549 +:109CB000DDD13068C01C20F003003060BBF1000F24 +:109CC00000D000204246394605F058FF316808446C +:109CD0003060BDE8FC9F3C49443108710020C870E9 +:109CE000704739494431CA782AB10A7801EB4211E8 +:109CF0000831814201D001207047002070472DE9D2 +:109D0000F041044600201880601E1D4616460F468E +:109D1000052800D3FFDF2B482A46103000EB8400D3 +:109D2000314650F8043C3846BDE8F041184738B594 +:109D30000446407800F00300012803D002280BD02D +:109D4000072038BD606858B109F0C5F9D0B960681E +:109D500009F0B8F920B915E0606809F06FF988B921 +:109D600069462046FCF77BF90028EAD1607800F0CC +:109D70000300022808D19DF8000028B1606809F0AE +:109D8000A1F908B1102038BD6189F8290DD82089C2 +:109D900088420AD8607800F003020B48012A06D1F5 +:109DA000D731C26989B28A4201D2092038BD94E80C +:109DB0000E0000F10C0585E80E000AB90021818231 +:109DC000002038BD740C020028040020F13C000083 +:109DD0006DC90000892F00009310010010B5EFF34A +:109DE000108000F0010472B6E9484178491C4170C6 +:109DF0004078012801D108F0D9FC002C00D162B6CE +:109E000010BD70B5E24CE07848B90125E570FFF768 +:109E1000E5FF08F0D3FC20B1002008F0AFFC0020E3 +:109E200070BD4FF080406571C0F80453F7E770B51E +:109E3000EFF3108000F0010572B6D54C607800B9E0 +:109E4000FFDF6078401E6070607808B908F0B2FCEF +:109E5000002D00D162B670BDCD4810B5C17821B1DA +:109E600000214171C170FFF7E2FF002010BD10B565 +:109E7000044608F0A3FCC649C978084000D0012078 +:109E80002060002010BD2DE9F05FDFF804934278D8 +:109E9000817889F80620002689F80710074689F896 +:109EA00008600078354620B101280FD002280FD075 +:109EB000FFDF08F090FC98B108F094FCB0420FD19D +:109EC000304608F093FC0028FAD047E00126F0E77E +:109ED000FFF784FF08F072FC0028FBD00226E8E7B9 +:109EE00001208407E060C4F80451AA490E6001070C +:109EF000D1F84412A74AC1F3423124321160A54976 +:109F00004FF0020B34310860C4F804B3A060DFF8EE +:109F100088A2DAF80010C94341F3001101F10108E9 +:109F2000DAF8001041F01001CAF8001000E020BF7C +:109F3000D4F804010028FAD0304608F057FC002875 +:109F4000FAD0B8F1000F05D1DAF8001021F01001B5 +:109F5000CAF80010C4F808B3C4F8045199F807000F +:109F60004C4670B1387860B908F028FC074608F014 +:109F700019FE6FF0004117B1C4E9031001E0C4E914 +:109F8000030116B12571BDE8F09F0127BE072771B7 +:109F90004FF01908C6F80883B761C6F80051C6F833 +:109FA0000C51C6F8105108F009FC10B1A7703761C8 +:109FB00000E02770FFF712FF7649A0792031086092 +:109FC000C6F80483DFE770B5050000D1FFDF4FF06E +:109FD00080424FF0FF30C2F808030021C2F80011A0 +:109FE000C2F80411C2F80C11C2F81011684C61706B +:109FF00008F0EAFB10B10120E07060702846BDE86F +:10A00000704040E72DE9F041614C4FF08047012559 +:10A01000E079F0B1012803D0217A401E814218DA9C +:10A0200008F0CCFB064608F0BDFDE179012902D914 +:10A03000217A491C21720EB1216900E0E168411AC0 +:10A04000022902DA11F1020F0BDC0EB1206100E0EF +:10A05000E060FFF7C3FE08F0B1FB28B13D61A570D9 +:10A0600003E07D61BDE8F081257000202072F9E7F2 +:10A070002DE9F05F4948D0F800B0484A4849083215 +:10A0800011608406D4F8080110B14FF0010801E016 +:10A090004FF00008D4F8000100B101208146D4F847 +:10A0A000040108B1012600E00026D4F80C0100B13B +:10A0B00001208246D4F8100108B1012700E00027F2 +:10A0C00048EA090126EA010020EA0A00B84300D064 +:10A0D000FFDF0025B8F1000F04D0C4F808510120BB +:10A0E00008F04CFB5FEA0900DFF8A4804FF001099B +:10A0F00013D0C4F8005198F8050020B188F8055035 +:10A10000002008F03BFB98F8000030B108F056FB47 +:10A1100018B188F80290C4F810900EB1C4F8045138 +:10A12000BAF1000F0CD0C4F80C5198F80200464662 +:10A1300000B9FFDFB5703570C4F81490FFF777FEF3 +:10A1400037B1C4F8105198F8040008B1FFF75AFF6E +:10A150001249091DC1F800B015E770B50C4DE8783B +:10A1600008B908F027FB01208407A061A87850B146 +:10A17000D4F80C0120B9002008F038FB0028F7D1F2 +:10A180000020C4F80C014FF0FF30C4F8080370BD84 +:10A19000300000201805004010ED00E010050240DE +:10A1A000010000014FF0E0214FF00070C1F8800184 +:10A1B000C1F88002384B802283F80024C1F80001E6 +:10A1C000704700B502460420344903E001EBC003A8 +:10A1D0001B792BB1401EC0B2F8D2FFDFFF2000BDBB +:10A1E00041F8302001EBC00100224A718A7101223E +:10A1F0000A7100BD294A002102EBC00001717047BD +:10A2000010B50446042800D3FFDF244800EBC40443 +:10A210002079012800D0FFDF6079A179401CC0B20D +:10A22000814200D060714FF0E0214FF00070C1F822 +:10A23000000210BD2DE9F041194805681849194878 +:10A24000083108601448042690F80004134F4009B0 +:10A25000154C042818D0FFDF16E0217807EBC10069 +:10A260000279012A08D1427983799A4204D042794D +:10A27000827157F8310080472078401CC0B22070AE +:10A28000042801D300202070761EF6B2E5D20448DF +:10A29000001D0560BDE8F08119E000E01C0600200B +:10A2A000100502400100000144000020F8B51D46E1 +:10A2B000DDE906470E000AD005F019FD2346FF1D13 +:10A2C000BCB231462A46009405F09EF9F8BDD0197B +:10A2D0002246194616F052FA2046F8BDF84B58604F +:10A2E00019721A80C90016F0E2BA70B50D4604461C +:10A2F000102116F0BAFA258117206081A07B40F06A +:10A300000A00A07370BD4FF6FF720A800146032059 +:10A3100008F050BE704700897047827BD30701D197 +:10A32000920703D480890880002070470520704779 +:10A33000827B920700D58181704701460020098801 +:10A3400047F2FE12114200D00120DD49497A00296E +:10A3500001D040F00800704700B50346807BC0077D +:10A3600001D0052000BD59811846FFF7E6FFC00760 +:10A3700003D0987B40F004009873987B40F0010074 +:10A380009873002000BD827B520700D509B1408937 +:10A39000704717207047827B61F3C3028273704756 +:10A3A0002DE9F04F0E46017804464FF0010B0BFAF1 +:10A3B00001F047F2FF1100EA010961684FF6FF78EA +:10A3C00087B008881D469646404506D0B9F1000F73 +:10A3D00007D047F2FE12104203D0012007B0BDE8BB +:10A3E000F08F40EA090008804FF0000A95B185F827 +:10A3F00000A022780027052003210223102A6FD213 +:10A40000DFE802F06E0D2C35546F768054CBC79C7C +:10A41000CFFEFDFC20780B28EBD00420DEE762683D +:10A420002089937B9B077DD5172851D313898342BD +:10A43000FBD39289172A01D3824249D12A7822F08C +:10A440003F02921C2A70A5F8010031806168888162 +:10A450006068817B21F00201817342E1042129704F +:10A460002189A5F801106189A5F803108FE0208AE1 +:10A470003188C01D1FFA80F84145D6D306202870C8 +:10A480002089A5F801006089A5F80300A089A5F836 +:10A4900005000721208ACDE9000160882A4671461F +:10A4A0006369FFF703FFA6F800801AE1082A10D0BD +:10A4B000082129702189A5F801106189A5F80310E8 +:10A4C00030806A1D694604F10C0006F082FF10B16D +:10A4D000CCE01021EDE730889DF80010084456E0EC +:10A4E0000EE10A2028702089A5F801003180B2E031 +:10A4F0000C2129702189A5F801106189A5F80310A4 +:10A500003080A8E0218933880BEB41021FFA82FAE0 +:10A51000534576D3BAF1050F73D30E222A7008EA99 +:10A52000410100E07FE0CDE9001B60882A467146CA +:10A53000E368FFF7BBFEA6F800A0D2E06048417ACE +:10A54000002970D0491E41724068217AE26800EB10 +:10A55000C105D046A9882868D2F800C00844A0F1F7 +:10A56000080140F808CC506848608DF800308DF83C +:10A5700001A028680290A888ADF8040060886946A8 +:10A58000F7F769FCA5F80480002E01D04046308022 +:10A59000A7E0287840F080022A70287840F0400236 +:10A5A0002A7060893288C01C1FFA80F842455DD34A +:10A5B000287820F03F00123028702289A5F8012069 +:10A5C0006089CDE9000160882A467146E368FFF79B +:10A5D0006DFEA6F80080287841063CD500065ED5C1 +:10A5E0008DF800B08DF801A03188CDE9025A091D1F +:10A5F000ADF804100420DFF8C88003E059E04FE014 +:10A600002DE033E0049098F808008DF8140060887D +:10A610006946F7F720FC074630880C303080022F5F +:10A6200002D0E7B36FE048E09DF81420D8F804109A +:10A6300098F80830404601EBC2019A4216D28A8847 +:10A64000A2B9427A521C88F809200D6030888880AF +:10A65000A6F800A057E061682089888041E0A189C0 +:10A660003288491D1FFA81F8424501D204274AE089 +:10A6700029782A4621F03F01163129702189A5F851 +:10A6800001106189A5F80310A189CDE90010608847 +:10A6900071462369FFF70AFEA6F80080DBE720E099 +:10A6A000287820F03F0018302870207A68703380B6 +:10A6B00017E060680188090404D4052723E000003E +:10A6C0003C060020C0882189884201D006271AE074 +:10A6D0001E202870A6F800B06068018821F40041AF +:10A6E0000180B9F1000F0ED0DF4861880022008898 +:10A6F0008300032008F0BEFB61682078887007E0C3 +:10A70000A6F800A003276068018821EA09010180FA +:10A71000384663E62DE9F04F87B01746109C0D00D0 +:10A7200083461E461AD03078C10703D000F03F00A0 +:10A73000192801D9012100E000212046FFF723FE5E +:10A74000A8420BD32088A0F57F41FF3906D030788E +:10A75000410601D4000603D508203FE607203DE668 +:10A7600000208DF800008DF8010030786B1E00F09D +:10A770003F0C0122A81E4FF0050A4FF0020999B2C2 +:10A78000BCF1200F76D2DFE80CF08C10755F756994 +:10A79000758D759E75B875BD75CB75D775E4757576 +:10A7A00075F475F275F175F0758C052D79D104206D +:10A7B0008DF80000A0788DF804007088ADF80600D0 +:10A7C00030798DF80100707800F03F000C2829D016 +:10A7D0000ADCA0F10200092863D2DFE800F012626F +:10A7E00015621A621D622000122824D004DC0E2893 +:10A7F0001BD01028DAD11BE016281FD01828D5D17D +:10A800001FE02078800701E020784007002848DA20 +:10A81000F1E020780007F9E72078C006F6E7207815 +:10A820008006F3E720784006F0E720780006EDE7A1 +:10A830002088C005EAE72088C004E7E72088800474 +:10A84000E4E720884004E1E72078800729D5032D3C +:10A8500027D18DF800A0B6F8010083E021784907E0 +:10A860001FD5062D1DD381B27078012803D0022890 +:10A8700017D102E0CCE0022000E0102006228DF883 +:10A88000002072788DF80420801CB1FBF0F2ADF846 +:10A89000062092B242438A4203D10397ADF8089052 +:10A8A000A9E07BE02078000778D5072198B28DF8E1 +:10A8B00000108108ADF80410B0EB810F6ED1029743 +:10A8C000ADF8062097E02178C90667D5022D65D33B +:10A8D00081B208208DF80000707802285ED300BF96 +:10A8E000B1FBF0F28DF80400ADF8062092B24243BD +:10A8F0008A4253D1ADF808907CE0207880064DD58F +:10A90000092003E02078400648D50A208DF8000091 +:10A91000A088ADF80400ADF80610ADF8082069E095 +:10A920002078000672D50B20ADF804108DF80000D9 +:10A93000ADF8062002975EE02188C90566D5022D94 +:10A9400064D381B20C208DF80000707804285DD3A8 +:10A95000C6E72088C00459D5012D57D10D208DF8A8 +:10A960000000A088ADF8040045E021E026E016E0F4 +:10A97000FFE72088800449D5052D47D30E208DF8A8 +:10A980000000A088ADF80400B6F803006D1FADF814 +:10A990000850ADF80600ADF80AA02BE036E020889C +:10A9A000400433D5012D31D10F208DF8000022E075 +:10A9B000208800042AD4B6F80100E080A07B0007BC +:10A9C00024D5032D22D3307800F03F001B2819D066 +:10A9D00011208DF80000208840F40040A4F8000009 +:10A9E000B6F80100ADF80400ED1E0320ADF80650E6 +:10A9F000ADF80800039769465846F7F72CFA0500AA +:10AA000008D016E010208DF80000E9E7072510E0D7 +:10AA100008250EE0307800F03F001B2809D01D28E3 +:10AA200007D05946032008F0C5FA208800F40040FA +:10AA30002080A07B400708D52046FFF77EFCC0079A +:10AA400003D1A07B20F00400A0732846C6E400B523 +:10AA500087B0032805D18DF8000088B26946F7F762 +:10AA6000FAF907B000BD00003C060020F8B51D460D +:10AA7000DDE906470E000AD005F039F92346FF1D2F +:10AA8000BCB231462A46009404F0BEFDF8BDD01990 +:10AA90002246194615F072FE2046F8BD2DE9FF4FFB +:10AAA0008DB09B46DDE91B57DDF87CA00C46082BDA +:10AAB00005D0E06901F00CF950B11020D2E02888EF +:10AAC000092140F0100028808AF80010022617E0C3 +:10AAD000E16901208871E2694FF420519180E169B8 +:10AAE0008872E06942F601010181E0690021817309 +:10AAF0002888112140F0200028808AF800100426C0 +:10AB000038780A900A2038704FF0020904F11800D2 +:10AB10004D460C9001F0ACFBB04681E0BBF1100F4C +:10AB20000ED1022D0CD0A9EB0800801C80B20221AE +:10AB3000CDE9001005AB52461E990D98FFF796FF20 +:10AB4000BDF816101A98814203D9F74800790F9082 +:10AB500004E003D10A9808B138702FE04FF00201E9 +:10AB6000CDE900190DF1160352461E990D98FFF715 +:10AB70007DFF1D980088401B801B83B2C6F1FF003B +:10AB8000984200D203461E990BA8D9B15FF000028B +:10AB9000DDF878C0CDE9032009EB060189B2CDE9E3 +:10ABA00001C10F980090BDF8161000220D9801F019 +:10ABB000E2FB387070B1C0B2832807D0BDF8160030 +:10ABC00020833AE00AEB09018A19E1E7022011B07B +:10ABD000BDE8F08FBDF82C00811901F0FF08022DAF +:10ABE0000DD09AF80120424506D1BDF820108142CF +:10ABF00007D0B8F1FF0F04D09AF801801FE08AF85F +:10AC00000180C94800680178052902D1BDF81610F5 +:10AC1000818009EB08001FFA80F905EB080085B276 +:10AC2000DDE90C1005AB0F9A01F025FB28B91D9842 +:10AC30000088411B4145BFF671AF022D13D0BBF117 +:10AC4000100F0CD1A9EB0800801C81B20220CDE9C5 +:10AC5000000105AB52461E990D98FFF707FF1D989E +:10AC60000580002038700020B1E72DE9F8439C46AC +:10AC7000089E13460027B26B9AB3491F8CB2F18F1E +:10AC8000A1F57F45FF3D05D05518AD882944891DA4 +:10AC90008DB200E000252919B6F83C800831414505 +:10ACA00020D82A44BCF8011022F8021BBCF803107B +:10ACB00022F8021B984622F8024B914605F005F84F +:10ACC0004FF00C0C41464A462346CDF800C004F034 +:10ACD00062FCF587B16B00202944A41D2144088043 +:10ACE00003E001E0092700E083273846BDE8F88348 +:10ACF00010B50B88848F9C420CD9846BE0180488B3 +:10AD000044B1848824F40044A41D23440B801060C3 +:10AD1000002010BD822010BD2DE9F0478AB000252B +:10AD2000904689468246ADF8185007274BE00598B3 +:10AD300006888088000446D4A8F8006007A801951A +:10AD400000970295CDE903504FF40073002231467D +:10AD5000504601F010FB04003CD1BDF81800ADF8DE +:10AD60002000059804888188B44216D10A0414D4BE +:10AD700001950295039521F400410097049541F453 +:10AD8000804342882146504601F0CCF804000BD1A4 +:10AD90000598818841F40041818005AA08A94846A8 +:10ADA000FFF7A6FF0400DCD00097059802950195F7 +:10ADB000039504950188BDF81C300022504601F02F +:10ADC000B1F8822C06D105AA06A94846FFF790FFE4 +:10ADD0000400ACD0ADF8185004E00598818821F447 +:10ADE0000041818005AA06A94846FFF781FF002897 +:10ADF000F3D0822C03D020460AB0BDE8F0870020B3 +:10AE0000FAE710B50C46896B86B051B10C218DF86C +:10AE10000010A18FADF80810A16B01916946FCF7F5 +:10AE20009BF900204FF6FF71A063E187A08706B071 +:10AE300010BD2DE9F0410D460746896B0020069EA6 +:10AE40001446002911D0012B0FD13246294638462D +:10AE5000FFF762FF002808D1002C06D032462946B1 +:10AE60003846BDE8F04100F042BFBDE8F0812DE971 +:10AE7000FC411446DDE9087C0E46DDE90A15521D49 +:10AE8000BCF800E092B2964502D20720BDE8FC81F2 +:10AE9000ACF8002017222A70A5F80160A5F803304D +:10AEA0000522CDE900423B462A46FFF7DFFD0020A0 +:10AEB000ECE770B50C4615464821204615F0F7FC26 +:10AEC00004F1080044F81C0F00204FF6FF71E06108 +:10AED00061842084A5841720E08494F82A0040F03F +:10AEE0000A0084F82A0070BD4FF6FF720A800146FE +:10AEF000042008F05FB830B585B00C460546FFF772 +:10AF000080FFA18E284629B101218DF800106946E5 +:10AF1000FCF722F90020E0622063606305B030BDD9 +:10AF2000B0F84000704700004800002090F846202C +:10AF3000920703D4408808800020F3E70620F1E759 +:10AF400090F846209207EDD5A0F84410EAE70146B4 +:10AF5000002009880A0700D5012011F0F00F01D068 +:10AF600040F00200CA0501D540F004008A0501D571 +:10AF700040F010004A0501D540F020000905D1D568 +:10AF800040F04000CEE700B5034690F84600C00709 +:10AF900001D0062000BDA3F842101846FFF7D7FFE6 +:10AFA00010F0760F05D093F8460040F0040083F8C7 +:10AFB000460013F8460F40F001001870002000BD55 +:10AFC00090F84620520700D511B1B0F84200A9E729 +:10AFD0001720A7E710F8462F61F3C3020270A1E71C +:10AFE0002DE9FF4F9BB00E00DDE92B34DDE9297818 +:10AFF000289D25D02878C10703D000F03F001928EC +:10B0000001D9012100E000212046FFF7D9FFB0421D +:10B0100016D3287841060FD400F03F011E2909D02D +:10B02000218811F47F6F0BD13A884AB1A1F57F4294 +:10B03000FF3A05D0010606D500F03F00122802D0E5 +:10B0400004201FB0C4E5FC491D984FF0000A0871A8 +:10B050008DF818A08DF830A00CAA0A60ADF81CA0DD +:10B06000ADF824A02978994601F03F02701F5B1CBF +:10B0700004F1180CD3464FF0030ECDF828C01F2A58 +:10B080007ED2DFE802F07D7D107D227DAE7DF77DF2 +:10B09000F67DF57DF47DF77DF37D7D7DF27DF17D9F +:10B0A0007D7D7D7DF00094F84610B5F8010089079C +:10B0B00067D5032E65D14FF40061ADF82410608090 +:10B0C0008DF830E0ADF83400E9E2052EF2D1B5F8A4 +:10B0D00001002083ADF81C00B5F80310618300283F +:10B0E00070D088426ED884F80AB0A4F808B04FF641 +:10B0F000FF7020840A9801F0BBF8052089F8000051 +:10B1000002208346029011AB1D9A0A991B9801F008 +:10B11000B2F820B15EE000BF8DF81800FEE29DF8A5 +:10B120004A00012804D0022089F80100102003E021 +:10B13000012089F8010002200390002204A912A82E +:10B1400006F047F9E8BB9DF81010039888423ED1FD +:10B150003A88891CA2EB0B00884238DB0299022056 +:10B16000CDE900010DF146034A4641461B98FFF721 +:10B170007DFC02980BF1020B801C81B217AA01E042 +:10B18000ACE2B1E0029104A912A806F022F90299FA +:10B190009DF81000CDE9000117AB4A4641461B98C7 +:10B1A000FFF764FC9DF8100011AB0BEB00011FFAD8 +:10B1B00081FB02991D9A084480B202900A991B985B +:10B1C00001E004E091E001F056F80028B5D0BBF1B1 +:10B1D000020F03D10A208DF818005DE2A7F800B035 +:10B1E0005AE2CDF80CB0072E7ED3B5F801002083CB +:10B1F000ADF81C00B5F803206283002875D090429A +:10B2000073D84FF0010B84F80AB0B5F8050020811F +:10B210000020A073E06900F05BFD80B9E16942F6AF +:10B22000010081F806B0E2694FF420519180E16994 +:10B2300081F80AB0E1690881E16900208873F01F94 +:10B2400020841E984FF0070B6062A4F822B00A9881 +:10B2500001F00EF889F800B0012083460490002028 +:10B26000ADF846002AE026E2B0E147E1EDE01FE25A +:10B27000B0E088E04FE000BFBBF1010F15D0E069FE +:10B280008079012803D1BDF84400ADF80E0004997F +:10B290000420CDE9000103AB4A4641461B98FFF765 +:10B2A000E5FB0498001D80B20490BDF84600ADF89F +:10B2B0000C00ADF80E0005981FFA80FB11AB1D9A2B +:10B2C0000A991B9800F0D7FF28B939880BF10400C0 +:10B2D00005908142D0D2BBF1010F3FF41BAFE06972 +:10B2E0008079012808D001E098E023E0BDF84410FF +:10B2F000A1F57F40FF3803D1BDF84400ADF80E0042 +:10B3000004990420CDE9000103AB4A4641461B984D +:10B31000FFF7ACFB62E7072E01D0152E7ED1B5F802 +:10B3200001102183ADF81C10B5F80320628309B128 +:10B33000914201D90120EFE60121A172A4F808B0E1 +:10B3400084F80EB0052E07D0C0B2691DE26906F080 +:10B3500021F800287FF4DEAE4FF6FF70208401A8AC +:10B3600006AA09A9CDF800B080E88603287821460E +:10B3700000F03F031D9A1B98FFF790FB8246208B3D +:10B38000ADF81C0088E10120032EC7D14021ADF8A3 +:10B390002410B5F801102183ADF81C100AAAB8F1E9 +:10B3A000000F00D00023CDE9020304921D98CDF8D0 +:10B3B0000480009038880022401E83B21B9800F061 +:10B3C000DAFF8DF8180050BB0B2189F80010BDF88A +:10B3D000280038E04FF0010C052E9FD18020ADF8F9 +:10B3E0002400B5F801102183B5F803002084ADF8DE +:10B3F0001C10B0F5007F01D907208DE640F47C4297 +:10B40000228412A8B8F1000F00D00023CDE9033048 +:10B41000CDE9018C1D980090388801E09CE007E0A0 +:10B42000401E83B21B9800F0A6FF8DF8180028B1CB +:10B430008328A7D10220C7E0480000200D2189F809 +:10B440000010BDF84800401C25E1C80900EB40028F +:10B450000EEB8200B04203D948067DD558461AE16A +:10B46000B5F80110ADF81C102A78520608D506224E +:10B470008DF830202A78120605D58DF830B02FE1EE +:10B4800007228DF830200323CDE9023BDDF878C098 +:10B49000CDF810B01D9AA6EB00080092CDF804C0BC +:10B4A0001FFA88F300221B9800F03CFD8DF818006D +:10B4B0008DF830B0297849060DD52088C00506D50D +:10B4C000208BBDF81C10884201D1C4F824B0584626 +:10B4D0008DF818B0DFE0832801D14FF0020A4FF455 +:10B4E0008070ADF82400BDF81C002083A4F82080F3 +:10B4F0001E986062032060841321C9E0052E2BD3BF +:10B50000B5F80110ADF81C10A28F32B3A2F57F433D +:10B51000FE3B29D008228DF830200523CDE9023BDF +:10B52000DDF878C0CDF810B01D9A80B2CDF804C017 +:10B5300040F400430092B5F803201B9800F0F2FCA1 +:10B540004FF400718DF818008DF830B0ADF824106C +:10B55000832813D010B301E0DBE005E0A08FA0F555 +:10B560007F41FE3907D0D9E00B228DF830204FF60D +:10B57000FE72A287D1E7A4F83CB0CFE000942B463E +:10B5800031461E9A1B98FFF770FB8DF8180008B122 +:10B5900083284BD1BDF81C0020834BE700942B4639 +:10B5A00031461E9A1B98FFF760FB8DF81800E8BB28 +:10B5B000E18FA06B0844831D8DE88803438882884F +:10B5C00001881B98FFF753FC824665E095F80180DF +:10B5D000022E6FD15FEA080002D0B8F1010F7FD1CF +:10B5E00009208DF8300007A800908DF8348043467C +:10B5F000002221461B98FFF71CFC8DF835008DF8C2 +:10B6000036B050B9B8F1010F11D0B8F1000F04D124 +:10B61000A08FA0F57F41FF3909D0A08F38B14FF43A +:10B6200080608DF830B0ADF824000EE034E00CA955 +:10B630001B98FBF791FD82464FF480608DF830B087 +:10B64000ADF82400BAF1020F06D0FB4800688079FB +:10B6500028B18DF8180027E0A4F8188042E0BAF16C +:10B66000000F03D081208DF818003BE007A8009060 +:10B670004346012221461B98FFF7DBFB8DF818009B +:10B6800021461B98FFF7BDFB9DF8180020B9192132 +:10B6900089F80010012038809DF8300020B10CA9F5 +:10B6A0001B98FBF759FD8246BAF1000F33D019E021 +:10B6B000062031E514E02078000711D5012E0FD1C6 +:10B6C0000A208DF83000E088ADF8340004201B9982 +:10B6D00007F070FC0820ADF824007FE5480618D577 +:10B6E0004FF0040A2088BDF8241008432080BDF8DC +:10B6F000240080050BD5A18FA1F57F40FE3806D12F +:10B700001E98E06228982063A6864FF0030A5046F0 +:10B7100097E4042000E59DF8180078B1012089F82D +:10B720000000297889F80110BDF81C10A9F8021052 +:10B730009DF8180089F80400052038802088BDF89D +:10B74000241088432080E2E72DE9FF4F88460878DF +:10B7500095B0012181404FF20900249C0140ADF8D1 +:10B7600020102088DDF88890A0F57F424FF0000A75 +:10B77000FF3A02D029B1000703D5012019B0BDE876 +:10B78000F08F239E4FF0000B0EA886F800B018999A +:10B790005D460988ADF83410A7498DF81CB0179A9A +:10B7A0000A718DF838B0086098F8000001283BD085 +:10B7B000022809D003286FD1307820F03F001D30D7 +:10B7C0003070B8F80400E08098F8001003200229D7 +:10B7D00004D1317821F03F011B31317094F84610CB +:10B7E000090759D505ABB9F1000F13D0002102AA02 +:10B7F00082E80B000720CDE90009BDF83400B8F855 +:10B800000410C01E83B20022159800F0B4FD002879 +:10B81000D1D101E0F11CEAE7B8F80400A6F8010074 +:10B82000BDF81400C01C04E198F805108DF81C1038 +:10B8300098F80400012806D04FF4007A02282CD092 +:10B840000328B8D16BE12188B8F8080011F4006131 +:10B85000ADF8201020D017281CD3B4F84010814236 +:10B8600018D3B4F84410172901D3814212D131788A +:10B8700021F03F01C91C3170A6F801000321ADF889 +:10B880003410A4F8440094F8460020F0020084F834 +:10B89000460064E105257DE176E1208808F108078E +:10B8A00000F4FE60ADF8200010F0F00F1BD010F097 +:10B8B000C00F03D03888228B9042EBD199B9B87869 +:10B8C000C00710D0B9680720CDE902B1CDF804B0A7 +:10B8D0000090CDF810B0FB88BA883988159800F030 +:10B8E00021FB0028D6D12398BDF82010401C8029C8 +:10B8F0004ED006DC10290DD020290BD0402987D14D +:10B9000024E0B1F5807F70D051456DD0B1F5806FE6 +:10B9100097D1DDE0C80601D5082000E0102082465E +:10B920000DA907AA0520CDE902218DF83800ADF850 +:10B930003CB0CDE9049608A93888CDE9000153460A +:10B94000072221461598FFF7A9F8A7E09DF81C20CB +:10B9500001214FF00A0A002A9BD105ABB9F1000F73 +:10B9600000D00020CDE902100720CDE90009BDF884 +:10B9700034000493401E83B2218B0022159800F0FE +:10B98000FAFC8DF81C000B203070BDF8140020E08C +:10B990009DF81C2001214FF00C0A002A22D113AB84 +:10B9A000B9F1000F00D00020CDE902100720CDE949 +:10B9B00000090493BDF83400228C401E83B2218B11 +:10B9C000159800F0D8FC8DF81C000D203070BDF8E3 +:10B9D0004C00401CADF8340005208DF83800208B59 +:10B9E000ADF83C00BBE000E028E03888218B8842BD +:10B9F0007FF450AF9DF81C004FF0120A00281AD1B6 +:10BA0000606A98B1B878C0073FF444AFBA680720BD +:10BA1000CDE902B2CDF804B00090CDF810B0FB88AB +:10BA2000BA88159800F07EFA8DF81C00132030704B +:10BA30000120ADF8340092E0480000203988208BC6 +:10BA40008142D5D19DF81C004FF0160A0028A06B4A +:10BA500008D0E0B34FF6FF7000215F46ADF808B0A4 +:10BA6000019027E068B1B978C907C1D1E18F0DAB6A +:10BA70000844821D03968DE80C0243888288018861 +:10BA800009E0B878C007BFD0BA680DAB03968DE85F +:10BA90000C02BB88FA881598FFF7E9F905005ED01B +:10BAA000072D72D076E0019005AA02A92046FFF783 +:10BAB0001FF90146E28FBDF80800824201D000293B +:10BAC000F1D0E08FA16B084407800198E08746E041 +:10BAD0009DF81C004FF0180A40B1208BC8B138887F +:10BAE000208321461598FFF78CF938E004F11800FF +:10BAF0000090237E012221461598FFF79AF98DF8D0 +:10BB00001C000028EDD1192030700120ADF8340060 +:10BB1000E7E7052521461598FFF773F93AE02088F5 +:10BB200000F40070ADF8200050452DD1A08FA0F595 +:10BB30007F41FE3901D006252CE0D8F808004FF0EF +:10BB4000160A48B1A063B8F80C10A1874FF6FF7130 +:10BB5000E187A0F800B002E04FF6FF70A087BDF8C3 +:10BB6000200030F47F611AD0782300220420159938 +:10BB700007F080F998F8000020712088BDF82010A7 +:10BB8000084320800EE000E007252088BDF8201043 +:10BB900088432080208810F47F6F1CD03AE02188F1 +:10BBA000814321809DF8380020B10EA91598FBF73C +:10BBB000D3FA05469DF81C000028EBD086F801A0BA +:10BBC00001203070208B70809DF81C0030710520A2 +:10BBD000ADF83400DEE7A18EE1B118980DAB008816 +:10BBE000ADF834002398CDE90304CDE90139206B89 +:10BBF0000090E36A179A1598FFF7F2F905460120BD +:10BC00008DF838000EA91598FBF7A6FA00B1054685 +:10BC1000A4F834B094F8460040070AD52046FFF750 +:10BC200096F910F0760F04D114F8460F20F00400B6 +:10BC300020701898BDF83410018028469EE500B5A4 +:10BC400085B0042806D102208DF8000088B269462C +:10BC5000FBF782FA05B000BD10B5384C0B782268AE +:10BC6000012B02D0022B2AD111E013780BB1052B46 +:10BC700001D10423137023688A889A802268CB88B4 +:10BC8000D38022680B891381498951810DE08B880B +:10BC900093802268CB88D38022680B8913814B89DB +:10BCA00053818B899381096911612168FBF754FAEB +:10BCB000226800210228117003D0002800D08120C2 +:10BCC00010BD832010BD806B002800D0012070477C +:10BCD0008178012909D10088B0F5205F03D042F6B0 +:10BCE0000101884201D10020704707207047F0B55C +:10BCF00087B0002415460E460746ADF8144010E004 +:10BD0000069801882980811DCDE90241072101940F +:10BD100004940091838842880188384600F002F933 +:10BD200030B906AA05A93046FEF7E2FF0028E7D0A1 +:10BD3000822800D1002007B0F0BD0000480000209C +:10BD400010B58B7883B102789A4205D10B885BB12C +:10BD500002E08B79091D4BB18B789A42F9D1B0F88A +:10BD600001300C88A342F4D1002010BD812010BD09 +:10BD7000072826D012B1012A27D103E0497801F023 +:10BD8000070102E04978C1F3C20105291DD2DFE8AD +:10BD900001F00318080C12000AB1032070470220BA +:10BDA000704704280DD250B10DE0052809D2801E3D +:10BDB000022808D303E0062803D0032803D0052077 +:10BDC0007047002070470F20704781207047C0B235 +:10BDD000820610D400060CD5FA48807A421ED3178A +:10BDE00002EB5372012303EBE20201FB002080B25D +:10BDF0007047084670470020704770B513880B8065 +:10BE00000D782B062AD5EF4B9B7A834204D845F058 +:10BE100010000870002070BD946800F0070604EB65 +:10BE2000D0042478F44064F304150D701478D178AC +:10BE300004F0030441EA042140F20124B1FBF4F5CB +:10BE400004FB151192685B1E00FB0120D91703EB60 +:10BE50005171012202EBE101084470BD906870BD90 +:10BE600037B51446BDF8041011809DF804100A0679 +:10BE700022D5C1F30013D3490122A568897A8142F2 +:10BE80000CD8FE2814D1491EC81701EB507002EBE4 +:10BE9000E0015A422846F7F7A4F809E005EBD00183 +:10BEA00000F007050878AA409043AB40184308709B +:10BEB000207820F0100020703EBD2DE9F0410746AB +:10BEC000C81C0E4620F00300B04202D08620BDE818 +:10BED000F081BC4D002034462E60AF802881AA72CC +:10BEE000E8801AE0E988491CE980810614D4E178E9 +:10BEF00000F0030041EA002040F20121B0FBF1F222 +:10BF000001FB12012068FFF762FF2989084480B213 +:10BF10002881381A3044A0600C3420784107E1D4DD +:10BF20000020D4E72DE9FF4F89B01646DDE9168AD7 +:10BF30000F46994623F44045084600F00CFB0400E8 +:10BF40000FD0099803F07EFD0290207800060AD5F4 +:10BF50009C48817A0298814205D887200DB0BDE8BF +:10BF6000F08F0120FAE7224601A90298FFF745FF6A +:10BF7000834600208DF80C004046B8F1070F1AD018 +:10BF800001222146FFF7F4FE0028E7D12078400681 +:10BF900011D502208DF80C00ADF81070BDF804002A +:10BFA000ADF81200ADF814601898ADF81650CDF841 +:10BFB0001CA0ADF818005FEA094004D500252E4604 +:10BFC000A84601270CE02178E07801F0030140EA5F +:10BFD000012040F20121B0FBF1F2804601FB128703 +:10BFE0005FEA494009D5B84507D1A178207901F029 +:10BFF000030140EA0120B04201D3BE4201D907202B +:10C00000ACE7A8191FFA80F9B94501D90D20A5E7B9 +:10C010009DF80C0028B103A90998FBF79BF80028AC +:10C020009CD1B84507D1A0784FEA192161F30100EE +:10C03000A07084F804901A9800B10580199850EA0D +:10C040000A0027D0199830B10BEB06002A4619993F +:10C0500014F094FB0EE00BEB06085746189E099867 +:10C0600003F033FE2B46F61DB5B239464246009525 +:10C0700003F091FA224601A90298FFF7BEFE9DF84F +:10C080000400224620F010008DF80400DDE90110C4 +:10C09000FFF7E6FE002061E72DE9FF4FDFF824916E +:10C0A00082461746B9F80610D9F8000001EB4101A5 +:10C0B00000EB810440F20120B2FBF0F185B000FBFF +:10C0C00011764D46DDF84C8031460698FFF77FFE2D +:10C0D00029682A898B46611A0C3101441144AB88C6 +:10C0E00089B28B4202D8842009B038E70699CDB2D4 +:10C0F000290603D5A90601D58520F5E7B9F806C0BC +:10C100000CF1010C1FFA8CFCA9F806C0149909B1B6 +:10C11000A1F800C0A90602D5C4F8088007E01044C1 +:10C1200080B2A9F80800191A01EB0B00A0602246A2 +:10C13000FE200699FFF794FEE77026712078390AF1 +:10C1400061F30100320AA17840F0040062F30101BA +:10C15000A17020709AF802006071BAF80000E080C7 +:10C1600000262673280602D599F80A7000E00127F8 +:10C17000A80601D54FF000084D4600244FF00709EE +:10C180000FE0CDE902680196CDF800900496E988A9 +:10C190002046129B089AFFF7C5FE0028A4D1641C14 +:10C1A000E4B2BC42EDD300209EE72DE9F047804683 +:10C1B00000F0D1F9070007D000264446014D40F2B7 +:10C1C000012918E0480600200120BDE8F08720463C +:10C1D00000F0C1F90278C17802F0030241EA0222BC +:10C1E000B2FBF9F309FB13210068FFF7F0FD3044BF +:10C1F000641C86B2A4B2E988601E8142E7DCA8F123 +:10C200000100E8802889801B288100203870DCE745 +:10C2100010B5144631B1491E218003F013FCA07003 +:10C22000002010BD012010BD10B5D3490446008880 +:10C23000CA88904201D3822010BD096800EB4000FB +:10C2400001EB80025079A072D0882081917810791A +:10C2500001F0030140EA0120A081A078E11CFFF772 +:10C26000CCFD20612088401C2080E080002010BD93 +:10C270000121018270472DE9FF4F85B04FF6FF780D +:10C280008246A3F8008048681F460D4680788DF8E6 +:10C29000060048680088ADF8040000208DF80A0008 +:10C2A000088A0C88A04200D304462C8241E0288AE8 +:10C2B000401C2882701D6968FFF742FDB8BB3988B1 +:10C2C000414501D1601E38806888A04236D3B178DC +:10C2D000307901F0030140EA012901A9701DFFF73F +:10C2E0002FFD20BB298941452CD0002231460798DB +:10C2F000FFF73EFDD8B92989494518D1E96803916E +:10C30000B5F80AC0D6F808B05046CDF800C003F022 +:10C31000DCFCDDF800C05A460CF1070C1FFA8CFC5F +:10C320004B460399CDF800C003F0F8F850B1641CF7 +:10C33000A4B2204600F00FF90600B8D1641E2C828A +:10C340008220D1E67C807079B871F088B88031782D +:10C35000F07801F0030140EA01207881A7F80C9001 +:10C36000504603F06FFB324607F10801FFF745FD29 +:10C3700038610020B8E62DE9FF4F87B081461C46A2 +:10C380009246DDF860B0DDF85480089800F0E3F8DC +:10C3900005000CD0484603F055FB2978090608D55E +:10C3A0007549897A814204D887200BB0D7E50120EE +:10C3B000FBE7CAF309062A4601A9FFF71EFD074657 +:10C3C000149807281CD000222946FFF7D1FC00282A +:10C3D000EBD12878400613D501208DF80800089885 +:10C3E000ADF80C00BDF80400ADF80E00ADF810601B +:10C3F000ADF8124002A94846FAF7ACFE0028D4D1A5 +:10C400002978E87801F0030140EA0121AA78287927 +:10C4100002F0030240EA0220564507D0B1F5007F42 +:10C4200004D9611E814201DD0B20BEE7864201D99D +:10C430000720BAE7801B85B2A54200D92546BBF18B +:10C44000000F01D0ABF80050179818B1B9192A465F +:10C4500014F094F9B8F1000F0DD03E44484644461C +:10C46000169F03F044FC2146FF1DBCB232462B460A +:10C47000009403F0C9F8002097E72DE9F041074642 +:10C480001D461646084600F066F804000BD03846F4 +:10C4900003F0D8FA2178090607D53749897A81420D +:10C4A00003D8872013E5012011E522463146FFF726 +:10C4B000A4FC65B12178E07801F0030140EA012095 +:10C4C000B0F5007F01D8012000E000202870002096 +:10C4D000FDE42DE9F04107461D461646084600F0EA +:10C4E0003AF804000BD0384603F0ACFA217809067C +:10C4F00007D52149897A814203D88720E7E40120C2 +:10C50000E5E422463146FFF7ABFCFF2D14D021783D +:10C51000E07801F0030240EA022040F20122B0FB81 +:10C52000F2F302FB130015B900F2012080B2E070B3 +:10C53000000A60F3010121700020C8E410B50C4628 +:10C5400000F009F828B1C18821804079A07000204E +:10C5500010BD012010BD0849CA88824209D340B1EC +:10C56000096800EB40006FF00B0202EB800008440A +:10C5700070470020704700004806002010B50C46A8 +:10C5800002F0F3FA78B3204600F05FFE60B3227841 +:10C59000102A09D0112A07D0022A05D0032A03D075 +:10C5A000162A2DD0FFDF1CE0A0781A2817D00DDC4A +:10C5B000132814D2DFE800F0151319131320201CE0 +:10C5C0001E28131322131313131326002A2806DD23 +:10C5D0003C280FD003DC302814D03A2810D0032098 +:10C5E00010BD002010BD14E011E043F20200F9E795 +:10C5F0000420F7E70D20F5E70F20F3E70820F1E727 +:10C600001120EFE70720EDE743F20600EAE7FFDF3E +:10C61000E7E7FFDFE5E700F018BE70B5034600204E +:10C6200002466FF02F050EE09C5CA4F130060A2E46 +:10C6300002D34FF0FF3070BD00EB800005EB4000EF +:10C64000521C2044D2B28A42EED370BD30B50A24C7 +:10C650000AE0B0FBF4F304FB13008D18303005F84A +:10C66000010C521E1846D2B2002AF2D130BD30B5AC +:10C6700000234FF6FF7510E0040A44EA002084B25C +:10C68000C85C6040C0F30314604005EA00344440D5 +:10C69000E0B25B1C84EA40109BB29342ECD330BD05 +:10C6A000F0B516460B880122B240134215D1134350 +:10C6B0000B800446051D018840880F18092F00D300 +:10C6C000093F401C092800D9FFDF781C092800D940 +:10C6D000FFDF6088401C6080EE55F0BDF0B5068835 +:10C6E0000446051D0F46701C81B22180092901D323 +:10C6F000093921806088012800D2FFDF701C0928D9 +:10C7000000D9FFDF60880122401E6080A85D398863 +:10C71000824091433980F0BD2DE9F0410E468046BC +:10C72000DDE9065089781746090612D420F8045D21 +:10C730004380404603F0DBFA040000D1FFDF2D1DEB +:10C740002046A9B202F038FC00B9FFDF404600F0F5 +:10C750001AFC06EB4701087C401C0874BDE8F08118 +:10C760007CB505461220187048780C46801C58701D +:10C7700008205880108898805088D8809088188128 +:10C78000D08858810C20CDE90003052306222146DC +:10C790002846FFF7C1FFF02300222946012006F0BA +:10C7A00069FB6078801C60707CBD2DE9F84F0F46F6 +:10C7B0009A4691460546032103F07CF90446808C95 +:10C7C000DFF86085002618B198F80000B84221D142 +:10C7D000284603F08CFA050000D1FFDF09F10401BF +:10C7E000284689B202F098FB060013D002F046FFFB +:10C7F0000770284631466A4602F07FFE0098002105 +:10C800000A460180817000F084FC0098C01DCAF8BF +:10C81000000030E098F80000B84225D104F122056C +:10C8200034F8301F012000FA07F911EA090F00D08F +:10C83000FFDF208840EA090020802C8805F10409E8 +:10C84000641E092C00D309342C806888401C0928F8 +:10C8500000D9FFDF601C092800D9FFDF6888401C71 +:10C86000688009F8047006E03A4604F1300104F1EA +:10C870002200FFF715FF092188F800103046BDE8B7 +:10C88000F88F38B50546032103F014F90446807883 +:10C8900000F07F00012814D002226B4606212846B2 +:10C8A000121DFFF782FF00280AD0A07800F07F0059 +:10C8B000012808D0228921462846009B00F084FAEE +:10C8C00038BD0822E9E704F1080221462846009B0A +:10C8D000FFF746FF38BDFEB514460D46064602ABCF +:10C8E00006220721FFF761FF80B1029B012007228A +:10C8F00018705C700220588000249C800620CDE9CE +:10C900000003052329463046FFF706FFEC70FEBD05 +:10C9100010B50446032103F0CDF80146C278204645 +:10C92000BDE81040D7E7FF4909200870704770B58F +:10C930000C4615463421204613F0B9FF01206070E3 +:10C940002078122120F00F00207004F1100013F065 +:10C95000AEFF05B9FFDF2978A07861F30600A0706B +:10C9600070BD70470146012006F024BB3EB58DB274 +:10C970000321284603F09EF8040000D1FFDF207851 +:10C98000002220F00F00207002208DF800004FF6EA +:10C99000FF70ADF80200ADF8040069462846F7F7CD +:10C9A00019FA3EBDF0B50C46002600780121174665 +:10C9B0003546B1EB101F00D0FFDFFFDF3D800CB12B +:10C9C000268065800020F0BD2DE9FC4788461D4685 +:10C9D0001746814603210A9E03F06CF8040000D13B +:10C9E000FFDFCDE900563B46424621464846FFF769 +:10C9F00093FEBDE8FC8738B50546A0F57F40FF38BB +:10CA00001CD0284603F061F9040000D1FFDF204666 +:10CA100002F052FD002810D001466A46204602F07E +:10CA20006CFD0098B0F80500052807D103212846C1 +:10CA300003F040F8C07808B1002038BD012038BDAF +:10CA40002DE9FF410546408803F03FF9040000D17D +:10CA5000FFDF03AA2046696800F0ADF9039C001FC0 +:10CA600034F8032F618882420AD104290AD00529AB +:10CA700017D0062904D16888211D6B68F8F74DFF8F +:10CA8000BDE8FF811646241D2A4621463046F5F7AB +:10CA900089FC0828F4D12A4621463046FAF7B9FE27 +:10CAA000EEE716466888032103F004F801460020EB +:10CAB0008DF80000042EE3D36279002AE0D02379B8 +:10CAC00043F30000401C05D14F789742D8D10F782E +:10CAD0003F07D5D0142B3CDA4FF002074FF6FF7812 +:10CAE000012B34D0122B02D0132B32D11DE00C2E8F +:10CAF0002FD18B7803F07F03012B2AD0087820F008 +:10CB00000F00401C08706079487001208DF800000B +:10CB10002089ADF802006089ADF80400A089ADF865 +:10CB20000600E089ADF8080028E0062E11D108784B +:10CB300020F00F0008706988012006F03BFA8DF89C +:10CB40000070ADF802802089ADF8040016E0062ED2 +:10CB500005D0002894D06888FFF7BDFE90E70878DC +:10CB600020F00F0008706988012006F023FA8DF884 +:10CB700000702089ADF80200ADF8048068882A466C +:10CB80006946F7F727F97BE7F8B50D460646032116 +:10CB900002F090FF040012D0207800F00F0001286E +:10CBA00010D06B460C2206213046FFF7FEFD58B12F +:10CBB0002A4621463046009BFFF7D2FD08E043F2AB +:10CBC0000200F8BD1120F8BD2868A0606868E06028 +:10CBD000207820F00F00401C20700020F8BDF8B530 +:10CBE0000D460646032102F065FF040006D02078BA +:10CBF00000F00F00012804D00820F8BD43F2020025 +:10CC0000F8BD06226B4611463046FFF7CEFD30B127 +:10CC10002A4621463046009B00F0D6F800E02581E8 +:10CC2000207820F00F0020700020F8BD2DE9F04F93 +:10CC30000F4691B08046032102F03CFF0446404677 +:10CC400003F055F84FF00009CDF82090CDF824906E +:10CC5000ADF834900546CDF82890CDF82C90CDF85D +:10CC60000890CDF80C90CDF8109004B9FFDF02AE1B +:10CC700005B9FFDFB2467F1EFFB219D328460CA9C3 +:10CC8000002202F0A2FA9DF83060092E00D3FFDFE7 +:10CC900004EB46013246087C401E08740DA908A822 +:10CCA000FFF7FEFC1AF80610491C0AF80610E2E726 +:10CCB00004F1300006900E381A4FDFF86CB0051DF5 +:10CCC000059010E0DDE90501FFF708FD0646387024 +:10CCD000092800D3FFDF5BF8261040468847608CA8 +:10CCE000405DB04202D0A08C0028EBD109200E4E4E +:10CCF0003870243620E00DA908A8FFF7EFFC0546A0 +:10CD000004EB4507787CC00716D02946204600F082 +:10CD100054F808B987F811901AF8057056F82500EC +:10CD200028B903E0500000209C0C0200FFDF56F8F9 +:10CD30002520394640469047BDF822000028DAD128 +:10CD400011B0BDE8F08F10B5032102F0B3FE04006E +:10CD500000D1FFDF122104F1100013F0A8FDA0782C +:10CD600040F08000A07010BD70B50D46032102F0A8 +:10CD7000A1FE040000D1FFDF092D00D3FFDF29460B +:10CD8000204600F01AF8002803D004EB45020121E8 +:10CD9000517470BD70B50D46032102F08BFE044640 +:10CDA000294600F00AF820B9208E0121A940084048 +:10CDB00000D0012070BD02F0A0BB00EB4100007C60 +:10CDC000002800D0012070471CB513241C704C783B +:10CDD0005C7002245C809A800622CDE90023052342 +:10CDE000FFF79AFC1CBD000010B50AF047FB0428B1 +:10CDF00003D00AF043FB052802D108F0F9FC28B95A +:10CE00000BF008FD20B107F0FEFB08B1012010BDBA +:10CE1000002010BD0178406819B190F8711059B91F +:10CE200001E001F02EBF90F80C1129B190F80C012F +:10CE3000042801D0012070470020704770B50C46CF +:10CE40000546062102F036FE606008B1002006E0CB +:10CE50000721284602F02EFE606018B101202070E4 +:10CE6000002070BD022070BD2DE9FC470C4606462F +:10CE70006946FFF7E3FF00287DD19DF8000050B11F +:10CE800007F060FBB0427CD0214630460EF06BF9D3 +:10CE9000002873D12DE008F0ABF9B04271D02146E3 +:10CEA00030460CF0BFFD002868D1019D95F8D000F8 +:10CEB00022E0012000E00020804695F835004FF088 +:10CEC000010A4FF00009F0B195F8360080071AD535 +:10CED00084F8019084F800A084F80290A68095F868 +:10CEE0003710A171298F2181698F618185F8359073 +:10CEF00044E0019D95F80C0158350028DBD1687E8F +:10CF00000028D8D0D5E7304602F0F1FE070000D166 +:10CF1000FFDF384602F00DF940B184F801900E2190 +:10CF20002170A680E08084F802A027E0304602F05D +:10CF3000CCFE070000D1FFDFB8F1000F21D038464A +:10CF400002F088F9B8B19DF8000038B90198D0F81E +:10CF5000F8004188B14201D180F80090304607F0D6 +:10CF6000A7F984F801900B21217084F80290A68023 +:10CF7000A97EA17100E004E085F819900120BDE8C8 +:10CF8000FC870020FBE71CB56946FFF757FF00B19F +:10CF9000FFDF684601F083FEFB4900208968A1F8A5 +:10CFA000D2001CBD2DE9FC4104460E46062002F0CD +:10CFB0002BFD0546072002F027FD2844C7B20025B7 +:10CFC000A8463E4417E02088401C80B22080B04232 +:10CFD00002D34046A4F8008080B2B84204D3B042E5 +:10CFE00002D20020BDE8FC816946FFF727FF002838 +:10CFF000F8D06D1CEDB2AE42E5D84FF6FF70208040 +:10D000001220EFE738B54FF6FF70ADF800000DE0E5 +:10D010000621BDF8000002F05FFD04460721BDF8BF +:10D02000000002F059FD0CB100B1FFDF002168469D +:10D03000FFF7B8FF0028EBD038BD2DE9F047D3A1AA +:10D040000F79D1F8008007F0A1F910F0B3F9D14CB5 +:10D050004FF004091020A4F84690A4F848004FF6B9 +:10D06000FF76A4F86460A4F86660002584F8415057 +:10D0700004F83E5BC7492570A57142312573C1F89C +:10D0800009804F730931481E0CF095FEA5741B20D2 +:10D09000A0824FF4A471E182208361830121217772 +:10D0A00061770321A17784F81F9020846084B948B8 +:10D0B000A1843E3805704680B3480C300570B548F1 +:10D0C000103805704680BDE8F08770B5AE4C0D464F +:10D0D0006060217007F0D4F8FFF794FFFFF7ADFF11 +:10D0E000207809F02AFE08F0C7F9217860680CF072 +:10D0F00079FD20780FF094F928460BF048F807F0F6 +:10D100002CFA217860680EF021F9BDE8704010F02B +:10D1100051B910B501240AB1002010BD21B1012977 +:10D1200003D00024204610BD022111F03BFDF9E799 +:10D130002DE9F047040000D1FFDF964D002695F859 +:10D14000410058B166701620207095F84200A0701A +:10D1500095F84300E07085F8416069E0287840B1B7 +:10D160003C22A91C204613F009FB102020702E70D1 +:10D170005EE095F83E0060B10120E07095F83F0058 +:10D18000A07095F8400060701120207085F83E6016 +:10D190004EE08048022166308246FFF703FF00B16F +:10D1A000FFDFB5F86690062002F02EFC0746072048 +:10D1B00002F02AFC3844C7B2781C00F0FF0800BF18 +:10D1C000B5F86600B84212D1204607F09DFF50BB6B +:10D1D00095F8440070B36670132020702021A01CC5 +:10D1E00013F043FB0220A07085F8446020E0404526 +:10D1F0001AD1204607F070F9E0B12078132817D132 +:10D20000A0783C2814D1A088072102F053FC050027 +:10D2100000D1FFDF288807F04BF8A088072102F033 +:10D220005BFC00B1FFDF03E02146FFF71DFE08B104 +:10D23000012048E702215046FFF7B4FE18B9B5F8BF +:10D2400066104945BCD100203DE771E710B5514C4F +:10D25000207828B10A21BDE81040102001F0B3BCAD +:10D26000FFF7C2FD08B10C2002E010F0E9F8002041 +:10D270002071012060710A21E170207010BD70B52D +:10D28000444D0446287828B1BDE870403221102072 +:10D2900001F099BC207818B1012801D0122010E0CB +:10D2A00001F09EFC20B110F016FA08B10C2008E045 +:10D2B000207801F068FC04F11703E21D611C10F0F6 +:10D2C00017F92871012068713221E970287070BD4A +:10D2D00070B5304C0546207828B1BDE870400B2170 +:10D2E000102001F070BC287818B1012801D012205C +:10D2F0000EE0FFF779FD08B10C2009E0287801F075 +:10D3000042FC691C10F063F808B1002000E007201F +:10D310002071012060710B21E170207070BD10B58B +:10D320001C4C217829B13021BDE81040102001F0BB +:10D330004ABC008810F0D2F9302110B100202071D1 +:10D3400000E0217101206071E170207010BD70B5A6 +:10D35000104C0546207828B1BDE8704031211020DE +:10D3600001F031BC01F03CFC08B10C2005E028784C +:10D3700000F0010010F0ACF9002020710120607174 +:10D380003121E170207070BD54000020FFFFFFFFCD +:10D390001F0000009206002010B5F74C207828B13D +:10D3A0003421BDE81040102001F00DBC01F018FC44 +:10D3B00020B110F090F908B10C2002E010F0EFF865 +:10D3C00000202071012060713421E170207010BDB7 +:10D3D000E948017819B10F21102001F0F4BB0021B8 +:10D3E0000171102181700F21C170FF2181714FF6F1 +:10D3F000FF710181E14949680A7882728A888281D5 +:10D400004988C181012141710170704710B5DA4C22 +:10D41000207828B12B21BDE81040102001F0D3BBAB +:10D420000821A01D05F0B4FA0020207101206071D0 +:10D430002B21E170207010BD70B5CF4C217829B13F +:10D44000BDE870404521102001F0BDBB90F90000FF +:10D45000042822D0092820D008281ED007281CD054 +:10D4600006281AD0052818D0022816D0032814D070 +:10D4700098B1011D11D010F1080F0ED010F10C0F52 +:10D480000BD010F1100F08D010F1140F05D010F1CF +:10D49000280F02D01220207103E0002506F0B3F817 +:10D4A00025714520E0700120607120706BE710B598 +:10D4B000B14C217829B12A21BDE81040102001F09B +:10D4C00082BBA31D012200F1100110F0E0FE00203C +:10D4D00020711020A0702A20E0700120607120705F +:10D4E00010BD70B5A44C0546207828B1BDE8704049 +:10D4F0004821102001F067BB09F0C0FF052804D0C7 +:10D50000284609F0F8FB002000E00C2020710120E3 +:10D5100060714821E170207035E770B5964C054682 +:10D52000207828B1BDE870405721102001F04BBB96 +:10D5300009F0C6FC80B10BF060F968B128780128C9 +:10D5400000D000200EF077FF0020207101206071D4 +:10D550005721E170207016E70C20F6E770B5864C75 +:10D560000546207828B1BDE870404621102001F022 +:10D570002ABB01F035FB38B10C202071012060710D +:10D580004621E1702070FEE62946002006F0FFFEED +:10D590000020F2E770B5784C0546207828B1BDE848 +:10D5A00070404421102001F00EBB09F089FC50B1FD +:10D5B0000BF023F938B128780AF00DFE287808F02E +:10D5C00052F9002000E00C202071012060714421FC +:10D5D000E1702070D7E670B5674C0546207828B119 +:10D5E000BDE870401721102001F0EDBA01F0F8FA03 +:10D5F00038B10C202071012060711721E17020707A +:10D60000C1E62946012006F0C2FE0020F2E738B547 +:10D61000594D0446287828B1BDE838404F211020E4 +:10D6200001F0D1BAA079E179884213D021791F297C +:10D6300010D861791F290DD80022114612F0B0FBD5 +:10D6400040B90022E079114612F0AAFB10B9207A05 +:10D65000072801D9122012E04FF6FF70ADF8000044 +:10D660000BF0D8F890B909F009FF78B900216846A5 +:10D67000FFF798FC50B1204605F0EAFE0020287123 +:10D68000012068714F21E970287038BD0C20F6E741 +:10D690002DE9FC47384C054694F83E0020B128217E +:10D6A000112001F090FA6AE4282084F8400001215A +:10D6B00084F83E10A8784FF000091A2825D00EDC17 +:10D6C000162831D2DFE800F03030303030213030F1 +:10D6D00030303030303030303030302121212A2885 +:10D6E00022D00BDCA0F11E000C281DD2DFE800F0D8 +:10D6F0001C1C1C1C1C1C1C1C1C1C1C0D3A3804284B +:10D7000012D2DFE800F0110211022888B0F5706F24 +:10D710000AD21F20884684F83F0028886946FFF710 +:10D720008DFB18B1022019E0122017E09DF80000CF +:10D73000019F002806D007F5B777019E05D106F1B5 +:10D74000F10604E007F1F007F7E706F26F16684606 +:10D75000FFF760FB08B1387818B10C2084F83F005F +:10D760000DE487F80080A878307084F83F90684610 +:10D7700001F095FA03E40000920600205400002016 +:10D780007CB5F84C0546207820B12521102001F009 +:10D790001AFA7CBD28886946FFF750FB0200F14861 +:10D7A0004FF00001A0F13E000DD00222227140F89E +:10D7B000461F0171E1801020A0702520E07001203B +:10D7C000607120707CBD019A1346583282F83F1078 +:10D7D0009E68C0F846601E7B80F84A6092F83F6001 +:10D7E000002EF3D12888E080E5E710B540B1047839 +:10D7F000406813B1B0F8480003E0B0F84A0000E018 +:10D80000FB201B2908D3814206D8B2F5A47F03D39D +:10D8100040F64800824201D9122010BD002010BD00 +:10D820002DE9FC41CF4D0446287828B1BDE8FC41E4 +:10D830005221102001F0C7B94FF0010885F805808A +:10D840001F2129711021A9705221E9702188E980D6 +:10D8500085F8008020886946FFF7F0FA08B10220B9 +:10D860000DE02289E18801236846FFF7BEFF30B949 +:10D87000A288618800236846FFF7B7FF10B12871BE +:10D88000BDE8FC819DF800103A20019E002749B1B7 +:10D8900086F89181019991F8D21106F5C876C1B147 +:10D8A000287114E086F80981019991F82C1106F588 +:10D8B00084760029F4D12F71E08870802089B080AF +:10D8C0006088F080A0883081012201990CE0777097 +:10D8D000D6E72F71E08870802089B0806088F08062 +:10D8E000A088308101990022304610F085FE86F82C +:10D8F0000080ECE770B59B4D044686B0287830B1C7 +:10D9000006B05321BDE87040102001F05CB9012041 +:10D91000687100262E711021A9705321E9702870BA +:10D92000208803A9FFF78AFA18B10220287106B0EF +:10D9300029E59DF80C0040B100220499E088B1F877 +:10D940004830984203D9C01A02E00122F5E70020CE +:10D95000E8806388B1F84A00834201D9181A00E0D0 +:10D9600000202881009601960296E088ADF802001A +:10D970002089ADF804006088ADF80600A088ADF8F5 +:10D980000800684610F038FE2089BDF80410401ADF +:10D990006881A088BDF80810401AA881E088BDF809 +:10D9A0000210401AE988884200DC0846E880608856 +:10D9B000BDF80610401A2989884200DC08462881F3 +:10D9C000B5E7034600200AB1012200E002221A4214 +:10D9D00002D1490700D1122070477CB5614D044641 +:10D9E000287820B13F21102001F0EDF87CBD012006 +:10D9F00068711F2129711021A9703F21E9702870D9 +:10DA0000617820780122FFF7DCFF28B9A17820781F +:10DA10000022FFF7D6FF08B128717CBD617820781D +:10DA20006B46012201F04AF9A178207801AB00226F +:10DA300001F044F99DF8000085F85A009DF80400B3 +:10DA400085F85B000020E7E770B5464D86B00446D8 +:10DA50001F200E4685F83F00208803A9FFF7EEF946 +:10DA600008B102200BE0E178A0780122FFF7A9FFBE +:10DA700028B92179A0780022FFF7A3FF10B185F81B +:10DA80003F0054E7E178A07802AB012201F016F9DB +:10DA90002179A0786B46002201F010F99DF808006A +:10DAA0009DF800100843400719D59DF80C00092483 +:10DAB00038B90020049910F01BFD0499496A884286 +:10DAC0000AD89DF80C00012809D1049910F010FD26 +:10DAD0000499496A884202D985F83F4027E79DF8B2 +:10DAE0000C3001203A220021002B049B93F898303F +:10DAF0001BD0012B32D0049A82F89C01049A82F840 +:10DB00009A01049880F89B61049A9DF8080082F8B5 +:10DB10009D01049A9DF8000082F89E01049880F807 +:10DB20009C1100BF85F83F1001E7012B16D0049A25 +:10DB300082F81401049A82F81201049880F81361A3 +:10DB4000049A9DF8080082F81501049A9DF80000D7 +:10DB500082F81601049880F81411E3E785F83F2055 +:10DB6000E5E60000920600201CB5FE4991F83E2033 +:10DB70002AB1BDE81C405621112001F024B85622DC +:10DB800081F84020012281F83E200188ADF8001084 +:10DB900081788DF80210C1788DF8031001798DF825 +:10DBA0000410C088ADF8060000216846FFF74CFF5E +:10DBB0001CBD2DE9F041EB4C0546207828B1BDE8AD +:10DBC000F0411D21102000F0FEBF1F27277101200A +:10DBD00060711D21E170207009F050FC0C260428B2 +:10DBE00045D0052843D0A9791220012904D019B1C4 +:10DBF000022901D003292BD1297809B1012927D184 +:10DC0000E97929B1012903D0022901D003291FD1C3 +:10DC1000698843F6FD720B1F3020934218D2AB88FF +:10DC20001B1F934214D2A4F84610A888A4F84800F9 +:10DC30004FF00008A87907F03EFDC0B1E87907F081 +:10DC400095FD012007F031FD20B12771BDE8F0817D +:10DC50002071FBE72878012801D018B109E00021E4 +:10DC6000022001E00021012007F0B2FD08B1267179 +:10DC7000ECE784F80480E9E770B5BA4C217829B163 +:10DC8000BDE870401E21102000F09DBF1F212171B2 +:10DC9000012161711E22E270217002781221012A95 +:10DCA00000D01AB9407818B1012801D0217133E4AD +:10DCB00000260C25012A08D009F0E0FB052802D037 +:10DCC00008F076FF78B1257126E407F00DFD0120FC +:10DCD00007F088FD00B1FFDFB4F84810B4F8460043 +:10DCE00009F0FBF8EEE7267116E42DE9F0479D4CAC +:10DCF00007469246B4F85200B7F84A200E469042C2 +:10DD000000D31046804697F85210104600F04BFFA3 +:10DD1000B4F85410814200D208460546A146B4F832 +:10DD20005640B7F84800844200D3044697F8511093 +:10DD300000F039FFB9F85810814200D208464FF47C +:10DD4000A4721B2C01D0904204D1B8F11B0F0DD04E +:10DD500095420BD0A6F8068035817480B08052467B +:10DD60003946304610F048FC01203070BDE8F0879D +:10DD70002DE9F04F85B00546AFF6F011794ED1E9A7 +:10DD8000009196F83E00884630B12121112000F024 +:10DD90001AFF05B0BDE8F08F1F2086F83F00212054 +:10DDA00086F840004FF0010B86F83EB0284600F0A0 +:10DDB00091FF002811D109F061FB05280CD009F072 +:10DDC0005DFB042808D096F8440028B907F010FA43 +:10DDD000A0F57F41FF3901D00C20D5E0614801AAB0 +:10DDE0003E380190604802905E480621103803904A +:10DDF00004A801F02FFE04007ED0032110F069F882 +:10DE0000B6F85E00A4F84800B6F86000A4F84A002E +:10DE100096F85A0084F84F0096F85B0084F850009A +:10DE200096F85D00009096F85C30B6F86020B6F881 +:10DE30005E10208801F0D2FE00B1FFDF208806F0DE +:10DE400036FA218804F10D0000F0D9FE47A004F154 +:10DE50001107006800900321684604F024FD0020AB +:10DE600069460A5C3A54401CC0B20328F9D3288A98 +:10DE70006080688AA080A88AE08094F8522094F894 +:10DE80005110B6F8620009F0A5F80146A0622046DC +:10DE900009F0E4F84FF0000A84F85EA084F85FA06F +:10DEA0005746687900F06FFE6076D5F80600C4F832 +:10DEB0001A006889E083C4F8089084F80C8084F81C +:10DEC00000B1012204F584712046FFF70EFF8DF8A2 +:10DED00000700121684604F0E6FC9DF8000000F0A7 +:10DEE0000701C0F3C1021144C0F3401008448DF88B +:10DEF0000000401D207600E015E0092801D208301E +:10DF00002076002120460FF0E4FF287B07F0D3FBAA +:10DF100058B107F0E9FB69792879AA1D07F032FCAE +:10DF200007000ED01AE009202EE0208806F0C0F984 +:10DF30002088062101F0D0FD00283FF44DAFFFDF1F +:10DF40004AE72146032007F043FC070006D16A8810 +:10DF50002988204608F01DFF070012D0208806F00F +:10DF6000A7F905E09206002060000020112233008E +:10DF70002088062101F0B0FD00B1FFDF86F83F7078 +:10DF800007E7504684F8F4A086F83F0001E738B56B +:10DF9000FE4C207820B12221102000F014FE38BD64 +:10DFA0001F202071012565712220E070257094F8F2 +:10DFB000440010BB09F062FA052805D007F018F9F3 +:10DFC000A0F57F41FF3918D000202071684608F085 +:10DFD000D3FF0028E3D10098008806F069F9009883 +:10DFE0000621008801F078FD00B1FFDFE84884F8E1 +:10DFF00044500078FCF704F938BD0C20207138BD7E +:10E000002DE9F041E14D044695F83E0028B1BDE808 +:10E01000F0412321112000F0D6BD1F2085F83F00DC +:10E02000232085F84000012085F83E00618840F6F5 +:10E030007B438A1F30209A4251D2A288961F9E426B +:10E040004DD291424BD8E188B1F5FA7F47D2218970 +:10E0500040F67746A1F10A03B34240D2B1EBD20FAA +:10E060003DD96189A289914239D84FF000082088B2 +:10E07000062101F01FFD06004FF0020707D000F057 +:10E0800000FE20B1D6F8F800017839B902E085F831 +:10E090003F70DBE5D6F84011097809B13A201EE05F +:10E0A00005218171D6F8F8004146A0F80880D6F81D +:10E0B000F820A0885081D6F8F820E0889081D6F822 +:10E0C000F8202089D081D6F8F800028943899A4245 +:10E0D00004D88279082A01D89A4203D3122085F8FD +:10E0E0003F00B3E522884280D6F8F800077085F833 +:10E0F0003F10ABE5FEB5A54C0646207820B12421A3 +:10E10000102000F060FDFEBD012565712420E07047 +:10E110002570304610F04BF808B1002000E01220C6 +:10E1200020710028EFD1994884F84A504230316874 +:10E13000C0F8091031794173002684F84A606946B5 +:10E14000062001F042FC00B1FFDF684601F01BFC35 +:10E1500060B9BDF80470029880F80051684601F07B +:10E1600012FC18B9BDF80400B842F4D12671FEBD06 +:10E170002DE9F041854D064695F83E0028B1BDE8F1 +:10E18000F0412C21112000F01EBD1F2085F83F001A +:10E190002C2085F84000012085F83E0030880621BB +:10E1A00001F088FC040007D000F06BFD20B1D4F82A +:10E1B000F810087830B901E0022026E0D4F84001D8 +:10E1C000007808B13A2020E094200027005D10F08C +:10E1D000010F19D0D6F802004860D6F80600886012 +:10E1E00054F8F80F718910228181206806F10C0122 +:10E1F0000E3012F0C3FA21680320087021683088BD +:10E20000488085F83F7021E50C2085F83F001DE52A +:10E2100010B586B004464088ADF81000049800F0B0 +:10E220009FFD8DF80400A088ADF800002089ADF8AE +:10E230000200607B8DF80500A07B8DF80600D4F805 +:10E240000F00CDF80700B4F81300ADF80B00207BE9 +:10E250008DF80D00607D8DF80E00684606F037FAE7 +:10E2600006B010BD70B5044680780C25800603D436 +:10E27000607B06F0D0F918B12046FFF7C9FF0546CC +:10E28000284614E5F0B5414E044689B030780C2795 +:10E2900030B109B01821BDE8F040102000F093BC67 +:10E2A0000AF0B8FA012500287AD1607900270328FE +:10E2B0002ED8A07901282BD8A07B032828D8607BF2 +:10E2C00030B3072824D821792020052920D2DFE87F +:10E2D00001F0040D03030400A0202188814217D31C +:10E2E0006088814214D8B0F5804F11D8FF208DF896 +:10E2F000040021790097BDF80000052940F01000C6 +:10E30000ADF8000015D2DFE801F0050A07150D0091 +:10E31000122745E040F0010040F0020006E040F026 +:10E32000090001E040F0010040F00400ADF80000F9 +:10E3300000E0FFDFBDF800000090BDF80000ADF880 +:10E3400006002088029060880390607B8DF81000A2 +:10E3500060798DF81100A0798DF81200D4F80700CB +:10E36000CDF81300B4F80B00ADF81700A07B8DF8C2 +:10E3700019007F208DF81C708DF81A008DF81D5043 +:10E380008DF81B508DF81E7004E0000092060020EE +:10E39000540000208DF81F7001A8FFF763FF0746A7 +:10E3A000377175711820F070357009B0F0BD38B54F +:10E3B00004460078EF283ED8D4E90101884202D90A +:10E3C000A078000737D56088ADF80000009800F00D +:10E3D000FFFC80B36188C806E07D02D501282AD100 +:10E3E00003E0012801D0032825D1607E012803D055 +:10E3F000022801D003281ED1207BE0B107281AD8BB +:10E40000607B28B1012803D0022801D0032812D153 +:10E41000A07B08B101280ED1607D28B1012803D06E +:10E42000022801D0032806D1E07E08B1012802D1DC +:10E43000A07E0F2801D9122038BDA068B0F1807FDE +:10E4400002D26068202803D2080701D4112038BD09 +:10E45000002038BD70B5FB4D0646287828B1BDE8D0 +:10E4600070404121102000F0AEBB0C240AF0D2F91C +:10E4700050B93046FFF79BFF040005D13046FFF747 +:10E48000F1FE040000D1A87101202C7168714121B6 +:10E49000E97028700BE400781F2801D9122070471A +:10E4A00000207047F0B5E74C014689B0207830B1C4 +:10E4B00009B01A21BDE8F040102000F084BB0846E6 +:10E4C000FFF7E9FF30B120711A20E0700120607180 +:10E4D00020706AE7FF208DF8000003208DF801000E +:10E4E00000278DF8027011F8016B8DF803601F2270 +:10E4F0006D4601A812F042F92771291D304606F039 +:10E500003DF9E1E7C1781F2907D84078042803D0F6 +:10E51000032806D009B102E009B11220704711208A +:10E5200070470020704710B5C64C0246207828B1CD +:10E530004221BDE81040102000F045BB1046FFF717 +:10E54000E1FF30B120714220E07001206071207045 +:10E5500010BD00202071D078111D06F00FF9F2E7F0 +:10E5600010B5B84C217829B12021BDE81040102009 +:10E5700000F029BB01781F2902D91220207106E082 +:10E58000002121710278411C104606F0E5F81020A8 +:10E59000A070012060712021E170207010BD7CB559 +:10E5A000A84D04460C20287162781220012A16D842 +:10E5B00021780026012901D049B110E07AB105F097 +:10E5C000F1FF002876D00AF025F950B172E008F08A +:10E5D00067FF044609F03AFD002860D06AE0287120 +:10E5E00068E006F02DF8A07806F0DFF850B10128B9 +:10E5F00008D0042806D0002009F0F0FD00B1FFDFAC +:10E600002E7157E005F09EFFA0F57F41FF3951D1F3 +:10E610000022072101A801F01DFA04004AD08A480F +:10E620000321846020460FF019FB204606F04DFAC6 +:10E63000B5F85E0024F8480FB5F86000608015F862 +:10E640005A0FE07168782072A17A288909F086FE55 +:10E6500044F8200C28890121483C09F07FFE01463E +:10E660000022204608F068FFE8780090AB78EA883E +:10E67000A98820885A3D01F0B1FA00B1FFDF208857 +:10E6800005F015FE204609F0A9FD00B1FFDF2E714F +:10E69000002204F5C8712046FFF727FB0AE02E711F +:10E6A00044B1208805F004FE2088072101F014FA07 +:10E6B00000B1FFDF1020A8700120687128707CBDB8 +:10E6C00060490A781AB14321102000F07CBA432235 +:10E6D000CA70012163E71CB55A4C217829B1BDE805 +:10E6E0001C401B21102000F06EBA00788DF800004D +:10E6F00001208DF80100FF208DF802000020ADF808 +:10E7000004008DF8060001466846FFF748FF1B200D +:10E71000E0701CBD2DE9F0414A4C0646207828B136 +:10E72000BDE8F0412D21102000F04DBA30880721BE +:10E7300001F0C0F905004FF0010720D095F87101F4 +:10E7400040B995F86400112801D0122802D195F83B +:10E75000B40150B10C2020711020A0702D20E07069 +:10E760003088E0806771277093E41022B11C05F5B2 +:10E77000B97012F003F885F871710020EBE7022000 +:10E78000E9E770B52F4C0546207828B1BDE8704008 +:10E790002E21102000F017BA2888072101F08AF9ED +:10E7A000022178B190F871212AB990F86420112AD9 +:10E7B00004D0122A02D00C20207104E080F87111DC +:10E7C0000020F9E721711020A0702E20E070288829 +:10E7D000E08001206071207053E52DE9FC47194C61 +:10E7E0000646207828B13821102000F0ECF9BDE869 +:10E7F000FC8770884BF68032122190420AD848B1CB +:10E800004FF0000830886946FEF718FB20B102205F +:10E81000207110E021710EE0019800F15809851C6B +:10E820002F887288394648460FF0E6F92888B842A2 +:10E83000F6D184F80480012060713821E1702070E5 +:10E84000D5E7000092060020540000207CB5FF4C64 +:10E850000546207820B14B21102000F0B4F97CBD92 +:10E8600028886946FEF7EAFA38B1022020710120B3 +:10E8700060714B21E17020707CBD01987F220146C0 +:10E8800080F8602080F86120002280F86220A8785B +:10E8900001F82C0FE8784870287988702271E6E733 +:10E8A0001CB5EA4C217821B15821102000F08BF9D9 +:10E8B0001CBD00886946FEF7C1FA48B102202071EC +:10E8C000012060715821E1701021A17020701CBDE1 +:10E8D000019890F8710000B1012000212171A07110 +:10E8E000EEE71CB5D94C217821B11321102000F09E +:10E8F0006AF91CBD00886946FEF7A0FA08B102203B +:10E9000005E0019890F82C10012902D00C2020710C +:10E9100006E0602100222271095C21720088E080FB +:10E92000012060711321E1701021A17020701CBDC5 +:10E930002DE9F041C54C0546207828B1BDE8F041ED +:10E940004C21102000F03FB92888072101F0B2F8CF +:10E95000012358B382886D88C688418803EB42073B +:10E96000BD4217D342F210777E43BF107943B6FB06 +:10E97000F1F1491E89B24FF4FA76B14200D931461D +:10E980008D4200D22946491C521CB1FBF2F1514381 +:10E99000491E8AB290F8A01101B90284E2800020D9 +:10E9A000207163714C20E07023702CE40220F7E7A3 +:10E9B00070B5A64C0546207828B1BDE870404E21C0 +:10E9C000102000F000B92888072101F073F890B1F9 +:10E9D000A97811F0010180F8DF1004D090F8DD1063 +:10E9E00009B109F0EBFC00202071012060714E217B +:10E9F000E170207045E40220F6E794490A781AB1E4 +:10EA00005421102000F0DFB802789AB142788AB120 +:10EA100042881B2A0ED382881B2A0BD3C288022A63 +:10EA200008D38A4A0368423242F81A3F406850606D +:10EA3000002000E012200871012048715422CA70A1 +:10EA40000870704770B5814C0546207828B1BDE844 +:10EA500070405521102000F0B6B8287800F0010071 +:10EA600008F0B5FA287800F0010009F043FC002016 +:10EA70002071012060715521E17020700AE570B5A8 +:10EA8000724D0646287828B1BDE870405921102003 +:10EA900000F099B801227088114608F09BFA0446EC +:10EAA0007088012109F05AFC844200D20446308863 +:10EAB000012100F06FF806460121002000F06AF8FD +:10EAC000304401219630844206D900F19601201A83 +:10EAD000B0FBF1F0401C81B2E980002028710120D8 +:10EAE00068715921E9702870D4E470B5574D044617 +:10EAF000287828B1BDE870405021102000F063B89C +:10EB000000F06EF808B10C200DE0601C0EF01EFF46 +:10EB1000207800F0010005F08EFD207800F0010063 +:10EB200006F0DDFD00202871012068715021E97098 +:10EB30002870AFE470B5454C0546207828B1BDE893 +:10EB400070404D21102000F03EB809F063FE08B17E +:10EB50000C2003E0287805F023FE0020207101201E +:10EB600060714D21E170207094E410B501785A294C +:10EB700007D2374A52F8211019B1001D88470120E9 +:10EB800010BD002010BD18B1022801D0012070472F +:10EB900000207047012903D080002C3080B27047DC +:10EBA000C0005030FAE7032904D0022907D0C00082 +:10EBB000703006E04FF4747101EB801001E08000CA +:10EBC0003C3080B27047214A92F84130002B06D188 +:10EBD00082F8420082F84310012082F84100704719 +:10EBE00010B508F04BFC042807D008F047FC0528B6 +:10EBF00003D009F00FFE002800D0012010BD2DE940 +:10EC0000FE4300250F4680460A260421404603F0B5 +:10EC1000BFFE40460FF0A7FA062000F0F5FE0446BE +:10EC20001AE06946062000F0D0FE0AE0BDF80400B4 +:10EC3000B84206D00298042241460D3011F072FD10 +:10EC400078B1684600F09FFE050003E092060020C0 +:10EC5000E40C0200EAD0641E002C06DD002DE0D09A +:10EC600005E040460FF088FAF5E705B9FFDFD8F870 +:10EC700000000EF0CBFF761E01D00028C5D0BDE805 +:10EC8000FE8390F8711041B990F8D01029B190F836 +:10EC9000D000042801D0012070470020704701787F +:10ECA00001290AD1416891F8DD20002A05D000220F +:10ECB00081F8DD20406809F081BB70470AB101226C +:10ECC00000E00222024201D0072001E001F007002B +:10ECD0001870704710B5038843F6FD711A1F8A42F9 +:10ECE00023D24288141F8C421FD29A421DD8C28957 +:10ECF00040F67B43911F994217D2018A8C1F9C4298 +:10ED000013D28A4211D8428AB2F5FA7F0DD2828A92 +:10ED100040F67744A2F10A03A34206D2B2EBD10F28 +:10ED200003D9C18A028B914201D9302010BD0179EB +:10ED300011B1012910D107E0417929B1012903D08E +:10ED4000022901D0032907D1007B38B1012805D061 +:10ED5000022803D0032801D0122010BD002010BDCE +:10ED600080B200B5C1074FEA807112D000294FEA86 +:10ED7000007104DA002926DB410727D523E00029AA +:10ED80004FEA407119DA00291DDAC0061ED50120AC +:10ED900000BD00294FEA007107DA002913DB4107A3 +:10EDA00011D4C00612D5022000BD00290BDB41079B +:10EDB00009D4C0060AD5032000BD002903DAC00625 +:10EDC00004D5042000BDC00600D5FFDF002000BD33 +:10EDD00080B2C10605D4010713D4C1070FD0800744 +:10EDE0000BE0C1074FEA807104D0002902DB400725 +:10EDF00005D406E0010704D44007002801DB012008 +:10EE000070470020704720B100234360021D01813C +:10EE10000260081D7047026800212AB193881268B9 +:10EE2000194489B2002AF9D100234360021D0181EF +:10EE30000260704730B4026800230AB30268938806 +:10EE40008B421EBF1368002B1046F7D1B2F804C0E6 +:10EE500013468C4508BF116811D001F10804A5B212 +:10EE60000024AC4538BF00230AD3ACEB010C11449D +:10EE70000C60A1F804C00268126802600A600160B8 +:10EE800030BC1846704700230B608A8002680A6015 +:10EE90000160704708440830424301F14A001044C1 +:10EEA00080B27047F0B51D460446A818059B08308F +:10EEB00000FB03F205F14A00104486B2B14238BFAC +:10EEC000FFDF002727606760A760E7602761676151 +:10EED000A761E76127624FF6FF706762A082A6F123 +:10EEE000280080B265776080B0F5004F88BFFFDFF3 +:10EEF000608805F13C01884238BFFFDF6088401B15 +:10EF00003C3880B220801B2838BF1B202080A77788 +:10EF1000F0BD8161886170472DE9F04F0D46C188D1 +:10EF2000044600F12808008921F4004320F400423F +:10EF300021F4004620F400474FF0010A4FF0000989 +:10EF40009A4208D100F4004001F4004188421CBFFD +:10EF50000020BDE8F08FB7420BD9617FB81B401A83 +:10EF6000083885421BDC08EB060000210580418043 +:10EF70001EE06088617F801B401AB0F1080B0ED440 +:10EF8000BBF11B0FB8BFFFDF5D45D4BF29461FFA99 +:10EF90008BF1681A0204120C18BFBA4204DD84F81F +:10EFA00017900020BDE8F08F08EB0600018042803A +:10EFB00084F817A0BDE8F08F2DE9F041044600F178 +:10EFC0002802C08820F40043E07D002808BFBDE887 +:10EFD000F081D0180288438813448B423CBF002044 +:10EFE000BDE8F081002791429CBF0180478013D982 +:10EFF000891A0D042D0C45800ED0E088A61D20F442 +:10F000000040854288BFFFDF30884FF4004121EA8D +:10F010000000284330800AE0627F008802F1080384 +:10F020001044083081B26288A01D00F0A8FBE7758B +:10F030000120BDE8F08130B4B0F804C0C4880346B4 +:10F0400000F128052CF400402844A44503D10020F9 +:10F05000188230BC7047B3F80CC00488A44509D3AB +:10F060004088ACEB040CA0EB0C0084B20CEB050068 +:10F07000C01E06E0A4EB0C045D7FA4B2AC44604467 +:10F08000401DB1F800C0A44588BF0C80B3F80CC087 +:10F09000BCF1000F0CBF4FF0010C4FF0000C82F8D8 +:10F0A00000C00988198230BC70472DE9F041044640 +:10F0B00000F12801808820F400404518208A0028AB +:10F0C00008BFBDE8F081A08910B9A069807F2871D0 +:10F0D000A089218A084480B2A08129886A881144C5 +:10F0E000814238BFFFDF28886D88A2894119002737 +:10F0F00091421AD175B1A088261D20F40040A84283 +:10F1000038BFFFDF30884FF4004121EA0000284378 +:10F11000308009E0627F1044083081B202F10803B8 +:10F120006288201D00F02BFBA78127820120BDE80B +:10F13000F0812DE9F0474189B0F8048000270446AA +:10F1400000F1280A414518BF4FF400493AD000BFEA +:10F1500021F40040504446886EB1608904F10A05EC +:10F1600020F40040B04238BFFFDF288829EA0000C1 +:10F170003043288021E0637F008803F1080C1844A5 +:10F180006389083023F400456288284480B204F182 +:10F190000A0190420BD2121A92B20CF11B0C62457A +:10F1A0002CBF03F4004229EA030004D204E0801AD1 +:10F1B00080B229EA030210430880781C618987B273 +:10F1C0004145C5D13846BDE8F0872DE9F047B0F894 +:10F1D00008800B46044600F12801B0F80A908088A8 +:10F1E00028F4004C01EB0C05804504BF0020BDE86D +:10F1F000F087002A1CBF681D106023B1627F691D63 +:10F20000184611F0BBFA2F886D888DB1E81987B2C6 +:10F21000208904F1080620F40040A84238BFFFDF2F +:10F2200030884FF4004121EA0000284330800AE092 +:10F23000607F6288C119083100F1080389B204F1C6 +:10F24000080000F09CFAC84504BF20896081384658 +:10F25000BDE8F0878188C08881420CBF0120002072 +:10F2600070470189808881420CBF012000207047CF +:10F2700030B48488C28800F1280324F4004C22F4BE +:10F280000041634494421BD08289048A15191C886A +:10F290005A88A3189D4216D312B18A4210D212E0A6 +:10F2A000437F0CF1080C1A196244408892B2801A0C +:10F2B00080B22333984201D211B104E08A4202D1D4 +:10F2C00030BC0020704730BC012070472DE9F007AA +:10F2D000B0F806C0048900F1280702462CF4004566 +:10F2E0007E1924F400492CF4004A002024F4004341 +:10F2F0004FF00108D1450AD104F400440CF4004C4D +:10F30000644504D05082BDE8F00700207047AB424E +:10F3100008D992F81DC05B1BA3EB0C03A3F10804F2 +:10F32000002308E0B2F802C0547FACEB050CACEB54 +:10F33000040CACF10804002CE4DBB2F80EC0BCF104 +:10F34000000F0DD0B6F800C075884DB15B1B10776B +:10F350008B42D7DBD0893844A0EB0C00C01E09E0FB +:10F36000A4EB0C0410778C4208DB507FD38918443F +:10F370003044401D5182BDE8F00770478B42A8BF62 +:10F3800082F81C80E6DABDE72DE9F05F044600F163 +:10F39000280AC088934620F400400AEB0005608AE2 +:10F3A000894608B1484502D20020BDE8F09FE089B7 +:10F3B00080B1B5F800806E8808EB0601884218BF5E +:10F3C000FFDF207F4FF0000750EA060108D0002839 +:10F3D00040D04AE04FF00008A17F46462971F0E78F +:10F3E000E08948B1617F01444819B4F81F10A0F8C2 +:10F3F000051094F82110C171E18908EB0900494416 +:10F40000E18128806F80BBF1000F19D0607F2988CF +:10F4100000F108030144083189B26288A01D00F0A0 +:10F42000AEF9E781A07F401CA077A07D00281CBF1B +:10F43000E088A082A7756782E7750120BDE8F09F8C +:10F44000607FE18908442844B0F80510A4F81F1033 +:10F45000C0792EE0E089B4F81F105044A0EB0800FA +:10F4600020F8031D94F82110817006EB090086B284 +:10F47000E089BBF1000F4844E081A5F800806E8070 +:10F480000ED0E088A51D20F40040B04238BFFFDF59 +:10F4900028884FF4004121EA000030432880C0E76B +:10F4A000E0895044A0EB080030F8031DA4F81F10B9 +:10F4B000807884F82100BEE7818800F1280221F4D9 +:10F4C000004C6244B0F814C0C388614518BF99422B +:10F4D0000FD0818969B9806968B1018983889942AF +:10F4E00009D021F40041283008441179007988427C +:10F4F00001D1002070471046704700F12803407F7B +:10F5000001F1050C604410600888002804BFD81E73 +:10F51000106008884988084480B270472DE9F0419E +:10F5200015460A4600F128061C46407F531D034439 +:10F5300010885788069900281CBFC01C80B226D0AE +:10F5400088429CBF081A80B213D9401AA042A8BFB3 +:10F5500020461FFA80F858184246294611F0E2F872 +:10F56000002818BFBDE8F0814544A4EB080084B230 +:10F57000002001198F423CBF4FF0FF30BDE8F08101 +:10F58000304422462946BDE8F04111F0CBB8FA1CC0 +:10F5900097B2F61ED4E72DE9F04100F128071D4689 +:10F5A000407F4B1D0344164608880024B1F80280B2 +:10F5B000069A00281CBFC01C80B21FD090429CBF7E +:10F5C000101A80B20DD9801AA842A8BF284684B26A +:10F5D00099182246304611F0D1F8281B85B22644EE +:10F5E00000204119414506D839182A46304611F005 +:10F5F000C5F8601984B22046BDE8F08108F1030126 +:10F600001FFA81F8FF1ED9E72DE9F04116460A4698 +:10F6100000F128071D46407F531D03441088002435 +:10F62000B2F80280069900281CBFC01C80B21FD00F +:10F6300088429CBF081A80B20DD9401AA842A8BFC0 +:10F64000284684B258182246314611F097F8281BF4 +:10F6500085B2264400204119414506D838442A463F +:10F66000314611F08BF8601984B22046BDE8F08174 +:10F6700008F103021FFA82F8FF1ED9E7401D704708 +:10F6800070B5044600F12801C288808820F4004348 +:10F690001944904208D0A289002A04BF228A002A75 +:10F6A00002D1A28A904201D1002070BDB1F800C001 +:10F6B0004D8885B1261D20F40040A84238BFFFDFE9 +:10F6C00030884FF4004121EA0000284330800020B8 +:10F6D0002082012070BD607F0CF1080100F1080359 +:10F6E000084481B26288201D00F049F8EFE700214C +:10F6F000C18101774182C17581757047038813808C +:10F70000C289002A04BF00207047C28800F1280384 +:10F7100022F400421A440A60C089704710B50446BA +:10F72000808AA0F57F41FF3918BFFFDFE088A08203 +:10F73000E089002818BF0120A07510BD4FF6FF71A9 +:10F74000818200218175704710B50446808AA0F53A +:10F750007F41FF3908BFFFDFA07D28B9A088A18ABB +:10F76000884204BF002010BD012010BD8188828A1C +:10F77000914205BF807D002800200120704710B411 +:10F78000B0F800C02CF40044214489B24FF4004486 +:10F7900091420AD2521A92B21B339A422CBF0CF4F5 +:10F7A000004224EA0C0104D204E0891A89B224EA56 +:10F7B0000C021143018010BC704770B516464FF61D +:10F7C000FC72C91C01EA0205D8B10446C01C20F035 +:10F7D0000301A14200D0FFDF201D012108E0024605 +:10F7E000284401D2034600E00023491CC9B213603B +:10F7F000B142F4D916B104F1040001E04FF0000069 +:10F80000206005FB06F000F1040070BD02460020F8 +:10F810001168002902D00846096811607047026823 +:10F820000A60016070474FF6FC73C91C1940101A3A +:10F83000001F90FBF1F0C0B270474FF6FC73C91C7B +:10F840001940001D01FB0200704700002DE9F04146 +:10F85000C14D04469046A8780E46A04200D8FFDF6E +:10F8600005EB8607B86A50F8240000B1FFDFB868DE +:10F87000FFF7CCFF05000CD0B86A082E40F82450E2 +:10F8800000D3FFDFB5484246294650F826302046CF +:10F8900098472846BDE8F0812DE9F0471E46040050 +:10F8A000074602EB060091468A46C5B227D00021E2 +:10F8B0008846FF2800D9FFDFE01C20F00300A042AB +:10F8C00000D0FFDFB24500D9FFDFA34880F800A0D9 +:10F8D00080F801908570C570057145718671DFF8FB +:10F8E0007CA280F8079000260AF1400A8146FF1C9E +:10F8F00027F003000746B8F1000F03D005E04FF0F2 +:10F900000101D5E709EB860188603AF8161019F86D +:10F91000062001D04FF00000FFF74FFF761CF6B233 +:10F920000744082EE3D3FF1C27F003002A460646AF +:10F93000B8F1000F0DD000200221FFF73EFF434633 +:10F94000002130440F46C846C01C20F003021BB102 +:10F9500010E0C9F84800EFE708EB81060020B2622A +:10F9600006E000BFD6F828C04CF82070401CC0B29A +:10F97000A842F7D3491CC9B202EB85000829E3D39A +:10F98000001BBDE8F08710B5044603F07DFB08B10D +:10F99000102010BD2078704A618802EB80009278B8 +:10F9A0000EE0836A53F8213043B14A1C6280A18083 +:10F9B000806A50F82100A060002010BD491C89B267 +:10F9C0008A42EED86180052010BD70B505460C4610 +:10F9D000084603F059FB08B1102070BD082D01D373 +:10F9E000072070BD25700020608070BD0EB569468F +:10F9F000FFF7EBFF00B1FFDF6846FFF7C4FF08B178 +:10FA000000200EBD01200EBD10B50446082800D30D +:10FA1000FFDF5148005D10BD3EB505460024694634 +:10FA2000FFF7D3FF18B1FFDF01E0641CE4B26846C2 +:10FA3000FFF7A9FF0028F8D02846FFF7E5FF001BD5 +:10FA4000C0B23EBD44498978814201D9C0B27047F5 +:10FA5000FF2070472DE9F04190460C4605460629E7 +:10FA600001D0072C10D13C4FB86CFFF7CFFE02003D +:10FA70004FF6FF7604D00221B86CFFF7D4FE00E009 +:10FA800030462880B04201D1002003E7424621469B +:10FA9000FFF7DCFE040002D1288800F04FF8204672 +:10FAA000F8E6A0F57F43FF3B01D0082901D30020F1 +:10FAB0007047CBE6A0F57F42FF3A0BD0082909D268 +:10FAC000254A9378834205D902EB8101896A51F86E +:10FAD00020007047002070472DE9F04105460C4694 +:10FAE000A5F57F4143F20200FF3902D0082C01D373 +:10FAF0000720CFE618494FF000088A78AA42F8D9C3 +:10FB000001EB8406B26A52F82570002FF1D0134839 +:10FB10003946203050F8242028469047B16A062CF8 +:10FB200041F8258001D0072C02D1284600F006F8C4 +:10FB30003946B068FFF773FE0020ABE610B5064CFF +:10FB4000C2B20221A06CFFF778FE0146A06CBDE8AE +:10FB50001040FFF764BE0000FC0600204C0E0200BF +:10FB600070B50E461D46114600F0D5F804462946EC +:10FB7000304600F0D9F82044001D70BD2DE9F04159 +:10FB800090460D4604004FF0000610D00027E01C00 +:10FB900020F00300A04200D0FFDFE5B14146002085 +:10FBA000FFF731F90C3000EB850617B113E00127A0 +:10FBB000EDE7624F04F10C00A9003C602572606023 +:10FBC00000EB85002060606810F071FE38684146E7 +:10FBD0000068FFF718F93046BDE8F0812DE9FF4FC6 +:10FBE000564C804681B020689A46934600B9FFDFA4 +:10FBF0002068027A424503D9416851F8280020B1B3 +:10FC000043F2020005B0BDE8F08F5146029800F0C3 +:10FC100082F886B258460E9900F086F885B27019BF +:10FC2000001D87B22068A14639460068FFF702F937 +:10FC300004001FD0678025802946201D0E9D0746A1 +:10FC40005A4601230095FFF72DF9208831463844A4 +:10FC50000123029ACDF800A0FFF724F92088C119EA +:10FC60003846FFF756F9D9F800004168002041F8FE +:10FC70002840C7E70420C5E770B5304C054620682A +:10FC800000B9FFDF2068017AA9420ED9426852F814 +:10FC9000251051B1002342F825304A880068FFF74B +:10FCA000F2F8216800200A7A08E043F2020070BDF1 +:10FCB0004B6853F8203033B9401CC0B28242F7D8A9 +:10FCC0000868FFF7A8F8002070BD70B51B4E054608 +:10FCD0000024306800B9FFDF3068017AA94204D9F6 +:10FCE000406850F8250000B1041D204670BD70B575 +:10FCF000124E05460024306800B9FFDF3068017AF3 +:10FD0000A94206D9406850F8251011B131F8040B0A +:10FD10004418204670BD10B50A460121FFF7BAF815 +:10FD2000C01C20F0030010BD10B50A460121FFF7EA +:10FD3000B1F8C01C20F0030010BD000068000020D6 +:10FD400070B5044600780E4601281AD0072802D064 +:10FD50000C281AD115E0A068216905780B2D0CD06C +:10FD6000052003F027F9052D0FD078230022052068 +:10FD7000D4F8101003F07EF807E078230022062064 +:10FD8000F8E70520216903F015F931462046BDE862 +:10FD9000704001F0ADB910B500F13902C379947823 +:10FDA000411D64F003042340C371DB070DD04B7980 +:10FDB000547923404B710B79127913400B7182787F +:10FDC000C9788A4200D9817010BD00224A710A7137 +:10FDD000F5E74178012900D00C21017070472DE929 +:10FDE000F74F86B000208C690D468DF80400097825 +:10FDF0000127FA4816464FF0070A4FF011094FF055 +:10FE00000A0B2A2978D2DFE811F02A0011035203E5 +:10FE10006903A803B303CC03FA030F043B04620491 +:10FE200081049A04D504E60405051005300554053F +:10FE300077059C05C605E005EE050F06270630068A +:10FE400063068506D6060D071B074B076A07790769 +:10FE50008A07C407FB072708E407E807ED0714B182 +:10FE600020781D2829D0D5F808805FEA080043D003 +:10FE700001208DF80400686A059003208DF80800C1 +:10FE80008DF809B0286A0390A8880028EFD098F868 +:10FE9000001091B10F2910D27ED2DFE801F07D145D +:10FEA0004CDCFDFCFBFAF9F8F7089FF6F500022898 +:10FEB00022D124B120780C2801D0002770E3022041 +:10FEC0008DF80400ACE10620696A03F073F8A88895 +:10FED0000728EDD1204601F006F9022809D0204676 +:10FEE00001F001F9032808D9204601F0FCF80728A1 +:10FEF00003D20120207005E011E2002CB7D0207859 +:10FF00000128D5D198F80400C11F0A2903D300BFE6 +:10FF100085F81CB089E2A070D8F80010A163B8F889 +:10FF20000410A18798F8060084F83E00012028708C +:10FF30000320207046E00728BAD1002C97D0207803 +:10FF40000D28B5D198F8031094F83B20C1F3C000F8 +:10FF5000C2F3C002104201D00E2000E00F2089073A +:10FF600007D198F805100142D2D198F80610014245 +:10FF7000CED194F83D2098F8051020EA02021142F3 +:10FF8000C6D194F83E2098F8061090430142BFD1A4 +:10FF900098F80400C11F00E045E20A29B8D2617F49 +:10FFA000814201D90620C2E3D8F800106160B8F898 +:10FFB0000410218198F80600A072012028700E20FC +:10FFC000207003208DF80400686A059004F1390060 +:10FFD0000290601D03901730049067E2412890D191 +:10FFE000204601F080F8042802D1E078C00704D14F +:10FFF000204601F078F80F289ED1A88CEF6880B2D7 +:020000040001F9 +:100000004FF0400AD4F82480FFF75FFE39460827F6 +:10001000424653460097FFF7BEFA0E208DF80400C3 +:10002000686A0590606A0290002101A8FFF788FEC7 +:100030002078042806D0A07F38B1012805D00328F5 +:1000400006D0AEE3052020700BE284F8009034E780 +:100050001220207066E01128C1D1204601F043F83B +:10006000042802D1E078C00719D0204601F03BF8FF +:10007000062805D1E078C00711D1A07F02280ED054 +:10008000204601F030F808E0AFE07DE09AE16EE153 +:100090004EE106E1E5E0CBE01CE011289FD1102203 +:1000A00008F1010104F1480010F068FB60780128B4 +:1000B0000DD012202070E078C00703D0A07F88B355 +:1000C00001282FD085F800B08DF804B0F0E384F853 +:1000D00000A027E011288FD1204601F004F808285D +:1000E00004D0204600F0FFFF132885D12869D8B13D +:1000F0006869C8B104F17800102208F101010746CF +:1001000010F03CFB2078082812D014202070E078F2 +:10011000C0070FD0A07F022818D06178022912D022 +:100120000328CFD10420FDE300208DF80400F6E081 +:100130000920EBE70B202870296901204870206C0A +:10014000C1E9010792E208B1012870D10B202870A3 +:10015000296981F801A0606A4860206AC1E9020744 +:1001600078E2206CE2780068C2F34402521ED0406C +:1001700000F0010040F0800000E000200874E06A18 +:1001800048617CE20746F9E31128D0D1204600F00F +:10019000AAFF0A2802D1E078C00704D1204600F067 +:1001A000A2FF1528C3D1102208F1010104F1480073 +:1001B00010F0E4FA20780A2812D0162020701220BD +:1001C000287029690920487004F1580048602030DF +:1001D00088601038C860206C0861ACE3C40F02006E +:1001E0000B202070E4E22870D9E102289FD120463C +:1001F00000F079FF042804D3204600F074FF08289B +:1002000009D3204600F06FFF0E2890D3204600F05F +:100210006AFF12288BD2A07F022888D18DF8049023 +:10022000686A059098F801008DF80800FBE36CE21D +:100230000228AAD1204600F056FF00286FD02046A1 +:1002400000F051FF0128F9D0204600F04CFF0C28A7 +:10025000F4D005208DF8080098F801008DF8090009 +:1002600065E71128FCD1002CFAD020781728F7D1A7 +:100270006178E06A022912D05FF0000101EB4101D0 +:10028000182606EBC1011022405808F1010110F0B8 +:1002900075FA0520696A00F019FF26700DE6012144 +:1002A000ECE70B28DCD1002CDAD020781828D7D145 +:1002B0006178E06A02292CD05FF0000101EB410176 +:1002C000102202EBC1014158B8F8010008806078A3 +:1002D000E16A022820D0002000EB4002142000EB4D +:1002E000C2000958404650F8032F0A604068486031 +:1002F0000520696A00F0EAFE6078022810D04FF00D +:1003000000002044407A20F001000CD14FF00101A0 +:100310000BE04FF00101D1E74FF00100DCE77FE295 +:100320004FF00100EDE74FF000012144487279E3FE +:10033000112895D1002C93D02078192890D160787D +:10034000E16A022811D0002000EB40021C2000EBE3 +:10035000C2001022085808F1010110F00FFA052020 +:10036000696A00F0B3FE1A20F5E00120ECE70828E6 +:1003700098D1002C98D020781A2893D1E06A98F868 +:100380000120017862F347010170E16AD8F8022088 +:1003900041F8012FB8F8060088800520696A00F04E +:1003A00095FE6078022807D04FF000002044407A84 +:1003B00020F002012BD033E04FF00100F6E720449B +:1003C00041722FE31128B4D1002CB4D020781B281F +:1003D000AFD16178E06A02291CD0002101EB410114 +:1003E000202202EBC1011022405808F1010110F057 +:1003F000C5F90520696A00F069FE607802280CD012 +:100400004FF000002044407A20F0040108D14FF062 +:100410000100D4E74FF00101E0E74FF00100F1E700 +:100420004FF00000CBE785F81CA0FAE330780128F4 +:1004300084D11C2204F11C00716810F0E4F9E07909 +:10044000C10894F83B0001EAD001E07861F30000B4 +:10045000E070217FF1BB217803290AD0C0073FF467 +:10046000F9AD032028708DF804B0686A059041202A +:100470009EE3607FA17888423FF694AD0227277102 +:10048000E179204621F0E001E171617A21F0F0018B +:100490006172A17A21F0F001A172FFF77CFC2F704C +:1004A0008DF804B0686A05908DF808A0F2E3307802 +:1004B000112888D18DF804A0696A0591B16803916B +:1004C000ADF808A008466168016021898180A17AA1 +:1004D000817100E06AE004202070A4E230781128E5 +:1004E000A6D18DF804A0686A0590301D02AB07C83C +:1004F00083E807004120ADF8080008460C21017090 +:10050000A88CD6F80C8080B24027D4F82090FFF752 +:10051000EEFB41464FF008084A463B46CDF80080C6 +:10052000FFF772F8002101A8FFF70AFCE07820F03D +:100530003E00801CE0702078052801D00F200AE0E2 +:10054000A07F00283FF4C3AD0128FBD003287DD154 +:1005500084F80080B1E42070AFE430780328A8D19B +:1005600070680168A1664068E0660520287035E281 +:10057000317803299DD171680A68226749686167EB +:10058000216C51B9A17F19B1012901D0062029E1BF +:1005900085F800A02064606401E085F800A00327CE +:1005A000F3E33178022984D1317909B1297737E130 +:1005B000A17F022910D00329EFD16178012910D041 +:1005C000A17994F83A2001290FD02064E178C90775 +:1005D00013D0012A0ED010E0B0680028E7D02064C4 +:1005E0000BE0A27994F83A10EDE7B1680029DED06B +:1005F0002164EBE7F0680028D9D06064CDE78DF87E +:1006000004B0696A0591E1785846C90709D0617854 +:10061000022903D1A17F29B1012903D0A17F032998 +:1006200000D00820287012E230781128BFD1B068BD +:10063000286209202870E0782969C0070FD081F866 +:1006400001A0206A4860606A886000E0ABE004F1C5 +:100650006800C860A07F02287FF48FAD81E501208B +:100660004870206C486004F16800886004F138002C +:10067000C860201D0861206B4861606B88611FE2C3 +:10068000E1783078C90701D0062100E00A218842CC +:100690008DD12078072817D084F800908DF804A019 +:1006A000686A0590286A0390ADF80890032100F865 +:1006B000011B1022716810F061F8002101A8FFF7FA +:1006C0003FFB00202862C2E408202070E6E7307873 +:1006D0001128ABD18DF804A0686A0590B06803902A +:1006E000ADF80890042100F8011B102204F1680104 +:1006F00010F044F8002101A8FFF722FB2078092818 +:1007000001D0132027E784F800B016E0E1783078B4 +:10071000C90701D0062100E00A21884286D11022B3 +:1007200004F1480071680FF0FDFF10B10420287734 +:10073000A2E3207809283FF4C5AC0C2053E5E0780B +:10074000C10735D0A17F012902D002291BD02CE09E +:100750000D202870296981F801B06078012809D03E +:10076000206A4860606A886004F16800C8601030E0 +:10077000086104E5606A4860206A886004F17800D6 +:10078000C8601038F4E7C0F3440114290DD24FF0CB +:10079000006101EBB0104FEAB060E07060780128B2 +:1007A00001D0102055E40620D5E6607801288AD0D3 +:1007B0000E2018E5307809288BD185F800B010207C +:1007C0008DF80400686A059070680290002101A805 +:1007D000FFF7B6FAE9E7E078C00706D0A07F012866 +:1007E0001FD10F2028700420F8E0152028702969F7 +:1007F00002204870206C48606078012805D004F120 +:10080000780088601038C8605AE104F16800886098 +:100810001030F8E730780228CED1307908B1287747 +:1008200028E3102028700F20D8E030781328F7D163 +:1008300085F80090296908204870706848606078E1 +:1008400001280DD004F1680088601030C860206B6A +:100850000861606B486104F158008861A06A21E07A +:1008600004F1780088601038F0E730780728D7D195 +:10087000607801281AD1A078A16A0A18C0F1100185 +:1008800010460FF0F2FF12202870296909204870E5 +:1008900004F158004860203088601038C860206C2F +:1008A000086141E0C861E06A086209E11320C9E01B +:1008B000CBE030780828B3D1102204F148007168E9 +:1008C0000FF030FF08B10B2031E720780B28EDD076 +:1008D0002046FFF760FAA078A16A0A18C0F110015B +:1008E00010460FF0C2FF1620287008208DF8040073 +:1008F000686A0590002049E03078112890D1B068EE +:1009000028621420287029690920487004F15800D1 +:100910004860103088601030C860606C0861607892 +:10092000012800E09EE006D004F139004861206B08 +:100930008861606BB6E7601D4861606B8861206B01 +:10094000B0E73078082892D18DF804A0686A059045 +:10095000286A0390ADF808900D2100F8011B1022C1 +:1009600071680FF00BFF002101A8FFF7E9F90020E3 +:1009700028626178012902D01520ECE569E2162190 +:10098000297008218DF80410696A05910290A078F9 +:100990008DF80C007EE130780B288CD11620287061 +:1009A0006078022802D12046FFF7F5F9A078716837 +:1009B0000A18C0F1100110460FF057FF08208DF8FB +:1009C0000400686A05907068E0E730780F2895D1D8 +:1009D000E079C0077BD01720287009208DF804002B +:1009E000686A059056E13078102887D11422311DAD +:1009F00004F11C000FF007FFE16A208DA1F8090047 +:100A0000E16AA078C871E179E26A01F0030111722C +:100A1000E16A627A0A73E16AA07A81F82400607858 +:100A2000012876D0B3E13EE26078022801D00120AF +:100A300000E000202044407AC0070BD0E078C007D7 +:100A400008D1192028708DF804B0686A05908DF8D7 +:100A500008901FE11E2071E63078112874D1B0682B +:100A600028621A2028700520B8E7307803286BD157 +:100A70006078E26A022801D0012000E0002000EB4B +:100A80004001142000EBC1015158726813680B60DB +:100A900052684A601B212970D5E9041205234B7066 +:100AA000636A4B606778E36A022F01D0012700E098 +:100AB000002707EB470700EBC7001858C1E90202FF +:100AC000686A4862069800F02AFBFFF75BBB87E183 +:100AD00030780E2838D16078E26A022801D00120EF +:100AE00000E0002000EB4000102101EBC0000223D9 +:100AF0001058093271680EF055FA1C2028702969C7 +:100B000004204870206A4860E06A09308860FA482A +:100B100079E65AE130780D2816D16178E06A022929 +:100B200001D0012100E0002101EB4101182707EB72 +:100B3000C101A278405871680FF020FE6178E06A28 +:100B4000022902D0012101E0A9E0002101EB4101CD +:100B500007EBC1014058A1780844C1F110010FF022 +:100B600084FE8DF804A0686A0590286A0390ADF8A9 +:100B70000890062101706278E16A022A01D0012200 +:100B800000E0002202EB420207EBC202401C89583F +:100B900010220FF0F3FD002101A8FFF7D1F800208B +:100BA00028621D2028708DF804B0686A05900B201B +:100BB0008DF808006EE03078112870D18DF804A00F +:100BC000686A0590B06803900B20ADF808000398A0 +:100BD00080F800A06278E16A022A01D0012200E0D8 +:100BE000002202EB4202102303EBC202895809885B +:100BF000A0F801106178E26A022901D0012100E029 +:100C0000002101EB4103142101EBC30151580A6893 +:100C100040F8032F49684160002101A8FFF790F8D0 +:100C200018E729E16078022801D0012000E00020C7 +:100C30002044407A800701D51F2003E721207DE56D +:100C4000307811282BD18DF804A0686A0590B0681F +:100C50000390ADF80890082707706178E26A0229CE +:100C600001D0012100E0002101EB41031C2101EB37 +:100C7000C301401C515810220FF080FD002101A833 +:100C8000FFF75EF8202028708DF804B0686A0590A0 +:100C90008DF80870314601A8FFF752F815E775E0A6 +:100CA0003078112872D18DF804A0686A0590B06878 +:100CB00003900820ADF80800039809210170E1694C +:100CC000097849084170E16951F8012FC0F8022004 +:100CD0008988C180002101A8FFF732F8AEE760786B +:100CE000022801D0012100E000212144497A49076E +:100CF00001D52220A6E6012849D068E030781128E5 +:100D000044D1B068286223202870296904204870E3 +:100D1000206A4860E06A09308860784873E5307876 +:100D20000D2833D16178E06A022901D0012100E069 +:100D3000002101EB4101202707EBC101102240589F +:100D400071680FF01BFD8DF804A0686A0590286A91 +:100D50000390ADF8089080F800B06278E16A022A4A +:100D600001D0012200E0002202EB420207EBC202A6 +:100D7000401C895810220FF001FD002101A8FEF748 +:100D8000DFFF002028626078B5E791E037E024209B +:100D9000D4E4607802280BD000202044407AC107B8 +:100DA00002D0E178C90705D0810705D51920A9E44B +:100DB0000120F2E71720A5E4400701D51B20A1E49C +:100DC0001C2020706078012801D01820B6E427206C +:100DD000B4E4282028700B2000E63078122849D18E +:100DE0002920ABE42078012844D00C2842D02046AA +:100DF000FEF7EFFF0C208DF80400686A059039E0DB +:100E000030784FF02608112805D0122030700327C3 +:100E100085F800804CE08DF804A0686A0590B06801 +:100E200003900220ADF80800039805210170297F86 +:100E30004170002101A8FEF783FF0B208DF804000C +:100E4000686A0590314601A8FEF77AFF074685F8E3 +:100E50000080012F0ED02BE001208DF80400686A7D +:100E6000059004208DF80800287F8DF809000020E7 +:100E7000287712E0287F80B11D202070252028705F +:100E80008DF804B0686A059002208DF8080031469C +:100E900001A8FEF755FF07460AE00CB1FE202070BE +:100EA0009DF8040020B1002101A8FEF749FF0AE4E3 +:100EB00009B03846BDE8F08F2DE9F04F85B00C46FB +:100EC0004E69002190468DF8041001272278BA4619 +:100ED0004FF00209072022B1012A51D0022A20D165 +:100EE000CAE0217901290BD0022916D0032911D09B +:100EF000042916D11CE00000BC0F0200FE2F0000E8 +:100F0000707801280CD10620616A02F029F80028C7 +:100F100007D11CE01D20307019E07178022901D042 +:100F2000052798E031780C2929D18DF8040010E0CC +:100F3000B07F022823D13078011F042904D30A3955 +:100F4000032901D31D281AD12089022817D38DF82F +:100F5000049084F800A020899DF80410884203D2F0 +:100F60000A208DF800003FE01121083488F80010B5 +:100F700094E80E00C8E901120327C8F80C306AE0B3 +:100F800098F80020112A66D18DF80000626A049258 +:100F9000D8F80850029522794FF00B0B012A06D0A1 +:100FA000022A29D0032A11D0042A54D159E0ADF8DD +:100FB000049085F800B0207E4F4600F01F00687056 +:100FC00000216846FEF7BCFE377043E0ADF80490A0 +:100FD00005202870207E68704E4600216846FEF786 +:100FE000AFFE26708DF800B0606A049041466846F6 +:100FF000FEF7A6FE07462EE0ADF8040085F800A037 +:10100000207F6870607F00F00100A870A07F00F072 +:101010001F00E870E27F2A71C0071FD094F82000FB +:1010200000F00F00687194F8210000F00F00A87123 +:1010300000216846FEF784FE2868B063A888B08760 +:10104000A87986F83E00A069407870772879B0705A +:101050000D2030700027384605B02BE7A971697163 +:10106000E6E7ADF804900E202870207E687000211D +:101070006846FEF765FEEDE7FE2030708DF800A0B3 +:10108000606A049004208DF80400207E8DF805002D +:10109000EDE700B50023012285B0052810D0062811 +:1010A0000CD102208DF8002004918DF8040000BFBF +:1010B0008DF8053000216846FEF742FE05B000BD00 +:1010C0008DF8002004918DF80420F1E770B50C46EE +:1010D000054601F06FFF21462846BDE870407823A1 +:1010E000002201F0C7BE08B1007870470C2070479D +:1010F00070B50C0005784FF000010CD0217021462E +:10110000F4F7B4F874482178405D884201D1032097 +:1011100070BD022070BDF4F7A9F8002070BD027BFD +:10112000032A05D000220A704B780B2B02D003E073 +:10113000042070470A770A62027B9300521C0273F4 +:10114000C15003207047F0B585B00F460546012415 +:10115000287B05EB800050F8046C7078411E0C2948 +:101160000AD25D493A46123101EB8000314650F80F +:10117000043C2846984704460CB1012C11D1287B29 +:10118000401E10F0FF00287301D00324E0E70D207B +:101190008DF80000706A0490002101966846FFF700 +:1011A000A7FF032CD4D005B02046F0BD70B515467E +:1011B0000A46044629461046FFF7C5FF064674B1A5 +:1011C0002078FE280BD1207E30B1002028702946DF +:1011D00004F10C00FFF7B7FF2046FEF7FAFD30469A +:1011E00070BD704770B50E46044688210FF05FFB56 +:1011F0000225012E03D0022E04D0052070BD01204F +:10120000607000E065702046FEF7E3FDA5770020E2 +:1012100070BD28B1027E1AB10A4600F10C01C5E783 +:101220000120704730B5044687B00D46062001F016 +:10123000C1FE2946052001F0BDFE2078FE2806D01B +:1012400000208DF8000069462046FFF7E2FF07B056 +:1012500030BD7FB50E4600218DF80C1041780B296A +:1012600003D00C2903D0002405E0846900E0446920 +:101270000CB1217E91B16D4601462846FFF74FFF24 +:10128000032809D1324629462046FFF78FFF9DF8F3 +:101290000C10002900D0042004B070BD04F10C052E +:1012A000EAE710B590B00C4607900B480421801E69 +:1012B00008900A488DF8191009900F92694606A8FF +:1012C000FFF7C7FF002805D11022204601990FF033 +:1012D00055FA002010B010BD9E0E0200BC0F020097 +:1012E00070B50D46040011D085B1210128460FF0DC +:1012F000BCFA10224E4928460FF040FA4C48012112 +:101300000838018044804560002070BD012070BD18 +:1013100070B5474E00240546083E10E07068AA7B71 +:1013200000EB0410817B914208D1C17BEA7B9142A2 +:1013300004D10C2229460FF0F5F930B1641C308835 +:101340008442EBDB4FF0FF3070BD204670BD70B5BE +:101350000D46060006D02DB1FFF7DAFF002803DBAB +:10136000401C14E0102070BD314C083C208862887D +:10137000411C914201D9042070BD6168102201EB2B +:10138000001031460FF0FAF92088401C20802870A8 +:10139000002070BD70B514460D0018D0BCB10021FE +:1013A000A170022802D0102811D105E0288870B160 +:1013B0000121A170108008E02846FFF7A9FF00284E +:1013C00005DB401CA070A8892080002070BD012092 +:1013D00070BD70B5054614460E000BD0002030706D +:1013E000A878012808D005D91149A1F108010A8877 +:1013F00090420AD9012070BD24B128782070288835 +:10140000000A5070022008700FE064B14968102291 +:1014100001EB0011204610390FF0B0F92878207345 +:101420002888000A607310203070002070BD000012 +:10143000740000202DE9F04190460C460746002537 +:10144000FE48072F00EB881607D2DFE807F00707F2 +:10145000070704040400012500E0FFDF06F814700C +:10146000002D13D0F548803000EB880191F827005B +:10147000202803D006EB4000447001E081F82640AC +:1014800006EB44022020507081F82740BDE8F0812F +:10149000F0B51F4614460E460546202A00D1FFDF50 +:1014A000E649E648803100EB871C0CEB440001EB79 +:1014B0008702202E07D00CEB460140784B7848700D +:1014C000184620210AE092F82530407882F825005D +:1014D000F6E701460CEB410005704078A142F8D1D7 +:1014E00092F82740202C03D00CEB4404637001E0F9 +:1014F00082F826300CEB41042023637082F8271019 +:10150000F0BD30B50D46CE4B44190022181A72EBCF +:10151000020100D2FFDFCB48854200DDFFDFC94872 +:101520004042854200DAFFDFC548401C844207DAAA +:10153000002C01DB204630BDC148401C201830BDC6 +:10154000BF48C043FAE710B504460168407ABE4A76 +:1015500052F82020114450B10220084420F07F406E +:10156000F1F72BFB94F90810BDE81040C9E70420FF +:10157000F3E72DE9F047B14E803696F82D50DFF8AD +:10158000BC9206EB850090F8264038E009EB851701 +:101590004FF0070817F81400012806D0042816D0C9 +:1015A000052816D0062800D0FFDF00F056FF07EB15 +:1015B00044014A7806EB850181F8262091F827201E +:1015C000A24202D1202281F8272028B105E0022082 +:1015D00000E003208046E8E762B62A462146012063 +:1015E000FFF728FF9948414600EB041002682046A7 +:1015F000904796F82D5006EB850090F82640202C59 +:10160000C4D1BDE8F08710B58C4C2021803484F81B +:10161000251084F8261084F82710002084F828006C +:1016200084F82D0084F82E10411EA16044F8100BA0 +:101630002074607420736073A0738549E07720750F +:101640000870487000217D4AB4F1100402F81100BE +:10165000491CC9B22029F9D30120F1F79CF90020D7 +:10166000F1F799F9012084F82200F8F79BFD7948F9 +:10167000F8F7A7FD764CA41E20707748F8F7A1FD77 +:101680006070BDE81040F1F713B910B5F1F735F906 +:101690006F4CA41E2078F8F7ADFD6078F8F7AAFD2E +:1016A000BDE8104000F003BF202070472DE9F34F44 +:1016B000624E0025803606EB810A89B09AF8250033 +:1016C000202822D0691E02916049009501EB00108C +:1016D0008146D0E90112C0680391CDE90420B08BA6 +:1016E000ADF81C00B07F8DF81E009DF81500C8B144 +:1016F0000227554951F820400399E219114421F07D +:101700007F41019184B102210FE00120F1F743F9FB +:101710000020F1F740F9F1F70EF900F0C8FE86F865 +:101720002F508AE00427E4E700218DF818100228E2 +:1017300001D001281BD10398391901440998081ACE +:1017400020F07F4033280BD903208DF81500039833 +:10175000C4F13201401A20F07F40322403900CE0A3 +:1017600096F8240018B901F029F800284DD0322C41 +:1017700003D214B100F08FFE01E000F098FE344A6D +:10178000107820B393465278039B121B00219DF8DA +:101790001840984601281BD0032819D05FF000009C +:1017A0008DF81E00002A04DD981A039001208DF8A0 +:1017B00018009DF81C0000B102210398274A20F070 +:1017C0007F40039003AB099800F07DFE10B110E05C +:1017D0000120E5E79DF81D0018B99BF800000328DB +:1017E00012D08DF81C50CDF80C808DF818408DF873 +:1017F0001E509DF8180058B103980123C11900220A +:101800001846F1F71BF906E000200BB0BDE8F08F99 +:101810000120F1F7C0F899F90C200123002001996B +:10182000F1F70CF9012086F82F008AF828500348B8 +:101830002022694680300EF0E6FF11E048090020C2 +:10184000FF7F841E0020A107E00E02004807002051 +:1018500086000020232D010073150100FFFF3F00CB +:101860000120D2E72DE9F05FDFF88C84064608EB13 +:10187000860090F82550202D1FD0A8F180002C461E +:1018800000EB8617A0F50079DFF870B405E0A246FA +:1018900007EB4A004478202C0AD0F1F71BF909EB3A +:1018A00004135A4601211B1D00F00DFE0028EED046 +:1018B000AC4202D0334652461AE0F1F70BF998F8E1 +:1018C0002F206AB1D8F80C20411C891A0902CA17C6 +:1018D00001EB12610912002902DD0020BDE8F09F32 +:1018E0003146FFF7E3FE08B10120F7E733462A4609 +:1018F00020210420FFF7CCFDEFE72DE9F041FE4C5D +:101900002569F1F7E7F8401B0002C11700EB1160F1 +:10191000001200D4FFDF94F8220000B1FFDF01279E +:1019200084F8227094F82E00202800D1FFDF94F86C +:101930002E60202084F82E00002584F82F5084F893 +:10194000205084F82150EE4825600078022833D0DA +:10195000032831D000202077A068401C05D04FF02C +:10196000FF30A0600120F1F716F80020F1F713F81E +:10197000F1F711F9F1F709F9F0F7DDFF0EF0ACFA24 +:10198000E048056005604FF0E0214FF40040B846A4 +:10199000C1F88002F1F799F994F82D703846FFF7F5 +:1019A00061FF0028FAD0D448803800EB871010F887 +:1019B0001600022802D006E00120CCE73A46314664 +:1019C0000620FFF737FD84F8238004EB870090F8AA +:1019D0002600202804D0CA48801E4078F8F710FC62 +:1019E000207F002803D0F1F7C6F8257765774DE50D +:1019F0000146C14810B590F82D200024803800EB36 +:101A0000821000BF10F814302BB1641CE4B2202CFB +:101A1000F8D3202010BDBC4800EB04100160214623 +:101A20000120FFF707FD204610BD10B5012801D0A9 +:101A3000032800D171B3B04A92F82D30AE4C002289 +:101A4000803C04EB831300BF13F812400CB1082054 +:101A500010BD521CD2B2202AF6D3A94A48B102289E +:101A600007D0072916D2DFE801F01506080A0C0E88 +:101A7000100000210AE01B2108E03A2106E058216D +:101A800004E0772102E0962100E0B521517010704A +:101A9000002010BD072010BD994810B54078F1F71F +:101AA0008CF880B210BD10B5202811D2924991F85F +:101AB0002D30A1F1800202EB831414F810303BB1F9 +:101AC00091F82D3002EB831212F81020012A01D078 +:101AD000002010BD91F82D2001460020FFF7AAFC40 +:101AE000012010BD10B5F0F7F5FFBDE81040F1F78B +:101AF00064B8F0B5804F04782025803F264607EB78 +:101B0000831303E0254603EB45046478944202D036 +:101B1000202CF7D108E0202C06D0A64206D103EBFA +:101B200046025278027007E00020F0BD03EB44004B +:101B300003EB45024078507019B10878A04200D1FB +:101B40000D700120F0BD10B542680B689A1A1202A0 +:101B5000D41702EB1462121216D4497A91B1427A68 +:101B600082B96A4A006852F8211012681944104478 +:101B7000001D891C081A0002C11700EB1160001239 +:101B8000322801DB012010BD002010BD2DE9F047F7 +:101B9000814659485C4E00EB8100984690F82540FC +:101BA0002020107006F50070154600EB81170AE042 +:101BB00006EB04104946001DFFF7C5FF28B107EBEF +:101BC00044002C704478202CF2D1297888F8001039 +:101BD00013E000BF06EB0415291D4846FFF7B3FFCD +:101BE00068B988F80040A97B99F80A00814201D8B9 +:101BF000002006E507EB44004478202CEAD10120C0 +:101C0000FFE42DE9FC410E46074600243E4D08E066 +:101C10009DF8000005EB00108168384600F067FC75 +:101C200001246B4601AA31463846FFF7AFFF002872 +:101C3000EED02046BDE8FC8170B504462E48012553 +:101C40008038A54300EB841100EB851040220EF094 +:101C500095FD294800EB850100EB8400D0F82500B4 +:101C6000C1F82500284670BD2DE9FC418446224874 +:101C700015468038089C00EB85170E4617F81400AF +:101C8000012803D0022801D00020D3E70B461B4ACD +:101C90000121604600F017FCA0B101AB6A4629465D +:101CA0003046FFF773FF68B19DF804209DF80010DF +:101CB00011488A4200EB850608D02B460520FFF725 +:101CC000E7FB0BE02A462146042014E0202903D03C +:101CD00007EB4100407801E096F8250007EB44014E +:101CE00048709DF80000202816D007EB4000447093 +:101CF0002A46214603200BE0C8090020FFFF3F00D1 +:101D00008600002000F5004048070020E00E020099 +:101D1000FFF790FB01208DE706F8254F0120F070BA +:101D2000E6E7FA4901EB0010001D0CE47CB51D4606 +:101D3000134604460E4600F1080221461846F0F705 +:101D400049FF94F908000F2804DD1F38207220682D +:101D5000401C206096B10220ED4951F8261046182B +:101D600020686946801B20F07F40206094F90800BD +:101D70002844C01C1F2803DA012009E00420EBE7F7 +:101D800001AAF0F727FF9DF8040010B10098401C4D +:101D900000900099206831440844C01C20F07F4026 +:101DA00060607CBD2DE9FE430C46074609786079EA +:101DB0009072207998461546507241B1781D20F0F6 +:101DC0007F46D44890F82E00202808D00AE0D4E9B5 +:101DD0000223217903B02846BDE8F043A6E7CE48A8 +:101DE00040780644217900222846A368FFF79EFF29 +:101DF0003146284600F07BFBD4E90232217968465F +:101E0000FFF794FF41462846019CFFF7FAFE2B4658 +:101E100022460021384600F056FB002803D13946FF +:101E2000284600F064FBBDE8FE832DE9FE438046B2 +:101E300000F019FB28B1002798F8000018B1002025 +:101E4000F1E70127F8E7B34C4FF0000994F82D6053 +:101E500084F8239000251FB93046FFF7EDFE0646B3 +:101E6000F0F738FE33466A464146FFF79BFF94F889 +:101E70002E0020280CD021690098401A0002C217B9 +:101E800000EB1260001203D5684600F030FB01251C +:101E900094F823000028D9D1F0F71CFE6B469F4A26 +:101EA000002100F010FB0028BDD027B9314668465C +:101EB000FFF7A7FE054325B16846FFF744FBC8F8C6 +:101EC00008000120AFE72DE9FF5F8A46814600F058 +:101ED000CAFA904C48B19AF80000002710B10128C6 +:101EE00000D0FFDF4FF0010810E094F82E0001272A +:101EF000202800D1FFDF9AF800000028F2D0FFDF91 +:101F0000F0E700BFB8F1000F00D162B694F82D5091 +:101F1000002084F823003FB92846FFF78DFE0546D0 +:101F200094F823000028EDD1F0F7D4FD06462B46A7 +:101F300001AA5146FFF736FF3B462A4601A9304623 +:101F4000CDF80090FFF790FE064604EB850090F870 +:101F500028B000F082FA804694F823000028D1D1FE +:101F60006A490DF1040C01EB09109CE80E0000F128 +:101F7000040080E80E00D6B13BEA07000CD094F8CC +:101F80002E00202808D12846FFF76CFC20B99AF8CB +:101F9000000028B10128B5D0284600F057FA05E026 +:101FA00094F82D2049460420FFF744FA0126B8F1A1 +:101FB000000F00D162B666B194F82D0004EB8000EA +:101FC00090F82600202804D05348801E4078F8F767 +:101FD00017F9304604B081E42DE9F05F4D4C81469D +:101FE00094F82D004FF000080125474605B962B668 +:101FF00004F8237FA07AFFF71FFE064614F8230992 +:102000000028F3D14348803800EB861111F81900FD +:10201000032837D1334604EB830A4A469AF8250051 +:10202000904201D1012000E0002083460AF1250002 +:102030000021FFF75EFD014610EA0B0F03D00122DD +:102040008AF82820A777E9B1324649460120FFF7F0 +:10205000F1F99AF828A000F000FA054694F8230058 +:102060000028C3D1BAF1000F07D094F82E00202821 +:1020700003D13046FFF7F6FB20B1304600F0E6F919 +:102080004FF0010805B962B6404627E40020F0F79A +:102090005BBC0120F0F758BC1F48801E00787047D9 +:1020A0002DE9F0411B4C94F82E0020281FD194F804 +:1020B0002D6004EB860797F82550202D00D1FFDF17 +:1020C0001449803901EB861000EB4500407807F891 +:1020D000250F0120F87084F82300294684F82E503B +:1020E000324602202234FFF7A5F9002020707EE45A +:1020F0002DE9F041054E074C012588B101282BD070 +:10210000022874D0032873D0FFDF70E44807002052 +:10211000E00E0200C809002086000020FFFF3F00FB +:1021200000F0B9F9FFF7BCFF207E00B1FFDF84F8B3 +:1021300021500020F0F72FFCA168481C04D0012397 +:1021400000221846F0F77AFC14F82E0F217806EBDF +:1021500001110A68012154E0FFF7A2FF0120F0F706 +:102160001AFC94F8210050B1A068401C07D014F864 +:102170002E0F217806EB01110A68062141E0207E2E +:10218000DFF880830027012803D002281ED0FFDF5C +:102190002DE4A777F0F7EFFC98F80000032801D1B1 +:1021A00065772577607DD84951F8200094F8201094 +:1021B00051B948B161680123091A00221846F0F7A5 +:1021C0003DFC0220207612E4277610E484F82050AB +:1021D00000F061F9A07F60B198F801006168012307 +:1021E000091A00221846F0F729FC257602E00BE0D8 +:1021F00011E0277614F82E0F217806EB01110A68FA +:102200000021BDE8F0411047BE48801E0078BDE8BF +:10221000F041F7F7F5BFFFF743FF14F82E0F2178D1 +:1022200006EB01110A680521EBE710B5B74C94F8ED +:102230002E00202800D1FFDF14F82E0F2178B44A99 +:1022400002EB01110A68BDE81040042110477CB57B +:10225000AE4C054694F82E00202800D1FFDFA06880 +:10226000401C00D0FFDF94F82E00A94901AA01EB21 +:102270000010694690F90C002844F0F7ABFC9DF97A +:1022800004000F2801DD012000E00020009908442F +:102290006168084420F07F41A16094F82100002883 +:1022A00007D002B00123BDE8704000221846F0F7C5 +:1022B000C5BB7CBD30B5974A0B1A541CB3EB940FC9 +:1022C00012D3451AB5EB940F0ED3934203D9101ACB +:1022D00043185B1C08E0954204D9511A0844401C7D +:1022E000434201E0FFDF0023184630BD01230022F6 +:1022F00001460220F0F7A2BB0220F0F74CBBF0F73A +:10230000E9BB2DE9FC47814D044695F82E002028B5 +:1023100000D1FFDF642C4AD37F4A0021121B71EBEE +:10232000010044D395F82E20A8462846DFF8E09116 +:1023300090F82D7009EB0215D8F8000001AA20448E +:102340006946F0F747FC9DF90400002802DD00987B +:10235000401C0090A96800986A680E18B21A22F012 +:102360007F42B2F5800F22D208EB8702454692F8F1 +:102370002520202A07D009EB02125268511A21F0B9 +:102380007F41814213D3A868401C05D00120F0F79B +:1023900002FB4FF0FF30A86028682044286026F038 +:1023A0007F402861012085F82300BDE8FC870020DC +:1023B000FBE72DE9F041554C074694F82D00A4F1B8 +:1023C000800606EB801010F8170000B9FFDF94F8C4 +:1023D0002D5006EB851606E004280CD005280AD0FF +:1023E000062808D020BF16F817000128F4D10125CF +:1023F0004FF0000807E02A4639460120FFF71AF897 +:10240000F1E705B962B604F8238FA07AFFF714FC50 +:10241000064614F823090028F3D104EB860000F1E6 +:10242000270133463A462630FFF763FB00F015F8E4 +:10243000054694F823000028E3D184F82D6001209C +:1024400084F82300002D00D162B650E62F4981F8B0 +:102450002D00012081F823007047EFF3108000F079 +:10246000010072B670472D480068C005C00D10D03D +:10247000103840B2002806DA00F00F0000F1E0202A +:1024800090F8140D03E000F1E02090F800044009FA +:1024900070470820704710B51C4C94F824000028A1 +:1024A00004D1F7F79BFC012084F8240010BD10B57F +:1024B000164C94F82400002804D0F7F7B8FC00204C +:1024C00084F8240010BD10B51C685B68241A181A23 +:1024D00024F07F4420F07F40A14206D8B4F5800F5D +:1024E00003D2904201D8012010BD002010BDD0E9D8 +:1024F0000032D21A21F07F43114421F07F41C0E91C +:102500000031704786000020E00E0200C80900205C +:1025100048070020FF7F841EFF1FA10704ED00E095 +:10252000F0B5734AD2F80032724D002401212E78A2 +:1025300056B9714E3460704F03263F1D3E606E4F9A +:1025400004260C373E602970C2F80042D160116049 +:10255000694C4834D16425688542FBD35160D16011 +:10256000C2F80032F0BD2DE9F041044680074FF07B +:1025700000054FF0010604D560480560066024F0B0 +:102580000204E0044FF0FF3705D55D484660C0F80F +:10259000087324F48054600003D55A48056024F081 +:1025A0008044E0050FD55248C0F80052C0F80873C7 +:1025B00051490D60091D0D604F4A04210C32116014 +:1025C000066124F48074A00409D54F484660C0F821 +:1025D0000052C0F808734D48056024F40054C4F359 +:1025E0008030C4F3C031884200D0FFDF14F4404F84 +:1025F00014D047484660C0F8087346488660C0F863 +:102600000052C0F8087344490D600A1D16608660C8 +:10261000C0F808730D60166024F4404420050AD504 +:102620003E4846608660C0F80873C0F848733C486E +:10263000056024F400640DF029FC3A48044200D0FF +:10264000FFDFBDE8F08170B5202500224FEA0203CC +:1026500020FA02F1C90719D051B201F01F06012476 +:10266000B4404E09B60006F1E026C6F88041C6F82F +:102670008042002906DA01F00F0101F1E02181F822 +:10268000143D03E001F1E02181F80034521CAA421C +:10269000DED370BD70B5174C0D466060FFF763FF69 +:1026A0006068FFF7D0FF2846F7F78DFC0DF056F86D +:1026B00000F0D5F80DF0EAFB0DF035FBF7F772FDF1 +:1026C000BDE870400DF0F8B810B50A4C6068FFF72F +:1026D0004AFF6068FFF7B7FF0DF0D8FBF7F73DFD45 +:1026E0000020606010BD0348406870470A207047B2 +:1026F000008000408800002004850040FC1F00404E +:1027000000C0004004E5014000D0004004D5004076 +:1027100000E0004000F0004000F5004000B0004044 +:1027200008B50040FEFF0FFD70B51F490A68BAB139 +:1027300000231D4601244A68521C4A60092A00D31E +:102740004D600E7904FA06F20E6816420AD072B68F +:102750000B6893430B6062B649680160002070BD4E +:10276000052070BD5B1C092BE5D3FFDFF8E74FF0B8 +:10277000E0214FF48000C1F800027047EFF31081B0 +:1027800011F0010F72B64FF0010202FA00F2064892 +:10279000036842EA0302026000D162B6E7E702483A +:1027A00000210160416070479000002001208107F6 +:1027B0000860704701208107486070471248006830 +:1027C000C00700D0012070470F48001F0068C007F5 +:1027D00000D0012070470C4808300068C00700D0C6 +:1027E00001207047084810300068704706490C31D6 +:1027F0000A68D20306D5096801F00301814201D1BC +:1028000001207047002070470C040040C84911F8AF +:10281000210F4978884201D3401A02E0C1F1210119 +:102820000844C0B27047C249233111F8210F4978DA +:10283000884201D3401A02E0C1F121010844C0B22C +:102840007047BB49463111F8210F4978884201D3BE +:10285000401A02E0C1F121010844C0B27047B549F5 +:1028600010B5802081F80004B1490020233101F81F +:10287000210F4870AE4901F8210F4870AC4946312C +:1028800001F8210F4870AC480DF096F9AA48401C99 +:102890000DF092F9F0F728FABDE8104000F03DB9CC +:1028A00020207047B2E770B50C4605460026FFF7BA +:1028B000ADFF01469E48A14212D30022641EE4B23D +:1028C0000DD390F82210435C491CC9B205F8013BB6 +:1028D00080F822102129F1D180F82220EEE701268C +:1028E00000F01BF9304670BD202070479BE770B5A3 +:1028F0000C4605460026FFF796FF01468C4823301C +:10290000A14212D30022641EE4B20DD390F822102B +:10291000435C491CC9B205F8013B80F8221021290B +:10292000F1D180F82220EEE7012600F0F6F83046DB +:1029300070BD202101700020704710B50446FFF7DC +:1029400080FF2070002010BD70B50C460546FFF7D3 +:1029500078FF014676484630A14213D30022641E18 +:10296000E4B20DD390F82210435C491CC9B205F8BB +:10297000013B80F822102129F1D180F82220EEE7D6 +:10298000002401E042F2070400F0C7F8204670BDC1 +:1029900070B50C460546212900D9FFDF674800685D +:1029A000103840B200F0A0F8C6B20D2000F09CF83C +:1029B000C0B2864204D2FFDF02E000BFF0F7E4F9C4 +:1029C00021462846FFF76FFF0028F7D070BD2DE99C +:1029D000F047DFF86481564CA8F10108074623341C +:1029E00098F80000DFF84891002604F1230A38B96E +:1029F00094F8221094F82100212200F084F890B17C +:102A00004D4699F8221099F82100212200F07BF818 +:102A1000B8B155469AF822109AF82100212200F008 +:102A200072F848B335E094F82100275494F8210057 +:102A3000401CC0B284F8210021282AD184F82160EA +:102A400027E095F821002F5495F82100401CC0B2D2 +:102A500085F82100212801D185F8216098F800002F +:102A60004746B0B195F8221095F82100212200F0D8 +:102A70004AF870B13E700CE095F821002F5495F89B +:102A80002100401CC0B285F82100212801D185F821 +:102A9000216094F8221094F82100212200F033F8EC +:102AA00000281FD099F8221099F82100212200F067 +:102AB0002AF8002816D09AF822109AF8210021222C +:102AC00000F021F800280DD0F0F734F91A480DF085 +:102AD0007BF8B0F5005F00D0FFDFBDE8F047164897 +:102AE0000DF088B8BDE8F087002806DA00F00F0086 +:102AF00000F1E02090F8140D03E000F1E02090F8E0 +:102B0000000440097047401C884204D0904200D124 +:102B100009B1002070470120704710B506480DF03C +:102B200053F8002803D1BDE81040F0F7EEB810BD0F +:102B3000F80900200DE000E09900002004ED00E01D +:102B4000164908784A78401CC0B2904205D0144B10 +:102B500001221A60BFF34F8F087070472DE9F041D2 +:102B60000E4C4FF0E02600BFF0F794F920BF40BFB5 +:102B700020BF677820786070D6F80052EEF7BCFB73 +:102B8000854305D1D6F8040210B92078B842EBD0BD +:102B9000F0F77BF90020BDE8F08100009B000020E9 +:102BA000180502402DE9F041012528034FF0E021EE +:102BB0000026C1F880011E4CC4F800610C2000F012 +:102BC0002CF81C4801680268C94341F3001142F027 +:102BD00010020260C4F804532560491C00E020BFC5 +:102BE000D4F80021002AFAD019B9016821F01001A7 +:102BF0000160114807686560C4F80853C4F80061B3 +:102C00000C2000F00AF83846BDE8F08110B5044603 +:102C1000FFF7C8FF2060002010BD00F01F02012157 +:102C200091404009800000F1E020C0F88012704718 +:102C300000C0004010ED00E008C500402DE9F0475D +:102C4000F94C0646FF21606800EB061211702178EE +:102C5000FF2910D04FF0080909EB011109EB061705 +:102C60004158C05900F0E2F9002807DD616820787A +:102C700001EB061108702670BDE8F08794F800801B +:102C800045460DE0606809EB05114158C05900F058 +:102C9000CDF9002806DC6068A84600EB081005782E +:102CA000FF2DEFD1606800EB061100EB08100D70EE +:102CB0000670E1E7F0B5DC4B0446002001255A68B8 +:102CC0000C261B7A0CE000BF05EB0017D75DA7426E +:102CD00004D106EB0017D7598F4204D0401CC0B274 +:102CE0008342F1D8FF20F0BD70B5FFF708FBCE4C52 +:102CF00008252278616805EB0212895800F096F9E0 +:102D0000012808DD2178606805EB01114058BDE815 +:102D10007040FFF7EBBAFFF7BFF9BDE87040F7F777 +:102D20006FBA2DE9F041C04C2578FFF7E8FAFF2D86 +:102D30006ED04FF00808626808EB0516915900F054 +:102D400075F90228606801DD80595DE000EB05112E +:102D500009782170022101EB0511425C5AB1521E23 +:102D60004254815901F5800121F07F41815128466B +:102D7000FFF764FF34E00423012203EB051302EBA9 +:102D8000051250F803C0875CBCF1000F10D0BCF5F1 +:102D9000007F10D9CCF3080250F806C00CEB423C7F +:102DA0002CF07F4C40F806C0C3589A1A520A09E02A +:102DB000FF2181540AE0825902EB4C3222F07F421B +:102DC0008251002242542846FFF738FF0C216068E8 +:102DD00001EB05114158E06850F82720384690472C +:102DE0002078FF2814D0FFF78AFA2278616808EB70 +:102DF00002124546895800F019F9012893DD21781F +:102E0000606805EB01114058BDE8F041FFF76EBA6C +:102E1000BDE8F081F0B51D4614460E460746FF2B6F +:102E200000D3FFDFA00700D0FFDF7F48FF21002293 +:102E3000C76044600572067401704270104601223A +:102E400005E000BF02EB0013401CE154C0B2A842F1 +:102E5000F8D3F0BD70B5744C06466578207C854289 +:102E600000D3FFDFE06840F825606078401C6070A8 +:102E7000284670BD2DE9FF5F1D468B460746FF249F +:102E8000FFF73DFADFF8A091064699F80100B84235 +:102E900000D8FFDF00214FF001084FF00C0A99F82D +:102EA0000820D9F804000EE008EB0113C35CFF2BE7 +:102EB00027D0BB4205D10AEB011350F803C0DC4513 +:102EC00021D0491CC9B28A42EED8FF2C1BD008EB96 +:102ED00004110AEB0412475440F802B00421029B8B +:102EE0000022012B01EB041111D042504FF4007865 +:102EF00008234FF0020C454519D9E905C90D08D042 +:102F000008E00C46DDE7FF2004B0BDE8F09F455027 +:102F1000ECE7414606EB413203EB041322F07F421B +:102F2000C250691A0CEB0412490A81540BE005B92E +:102F3000012506EB453103EB041321F07F41C1501D +:102F40000CEB0411425499F800502046FFF776FE2E +:102F500099F80000A84201D0FFF7C6FE3846D3E733 +:102F600070B50C460546FFF7CAF9064621462846C5 +:102F7000FFF7A0FE0446FF281AD02B4D082101EBD5 +:102F8000041168684158304600F050F800F5805050 +:102F9000C11700EBD140401302216A6801EB041114 +:102FA000515C09B100EB4120002800DC012070BD1C +:102FB000002070BD2DE9F0410F468046FFF77AFEF4 +:102FC000FF281BD0184E357871682A462C4605E03C +:102FD000844206D0254601EB05131C78FF2CF7D15F +:102FE0000CE0FF2C0AD0A5420CD101EB02100078B6 +:102FF0003070FF2804D0FFF777FE03E0002007E7DA +:10300000FFF77AF939464046FFF7AAFFFF2201236E +:10301000716803EB0413CA5401EB041201EB0511B0 +:1030200012780A70F4E60000640A0020081A000210 +:10303000C11700EB116000127047000070B5044624 +:10304000A0F500002D4EB0F1786F02D23444A4F503 +:1030500000042B48844201D2012500E0002500F045 +:1030600043F848B125B9B44204D32648006808E0C3 +:10307000012070BD002070BD002DF9D1B442F9D3FC +:1030800021488442F6D2F3E710B50446A0F50000CB +:10309000B0F1786F03D219480444A4F5000400F09D +:1030A00023F84FF0804130B11648006804E08C42AC +:1030B00004D2012003E014488442F8D2002080F0BA +:1030C000010010BD10B520B1FFF7DEFF08B10120EF +:1030D00010BD002010BD10B520B1FFF7AFFF08B143 +:1030E000012010BD002010BD084809490068884231 +:1030F00001D101207047002070470000000000202F +:10310000002002002000002008000020A000002075 +:10311000BEBAFECA5348002101704170102181706F +:10312000704770B5054616460C460220EFF77BFB4C +:103130004C49012008704C49F01E08604B4805605E +:10314000001F046070BD10B50220EFF76CFB45490D +:103150000120087046480021C0F80011C0F8041191 +:10316000C0F8081143494FF40000086010BD3D4805 +:103170000178C9B1404A4FF4000111603C49D1F8CF +:1031800000310022002B1CBFD1F80431002B02D0EB +:10319000D1F8081111B14270102103E001214170F2 +:1031A00036490968817002700020EFF73CBB2D485A +:1031B0000178002904BF407870472D48D0F80011ED +:1031C000002904BF02207047D0F8001100291CBF5D +:1031D000D0F80411002905D0D0F80801002804BF58 +:1031E00001207047002070471E4800B50278204B30 +:1031F0004078C821491EC9B282B1D3F800C1BCF1E0 +:10320000000F10D0D3F8000100281CBFD3F8040130 +:1032100000280BD0D3F8080150B107E0022802D0F3 +:10322000012805D002E00029E4D1FFDF002000BD25 +:10323000012000BD0B480178002904BF8078704749 +:103240000B48D0F8001100291CBFD0F80411002948 +:1032500002D0D0F8080108B1102070470748006874 +:10326000C0B27047A400002010F5004008F50040EF +:1032700000F0004004F5014008F5014000F4004072 +:103280004D48002101704170704770B506461446E4 +:103290000D460120EFF7C7FA48480660001D04609C +:1032A000001D056070BD70B5434B012540EA024228 +:1032B0001D70434B42F080721A60424A424C002615 +:1032C0001160C4F80461414A4FF040711160002858 +:1032D00002BFC4F80052256070BD012818BFFFDF8F +:1032E000C4F8006225604FF000703949086070BD75 +:1032F0003148017879B1354A4FF040711160324957 +:10330000D1F804210021002A08BF417002D0314ABF +:103310001268427001700020EFF785BA26480178E4 +:10332000002904BF407870472748D0F804010028DE +:1033300008BF704727480068C0B27047002808BF20 +:10334000704730B51C480078002808BFFFDF1E48D2 +:10335000D0F80411002918BF30BD0224C0F804437E +:10336000DFF874C0DCF80010C1F30015DCF80010C1 +:1033700041F01001CCF80010D0F80411002904BF6E +:103380004FF400414FF0E02207D100BFC2F8801295 +:1033900020BFD0F80431002BF8D02DB9DCF8001094 +:1033A00021F01001CCF80010C0F8084330BD0649E8 +:1033B0000120886070470000A700002008F5004049 +:1033C00004F5004018F5004000F0004008F5014009 +:1033D00004F5014000F4004010ED00E070B5FE4C33 +:1033E000002501206570257025626572A572E07266 +:1033F00084F82950256304F13C00A5630CF0DCFB44 +:10340000002818BFFFDF84F82450F4480DF054FB67 +:10341000F3494FF011300860091D0860091D08606C +:10342000F0490860F0490D60091D0860091D086039 +:10343000091D0860091D0860091D0860091D086054 +:10344000091D0860091D0860091D0860657770BDC9 +:1034500030B4E1490268DFF898C34A6142688A6182 +:10346000007A08770A7DE14BACF1040401204AB1EF +:103470000A7E00FA02F21A608D7D002D0CBF2260D8 +:10348000CCF800204A7D002A04BF30BC70474A7E39 +:1034900090401860C97D00290CBF2060CCF8000066 +:1034A00030BC7047D449D3480860091DD348086030 +:1034B000704710B5044659B1012908BF4FF080711B +:1034C00006D0022917BF03294FF0C741FFDF0021B3 +:1034D00041F4847040F48010C7490860E0B240F4C1 +:1034E0004030091D40F000700860C548D0F8000168 +:1034F000002818BFFFDF10BD002800B5C14908BF74 +:1035000003200CD0012808BF042008D0022808BFDF +:10351000062004D0032816BFFFDF052000BD086089 +:1035200000BD70B502244FF0E02501200022C5F84F +:103530008041B5490A600860B44A40F25B6111609D +:10354000121F40F203111160111F0860AD490320E2 +:103550000860AF49962008609F4E96F9240000F05D +:1035600040FE707F002814BF4FF4C020A948AA492C +:103570000860AB49A9480860091FAA480860C5F857 +:1035800080429F491020C1F8040370BDA6494FF046 +:10359000004008607047904A0368C2F80230808893 +:1035A000D080117270478C4890F8290070478A4A81 +:1035B000517010707047F0B50546800000F18040F2 +:1035C00000F580508B88C0F820360B78D1F80110B8 +:1035D00043EA0121C0F8001605F10800012707FAA7 +:1035E00000F6924C002A04BF2068B04304D0012AA0 +:1035F00018BFFFDF206830432060206807FA05F11C +:1036000008432060F0BD10B5044600F0EAFD7248A2 +:1036100080F8244010BD704890F8340070476E4820 +:1036200090F836007047824AC1781160006881497D +:10363000000208607047252808BF02210ED0262806 +:1036400008BF1A210AD0272808BF502106D00A280F +:1036500094BF0422062202EB4001C9B2764A1160EF +:103660007649086070475C49086270475A498A7A0F +:10367000012A4AD0022A18BF70474B7D002B08BF91 +:103680007047DFF8BCC1012A43D0CA7D4B7E002AB7 +:1036900018BF012210F17D00CCF80000DFF8A4C1B2 +:1036A0000020CCF84C01180282F0010240EA0250DE +:1036B00040F00312087F830003F1804303F5C04309 +:1036C000C3F81025604A02EB8002887EC30003F134 +:1036D000804303F5F833C3F81425DFF870C1C3F84D +:1036E00010C5C97ECB0003F1804303F5F833C3F85E +:1036F00014254C4AC3F81025012202FA00F002FA00 +:1037000001F108435249086070470B7D002BB8D186 +:1037100070478A7D0B7E002A18BF01227E30BBE7EE +:103720002DE9F84F00280CBF012202222A4D344C0B +:103730000320AA72C4F80002687F002814BF4FF467 +:10374000C0203448424F38604FF00108002933D080 +:10375000012940D002291CBFFFDFBDE8F88F286A8D +:10376000002808BFFFDF296A286B08443949086030 +:103770003A4939480860A97A394801290EBF0460DE +:1037800038490160A86B40F40020A863D4F8009287 +:103790004FF0100AC4F808A30026C4F800621E48BF +:1037A0004FF4802BC0F800B0FF208DF80000C4F863 +:1037B0001061C4F8108084E0012A5DD0C4F8048050 +:1037C000022A18BFBDE8F88F687D002808BFBDE851 +:1037D000F88F1C4848E056E0780A00208C0A002048 +:1037E000040E0040000E0040100E0040180500506E +:1037F0000C050050060102001415004025000302CC +:103800000010004010150040FC1F0040381500401B +:10381000441500400000040408F5014040800040C9 +:10382000A4F50140101100407417004040160040FC +:10383000241500401C150040081500405415004098 +:103840004C85004000800040006000404C810040FA +:1038500004F501404885004048810040A8F501403A +:10386000ACF5014004100040C0F84C80F9480068F5 +:10387000BDE8F84F0A30F9E6C4F80080287D00283A +:10388000A7D1BDE8F88FF448012A806B07D0022A3F +:1038900018BFFFDF09D0BDE8F84F0A20E6E640F484 +:1038A0008010A8634FF4801004E040F40010A86377 +:1038B0004FF400103860EEE79DF80000401E8DF8D0 +:1038C00000009DF8000018B1D4F810010028F3D0D2 +:1038D0009DF80000002808BFFFDFC4F80061C4F8AD +:1038E0000C61C4F81061C4F80461C4F81461C4F830 +:1038F0001861C4F82861D94800680090C4F80092A3 +:10390000C7F800B0C4F804A34FF400203860296A57 +:10391000286BBDE8F84F08440A30A7E62DE9F847C0 +:10392000CF4CD4F8000220F00309D4F804034FF080 +:10393000100AC0F30018C4F808A30026C4F80062F7 +:10394000C54D687F002814BF4FF4C020C548C64944 +:103950000860A87A0127012802D0022803D014E0C9 +:10396000287D10B911E0687D78B1A87EEA7E07FA5B +:1039700000F007FA02F210430860287F800000F18F +:10398000804000F5C040C0F81065FF208DF80000B1 +:10399000C4F81061276104E09DF80000401E8DF816 +:1039A00000009DF8000018B1D4F810010028F3D0F1 +:1039B0009DF80000002808BFFFDFC4F81061C4F8BC +:1039C00028616E72AE72EF72C4F80092B8F1000F07 +:1039D00018BFC4F804A3BDE8F8870068A34920F025 +:1039E0007F40086070474FF0E0200221C0F880114E +:1039F000C0F8801270474FF0E0210220C1F80001AA +:103A000070479B490870704710B59A480CF0DCF875 +:103A1000002818BFFFDF10BD96480CF0EBB89649A0 +:103A20000860704730B58C4C0546206BA84228BF13 +:103A3000FFDF012020732561607F40B1A81C206159 +:103A40008748D0F8001241F04001C0F800128B49BD +:103A50000020C1F844018A4920690860A06B8949A7 +:103A600040F48000A0634FF48000086030BD00285F +:103A700004BF28207047012804BF1820704702287F +:103A800012BF03284FF4A870704700B5FFDF28204D +:103A900000BD002804BF41F2D4707047012804BF64 +:103AA00041F204007047022812BF032842F6A0002A +:103AB000704700B5FFDF41F2D47000BD002804BF9D +:103AC00042F2B8407047012804BF41F28830704785 +:103AD000022804BF44F690407047032804BF47F211 +:103AE000A030704700B5FFDF42F2B84000BDF0B52E +:103AF0000646594C02200D462073032914BF022D9F +:103B00004EF634170BD0002D08BF42F2B84706D04E +:103B1000012D1ABFFFDF42F2B84741F28837002E6D +:103B200008BF41F2D4700CD0012E08BF41F204004E +:103B300007D0022E17BF032E42F6A000FFDF41F28E +:103B4000D470381A002D504908444FF47A71B0FBF4 +:103B5000F1F708BF28200AD0012D08BF182006D091 +:103B6000022D17BF032D4FF4A870FFDF2820384423 +:103B7000032E16BF022E062101210844401D20619C +:103B8000617F41B1801C20613548D0F8001241F0BE +:103B90004001C0F8001239490020C1F844012169F0 +:103BA000206B084436490860F0BD2B490120487756 +:103BB000364902200860374935480860091F3648F1 +:103BC00008607047244900204877704726494FF421 +:103BD000800008602048816B21F48001816300210E +:103BE0000173704770B584B014460D46064604292B +:103BF00034BF042CFFDF294B0FCB8DE80F00684644 +:103C000000EB850026490057301A086004B070BDEB +:103C100070B584B014460D460646042A34BF042D00 +:103C2000FFDF204B0FCB8DE80F00684600EB8500CF +:103C30001B490057301A086004B070BD0F480121BD +:103C40004160C1600021C0F844110D480160024884 +:103C5000016370474C850040780A0020181100402D +:103C6000001000400000040408F501403C1500402D +:103C7000A9000020B40A0020041500400080004084 +:103C80004485004004F50140FF57020060150040E4 +:103C9000448000409CF5014028110040400F020084 +:103CA00044150040500F0200FE4800B5407F002838 +:103CB00018BFFFDF4020FC490860FC48D0F8001224 +:103CC00041F04001C0F8001200BDF64800B5407F49 +:103CD000002818BFFFDFF548D0F8001221F040019E +:103CE000C0F80012F0490020086000BDEF48D0F88D +:103CF000001221F01001C0F800120121816170470B +:103D0000EA480021C0F81C11D0F8001241F010015F +:103D1000C0F800127047E54981B0D1F81C21012A92 +:103D20001EBF002001B07047E14A126802F07F0216 +:103D3000524202700020C1F81C01DE480068009069 +:103D4000012001B0704730B50C00054608BFFFDF09 +:103D500014F0010F1CBF012CFFDF002D0CBF012050 +:103D60000220D04901284872CC72D04904BFD1F852 +:103D7000000240F0040007D0022807BFD1F800027B +:103D800040F00800FFDF30BDC1F8000230BD70B563 +:103D9000C44C0022E17A11F0020F18BF10F0040F9A +:103DA00016D111F0100F1CBF94F83530002B02D043 +:103DB00094F8373063B111F0080F1CBF94F8283025 +:103DC000002B05D111F0040F03D094F8291001B98C +:103DD0000122657AB54900234FF0010C35B100F09E +:103DE0000200104314D0BDE8704097E5607F0028C2 +:103DF00014BF4FF4C020B048B04A1060D1F80002A0 +:103E000020F00300C1F80002A37284F80BC070BD5B +:103E1000012D14D0022D18BFFFDF1CD0A07A01287D +:103E20000CBFA748A7484FF47A7100F2E730B0FB07 +:103E3000F1F0216BBDE87040081A8C3016E4D1F81F +:103E4000000220F00400C1F80002637284F80BC085 +:103E500084F80AC0E2E7D1F8000220F00800C1F8B7 +:103E60000002637284F80BC00220A072D6E72DE92D +:103E7000F84F954FD7F84C218A4C90494FF00108E4 +:103E8000A07A0026CAB1012802D0022803D014E08B +:103E9000227D12B911E0627D7AB1A27EE37E08FA3A +:103EA00002F208FA03F31A430A60227F920002F139 +:103EB000804202F5C042C2F81065A26B0A60A66398 +:103EC000217B29B1D7F84411012908BF012200D074 +:103ED0000022764DD5F8101101290CBF4021002198 +:103EE000012805BFD5F80C31012B002320231943ED +:103EF000012805BFD5F80431012B002310231943F5 +:103F0000724B022804BFD3F800C0BCF1010F07D1E7 +:103F1000D5F80CC1BCF1010F08BF4FF0080C01D05F +:103F20004FF0000C4CEA0101022804BF1B68002B73 +:103F300005D1D5F80C31012B08BF042300D0002394 +:103F40001943022803D1002A18BF022200D10022FF +:103F50001143022804BFD5F80401012805D1D7F880 +:103F60004401012818BF012000D1002040EA0109C6 +:103F70005748016811F0FF0F03D0D5F8141101293B +:103F800000D0002184F83410006810F0FF0F03D037 +:103F9000D5F81801012800D0002084F835004D48DC +:103FA000006884F836004048006818B1FFF7FFF851 +:103FB000012800D0002084F83700C5F80061C5F85A +:103FC0000C61C5F81061C5F80461C5F81461C5F845 +:103FD0001861C5F82861404800680090C7F844613E +:103FE0003E4800684D46DFF8F8900090D9F8000090 +:103FF000E062617F00291CBF801EE06239480068D2 +:104000002063A07ADFF8E0A002280CD1607850B1DC +:10401000DAF8001009780840217831EA000008BF7A +:1040200084F8288001D084F82860DFF8C08015F07B +:10403000010F15D098F800102D4A4908E06A52F88F +:104040002110884701212B4A98F80030206B52F844 +:104050002320904798F8000010F0010F0BD01FE0CC +:1040600015F0200F18BF0221EDD115F0020F18BF77 +:104070000021E8D1EEE7DAF80000062200F109019C +:10408000A01C0CF04FFB40B9207ADAF80010097838 +:10409000B0EBD11F08BF012000D0002084F8290018 +:1040A000284629E0780A00206015004000100040F2 +:1040B000481500401C1100400000040408F50140B0 +:1040C000F0FE0100B0F80100008000400014004044 +:1040D0004016004008140040181100404481004080 +:1040E000448500404085004004150040A9000020A0 +:1040F000F80E0200300F0200FFF749FE15F0020F24 +:1041000005D0594898F8001050F82100804715F064 +:104110000C0F07D0554898F8001050F82110C5F33F +:10412000C000884715F0200F05D0514898F80010BE +:1041300050F82100804798F80000022805D105F0CA +:104140006E00402806D101F093FB98F80000042887 +:1041500028BFFFDFA07A022818BFBDE8F88F207BB8 +:10416000002808BFBDE8F88FC7F84461022815D0C1 +:10417000012818BFFFDF216B2069884298BFFFDF4D +:10418000D4F81000C9F80000A06B3A4940F4800050 +:10419000A0634FF480000860BDE8F88F2169206BB0 +:1041A0000844EFE7002812BF012864207047022866 +:1041B00012BF03284FF4C870704700B5FFDF6420BA +:1041C00000BD2D49032818BF0228086803BF20F04E +:1041D000B30040F04C0040F0004020F00040086088 +:1041E000704700B52549022839D022DC10F10C0FA8 +:1041F00008BFF42033D010DC10F1280F02BFD82004 +:10420000086000BD10F1140F08BFEC2027D010F19A +:10421000100F08BFF02022D023E010F1080F08BFD4 +:10422000F8201CD010F1040F0CBFFC20002816D081 +:1042300017E0C01E072814D2DFE800F0100E0C0AA9 +:104240000806040009200AE0082008E0072006E02C +:10425000062004E0052002E0042000E003200860BE +:1042600000BDFFDF00BD0000000F0200100F0200C4 +:10427000200F020004F501403C1700400C150040DF +:1042800010B53F480AF08BFC00213D480AF0B6FC0F +:1042900001213B480AF086FC3A49002081F82200BF +:1042A0004FF6FF70888438490880488010BD7047F9 +:1042B00034498A8C824218BF7047002081F822005E +:1042C0004FF6FF70888470472D49016070472E4972 +:1042D000088070472B498A8CA2F57F43FF3B03D0AF +:1042E000002101600846704791F822202549012AE3 +:1042F0001ABF0160012000207047224901F122000D +:1043000091F82220012A04BF002070470122027088 +:104310001D4800888884104670471B4948807047B4 +:104320001849194B8A8C5B889A4206D191F8222051 +:10433000002A1EBF0160012070470020704711480D +:10434000114A818C5288914209D14FF6FF718184C4 +:1043500010F8221F19B100210170012070470020C0 +:1043600070470848084A818C5288914205D190F8DC +:10437000220000281CBF0020704701207047000069 +:10438000DE0A0020B80A0020AA0000207047514A27 +:10439000012340B1012818BF70471370086890606E +:1043A00088889081704753700868C2F80200888836 +:1043B000D0807047474A10B1012807D00EE05078EE +:1043C00060B1D2F802000860D08804E0107828B10B +:1043D00090680860908988800120704700207047AD +:1043E0003C4910B1012803D006E0487810B903E039 +:1043F000087808B1012070470020704730B58DB0B3 +:104400000C4605460D2104A80CF051FAE0788DF811 +:104410001F0020798DF81E0060798DF81D00286836 +:10442000009068680190A8680290E8680390684668 +:104430000BF02EFA20789DF82F1088420CD160786E +:104440009DF82E10884207D1A0789DF82D10884243 +:1044500002BF01200DB030BD00200DB030BD30B521 +:104460000C4605468DB00321E01CFEF740FA60794A +:104470000D2120F0C00040F04000607104A80CF055 +:1044800016FAE0788DF81F0020798DF81E0060790B +:104490008DF81D002868009068680190A868029057 +:1044A000E868039068460BF0F3F99DF82F00207040 +:1044B0009DF82E0060709DF82D00A0700DB030BDED +:1044C00010B504460621FEF712FA607920F0C0000C +:1044D000607110BDAE00002070B5FF4D0446286825 +:1044E00090F8D610002601291BD090F8B4100129AD +:1044F0001CBF002070BD66701321217000F1B60151 +:104500002022A01C0CF03AF90120A071286880F844 +:10451000B46068680088FBF7D8FBFBF70FF901204F +:1045200070BD667019212170D0F8D710C4F8021040 +:10453000D0F8DB10C4F8061090F8DF10A17280F8F4 +:10454000D660ECE7E448006890F8B410002914BF86 +:10455000B0F8B8004FF6FF70704710B5DE4C206819 +:10456000002808BFFFDF002120684170002808BF35 +:10457000FFDF2068417800291CBFFFDF10BDE42168 +:104580000CF095F921687F2081F83100FFF79DFB41 +:10459000FEF7EDFDD1480AF03DF9BDE81040D048E6 +:1045A0000AF038B9CC48006880787047CA4800B52E +:1045B000016891F82200C0F38002C0F340031A445E +:1045C00000F00100104491F82120C649062A10D2BB +:1045D000DFE802F00C070C03090BC34931F81000A7 +:1045E00000BDC24800BDC24900E0C24931F8100018 +:1045F00000BDFFDF002000BDB74840F27121006818 +:10460000808C48437047B448006890F83000002818 +:1046100018BF0120704710B5040016BF022C0020FF +:104620000120FFF7DDFE002808BF10BDAA48006882 +:104630000473012010BDA849096881F82A00704759 +:1046400010B5A54C2168087B002816BF0228002061 +:10465000012048730E31FFF7ADFE2168087B022868 +:1046600016BF03280122002281F82920082081F8A2 +:104670002700487B01F10E03012804BF5B7913F08A +:10468000C00F0AD001F10E03012804D1587900F0BF +:10469000C000402801D0002000E0012081F828005F +:1046A0002AB991F82100012818BF042806D1087DF5 +:1046B000153109F021F8216881F8270021684AF2B4 +:1046C000B8104860FDF70EFA2168886010BD30B55B +:1046D000814D0446407B296881F822002079052815 +:1046E0000ED2DFE800F0030507090B00002009E007 +:1046F000012007E0022005E0032003E0042001E0A0 +:10470000FFDF00202968012881F821000CBF00206C +:1047100020888884A07B81F83000A079002816BF0B +:104720000228002001200875D4F80700C1F8150000 +:10473000B4F80B00A1F8190091F8B1200120002A6B +:1047400018BF81F8B20091F89120002A18BF81F8B3 +:10475000B3008870002030BD70B55F4D0446002264 +:10476000286880F8B320224672300CF007F82868D9 +:10477000012180F8914080F8B31070BD10B5564CFF +:104780000022236883F8B22083F8B100024603F1C7 +:1047900092000BF0F3FF2168012081F8B20010BDF8 +:1047A0004D49096881F82F0070474B48006890F820 +:1047B000210070472DE9F041474C2068002808BFD0 +:1047C000FFDF00262068417831BB807820B3FFF7F7 +:1047D0001BF92068002580F82B5080F8E05028460F +:1047E000FFF70FF9FEF79DFEFEF75CFE4248FEF76D +:1047F0001AFF4248FFF7F1F800210846FFF777F962 +:104800002068002790F8220010F0010F07D0252023 +:10481000FEF711FF012711E00C20BDE8F08110F038 +:10482000020F04D02620FEF706FF022706E010F054 +:10483000040F03D02720FEF7FEFE0427FEF732FE0A +:10484000206880F82670FFF7D6F801210020FEF7D7 +:1048500067FF0F210520FEF7AAFE206890F82810B8 +:10486000002904BF90F82910002905D190F82100F3 +:10487000012818BF04286FD1FDF734F907462068D6 +:1048800039468068FDF716FD1D4990FBF1F801FBE4 +:10489000180041423846FCF734FE0146206881602A +:1048A00041684144416008F024FF014620684268A5 +:1048B000914251D8C0E90157012690F8270008F02D +:1048C00037FF07462068B04690F82900002818BF37 +:1048D000002F1BD0102115E0BC000020E40B0020AD +:1048E0000C0C0020680F0200780F0200C38913002F +:1048F000800F0200700F0200630F0200600F0200C1 +:1049000040420F00384609F08EFC70B1206890F8E4 +:104910002A1000291CBF90F8281000291CD0427BC7 +:1049200000F10E01012A0FD013E0206800F10E0102 +:1049300080F80D803846FFF792FD206890F8271028 +:104940000E3008F0D4FF07E0497901F0C00140299A +:1049500012D00E30FFF7B4FD2068417B0E30FEF719 +:104960001AFE2068FD4F90F8210005284FD2DFE89D +:1049700000F00A0F44490F0008F0EDFF21680E31E6 +:10498000FFF76DFDE8E70021384609F046FF3FE0FC +:104990000121384609F041FF206890F8270008F00F +:1049A000D0FE5FEA000803D0102109F03CFC68B19A +:1049B000206800F11501384609F061FF2068007D8C +:1049C000B0B1012818BFFFDF0DD021E02EB1206863 +:1049D00000F11B014046FFF742FD206800F11B017A +:1049E000384609F04CFF0121384609F063FF0FE01B +:1049F0000021384609F05EFF0AE00621384609F03A +:104A00000CFF05E00221384609F007FF00E0FFDF58 +:104A1000206800F10E01384609F023FF2068417B31 +:104A2000384609F03AFF206890F82110012918BF94 +:104A3000042916D090F8B21059B190F8B12080F83E +:104A4000712000F1920152300BF098FE206880F83E +:104A5000B250206800F1520190F87120384609F0F8 +:104A600052FF0421BE4809F0D8FE206800F10E0173 +:104A7000BB4809F0F6FE2068417BB94809F00DFFFC +:104A8000206890F8B31059B190F8912080F8512027 +:104A900000F1720132300BF071FE206880F8B350E3 +:104AA000206800F1320190F85120AD4809F04FFF25 +:104AB00008F091FEAB4808F00BFF216881F82E004A +:104AC000FEF7AAFF0020BDE8F081A74948607047C3 +:104AD00070B5A54C06002DD02068002590F8222046 +:104AE00090F8261022EA010010F0010F04D02520D2 +:104AF000FEF7A1FD012515E012F0020F02D011F022 +:104B0000020F06D012F0040F0CD011F0040F05D0E4 +:104B100008E02620FEF78FFD022503E02720FEF7A0 +:104B20008AFD0425FEF7BEFC206890F82610294374 +:104B300080F82610206890F82B1041B190F82100E1 +:104B4000012808BFFFDFBDE8704000F084BA1EB145 +:104B500002210020FEF7E4FD206890F82C007F4839 +:104B6000FEF75DFF206890F82100052809D2DFE8F4 +:104B700000F003030309030001210846FFF7E3F8EF +:104B800000E0FFDF206890F8221090F8262031EA3C +:104B900002024FF0010101D0417070BD90F8212058 +:104BA000012A12BF80F82B10002280F82620F3E79C +:104BB00010B5FEF729FF6C480068417831B980785C +:104BC00020B10020FFF784FF002010BDFFF736F86A +:104BD000FEF7FCFFFEF7A2FEFEF705FFFEF71CFF47 +:104BE0000C2010BD60490120096881F8E000704781 +:104BF0005D49096881F82D00704770B5002503F004 +:104C00007CFB70B14FF49670FEF72DFD564C20687A +:104C10004178012909D0022901D0032930D0FFDFD2 +:104C200070BDBDE8704000F016BA90F8211003295D +:104C300026D090F82E0018B1FEF785FAFFF734F869 +:104C40004848FEF7ECFE216891F82100012818BFC2 +:104C500004280AD091F83000012814BF0328102539 +:104C600045F00E010020FFF76EF8206890F82F0045 +:104C7000012808BFFFF744F802202168487070BD82 +:104C8000BDE87040012023E710B5374C206890F84C +:104C90002F10012909D13130FFF73DF818B92168EB +:104CA0007F2081F83100FFF721F8206890F82E006E +:104CB00018B1FFF70AF8FEF75AFA03F01EFBC0B16D +:104CC00020684078022818BFFFDF206890F8210094 +:104CD000012804BF4FF41970FEF7C5FC0120FFF74F +:104CE000F7FE2068417800291EBF40780128FFDFC9 +:104CF00010BDBDE8104000F0AEB92DE9F05F0546EB +:104D00000027FEF788FC184C80462068407802286F +:104D100018BFFFDF20684FF07F0A90F82F1001299D +:104D200037D0104809F099FDFF268146002D72D03A +:104D30000C4809F004FF00286DD0FEF734FC002871 +:104D400069D02068074D90F82E00B0B108F028FD1A +:104D50000646FF2811D00146E81C07E0E40B0020BE +:104D60000C0C0020340C0020BC00002008F009FDD1 +:104D7000304608F020FD40EA08084846DFF87893FE +:104D80004FF0010B062846D2DFE800F08F8F8F0E20 +:104D90008F623130FEF7BFFF002804BF206880F823 +:104DA00031A0FEF7A3FFBCE7206890F8211001298D +:104DB00018BF042979D0B8F1000F05D190F8301050 +:104DC000002918BF022970D190F82F10012904BFC3 +:104DD00090F8D610002906D0C848FEF720FE2168BA +:104DE0000320487062E080F8D6B0FF2180F8D71029 +:104DF000FF2E11D000F1D902511E304608F0AAFC56 +:104E0000002808BFFFDF206890F8D81041F00201A9 +:104E100080F8D8100DE048E02978C1F3801180F8BF +:104E2000D810D9F85310C0F8D910B9F85710A0F815 +:104E3000DD10206800F1DF0590F831007F2808BF01 +:104E4000FFDF206890F83110297080F831A0C3E7A7 +:104E50002878C0F380112068027D914206D100F1CC +:104E600015010622E81C0BF05DFC30B1206890F8BB +:104E70002700B04203D1FF2E01D0012200E0002222 +:104E8000206890F82110012918BF042900D14AB9DF +:104E900059B9B8F1000F05D190F83010002918BFAA +:104EA000012902D190F82D00D8B10127206890F88F +:104EB0002E0018B1FEF709FFFEF759F9002F1CBFAD +:104EC0000120FFF705FE2068417800291ABF4178CC +:104ED0000129BDE8F09F4078032818BFFFDFBDE837 +:104EE000F09F6068D9F85F10C0F80D10B9F8631032 +:104EF000A0F8111099F86510C174A97D0175B5F875 +:104F00001710C182B5F819104180B5F81B108180C7 +:104F1000B5F81D10C1807A4908300BF0D2FD95F824 +:104F2000240000F01F016068017695F824104909FB +:104F300080F86C11206890F8B400002818BFFFDFDB +:104F40004FF00008206880F8B68061680A88A0F8F1 +:104F5000B8204A88A0F8CE208A88A0F8D020CA8835 +:104F6000A0F8D22091F86C1180F8D41090F8291094 +:104F700049B1427B00F10E01012A04D1497901F0C7 +:104F8000C001402933D090F82A1041B1427B00F192 +:104F90000E01012A04BF497911F0C00F27D0C23099 +:104FA0000BF086FD2878FF2EC0F3801160684176F3 +:104FB000D9F85320C0F81A20B9F85710C1832168D6 +:104FC0001DD0C1F8C820C08BA1F8CC0001F1BC02F3 +:104FD0003046BB3108F0BEFB002808BFFFDF206869 +:104FE00090F8BB1041F0020180F8BB1015E0D0F83A +:104FF0000E10C0F8C210418AA0F8C610D2E7C1F85E +:10500000C880A1F8CC80427E81F8BB20D0F81A205D +:10501000C1F8BC20C08BA1F8C000206880F8B4B0F3 +:1050200060680088FAF751FEFAF778FB206880F88C +:105030000180FEF703FEFEF7C9FDFEF76FFCFEF7E9 +:10504000D2FCFEF7E9FC012003F09DFA2EE70023D5 +:105050001A4603F0A6BB70B5FEF7F0FDFEF7B6FDED +:10506000FEF75CFCFEF7BFFC264C0025206890F89C +:105070002E0030B1FEF729FEFEF779F8206880F89F +:105080002E5020684570FEF7C7FC206890F821007C +:10509000012804D0BDE87040002003F074BA02205B +:1050A00003F071FA206890F8B400002818BFFFDF01 +:1050B000206890F8E010002908BF70BD017D80F8DD +:1050C000BB10D0F81510C0F8BC10B0F81910A0F83B +:1050D000C0103C2180F8B61061680A88A0F8B8209A +:1050E000012280F8B4200888FAF7EFFDFAF716FBE2 +:1050F000206880F8E05070BDE40B00200C0C00200C +:10510000530C0020BC0000202DE9F041F94E04466C +:10511000304600217278406801270D4612B1012AFD +:1051200025D006E090F85E20002A18BF777000D0E6 +:1051300001217278C2EB021200EB820292F8223057 +:1051400019431BD002F124012A22A01C0BF016FBEC +:10515000657004202070A77070787168C0EB001033 +:1051600001EB800080F822500120BDE8F08190F82A +:105170002220002A18BF7570DAD1DAE790F89A1069 +:10518000C9B1D0F89B10C4F80210D0F89F10C4F831 +:105190000610D0F8A310C4F80A10D0F8A710C4F86D +:1051A0000E1090F8AB10A174657012212170A770D9 +:1051B00080F89A5019E0017801291CBF0020BDE851 +:1051C000F081657013212170811C2022A01C0BF03E +:1051D000D5FAA5717068057080F8CC50D0F8B80089 +:1051E0000088FAF772FDFAF7A9FA0120BDE8F0810C +:1051F000C04840680178002914BF80884FF6FF70CE +:1052000070472DE9F041BB4C0746606890F82200DA +:10521000002818BFBDE8F081384609F01EFB0146A2 +:105220000126002007294AD2DFE801F004080E49D0 +:1052300049491300616881F82E000EE0616881F829 +:105240002E6081F82C0015E06168032081F82E00A3 +:1052500003E06168022081F82E00606800F12F01F0 +:10526000384609F060FB0546FF2888BFFFDF60680D +:1052700080F82C50606890F8D20018B1FDF797FFC5 +:10528000012821D0384609F011FB616881F825001A +:105290003846263109F0ECFA606800F12D052078D7 +:1052A0007F2808BFFFDF207828707F20207060688B +:1052B00080F82260BDE8F041032001F0E7BF61689B +:1052C00081F82C00BDE8F081FDF7B4FF616801F1C1 +:1052D0002602253108F03EFA002808BFFFDF60688B +:1052E00090F8251041F0020180F82510D4E710B5A0 +:1052F000002001F039FF7F4CA8B1FEF77CFB0021B4 +:105300000120FEF70DFA7C48FEF789FB6068D0F8B3 +:10531000D800FEF787FB606890F8BC00032818BF30 +:10532000022822D025E0FEF789FCFEF74FFCFEF7AD +:10533000F5FAFEF758FB606890F8D20038B1FEF736 +:10534000C4FCFDF714FF6168002081F8D20060689A +:10535000012180F8DC10022180F8D510FEF75CFBFB +:10536000BDE81040002001F091BF01210020FEF7B0 +:10537000EAFCFEF7C5FC606890F8D20018B1FDF7B2 +:10538000E2FEFEF791FC6168032081F8D50010BDB4 +:10539000584B5968B1F8DE2060B3FF2A0CD24FF6A3 +:1053A000FF7000EA4200A1F8DE00FF2888BFFF205E +:1053B00002D900BFA1F8DE009868012812BF0028BA +:1053C0000D209860C043C0EBC00202EB001091F8C2 +:1053D000DD20D24302EB820CCCEB821210449860A9 +:1053E000B1F8DE20800CB0FBF2F302FB130081F871 +:1053F000DD007047012ADFD95008A1F8DE0008BFA0 +:105400000120D9D1D6E770B53A4D6B6893F8D50035 +:1054100002281FBF93F8D50001280C2070BD002181 +:1054200018460C46C1EB011200EB820282F82240C2 +:10543000491CC9B20229F5D31C7093F8D20030B1CF +:10544000FEF743FCFDF793FE686880F8D240686879 +:1054500080F8CC4080F8CD4080F8D140012180F820 +:10546000B71080F8BC4080F8D44040F2011120F819 +:10547000B41F8170002070BD1E4810B54068002127 +:1054800080F8D510012180F8D510FFF7BCFF002867 +:1054900018BFFFDF10BD2DE9F041164C06460C2762 +:1054A000606890F8D51001291FBF90F8D500022838 +:1054B0000C20BDE8F081FEF7A7FAFEF732F8FDF701 +:1054C000F1FF6068012590F8B410002901BF90F841 +:1054D000B510002990F8B61000291CBF90F8CD1027 +:1054E00000297BD090F8BC00032807D002280AD0FE +:1054F0000DE00000C40000203C0D00200521FE4806 +:1055000000F0F2FE03E00321FB4800F0EDFE6068CE +:1055100090F8CE10002904BF90F8D000002842D0A7 +:10552000FCF7E0FA074660683946D0F8C800FCF797 +:10553000C1FEF24990FBF1F801FB180041423846E8 +:10554000FBF7DFFF0146EE48C0F8C810D0F8C410E2 +:105550004144C0F8C41008F0CCF801466068D0F8A7 +:10556000C42091421FD80021C0E9311790F8D00023 +:10557000002818BF08F0C7F9606890F8D11000291A +:105580001CBF90F8CE1000290DD090F8AD2000F18E +:10559000AE01012A04D1497901F0C00140290FD0A0 +:1055A000AE30FEF78DFF606890F8AD10AE30FDF7BD +:1055B000F2FF6068002790F8D510012917D107E0A5 +:1055C00008F0C9F96168AE31FEF749FFEBE705E085 +:1055D00080F8DC50022180F8D51008E090F8D51052 +:1055E000022902BF80F8D5500C20BDE8F081606828 +:1055F00090F8B710B1B190F8BC00032818BF08F0BC +:105600000BF9C04808F064F90146606880F8D210D0 +:10561000C0F8D860BC48FEF7E0F9FEF7FDF938465F +:10562000BDE8F08108F0D7F8EBE770B5FEF7ECF9CC +:10563000B64C606890F8D510022903D0FEF7ECF95B +:105640000C2070BD012180F8DD10A0F8DE100220D2 +:10565000FEF7D7F9AE48FDF7E6FF6068DFF8B4C2A1 +:10566000002100F1B40300BF90F8D420521CACFB21 +:1056700002546408A4EB84042244D2B280F8D420FB +:10568000D25C012A08D0491CC9B20329ECD300BF5F +:10569000FFF72DFE002070BD90F8D4009E49085CF5 +:1056A000FDF7C9FFFDF7FEFEF2E79849496881F86A +:1056B000BD000020704710B5040016BF022C00206A +:1056C0000120FEF78DFE002808BF10BD8F48002185 +:1056D000406880F8AC4080F8CD10012010BD8B49A7 +:1056E000496881F8D100704710B5884C616891F81D +:1056F000AC00002816BF02280020012081F8AD0070 +:10570000AE31FEF757FE6068012180F8CD1090F8A9 +:10571000AC10022916BF03290122002280F8D020F4 +:1057200090F8AD1000F1AE03012904BF5B7913F0CE +:10573000C00F0AD000F1AE03012904D1597901F05C +:10574000C001402901D0002100E0012180F8CE10E5 +:10575000002904BF002A10BDFCF7C4F96168C1F834 +:10576000C8004AF2B810C1F8C40010BD002816BF26 +:105770000228012200226549496881F8B72081F892 +:10578000BE00704770B5614D0C4600280CBF012368 +:105790000023696881F8B73081F8BF004FF0080036 +:1057A00081F8C0000CD1002C1ABF022C012000206F +:1057B000114607F0A1FF6968082881F8C00001D0F0 +:1057C000002070BD022C14BF032C1220F8D170BD34 +:1057D0004E4A0328526808BFC2F8B81082F8BC00CD +:1057E000002070474949496881F8CF000020704780 +:1057F0004648416891F8BC00032804D0012818BF2E +:10580000022807D004E091F8BF00012808BF7047C4 +:105810000020704791F8BE00012814BF0328012022 +:10582000F6D1704710B5FEF709FAFEF7CFF9FEF78B +:1058300075F8FEF7D8F8354C606890F8D20038B1AA +:10584000FEF743FAFDF793FC6168002081F8D2006F +:105850006068012180F8DC10022180F8D510FEF785 +:10586000DBF8002010BD2949496881F8D60070474F +:1058700010B5FEF7E3F9FEF7A9F9FEF74FF8FEF7CA +:10588000B2F8224C606890F8D20038B1FEF71DFAE9 +:10589000FDF76DFC6168002081F8D200606801218D +:1058A00080F8DC10022180F8D510FEF7B5F8BDE8CD +:1058B0001040002001F0EABC2DE9F84F134DFF2104 +:1058C00000246A687F2782F8D31060B10D4809F080 +:1058D000E9F880B90B4809F01DF920B1094808F032 +:1058E000BCFF04281FD0686890F8D510052928BF90 +:1058F000BDE8F88F12E016E0640D002040420F0072 +:105900005C0C00203C0D0020880F0200C400002029 +:105910008E0F0200ABAAAAAA8B0F0200DFE801F0EB +:10592000F7F7F7F6F500686890F8D500FC4E4FF0F1 +:105930000108052880F0CC82DFE800F0EBEBEB03F8 +:10594000EA00F74808F089FFA870686890F8B70087 +:1059500028B9FDF760FE002808BF002400D001240C +:10596000686890F8D20080B107F01AFF6968FF28D4 +:1059700081F8D3000ED00146F01C07F002FF6868E2 +:1059800090F8D30007F017FF0443686890F8D3003D +:10599000FF280CD1686890F8B71091B190F8BC005E +:1059A000032804D007F089FF696881F8D300A8783C +:1059B000072880F0CC81DFE800F044B40AFDFDFD4B +:1059C000280007F048FF696881F8D300EFE76868AE +:1059D00090F8D20018B1FEF778F9FDF7C8FBD1486E +:1059E000FEF799F9002808BF2F70FEF77FF9002C09 +:1059F00000F04981686890F8BC00012818BF0228AF +:105A000040F04181FDF78AFF6AE0686890F8D200B3 +:105A100018B1FEF75AF9FDF7AAFBC248FEF77BF969 +:105A2000002808BF2F70FEF761F9002C00F02B81D1 +:105A3000686890F8BC0002284BD0012850D000F0D4 +:105A400022B9686890F8D20018B1FEF73EF9FDF768 +:105A50008EFBB448FEF75FF9002808BF2F70FEF7F1 +:105A600045F9002C00F00F81696891F8BC0002280C +:105A70002FD0012834D003281CBFFFDFBDE8F88FEA +:105A8000F278D1F8B800837E9A421BD13279C37E76 +:105A90009A4217D17279037F9A4213D1B279437F28 +:105AA0009A420FD1F279837F9A420BD1327AC37F27 +:105AB0009A4207D13278437EC2F380129A4208BFDD +:105AC000012200D0002291F8BF30012B0ED00AB382 +:105AD000D5E09348FFF795FBBDE8F84F00F01CBBFD +:105AE0008F48FFF78EFBBDE8F84F00E4002A77D11E +:105AF00000F11A018A4808F0BBFE894808F0D6FE7A +:105B00006968D1F8B8104876B9E0F9E1E3E1E0E17D +:105B10002CE1DDE191F8D30091F8C01088427CD1EE +:105B2000ADE0686890F8D20018B1FEF7CEF8FDF746 +:105B30001EFB7C48FEF7EFF8002808BF2F70FEF729 +:105B4000D5F8686890F8D01000290CBF4FF0010B11 +:105B50004FF0000B4FF000093178CA0906F1090136 +:105B600007D0497901F0C001402908BF4FF0010A70 +:105B700001D04FF0000A90F8BC10032906D190F82C +:105B8000B710002918BF90F8C00001D190F8D300D9 +:105B900007F0CEFD009088B1102108F044FB0028EA +:105BA00018BF4FF0010BBAF1000F07D006F1090141 +:105BB000009800E0CBE0FEF721FC8146686890F891 +:105BC000BC1003290DD0FDF7A9FE3CB3FDF7EBFC9B +:105BD00050EA09005DD05248FFF713FB00F048B9C6 +:105BE0004DE0D0F8B800F178827E91421ED1317933 +:105BF000C27E91421AD17179027F914216D1B17958 +:105C0000427F914212D1F179827F91420ED1317A55 +:105C1000C27F91420AD1317801E034E039E0407E20 +:105C2000C1F38011814208BF012600D00026B9F1DE +:105C3000000F05D1BBF1000F04D0FDF7B4FC08B193 +:105C4000012300E00023686890F8BF10012901D00B +:105C500011B10AE03CB908E02EB990F8D32090F8D1 +:105C6000C0C0624501D1012200E0002213420AD0E7 +:105C7000012904BF002ED0F8B8003FF439AFBDE8C9 +:105C8000F84F00F0BBBAFDF749FEBDE8F84FFFF74B +:105C90002EBB686890F8BE10032918BF02297DD179 +:105CA000BAF1000F7AD0B9F1000F77D11C4C90F8FF +:105CB0009A10002972D190F8CF1000296ED080F888 +:105CC0009C8090F8D20018B1FDF771FA01282BD012 +:105CD000204608F0EBFD0146686880F89D1000F151 +:105CE0009E01204608F0C4FD204608F0ECFD014668 +:105CF000686880F8A41000F1A501204608F0C6FDF0 +:105D0000686800F1AB0428787F2808BFFFDF287897 +:105D100020702F70686880F89A800320A6E0000049 +:105D20003C0D0020C4000020FDF784FA696801F1F1 +:105D30009E029D3107F00EFD002808BFFFDF686856 +:105D400090F89D1041F0020180F89D10CCE7686842 +:105D500090F8D20018B1FDF7B8FFFDF708FAFE4839 +:105D6000FDF7D9FF00286ED12F70C1E0FB4808F085 +:105D700074FDA870FA48F178427A91421ED13179C7 +:105D8000827A91421AD17179C27A914216D1B1794F +:105D9000027B914212D1F179427B00E054E09142C2 +:105DA0000CD1317A827B914208D131780078C1F3ED +:105DB0008011B1EBD01F08BF012600D00026FDF7EF +:105DC000ADFDA87804286CD1E6B3E348FDF7A3FF46 +:105DD000002808BF2F70FDF789FF686890F8DC0085 +:105DE00000281CBF0020FFF7D3FA6968DB4C81F85C +:105DF000DC8091F85E0038BB042081F86A0091F8DD +:105E0000D20018B1FDF7D3F9012835D0204608F0AB +:105E10004DFD6A680146204682F8611002F1620178 +:105E200008F026FD686800F16B01204608F09FFD30 +:105E30000446FF2888BFFFDFE1B268681F2980F8A9 +:105E4000681002E02DE053E012E084BF1F2180F8CB +:105E5000681000F1690428787F2808BFFFDF2878E0 +:105E600020702F70686880F85E80042001F00EFAC0 +:105E7000BDE8F84FFFF73BBAFDF7DCF9696801F1BF +:105E80006202613107F066FC002808BFFFDF696825 +:105E900001F13C0091F8611041F0020180F82510F9 +:105EA000C0E7AD48FDF737FF002808BF2F70FDF7AA +:105EB0001DFF686890F8DC00002804BF0120FFF790 +:105EC00067FA686880F8DC40BDE8F84FFFF70FBA62 +:105ED000FFDFBDE8F88F90F8D20018B1FDF7F5FEAE +:105EE000FDF745F99C48FDF716FF00283FF43CAF4D +:105EF000FDF7FCFEFDF712FDBDE8F84FFFF7F7B91F +:105F00009548FDF708FF002808BF2F70FDF7EEFE4B +:105F1000686890F8DC00002804BF0120FFF738FA19 +:105F2000686880F8DC40FDF7F9FCBDE8F84FFFF742 +:105F3000DEB92DE9F041884C606890F8D50007285B +:105F40007DD2DFE800F09898989898040F00834875 +:105F5000FDF765FDFDF7D4FE6168042081F8D500EA +:105F6000BDE8F081FDF76AFEFDF730FEFDF7D6FCD7 +:105F7000FDF739FD60680125022180F8DC5080F8CA +:105F8000D510FDF749FD60680078002818BFFFDFD5 +:105F9000002660688670D0F8B8100A8882804A8827 +:105FA00042838A888283C988C1836E4981F82060D0 +:105FB00090F8D02001F58471A1F584774AB10A7870 +:105FC000C2F38013CA1C23B1527902F0C002402AE6 +:105FD00030D090F8D12042B111F8032BC2F38012D7 +:105FE0001AB1497911F0C00F24D00E300AF060FDCB +:105FF000606890F8D20018B1FDF7D9F8012823D0D5 +:106000006068D0F8B8104A7EC271D1F81A20826058 +:10601000C98B81814661068360680570D0F8B8003D +:106020000088F9F752FEF9F779FBBDE8F04102204C +:1060300001F02CB9D7F80B11C0F80E1000E01AE0EF +:10604000B7F80F114182D3E7FDF7F4F8616801F169 +:106050000802C91D07F07EFB002808BFFFDF60684B +:10606000C17941F00201C171D7F8E3104161B7F87D +:10607000E7100183D0E7FFDFBDE8F08170B5364C53 +:10608000606890F8D5000025052828BF70BDDFE8BE +:1060900000F03E3E3E1D03002F48FDF73CFE002869 +:1060A00004BF7F202070FDF721FE606890F8DC00BF +:1060B000002804BF0120FFF76BF9606880F8DC500E +:1060C000FDF72CFCBDE87040FFF711B9FDF7B6FDF8 +:1060D000FDF77CFDFDF722FCFDF785FC606890F87C +:1060E000D20030B1FDF7F1FDFDF741F8606880F8AE +:1060F000D2506068012180F8DC10022180F8D510B0 +:10610000FDF78AFCBDE87040002001F0BFB870BD0B +:1061100000231A4601F08CB970B5012001F024F873 +:106120000D4C20B30E49A1F1280008F0CFFB6068A8 +:106130000B4E90F8AD10304608F0AFFB606800F1F0 +:10614000AE01304608F08DFB606890F8D010002951 +:1061500044D090F8BC1007E0C40000203C0D0020A3 +:10616000640D00205C0C0020032922D028E0FDF7FC +:1061700065FDFDF72BFDFDF7D1FBFDF734FC6068F5 +:1061800090F8D20038B1FDF7A0FDFCF7F0FF616890 +:10619000002081F8D2006068012180F8DC10022123 +:1061A00080F8D510FDF738FCBDE87040002001F004 +:1061B0006DB890F8B710002918BF90F8C00001D151 +:1061C00090F8D30007F0C9FB050007D00121304645 +:1061D00008F063FB2946304608F043FB7248FDF7A0 +:1061E0001EFC01210846FDF7AEFD00210846FDF723 +:1061F0007EFC6168052081F8D50070BD2DE9F04175 +:10620000022000F0B1FF694C0126F0B1012001F03D +:106210003DF86549A1F1280008F058FB6068624F1D +:1062200090F8AD10384608F038FB606800F1AE0118 +:10623000384608F016FB606890F8D01000293AD074 +:1062400090F8BC10032921D027E0FDF7F7FCFDF7FB +:10625000BDFCFDF763FBFDF7C6FB606890F8D2005C +:1062600038B1FDF732FDFCF782FF6168002081F84C +:10627000D2006068022180F8DC6080F8D510FDF75C +:10628000CBFBBDE8F041002001F000B890F8B7105A +:10629000002918BF90F8C00001D190F8D30007F092 +:1062A0005CFB050007D00121384608F0F6FA2946C4 +:1062B000384608F0D6FA6068D0F8B800C18A3A4883 +:1062C00008F07FFB6068D0F8B800017D364808F020 +:1062D0007CFB3548FDF7A3FB606880F8CC600621A5 +:1062E00080F8D510BDE8F08170B50C46054608F081 +:1062F00091FA032C51D0052C18BF70BD05212846FA +:1063000008F08BFA294C6068D0F8B80000F10D0154 +:10631000284608F040FB6068D0F8B80000F1110191 +:10632000284608F03CFB6068D0F8B800017D28469C +:1063300008F04BFB6068D0F8B800C18A284608F026 +:1063400040FB6068D0F8B8004188284608F02DFB73 +:106350006068D0F8B8008188284608F02AFB606899 +:10636000D0F8B800C188284608F027FB6068D0F84C +:10637000B80000F10801284608F041FB6068D0F839 +:10638000B800017E284608F022FB606890F8D6101D +:106390002846BDE8704008F024BB2846BDE87040A0 +:1063A000032108F03ABA0000640D0020C400002068 +:1063B0002DE9FF4F06460C46488881B040F2E24185 +:1063C00048430090E08A002500FB01FB94F863003D +:1063D0009046082816BF07284FF0010A4FF0000A20 +:1063E000049818B10121204603F000FC94F85100F4 +:1063F000012808BF002708D0022808BF012704D0C1 +:1064000003281ABFFFDF0027032794F8D000DFF826 +:10641000189448B101285CD0022842D0032818BF44 +:10642000FFDF56D000F0B6B8B8F1000F08BFFFDFAD +:10643000FE4D6868002808BFFFDF3846FDF729FBDE +:1064400000F2E7314FF47A70B1FBF0F0696800EBCD +:1064500001083846FDF71DFB012F04BF49464FF4E4 +:1064600096620BD0002F04BFF1494FF4C86205D0EB +:10647000032F0CBFEF49F04940F69802114408443D +:106480004AF2531101444FF47A70B1FBF0F040F23C +:10649000E241081A2969584441440844051D012075 +:1064A00014E0E24FA8F101017868084308BFFFDF5C +:1064B000E248B8F1000F006800EB0B0505D07868E2 +:1064C00000F21E30A84288BFFFDF032084F8D0000E +:1064D0005FE094F86300009D21281CBF94F86400DD +:1064E000212846D1B4F85800B4F80611401A401CCF +:1064F00000B200283DDB94F80401002839D00128BF +:1065000008BF002007D0022808BF012003D00328BD +:106510001CBFFFDF0020012F04BF49464FF49662E5 +:106520000BD0002F04BFC2494FF4C86205D0032F1F +:106530000CBFC049C04940F698021144012804BF6D +:1065400048464FF496620BD0002804BFB8484FF479 +:10655000C86205D003280CBFB648B74840F6980279 +:106560001044081A00F2E7314FF47A7091FBF0F012 +:106570000544B8F1000F0CD0AC4F786818B9788892 +:10658000002818BFFFDF786800F21E30A84288BFDD +:10659000FFDF05B9FFDF2946D4F8D400FAF7B1FFD1 +:1065A000C4F8D400B0600020307001203071204663 +:1065B00003F005FCAAF10101084204BF012070713B +:1065C00006D094F8D00001280CBF0220032070717F +:1065D00094F8510094F85280D4F824B0012808BFF0 +:1065E000002708D0022808BF012704D003281ABFBB +:1065F000FFDF00270327B8F1010F08BF00200AD0F2 +:10660000B8F1020F08BF012005D0B8F1030F1ABF7F +:10661000FFDF00200320FDF751FA012F08BF4FF4E0 +:1066200096610ED0002F04BFDFF804924FF4C861CA +:1066300007D0032F0CBFDFF8FC91DFF8FC9140F688 +:106640009801494408444AF2AB3101444FF47A704E +:10665000B1FBF0F0584400F5C770F060049830EAE0 +:106660000A0004BF05B0BDE8F08F2946304607F0A8 +:10667000D0FE87B2204603F0A2FBB8420FD801211A +:106680000746717105FB07F1D4F8D400FAF739FF1A +:10669000B0602946304607F0BCFE384487B2394620 +:1066A000204603F0A3FAB068C4F8D40005B0BDE8F2 +:1066B000F08F2DE9F0430446614885B00D4690F80F +:1066C0000004DFF88091400999F8001449098842D4 +:1066D00018BFFFDFDFF85481002708F13C06082DC2 +:1066E00080F02381DFE805F0047F898984FDFDCBFC +:1066F000202C28BFFFDF36F814000621F9F7DAF95D +:10670000050008BFFFDF202C28BFFFDF36F814008C +:106710002988884218BFFFDF95F8D000002808BFFD +:10672000FFDF284603F03BF8C8F80470A8F80270B1 +:1067300029460020C8F8107007F0F6FE00F1980610 +:10674000686AB0423CD995F85100012808BF00247E +:1067500008D0022808BF012404D003281ABFFFDF95 +:106760000024032495F85200012808BF002007D018 +:10677000022808BF012003D003281CBFFFDF002030 +:10678000FDF79CF9012C04BF27494FF496620BD00A +:10679000002C04BF26494FF4C86205D0032C0CBF5F +:1067A0002449254940F69802114408444AF2AB3185 +:1067B00008444FF47A71B0FBF1F1686A0844871B12 +:1067C00029460020C8F8087007F0AEFE698840F23C +:1067D000E24251439830081AA0F21E30C8F80C006B +:1067E00005B0BDE8F08305B0BDE8F04303F0D9B8CB +:1067F00005B0BDE8F043FDF73ABB99F8140D124916 +:10680000400991F800144909884218BFFFDF202C85 +:1068100028BFFFDF36F814000621F9F74BF9050011 +:1068200008BFFFDF202C11E0FC6601008C0D00206A +:10683000445B01000C1101002C5F0100D40000201A +:1068400001E000E00BE000E019E000E028BFFFDF1E +:1068500036F814002988884218BFFFDF0022012380 +:1068600029466846FFF7A4FD95F8DA006946FBF76C +:106870002AFB002808BFFFDF05B0BDE8F083202C0D +:1068800028BFFFDF36F814000621F9F713F90500D9 +:1068900008BFFFDF202C28BFFFDF36F8140029884F +:1068A000884218BFFFDF95F8D000042818BFFFDF2B +:1068B00085F8D07095F8DA404FF6FF79202C28BF84 +:1068C000FFDF26F8149095F8DA00FBF7ECF80028C3 +:1068D00008BFFFDF202085F8DA00D5F8E0000028A7 +:1068E00000E022E004BFD5F8DC00C8F8140008D0AE +:1068F000D5E939121144826911448161D5E9370122 +:10690000C860D5F8DC0000281CBFD5F8E010016194 +:1069100004D1D5F8E000002818BF8761FD48007851 +:1069200005B0BDE8F043F3F76BBCFFDF05B0BDE891 +:10693000F0832DE9F047F84D0746E88B6C68401C62 +:10694000E88328784FF00008002808BFFFDF07D051 +:10695000DFF8C8A3042814D0052818BFFFDF40D0F3 +:1069600021462869FAF7CDFDB86087F8008001203C +:106970003871A86800F25910F860287804287CD192 +:1069800085E00029ECD02E69DAF8141039B3894675 +:10699000C9680029FBD1B9F1000F20D099F8000097 +:1069A000002808BFFFDFD9F81410D9F8040001440B +:1069B0003046FBF77FFC002807DA211A4A1E92FBBB +:1069C000F4F202FB0406214604E090FBF4F202FB21 +:1069D000140621468E4288BFFFDF3446C0E7444696 +:1069E000BEE70029BCD0D5F81890B9F1000F08BF58 +:1069F000FFDF0026D9F8E410DAF814403046721EA2 +:106A00005CB1A069884228BF824284BF0246264604 +:106A10002046E468002CF4D106B9064609F1D004FA +:106A2000C9F8E060002E04BFC4F80C80CAF8144016 +:106A300005D0F068F460E060002818BF0461D4F865 +:106A40001090C4F81880B9F1000F0ED0D9F81800D2 +:106A500048B1D4F814A0504538BFFFDFD9F818006A +:106A6000A0EB0A00A061C9F81880002E08BFC5F885 +:106A7000208009D03078002800E00DE008BFFFDF5B +:106A8000716970680844286240F6B83468E7E88B9A +:106A90000A2838BF032000D302207871E88B012830 +:106AA00006D93846696807F0B4FCE98B0844E883E6 +:106AB000B8682861BDE8F0872DE9F0418046984824 +:106AC00084B00E4690F80004964F410997F80004F0 +:106AD0004009814218BFFFDF01210025082E8E4C9E +:106AE00062D2DFE806F0041A35353061614D61731A +:106AF0002173607800281CBF04B0BDE8F08187488E +:106B0000456005612573A068CD38FEF7C4FC0028F8 +:106B100018BFFFDF04B0BDE8F081607850B1207B82 +:106B2000002808BFFEF77EFE657304B0BDE8F041A3 +:106B3000FAF7E3BEA173FEF778FD002818BFFFDF68 +:106B400004B0BDE8F08104B0BDE8F041FDF78FB9B5 +:106B500097F8140D7449400991F8001449098842C6 +:106B600018BFFFDF00216846FFF7E3FE6946404695 +:106B7000FBF7A9F9002808BFFFDF04B0BDE8F081EA +:106B80002078052818BFFFDF207F002808BFFFDF1F +:106B900025772570207DFAF786FF002808BFFFDFE4 +:106BA000257504B0BDE8F081FFDF04B0BDE8F081D9 +:106BB00070B5594C0026207804281FBF207805287E +:106BC0000C2070BD01206070607B002518B372B688 +:106BD000607B00281CBFA07B002805D0FEF722FEAA +:106BE0006573A573FAF789FE62B6207DFBF7E1FBBA +:106BF000207F28B125772078052818BFFFDF0C26D5 +:106C000065702570207DFAF74EFF002808BFFFDF72 +:106C10002575304670BD207DFBF7DEF9E5E72DE9EF +:106C2000F04F3D4883B00078002818BFFFF7C0FF41 +:106C30000120DFF8E88088F8000069460620F8F7B0 +:106C4000C4FE002818BFFFDF00274FF6FF7934E0AD +:106C5000029800281CBF90F8D01000292DD0008881 +:106C600048451CBFDFF8C4A04FF0200B3BD00621E5 +:106C7000F8F720FF040008BFFFDF94F8DA00FBF705 +:106C800098FB84F8D07094F8DA504FF6FF76202DF8 +:106C900028BFFFDF2AF8156094F8DA00FAF703FF3F +:106CA000002808BFFFDF84F8DAB069460620F8F74D +:106CB0008CFE002818BFFFDF10E06846F8F763FE7F +:106CC0000028C5D00FE0029800281CBF90F8D01013 +:106CD000002903D000884845C9D104E06846F8F788 +:106CE00052FE0028EFD088F80070C8F8147003B086 +:106CF0000020BDE8F08F10B50078064CD8B101280F +:106D00000CBF40F6C410FFDF15D0A06841F66A0141 +:106D100088420DE0D0000020A40D00208C0D002042 +:106D200001E000E00BE000E019E000E0C80D002009 +:106D300028BFFFDF10BDA060E7E710B5FE4C0023C1 +:106D40002070FE48037043700377037343738373AB +:106D5000202183610175183843703A3010214FF6B5 +:106D6000FF72428020F8042F491EFAD1180008BF94 +:106D7000A36005D0002B0EBFFFDF40F6C410A0605B +:106D8000A06841F66A01884228BFFFDFBDE81040D5 +:106D900045E72DE9F047E94C054684B020781746D1 +:106DA000884600281EBF0C2004B0BDE8F08795F887 +:106DB000510095F85260D5F82490012808BF4FF093 +:106DC000000A0BD0022808BF4FF0010A06D00328A2 +:106DD0001ABFFFDF4FF0000A4FF0030A012E08BF71 +:106DE000002008D0022E08BF012004D0032E1ABFB5 +:106DF000FFDF00200320FCF761FE0146BAF1010F1E +:106E000004BFCF484FF496620DD0BAF1000F04BF13 +:106E1000CC484FF4C86206D0BAF1030F0CBFCA4881 +:106E2000CA4840F69802104408444AF2AB3108447C +:106E30004FF47A76B0FBF6F0484400F21E30C5F805 +:106E4000E400A56195F8D000002818BFFFDF40F2EC +:106E5000712008FB00F060600020FCF72FFE00F2BC +:106E6000E730B0FBF6F040F2712107FB0100A060B3 +:106E70006168A1F2E921884298BF01460020A16023 +:106E8000B34908610521217060702077E083B14823 +:106E9000FAF7AEFD2075202808BFFFDFFAF722FEC3 +:106EA000206101216846FFF744FD207D6946FBF71C +:106EB0000AF8002808BFFFDF002004B0BDE8F08713 +:106EC0009E48007800281CBF0020704710B506209F +:106ED000F8F78CFD80F0010010BD30B5974C85B0FF +:106EE0002278002A1EBF0C2005B030BD0D4640F2AE +:106EF0007121484360600020FCF7E0FD4FF47A7197 +:106F000000F2E730B0FBF1F040F2712105FB010027 +:106F1000A0606168A1F2E921884298BF0146002083 +:106F2000A160607004212170E0838A48FAF760FD57 +:106F30002075202808BFFFDF8548406938B1014629 +:106F4000C0680028FBD111B1FAF7CCFD05E0FAF7D3 +:106F5000C9FD40F6B831FAF7D4FA2061012168463C +:106F6000FFF7E7FC207D6946FAF7ADFF002808BF70 +:106F7000FFDF002005B030BD70B5704CA169016025 +:106F8000FFF716FE002300BBA169D1F8E0205AB13B +:106F9000D1E939C5AC449569AC44C2F818C0D1E90F +:106FA000372CCCF80C2005E0DFF8A4C1D1F8DC20A8 +:106FB000CCF81420D1F8DC20D1F8E010002A18BF5A +:106FC000116102D1002918BF8B61A36170BD6049B6 +:106FD0004870704770B540F2E24300FB03F6144678 +:106FE000012908BF002508D0022908BF012504D0C7 +:106FF00003291ABFFFDF00250325012C08BF00204D +:1070000008D0022C08BF012004D0032C1ABFFFDFD8 +:1070100000200320FCF752FD012D04BF48494FF426 +:1070200096620BD0002D04BF46494FF4C86205D0CC +:10703000032D0CBF4449454940F6980211440844C9 +:107040004AF2AB3108444FF47A71B0FBF1F000F230 +:107050001E3086428CBF301A002070BD2DE9F041F1 +:10706000064690F84F0000240D4610F0040F04BFB0 +:1070700096F8500010F0040F3146204611D007F06A +:1070800053FA07463146204607F032FAB8423146F5 +:10709000204602D907F02CFA01E007F045FA044631 +:1070A00002E007F041FA044696F85100012808BFB3 +:1070B000002708D0022808BF012704D003281ABFE0 +:1070C000FFDF0027032796F85200012808BF0020A1 +:1070D00007D0022808BF012003D003281CBFFFDF10 +:1070E0000020FCF7EBFC012F04BF15494FF496621A +:1070F0000BD0002F04BF13494FF4C86205D0032FF3 +:107100000CBF1149114940F69802114408444AF253 +:10711000AB3108444FF47A71B0FBF1F0718840F262 +:1071200071225143C0EB4100A0F21E30A54234BF92 +:107130002146294681420FE0D0000020A40D002006 +:10714000FC660100445B01000C1101002C5F010092 +:107150008C0D0020B96A010003D2A5422CBF28463D +:1071600020467062BDE8F081C64910B54968002824 +:1071700001F1980408BF04F5BC7409D0012808BFC8 +:1071800004F5317404D0022814BFFFDF04F5B07495 +:10719000BD488068A0428CBF0120002010BD10B502 +:1071A000B84C607828B1D4E90201626807F059F957 +:1071B000A060D4E9010188429CBF2078002814BF58 +:1071C0000020012010BD042210B584B005295AD238 +:1071D000DFE801F00A2B0330540080F8D02004B01F +:1071E000BDE81040FAF789BB0446A648007800289D +:1071F00018BF84F8D02004D004B0BDE81040FAF7DE +:107200007CBB0122002321466846FFF7D1F894F8A1 +:10721000DA006946FAF757FE002808BFFFDFB4F826 +:107220005800401CA4F85800E6E7032180F8D0106D +:1072300004B010BD0446408840F2E24148439349FF +:107240000860D4F8F8000089E082D4F8F80080796A +:107250002075D4F8F80040896080D4F8F80080895F +:10726000A080D4F8F800C089E0802046A16AFFF72A +:10727000F5FE022084F8D00004B010BD816A04B08D +:10728000BDE81040EAE6FFDF04B010BD2DE9F04193 +:10729000DFF8FC8100257C4C98F8001084B00528AC +:1072A00080F0C180DFE800F003166DB9B900E58316 +:1072B0000846F2F7A5FF6078002873D100216846E0 +:1072C000FFF737FB207D6946FAF7FDFD002808BF70 +:1072D000FFDF67E00020FCF7F1FB6E49694E0844D0 +:1072E0004FF47A71B0FBF1F02169726840F2E24329 +:1072F0001144081AA16900F2DE604A88D03102FB0D +:1073000003F772698A4208BF002514D0216AFAF790 +:10731000D1FF002807DA391A4A1E92FBF7F202FB66 +:107320000705394604E090FBF7F202FB17053946E2 +:107330008D4288BFFFDFD8F80800854208D2A069D7 +:1073400040F271224188C1824A4305EB420505E0C3 +:1073500040F2E240B5FBF0F0A169C882A0690521C6 +:107360000175C08A6FF41C71484305EB400040F67C +:1073700035413061B0EB410F28BFFFDF04B0BDE8FD +:10738000F081E5830846F2F73BFF01202077A069F2 +:107390002169C0F8D41080F8D0502178052918BF91 +:1073A000FFDF06D0FAF7A9FA6573A57304B0BDE84C +:1073B000F081002808BFFFDFA06990F8D000002806 +:1073C00018BFFFDFA06990F8DA00202818BFFFDFA0 +:1073D0003148FAF70DFBA1690646202881F8DA004A +:1073E0000F8828BFFFDF2D4820F81670A06990F89D +:1073F000DA00202808BFFFDF002301226846A169C8 +:10740000FEF7D6FFA069694690F8DA00FAF75BFD4F +:10741000002808BFFFDFA561C4E704B00846BDE847 +:10742000F041F2F7EDBEFFDF04B0BDE8F081704738 +:1074300070B5144D0446002904BF686070BD4FF458 +:107440007A76012910D002291CBFFFDF70BD688841 +:10745000401C68801046FCF71CFB00F2E730B0FBD4 +:10746000F6F0201A686070BD1846FCF79BFE00F22B +:10747000E730B0FBF6F0201A686070BD0248007873 +:10748000704700008C0D0020A40D0020D4000020C7 +:10749000D0000020D7020200B3660100C80D002012 +:1074A000FE48406870472DE9F04114460E460746F5 +:1074B000012A08BF002512D0022C08BF012504D0E4 +:1074C000032C1ABFFFDF00250325032C08BF4EF64F +:1074D000341007D0022C14BFFFDF012000D00020A1 +:1074E000FCF7ECFA012D08BFED4907D0002D08BFCD +:1074F000EC4903D0032D0CBFEB49EC4908444AF298 +:10750000531108444FF47A71B0FBF1F000EB4700DF +:107510008519012C08BF002008D0022C08BF0120CB +:1075200004D0032C1ABFFFDF00200320FCF79FFAD2 +:1075300028446030BDE8F0812DE9F041064690F81E +:107540004F00012490460D4610F0040F04BF96F83A +:10755000500010F0040F3146204611D006F0E4FF31 +:1075600007463146204606F0C3FFB8423146204662 +:1075700002D906F0BDFF01E006F0D6FF044602E0A6 +:1075800006F0D2FF044696F852000027012827D0C3 +:10759000022829D003282CD0FFDF3846FCF78EFACA +:1075A000C04940F2712208444AF2531108444FF492 +:1075B0007A71B0FBF1F071885143C0EB4100A0EB50 +:1075C0000800A0F55870A54234BF214629468142E3 +:1075D00003D2A5422CBF284620467062BDE8F08148 +:1075E0003846FCF76BFADBE70120FCF767FAAC4999 +:1075F000D7E70320FCF762FAAB49D2E72DE9FF4F4A +:107600008FB0044690F85200DDF8709098460690CE +:1076100049EA08000C9094F86400002617460828F0 +:107620000CBF012000200890B8F1000F04BF94F8AF +:107630000C01032846D10898002843D0B4F88401EF +:10764000B8423FD1D4F81401C4F80001618840F277 +:10765000E2404843C4F80401B4F85A01B4F8E61013 +:107660000844C4F80801204604F0FDFAB4F8880183 +:10767000E08294F886012075B4F88A016080B4F83D +:107680008C01A080B4F88E018A49E080884809788E +:1076900094F86C31628830F8111030F81300084407 +:1076A0000104090C4FF0000004D083485143B1FBA2 +:1076B000F0F0401C82B22046A16AFFF73DFF022095 +:1076C00084F80C01D4F864010B90B4F8E6B0B4F877 +:1076D0005801D4F860A1D4F854110491B8F1000F06 +:1076E00003D094F8201149B180E004F1E001019148 +:1076F0007431099104F5A075091D07E004F59A712C +:107700000191091D099104F59275091D0A91B4F8BA +:107710005810381A791A09B200B20091002805DA17 +:10772000D4F85001049001200C90084694F80C11F4 +:1077300000295FD0012900F0748102297DD003293E +:1077400018BFFFDF00F09E8131460498F9F7D9FE9B +:10775000099908600A980121078000202870297182 +:1077600009980068A8605348D0E90520824287BF85 +:10777000019A1060019802600198626A00681044E2 +:1077800000F28110E8606971B4F8D000C01B00B24B +:107790000028C4BF032068710898002800F0088200 +:1077A000B9F1000F19D000BFB4F8F820002A0CBFBF +:1077B0000020B4F8FA00A4F8FA0094F8FC30401C59 +:1077C0005843904209D26879401E002805DD69714E +:1077D000B4F8FA00401CA4F8FA00B8F1000F00F069 +:1077E0000B8294F82001002800F0028213B00220DE +:1077F000BDE8F08FBAF1000F08BFFFDFE18A40F269 +:107800007120484340F2E24101EB40021098002110 +:10781000002806D000FB02F12748B1FBF0F000F190 +:107820000101C4F81011608840F2E24100FB01F24E +:1078300010994FF0000008D000E05CE01E4801FB0A +:1078400002F1B1FBF0F000F10100C4F814014FF0B7 +:107850000000FCF7A7FC00F2E1414FF47A70B1FBA5 +:10786000F0F000EB0A060020FCF79CFC83460020A9 +:10787000FCF724F91149584401444FF47A70B1FBE4 +:10788000F0F0E18A40F271225143C0EB4101D4F89B +:107890001001091A314401F2C24611E0080E00201D +:1078A000FC660100445B01001C3801002C5F0100F4 +:1078B000920F0200DC00002040420F0091FD010009 +:1078C000217D520011FB02F10122FFF7ECFD811C2A +:1078D000FE48416181610020FCF764FC00F2E14157 +:1078E0004FF47A70B1FBF0F05044301AB0F53C7FA1 +:1078F00038BFFFDF28E7E18A40F27122D4F80401A3 +:10790000514300EB410210990020002906D0F048B5 +:1079100001FB02F1B1FBF0F000F10100C4F810012D +:10792000618840F2E24301FB03FC109B4FF0000131 +:1079300006D0E74903FB0CF3B3FBF1F101F10101C0 +:10794000C4F81411BBF1000F47D1B9F1000F44D0B6 +:1079500094F85200012805D0022809D0032818BF46 +:10796000FFDF0BD00020FCF7A9F80146D9480AE058 +:107970000120FCF7A3F80146D74804E00320FCF7F8 +:107980009DF80146D548E38A01444AF25310014468 +:107990004FF47A70B1FBF0F0D4F8101140F271227C +:1079A0000144D4F804015A4300EB4200461A94F80B +:1079B0005200012808BF002007D0022808BF01207C +:1079C00003D003281CBFFFDF0020FCF750F80B9901 +:1079D000081A3044A0F1200600E0161AD4F8082155 +:1079E000D4F80011D4F8100140F2E24301FB020088 +:1079F00094F85220217D11FB03F1FFF754FD01465D +:107A0000B24840F2712341616288D4F814115A439C +:107A1000C1EB4201A1F211318161012084F80C0116 +:107A200092E6628840F27123D4F814115A43C1EBF4 +:107A3000420202FB00F60098D4F800C10BEB0002F2 +:107A4000D4F80801D4F81031121A0CFB0030521E81 +:107A500002FB010094F85220217D40F2E24311FB29 +:107A600003F1FFF720FD01469848B9F1000F41618D +:107A7000A6F2113181613FF467AEBAF1000F08BF81 +:107A8000FFDF61E6628840F27123D4F814115A4393 +:107A9000C1EB420101FB00F694F8630021281CBFF2 +:107AA00094F8640021280AD1B4F88401381A00B28D +:107AB000002804DB94F88701002818BF06900C9872 +:107AC00030B10B98BBF1000F1AD0002818BFFFDFB0 +:107AD0000098D4F81411584448430021069AFFF73F +:107AE000E2FC0146794840F2712341616288D4F892 +:107AF00014115A43C1EB4201A1F21131816123E615 +:107B0000002814BFBAF1000FFFDF0698012808BF54 +:107B10004FF0000A0BD0022808BF4FF0010A06D030 +:107B200003281ABFFFDF4FF0000A4FF0030A94F852 +:107B30005200032808BF4EF634110BD0012808BFAD +:107B4000002004D002281ABFFFDF00200120FBF72D +:107B5000B5FF0146BAF1010F08BF5F4809D0BAF17D +:107B6000000F08BF5B4804D0BAF1030F0CBF5B489D +:107B70005B4801444AF2531001444FF47A70B1FB60 +:107B8000F0F0361A94F85200012808BF002007D000 +:107B9000022808BF012003D003281CBFFFDF0020FC +:107BA000FBF765FF0B99081A3044A0F120068FE718 +:107BB000B9F1000F7FF4F8AD94F80C0100283FF400 +:107BC0000CAE618840F27122D4F814015143C0EB2D +:107BD0004101284606F01DFC0004000C3FF4FDADF9 +:107BE0001D99002918BF0880012013B0BDE8F08F4F +:107BF00094F85C01FAF7F0F994F85C012946FAF779 +:107C000062F900281CBF88F0010084F821010020DF +:107C100013B0BDE8F08F2DE9F04F324F044683B02A +:107C200038788B460025294E4FF0020A4FF00308A2 +:107C3000032804BF387BA0427DD178683061387852 +:107C4000032818BFFFDFBBF1080F75D2DFE80BF088 +:107C5000040F1C1C1784847D7D62FCF7ABFD00289B +:107C600018BFFFDF86F8028003B0BDE8F08FFCF795 +:107C70009FFF002818BFFFDF03B0BDE8F08F03B0FF +:107C8000BDE8F04FFCF7F3B887F814803D74F87A3C +:107C9000012458B14FF47A71B869F9F732FCB86130 +:107CA000002107F1100006F0B4FB29E0012168462D +:107CB000FAF7F9FD9DF8000042F210710002B0FBE6 +:107CC000F1F201FB1204FCF797FC0DE0DC00002050 +:107CD00040420F00445B0100FC6601001C380100BB +:107CE0002C5F0100080E002004442146B869F9F712 +:107CF00008FCB861214607F1100006F08AFB441C1D +:107D0000388C411C0A293CBF20443884786830B143 +:107D1000388C401C0A2828BF87F815A001D287F8A4 +:107D20001580787A00281CBF03B0BDE8F08F387B3F +:107D300007F1100101E013E00EE0FAF7C4F80028A3 +:107D400008BFFFDF03B0BDE8F08F387BF9F7ABFE6B +:107D50003D7003B0BDE8F08FFFDF03B0BDE8F08FEA +:107D6000202C28BFFFDFDFF8EC94072139F814003E +:107D7000F7F7A0FE070008BFFFDF202C28BFFFDFBA +:107D800039F814003988884218BFFFDF3C46376154 +:107D90000127BBF1080F80F05581DFE80BF004A745 +:107DA000B1B1AAFDFDFCC4F86051F580C4F864517E +:107DB00094F8210138B9F9F795FED4F82C11FAF7A7 +:107DC00079FA00281BDCB4F81E11B4F8580081427F +:107DD00006D1B4F8D410081AA4F8D600204605E05D +:107DE000081AA4F8D600B4F81E112046A4F85810BA +:107DF000D4F84811C4F82C11C0F850111DE0B4F8A3 +:107E00001C11B4F85800081AA4F8D600B4F81C11D4 +:107E10002046A4F85810D4F82C11C4F84811C4F81E +:107E20005011D4F83411C4F8E010D4F83811C4F863 +:107E30005411B4F83C11A4F8581103F054FDF9F7AB +:107E40002BFE814694F85200012841D0022843D0ED +:107E5000032846D0FFDF2846FBF730FEFE4940F2FC +:107E6000712208444AF2531108444FF47A71B0FB6E +:107E7000F1F1D4F81401014460885043C1EB400093 +:107E8000A0F13008B9F1B70F98BF4FF0B7092146FC +:107E9000012006F049FB4844A8EB0000A0F2153889 +:107EA000A1462146012006F03FFBD9F824109C3062 +:107EB000814288BF0D1AC6F80C80454528BF45464B +:107EC000B56084F8207186F802A003B0BDE8F08F99 +:107ED0002846FBF7F3FDC1E73846FBF7EFFDDF4926 +:107EE000BDE74046FBF7EAFDDD49B8E703F0B9FE20 +:107EF00001E0FBF7BCFF84F8207103B0BDE8F08F10 +:107F0000F9F7F0FDD4F8502101461046FAF7D2F9FE +:107F100048B1628840F27123D4F814115A43C1EB7E +:107F20004201B0FBF1F094F8641008290FD0B4F8C6 +:107F30005810B4F81E210B189A42AEBF501C401CBA +:107F40000844A4F81E0194F8220178B905E0B4F8B9 +:107F50001E01401CA4F81E0108E0B4F81E01B4F88C +:107F6000D410884204BF401CA4F81E01B4F85A0182 +:107F7000DFF8F0A2401CA4F85A01B4F87E00B4F86F +:107F80007C100DF1080B401AB4F85810401E08443C +:107F90001FFA80F819E047E054E0307800233AF8FF +:107FA0001000CDE9005B94F86C113AF81110084408 +:107FB00081B22046FFF722FB002804BF03B0BDE8D2 +:107FC000F08F012818BFFFDF26D0B4F81E21A8EBE0 +:107FD000020000B20028E0DA082084F8720084F879 +:107FE0007170204603F0B6F984F80C5194F85C5196 +:107FF0004FF6FF77202D00D3FFDF29F8157094F896 +:108000005C01F9F750FD202084F85C01307903B061 +:10801000BDE8F04FF2F7F4B8B4F81E01BDF808104F +:108020000844A4F81E01D0E794F80C01042818BFF6 +:10803000FFDF84F80C5194F85C514FF6FF77202D48 +:10804000DBD3D9E7FFDF03B0BDE8F08F10B5864C76 +:10805000207850B101206072FCF7CAFD2078032817 +:1080600005D0207A002808BF10BD0C2010BD207B51 +:10807000F9F7B2FF207BFAF79CF9207BF9F713FDA3 +:10808000002808BFFFDF0020207010BD2DE9F04F51 +:10809000754F83B0387801244FF0000840B17C72EE +:1080A0000120FCF7A5FD3878032818BF387A0DD0D9 +:1080B000DFF8B89189F8034069460720F7F785FC97 +:1080C000002818BFFFDF4FF6FF7440E0387BF9F758 +:1080D00083FF387BFAF76DF9387BF9F7E4FC002869 +:1080E00008BFFFDF87F80080E2E7029800281CBF86 +:1080F00090F80C1100292AD00088A0421CBFDFF89C +:1081000054A14FF0200B3AD00721F7F7D3FC04001D +:1081100008BFFFDF94F85C01FAF74BF984F80C8193 +:1081200094F85C514FF6FF76202D28BFFFDF2AF828 +:10813000156094F85C01F9F7B6FC84F85CB1694607 +:108140000720F7F742FC002818BFFFDF12E068465F +:10815000F7F719FC0028C8D011E0029800281CBFCE +:1081600090F80C11002905D00088A0F57F41FF3957 +:10817000CAD104E06846F7F706FC0028EDD089F87C +:10818000038087F80B8003B00020BDE8F08F70B546 +:108190000446374890F80004364D400995F800141D +:1081A0004909884218BFFFDF95F8140D400932498C +:1081B00091F800144909884218BFFFDF2B490020BD +:1081C00001220C7188700A704870C87026490870C6 +:1081D000BDE870405AE72549087070472DE9F8431B +:1081E000214C06462078002877D12448F9F700FC76 +:1081F0002073202871D003276660277000256572E0 +:108200002572AEB1012106F1FC00FAF7C1FB062090 +:10821000F7F7FAFB80460720F7F7F6FB96F8FC1015 +:108220004044B1FBF0F200FB1210401C86F8FC0049 +:10823000F9F732FC1249091838BF40F2F65000F540 +:108240009C7086B2FCF7B2F9E061FCF7D5F94FF00B +:10825000010817E0300E0020445B0100FC660100BD +:108260001C380100920F0200080E0020DC000020E4 +:1082700001E000E00BE000E019E000E0177C010005 +:108280000AFAFFFF40B384F80A8001216846FAF732 +:108290000AFB9DF8000042F210710002B0FBF1F2FF +:1082A00001FB12000644F9F71DFC3146F9F729F9E4 +:1082B000A061277567752574207B04F11001F9F71B +:1082C00002FE002808BFFFDF25840020FCF790FC99 +:1082D0000020BDE8F88300E002E00C20BDE8F88350 +:1082E000F9F700FC3146F9F70CF9A061A57284F8A2 +:1082F0000B80DEE7FC4948707047FC4810B5417AB6 +:108300000124002918BF002408D1C17A31B1406A84 +:10831000F749884284BF0024FCF764FC204610BD66 +:1083200070B5F14C0546E088401CE080D4E90201BC +:108330006278D5F86061002A1CBF324606F091F8D9 +:10834000A060864208D895F80C01012804D0E07896 +:10835000002804BF012070BD002070BD70B5054627 +:10836000012908BF002408D0022908BF012404D035 +:1083700003291ABFFFDF0024032440F2E2404543F3 +:108380002046FBF79BFB012C08BFDA4907D0002CE5 +:1083900008BFD94903D0032C0CBFD849D849084499 +:1083A0004AF2531108444FF47A71B0FBF1F000F532 +:1083B0004C7085428CBF281A002070BD2DE9F04317 +:1083C00083B00026044680F8206190F8DE00002883 +:1083D00007BF94F80C01032803B0BDE8F083F9F758 +:1083E00081FBD4F8502101461046F9F763FF0028BD +:1083F000DCBF03B0BDE8F083628840F27123D4F89B +:1084000014115A43C1EB4201B0FBF1F0411CB4F826 +:1084100058000144A4F81C11B4F8D410B4F81C217D +:10842000891A09B20029DCBF03B0BDE8F08301213D +:1084300084F82211B4F87E10B4F87C20B14F891A68 +:10844000491E084485B2DFF8A0820DF108091EE03C +:1084500098F8000037F81000CDE90069B4F81C2145 +:1084600094F86C11012337F81110084481B22046AA +:10847000FFF7C4F8002804BF03B0BDE8F08301286B +:108480000FD0022812BFFFDF03B0BDE8F083B4F8BD +:108490001C01281A00B20028BCBF03B0BDE8F0835D +:1084A000D6E7B4F81C01BDF808100844A4F81C0174 +:1084B000EDE770B58C4E934B0025327882B04FF0CB +:1084C000040C06295CD2DFE801F0073B03181840D2 +:1084D000044680F80CC106E00446F078002818BF76 +:1084E00084F80CC10BD0F9F708FAA4F85A51B4F883 +:1084F0005800A4F81E0184F8225102B070BD33F870 +:10850000120094F80C210121032A13BF94F80C21C6 +:10851000C4F80851C4F80051012AE4D1CDE900158E +:1085200094F86C11B4F8D42033F8111000230844E7 +:1085300081B22046FFF762F8002818BFFFDFD2E7BC +:10854000032180F80C1102B070BD33F8121090F8BE +:108550006C21B0F802C033F8122011440A04120C46 +:108560004FF0000105D002FB0CF1674AB1FBF2F1BC +:10857000491C8AB2816A02B0BDE87040FEF7DCBFD8 +:10858000FFDF02B070BD2DE9F043584C0327564E73 +:10859000E27AA17A83B042F21079002558B101281D +:1085A00036D002281EBFFFDF03B0BDE8F0834FF0D6 +:1085B00000081AB9ACE04FF000080AB1E5721FE0FC +:1085C00051B101216846FAF792F99DF800000002C6 +:1085D000B0FBF9F109FB1108FCF70EF800EB0801FC +:1085E000A069F8F78EFFA06125746775607A30B9CD +:1085F000207B04F11001F9F766FC002873D0258474 +:10860000F9F77BF9307903B0BDE8F043F1F7F8BD35 +:10861000E572D4F818802570012727720021606860 +:1086200005F01CFB606880F8825180F88351C0F827 +:108630005081217B80F85C11616AC0F85481C0F8D8 +:10864000601190F85C81B0F80090B8F1200F28BF5D +:10865000FFDF2E4820F81890646884F80C51A4F8C5 +:108660005851DFF8A080307894F86C11628838F89F +:10867000100038F8111008440104090C4FF00000F4 +:1086800005D001FB02F02049B0FBF1F0401C82B2A2 +:108690002046A16AFEF750FF00950195307894F8C6 +:1086A0006C11002338F8100038F811101A460844ED +:1086B00081B22046FEF7A2FF002818BFFFDFC4F8F2 +:1086C0000851C4F8005184F80C71A4F81E51A4F8A4 +:1086D0001C5184F82251B4F85800401EA4F85800E8 +:1086E000A4F85A518CE735E0DC000020080E002089 +:1086F000CF821300FC660100445B01001C380100BE +:108700002C5F0100920F020040420F00300E00204B +:1087100051B101216846FAF7EAF89DF8000000021D +:10872000B0FBF9F109FB1108FBF766FF00EB08014C +:10873000A069F8F7E6FEA06125746775607A0028E5 +:108740007FF45DAF207B04F11001F9F7BCFB00283A +:108750007FF455AFFFDF52E770B5314CA1780229A5 +:1087600006BFE188002970BD2569C5F8640195F848 +:108770005200012808BF002007D0022808BF0120AE +:1087800003D003281CBFFFDF0020FBF770F9D5F8EA +:108790006411081AA1680144A160E1680844E0601E +:1087A00070BD70B505461E4890F802C0BCF1020FBE +:1087B00006BF006900F5B0741A4C002904BF25609B +:1087C00070BD4FF47A7601290DD002291CBFFFDF5E +:1087D00070BD1046FBF75DF900F2E140B0FBF6F02A +:1087E000281A206070BD1846FBF7DCFC00F2E1405F +:1087F000B0FBF6F0281A206070BD0B480078002806 +:108800001CBF0020704710B50720F7F7EFF880F085 +:10881000010010BD04480078002818BF01207047EF +:10882000DC0000202C0E0020080E002010B584B0C3 +:1088300004466846FBF74EFD002808BFFFDF00989E +:1088400006F0ADF90321009806F0C0F90098017810 +:1088500021F010010170214606F035FA192C80F044 +:108860002F81DFE804F03A2A0D65FEFEFD1C9FFE15 +:10887000FDFD88FEFEFEFEFCFDFDADCBE9FEFB002E +:10888000F748806890F8F110009806F0A1FAFBF71D +:1088900034FD00281CBF04B010BD00F0FDB8F04846 +:1088A000806890F8C910009806F0E2FAFBF725FD01 +:1088B000002840F0298100F026B9E9488068D0F806 +:1088C000FC00411C009806F074FAFBF716FD002826 +:1088D0001CBF04B010BD00F0DFB8E14CA068D0F8B8 +:1088E000F8008179009806F038FAA068D0F8F8000E +:1088F0000189009806F02AFAA068D0F8F8004189AA +:10890000009806F00EFAA068D0F8F8008189009867 +:1089100006F00EFAA068D0F8F800C189009806F0B9 +:108920000EFAFBF7EAFC00281CBF04B010BDB3E050 +:10893000CB4CA068D0F8F800011D009806F04CFA66 +:10894000A068D0F8F80000F10C01009806F04EFA8B +:10895000A068D0F8F80000F11E01009806F04CFA6B +:10896000A06800F1C001009806F054FAFBF7C5FCBE +:10897000002877D1C5E0BA4C60690178009806F00C +:1089800061FA60698188009806F05EFA6069418842 +:10899000009806F05DFAFBF7B0FC00281CBF04B09D +:1089A00010BD79E0AF49D1E90001CDE9020102A98A +:1089B000009806F061FAFBF7A0FC002852D1A0E075 +:1089C000A74CA068B0F84410009806F05FFAA068C1 +:1089D000B0F84610009806F05DFAA068B0F84010B4 +:1089E000009806F05BFAA068B0F84210009806F014 +:1089F00059FAFBF782FC002879D182E0984CA068F4 +:108A0000B0F84010009806F049FAA068B0F842109B +:108A1000009806F047FAA068B0F84410009806F0F5 +:108A200035FAA068B0F84610009806F033FAFBF764 +:108A300064FC002868D166E0894CA06890F81511A4 +:108A4000009806F056FAA06890F81611009806F003 +:108A500054FAFBF752FC002849D152E003E01EE033 +:108A60002FE02DE043E07E4CA06890F8040105F073 +:108A700065FE0146009806F044FAA06890F80501EA +:108A800005F05CFE0146009806F03FFAFBF735FC66 +:108A900000281CBF04B010BDFFDF04B010BD704C37 +:108AA000A06890F8ED10009806F053FAA06890F8CE +:108AB000EC10009806F051FAFBF71FFC20BB22E0F7 +:108AC000FFDFFBF71AFC002808BFFFDF0C2C19BFE3 +:108AD000132C182C04B010BD112C1CBF072C152C06 +:108AE00012D0012C19BF002C022C04B010BD0021A3 +:108AF0005B488068A0F88210012180F8861004B0DD +:108B000010BDFFDFF3E7FFDF554900208968A1F8BA +:108B1000880004B010BDF0B45148806890F84E3021 +:108B2000478EC68E458FB0F84010C28FB0F842C055 +:108B3000022B1FD08D4238BF29460186624528BFCF +:108B400062468286018FB0F84430994238BF0B46A6 +:108B50004386818FB0F84640A14238BF0C46C48698 +:108B6000BB4228BF1F464786B44228BF2646C6865A +:108B7000F0BC7047038E9D4228BF1D46838E9A42EB +:108B800028BF1A46A94298BF0D460586944598BF4E +:108B900062468286002180F84E10D3E770B5304CD3 +:108BA00082B0207910F0010F04BF02B070BD2069BF +:108BB00000230521C578A06890F86320583005F09F +:108BC000D1FB002818BF022D0CD00B2D18BF042D8F +:108BD00008D0052D1CBF062D0D2D03D0607840F068 +:108BE00008006070607800281CBF02B070BD20696A +:108BF000C078801E162880F0F683DFE810F016009B +:108C0000F403B700D5002E013500F403F001F4039E +:108C1000AD007801F000F403F403F403F4035F0201 +:108C200046027A02E4023703B003A0680023012160 +:108C300090F86520583005F095FB002840F0EE8351 +:108C4000206906F0C7F8A16881F8F200022081F8D7 +:108C50006500002081F88A0081F8860000F0DEBB04 +:108C6000F8000020AC0F0200A0680921002390F852 +:108C70006320583005F076FB20B1206906F0FAF841 +:108C8000122814D0A0680A21002390F863205830DD +:108C900005F068FB20B1206906F0ECF8142821D01B +:108CA000206906F0E7F8162840F0B88342E0A06893 +:108CB0000125002390F863200921583005F052FB6C +:108CC000002808BF657000F0A9836078002840F094 +:108CD000A583A16881F87A0081F8860081F8630095 +:108CE00000F09CBBA0680021012580F86310A0F86B +:108CF000821080F886100421FEF765FAA06890F8CB +:108D00004E10012900F0AE820288A0F82221028EC6 +:108D1000A0F82421828EA0F82621428E00F58C71C5 +:108D2000A0F82821C08E48820D72E078F1F768FA29 +:108D300000F074BBA06890F863101D2940F06E83AA +:108D4000002180F8981080F8631080F886101A20AF +:108D500001F06DF800F062BBA06890F863100C2978 +:108D600047D1002180F867100F2134E0A06890F807 +:108D7000631010293DD1D0F8F8100088498881424D +:108D800018BFFFDFA068D0F8F80000F126012069C5 +:108D900006F04DF8A06800F1C401206906F04FF814 +:108DA0001320A16800F086B9A26892F86300132826 +:108DB0001FD1D2F8F80002F1B00300F11E01002229 +:108DC0000E3005F064FAA0680021C0E928110121E5 +:108DD00080F86710152180F8631000F01FBBA068B1 +:108DE00090F86310132912BF102990F88C00002806 +:108DF00002D0022000F053BA206906F037F8A168CB +:108E0000002581F8C80081F88B5081F88650D1F890 +:108E1000F80009884088884218BFFFDFA068D0F8B2 +:108E2000F8100D70D0F840110A78002A18BFFFDF43 +:108E300040F026810288CA80D0F8402190F8C810FE +:108E40001171D0F840110D72D0F840210C21117031 +:108E5000D0F840210188518040E0A06890F863106C +:108E60001829C6D1002580F88B5080F88650D0F89C +:108E7000F81000884988814218BFFFDFA068D0F849 +:108E8000F8100D70D0F840110A78002A18BFFFDFE3 +:108E900040F0F68090F88C207AB180F88C500288EF +:108EA000CA80D0F840110D71D0F840210D21117009 +:108EB000D0F840210188518010E00288CA80D0F8A3 +:108EC00040110D71D0F8402101211172D0F84021DC +:108ED0000C211170D0F84021018851800088F6F7EC +:108EE000F4FEF6F71BFCE078F1F78AF9C8E0A06819 +:108EF0000023194690F86420583005F033FA50B931 +:108F0000A0680023082190F86320583005F02AFA61 +:108F1000002800F029826078002840F07F82A06855 +:108F200090F88E0010F0020F17D1206905F094FF21 +:108F3000A16881F88F00206905F090FFA168A1F871 +:108F40009000206905F08DFFA168A1F8920091F8CA +:108F50008E0040F0020081F88E00A06890F88E101C +:108F600011F0010F15D190F86420002319465830F4 +:108F700005F0F8F9002808BFFFDF0121A0680422EE +:108F800080F8641080F8F42080F88A100021A0F89E +:108F90008810A06890F86310012907D1002180F89B +:108FA000631080F88610E078F1F72AF9A168D1F80B +:108FB000F800098842888A4204BF0178042940F0F9 +:108FC0002D8200250570E078F1F71AF9A06890F875 +:108FD0006310002908BF80F8865000F01FBAA0680F +:108FE0000023072190F86320583005F0BBF90028D2 +:108FF00000F0BA816078002840F01082694620694C +:1090000005F072FFA0689DF80020002590F89410EC +:10901000114001F02F0180F8941090F895109DF800 +:109020000120114001F02F0180F8951080F8865042 +:10903000D0F8F81000884988814218BFFFDFA06887 +:10904000D0F8F8100D70D0F840110A78002A18BF37 +:10905000FFDF15D10288CA80D0F840110D71D0F819 +:109060004011009A8A60019ACA60D0F84021072115 +:1090700011700188D0F840014180E078F1F7C0F824 +:10908000A06880F8635000F0C9B9A06800230921E6 +:1090900090F86320583005F065F9002800F06481ED +:1090A0006078002840F0BA81A16881F87A0081F8E0 +:1090B000860000BF81F8630000F0B0B9A06800230B +:1090C000194690F86420583005F04CF9002800F05B +:1090D0004B816078002840F0A181A0680021A0F8B1 +:1090E0008810012180F88A100B2180F8641000F0AC +:1090F00095B9A0680023194690F86420583005F00F +:1091000031F900287DD0206905F0D8FE50B32069E0 +:1091100005F0D0FEA1680887206905F0C7FEA168A8 +:109120004887206905F0C8FEA1688887206905F096 +:10913000BFFEA168C88791F863001A2813BF91F891 +:109140004E00012081F84E00012807D091F8090156 +:10915000002804BF91F80801002813D01C2081F8D2 +:10916000640027E0A0680023194690F86420583076 +:1091700005F0F8F800286FD06078002800F03F81F3 +:1091800000F04CB91B2081F864000A88A1F82E2158 +:109190000A8FA1F830214A8FA1F832218A8F01F578 +:1091A0008C70A1F83421C98FC18301210175E07849 +:1091B000F1F726F8A0680021A0F88810012180F8B6 +:1091C0008A1000F02BB9A06800230A2190F86320D0 +:1091D000583005F0C7F8A0B1206905F06FFEB8B1AE +:1091E000206905F067FEA1680887206905F05EFE2A +:1091F000A1684887206905F05FFEA168888720691B +:1092000000E02AE005F054FEA168C887FFF783FC60 +:10921000A068002180F8861080F863100421FDF713 +:10922000D2FFA06890F84E1001291BD00288A0F848 +:109230002221028EA0F82421828EA0F82621428EBF +:1092400000F58C71A0F82821C08E48820120087298 +:10925000E078F0F7D5FFE1E04AE0607840F0010007 +:109260006070DBE0022180F84E10D7E0A068002398 +:10927000194690F86420583005F074F8C0B3A0681F +:1092800090F863201D2A0CD000230B21583005F0E4 +:1092900069F800281CBF607840F0200011D0607091 +:1092A000BCE0232180F8EC10162280F8ED20172175 +:1092B00080F86410012180F88A100021A0F888103D +:1092C000ACE0A06890F8630005F09DFA88B1A06852 +:1092D0002A22162180F8EC2080F8ED10172180F862 +:1092E0006410012180F88A100021A0F8881095E010 +:1092F0003AE0206905F0FFFD00F0070060F3070584 +:10930000206905F0FCFD00F0070060F30F25A06860 +:109310000122002680F88A20A0F888601E2280F8AA +:109320006420B0F84F20ADF80420B0F85100ADF83B +:1093300000002946019805F00AFA9DF80020C1B204 +:109340008A4219BFA26882F80411A16881F80461F9 +:109350009DF80110C0F3072081423CD13FE0A06896 +:1093600090F863001D2801D0012098E7206905F0DE +:10937000C2FD00F0070060F30705206905F0BFFD9E +:1093800000F0070060F30F25A0680121002680F897 +:109390008610A0F88260202180F86310B0F81511C3 +:1093A000ADF80410B0F85100ADF80000294601985E +:1093B00005F0CDF99DF80020C1B28A4219BFA2681C +:1093C00082F80411A16881F804619DF80110C0F3CE +:1093D0000720814203D0A16881F805011EE0A06842 +:1093E00080F805611AE0A0680023194690F864200F +:1093F000583004F0B7FF0028B6D0607870B9206903 +:1094000005F08DFCA16881F8C900052081F8640091 +:109410000020A1F88800012081F88A00A068D0E926 +:109420002A12491C42F10002C0E92A1202B070BDA2 +:109430002DE9F047FD4D04464FF0000768780843DA +:109440006870287910F0200F2846806818BFA0F8AF +:109450007C7004D1B0F87C10491CA0F87C1090F806 +:109460006810012639B990F863200023062158308E +:1094700004F078FF58B3A88810F4006F07D0A868EC +:1094800090F86810002918BFA0F874701FD1A86860 +:10949000B0F87410491C89B2A0F87410B0F87620A6 +:1094A0008A422CBF511A00218288521D8A4228BF4D +:1094B00080F87A60B0F87410B0F87620914206D344 +:1094C000A0F8747080F81E61E878F0F799FE2879AA +:1094D00010F0600F08D0A86890F8661021B980F8E5 +:1094E00066600121FDF76FFE4FF00808002C47D1A0 +:1094F0006878002842D1287910F0040F0DD0A868B0 +:1095000090F86300052808BFFFDFA86890F8651091 +:10951000022904BF2E7080F8657000F020FF2879C2 +:1095200010F0080F0AD0687840B9A86890F8651064 +:10953000032903D10221297080F86570FFF72EFB03 +:10954000A87810F0080F16D0A8680023052190F81D +:109550006320583004F006FF50B185F80180A868F8 +:10956000D0F8401108780C2808BF0020087002E0ED +:10957000002003F071FBA86800F07AFE00F08BFC7D +:10958000A868A14600F1580490F8F00030B9627B59 +:1095900000230121204604F0E5FE10B1208D401C7F +:1095A00020853D21B9F1000F18D12878022808BF85 +:1095B00016200ED0012804BFA86890F8F20008D049 +:1095C0006878E8B110F0140F1CBF1E20A07602D0FE +:1095D00005E0A07603E010F0080F02D0A1766676D1 +:1095E00041E010F0030F03D02A20A07666763AE01F +:1095F00010F0200F08BFFFDF2320A076667632E050 +:1096000094F82E0028B1608D411C6185A18D88429F +:1096100013D294F8320028B1208E411C2186A18DEE +:1096200088420AD2218DE08C814203D3AA6892F845 +:10963000F02012B9A28D914203D32220A076667643 +:1096400011E0A17B31B1A18C814228BF84F81A803E +:10965000C5D206E0A08C062803D33E20A07666760D +:1096600001E0607E58B1E7722773A7730221A868F2 +:10967000FDF7A9FDE878BDE8F047F0F7C1BDA8689F +:10968000BDE8F0470021FDF79EBD68494A788B7818 +:109690001A430ED101280AD0087910F0040F04D023 +:1096A000886890F86500022803D001207047FDF714 +:1096B00076BD0020704770B55C4C05460E46A0880C +:1096C0002843A08015F0020F04D015F0010F18BF39 +:1096D000FFDFE66015F0010F18BF266115F0020FDD +:1096E00012D0304605F01BFB062802D00B283BD0D9 +:1096F0000AE0A06890F86310152905D10021C0E99F +:109700002A11012180F8681015F0800F1CBF082075 +:10971000A07015F4806F08BF70BDA168B1F8580043 +:1097200089880844801D85B2304605F0F8FA012882 +:1097300022D0304605F0F3FA38B3304605F0EFFAA0 +:10974000182818BF70BDA06890F80411002902BF46 +:1097500090F8051100290025A0F806512946304649 +:10976000BDE8704005F0D5BBA06890F863100F29E4 +:1097700008BF0021C8D1C5E7A0682946A0F802515A +:109780003046BDE8704005F01CBBA0682946D0F803 +:10979000F80085803046BDE8704005F0E2BAF8B5C3 +:1097A000224D00260446A860AE806E70AE702E700A +:1097B0000088FAF78CFDA8680088FAF7AEFDB4F8C7 +:1097C000D800A968401C82B201F1580004F06FFC77 +:1097D000002818BFFFDF94F8640021280AD1B4F8EC +:1097E0005810B4F80601081A00B20028A4BF68781F +:1097F000002804D094F8630021283CD118E0A86820 +:1098000090F80411002908BF90F8511080F8511009 +:1098100090F80511002908BF90F8521080F85210F6 +:10982000002000F004FB84F8646024E0F8000020CD +:10983000B4F85810B4F80601081A00B20028A4BF02 +:109840006878002817D1A86890F80411002908BF8B +:1098500090F8511080F8511090F80511002908BFB8 +:1098600090F8521080F85210002000F0E0FA84F8CE +:10987000986084F86360A4F8D860A868374690F8C8 +:10988000861029B1B0F88210B0F8842091422AD213 +:1098900090F88A1029B1B0F88810B0F8842091426D +:1098A00021D2B0F88020B0F87E108A421BD290F806 +:1098B0006620B0F87C00002A47D0884213D2FD48C9 +:1098C0000090FD4BFD4A2146304603F041F8A86860 +:1098D0000023052190F86320583004F043FD002850 +:1098E00018BF02F0ABFDA86890F81211002908BF5C +:1098F000F8BD90F81411002906BF90F898100029BF +:10990000F8BD90F8632000230B21583004F02AFDA5 +:10991000002818BFF8BDA86800230B2190F8642028 +:10992000583004F01FFD002818BFF8BDA8680123B7 +:1099300090F8512090F81511012A09D0022A0AD076 +:10994000032A08BF042908D019E00628CBD2B6E7BD +:10995000012914D101E0022911D190F8522090F888 +:109960001611012A06D0022A07D0032A08BF0429AB +:1099700013D004E0012902D10FE002290DD080F8B4 +:109980009830A86890F8131100291CBFB0F8151181 +:10999000A0F84F1080F81271F8BD002000F047FACF +:1099A000EFE7C748806890F8861029B1B0F88210B8 +:1099B000B0F88420914219D290F88A1029B1B0F8F9 +:1099C0008810B0F88420914210D2B0F88020B0F80E +:1099D0007E108A420AD290F86620B0F87C001AB154 +:1099E000884203D203F0A7B80628FBD30020014623 +:1099F0001EE570B50C46064615464FF4A471204688 +:109A000006F055FF2680002D08BFFFDF2868C4F848 +:109A1000F8006868C4F8FC00A868C4F8400170BD8C +:109A2000F6F72AB92DE9F0410D4607460621F6F76B +:109A300041F8040008BFBDE8F081D4F840110026C9 +:109A4000087858B14A8821888A4207D1082810D05E +:109A50000D281FD00C2835D007284ED094F81E01B1 +:109A600000285CD06E700F20287084F81E616F8013 +:109A700025E06E7008202870D4F840014168C5F8D0 +:109A800002108168C5F8061080896881D4F8400109 +:109A9000067014E00846F6F718F90746F5F754FE85 +:109AA000B8B96E700D202870D4F840014068C5F830 +:109AB0000200D4F8400106703846F5F73FFE012059 +:109AC000BDE8F0810846F6F700F90746F5F73CFED9 +:109AD00010B10020BDE8F0816E700C202870D4F821 +:109AE00040014168C5F802100089E880D4F84001BF +:109AF00006703846F5F722FEE1E76E700720287001 +:109B0000D4F8400141688268C068C5F80210C5F801 +:109B10000620C5F80A00D4F840010670CFE794F893 +:109B20002001C8B16E701420287094F8200100281C +:109B3000C5D000BF84F82061D4F82201C5F8020026 +:109B4000D4F82601C5F80600B4F82A01688194F813 +:109B500020010028EED1B2E794F82C0180B16E709C +:109B60001A20287084F82C61D4F82E01C5F8020060 +:109B7000D4F83201C5F80600B4F8360168819EE7D2 +:109B800094F8180188B16E701820287094F81801A4 +:109B9000002894D084F81861D4F81A01C5F802009E +:109BA00094F818010028F5D189E794F838010028C5 +:109BB00008BFBDE8F0816E701520287094F8380158 +:109BC00000283FF47CAF00BF84F83861D4F83A0134 +:109BD000C5F80200B4F83E01E88094F83801002886 +:109BE000F2D16CE7364A5061D17070472DE9F047E9 +:109BF0000446481E85B238BFBDE8F0870127DFF86C +:109C0000C09004F108084FF0080A0026B4F8D80004 +:109C1000401CA4F8D800B4F87C00401CA4F87C00D8 +:109C200094F8680040B994F863200023062104F1F9 +:109C3000580004F097FBD8B1B4F87400401C80B20F +:109C4000A4F87400B4F8761081422CBF0A1A0022DE +:109C5000A3885B1D934228BF84F87A70884207D39B +:109C6000A4F8746084F81E7199F80300F0F7C8FA3C +:109C700094F8860020B1B4F88200401CA4F8820059 +:109C800094F88A0020B1B4F88800401CA4F8880039 +:109C900094F8F00040B994F865200023012104F104 +:109CA000580004F05FFB20B1B4F88000401CA4F819 +:109CB000800007E0319401008B960100B796010007 +:109CC000F800002094F8630007281FD1B4F858006A +:109CD000411CB4F80201814262D1D4F8FC00411C5D +:109CE000404606F0EEFE0221204604F0F2F884F829 +:109CF000636084F89770D4F8FC000078002808BFEF +:109D0000FFDFD4F8FC000178491E017094F863006D +:109D1000082845D1B4F85800411CD4F8F8008088D0 +:109D200081423DD1D4F840010178002918BFFFDFFE +:109D300022D12188C180D4F8F8004189D4F84001AB +:109D40000181D4F8F8008189D4F840014181D4F828 +:109D5000F800C189D4F840018181D4F8400106712E +:109D6000D4F8400180F800A0D4F840012188418057 +:109D700099F80300F0F744FA0121204604F0A9F80D +:109D800003212046FDF71FFAD4F8F8004188208807 +:109D9000814218BFFFDFD4F8F800067084F86360D2 +:109DA000B4F85800401C691EA4F858008DB2BFF4E6 +:109DB0002DAFBDE8F087FE4AC2E90601704770B5D5 +:109DC0000446B0F87C0094F86610002908BFC0F182 +:109DD000020503D0B4F87E10081A051F94F87A0023 +:109DE00040B194F863200023092104F1580004F0E5 +:109DF000B9FAA0B1B4F8746094F8680058B994F84E +:109E000063200023062104F1580004F0ABFA002877 +:109E100008BF284603D0B4F87600801B001F854297 +:109E2000C8BF0546002DD4BF0020A8B270BD10B534 +:109E3000DF4CA1680A88A1F83C2181F83A0191F829 +:109E40005100012808BF012108D0022808BF0221C3 +:109E500004D003281ABFFFDF00210321A06880F887 +:109E60003E1190F85200012808BF012108D00228B5 +:109E700008BF022104D003281ABFFFDF00210321FD +:109E8000A06880F83F11012180F83811E078BDE822 +:109E90001040F0F7B5B9F8B56846FAF71BFA002894 +:109EA00008BFF8BDC24C6078002818BFF8BDA06894 +:109EB0000023012190F86520583004F053FA00285F +:109EC00018BFF8BDA06890F8F010002918BF022054 +:109ED0004BD190F8632000231946583004F042FA21 +:109EE00038B1A06890F87A0018B11220FEF79EFCF5 +:109EF000F8BDA06890F863200E2A21D00F2A08BF71 +:109F00000B2032D0152A08BF06202ED00025202A8B +:109F10002ED000230421583004F024FA002818BF62 +:109F2000F8BDA0680227012690F8641017297CD09C +:109F300025DC012950D0052948D00B295AD022E030 +:109F4000F8F7D4FC0C2838BFF8BDA0680821D0F879 +:109F5000F8001E30F8F7CBFC28B1A0680421C0300F +:109F6000F8F7C5FC00B9FFDF0320FEF75FFCF8BD82 +:109F70001820FEF75BFCA068A0F88250F8BD1C29F1 +:109F800040D01E297ED0D0F8F8100A78002A7AD066 +:109F900049880288914276D190F8632000231946BF +:109FA000583004F0DFF900286DD0A068D0F8F81020 +:109FB0000978022908BF002066D0032979D0042936 +:109FC00071D0052908BF08207CD0A6E00720FEF745 +:109FD0002DFCA06800F049B90C20FEF727FCA06812 +:109FE000A0F8885090F88E1041F0010180F88E1092 +:109FF00000F03BB91320FEF719FCA068A0F88850C8 +:10A0000000F033B990F80911002918BFF8BD90F895 +:10A01000081199B1B0F80A11A0F84010B0F80C116D +:10A02000A0F84210B0F80E1100E03DE0A0F8441096 +:10A03000B0F81011A0F8461080F80851FEF76BFD3B +:10A040000421A068FDF7BFF8A06890F84E10012920 +:10A0500008BF80F84E7013D00288A0F82221028E2B +:10A06000A0F82421828EA0F82621428E00F58C7162 +:10A07000A0F82821C08E48820E72E078F0F7C0F870 +:10A08000152003E008E048E01CE012E0FEF7CEFBFC +:10A09000A068A0F88850E8E01820FEF7C7FBA06889 +:10A0A000A0F88850F8BD25E01120FEF7BFFBA0689E +:10A0B000DBE090F8671041B190F86800002808BF15 +:10A0C000FFDF0A20FEF7B2FB27E0F8F70FFC0C28B1 +:10A0D00023D3A0680821D0F8F8001E30F8F707FC59 +:10A0E00028B1A0680421C030F8F701FC00B9FFDFF7 +:10A0F0000320E7E790F88E0010F0030F0DD10C203D +:10A10000FEF794FBA068A0F8825080F8866090F873 +:10A110008E1041F0010180F88E106846FAF7DAF8E7 +:10A12000002808BFF8BDA0680023194690F86320F6 +:10A13000583004F017F9002808BFF8BDA06890F85F +:10A140000011B9B3A1690978A1BBB0F858100A2968 +:10A1500034D900F108010522E06906F0E3FA00288D +:10A16000A06804BF80F80051F8BDD0F8FC00017869 +:10A1700061B1411C0522E06906F0D4FA002818BF3D +:10A18000F8BDA068D0F8FC00007830B9A068E1699B +:10A19000D0F8FC00401C06F094FCA068D0F8FC004D +:10A1A0000178491C01700120FEF740FBA06802E025 +:10A1B000F800002002E080F80051F8BD90F8081186 +:10A1C00011B190F8091189B190F89810002908BFD1 +:10A1D000F8BD90F8642000230B21583004F0C2F839 +:10A1E000002808BF16203FF4C0AEF8BDB0F80A1131 +:10A1F000A0F84010B0F80C11A0F84210B0F80E1101 +:10A20000A0F84410B0F81011A0F8461080F80851DA +:10A2100090F864001B2818BF14207FF4A6AEFEF748 +:10A220007AFC0421A068FCF7CEFFA06890F84E10DD +:10A23000012908BF80F84E7013D00288A0F82221AF +:10A24000028EA0F82421828EA0F82621428E00F5ED +:10A250008C71A0F82821C08E48820E72E078EFF74A +:10A26000CFFF1520FEF7E2FAA06880F86450F8BD31 +:10A2700070B5044690F863000025072822D1B4F891 +:10A280005800B4F80211401C884218BF70BDD4F8C1 +:10A29000FC00411C04F1080006F013FC02212046DA +:10A2A00003F017FE84F86350012084F89700D4F877 +:10A2B000FC000078002808BFFFDFD4F8FC0001781C +:10A2C000491E017094F86300082818BF70BDB4F8E7 +:10A2D0005800D4F8F810401C8988884218BF70BD17 +:10A2E000D4F840010178002918BFFFDF22D121886E +:10A2F000C180D4F8F800D4F8401140890881D4F81E +:10A30000F800D4F8401180894881D4F8F800D4F8D6 +:10A310004011C0898881D4F840010571D4F84011FA +:10A3200008200870D4F8401120884880C148C078BF +:10A33000EFF766FF0121204603F0CBFD0321204605 +:10A34000FCF741FFD4F8F80021884088884218BF04 +:10A35000FFDFD4F8F800057084F8635070BD10B5C5 +:10A36000B44C207910F0020F08BF10BD60780028AF +:10A3700018BF10BDE068C078192880F05881DFE868 +:10A3800000F052420D82F8F8992232F86276A4F871 +:10A39000F8F8F8F7D42DE4F9F5F8F400A0680023F4 +:10A3A000012190F86520583003F0DCFF002818BF29 +:10A3B00010BD0321A06880F86510002180F8861088 +:10A3C00080F88A1010BDA0680023194690F8642018 +:10A3D000583003F0C7FF002808BF10BD0020A16857 +:10A3E00081F88A0010BDA0680023194690F8632008 +:10A3F000583003F0B7FF002808BFFFDF0920A1682D +:10A4000081F8630010BDA0680023194690F863200E +:10A41000583003F0A7FF002808BFFFDF0720A1681E +:10A4200081F8630010BDA0680023194690F86320EE +:10A43000583003F097FF002808BFFFDF0820A1680D +:10A4400081F8630010BDA0680023194690F86320CE +:10A45000583003F087FF002808BFFFDF0121A06804 +:10A4600080F88B105FF00C0180F8631010BDA068BD +:10A4700090F863000F2818BFFFDF0121A06880F863 +:10A480008C100E21F0E7A0680023194690F8632095 +:10A49000583003F067FF28B9A06890F88C000028B6 +:10A4A00008BFFFDF0121A06880F88B10102180F821 +:10A4B000631010BDA06890F86300152818BFFFDF77 +:10A4C0001820A16881F8630010BDA068D0F8F810CA +:10A4D00003884A889A4204BF0978042919D190F860 +:10A4E000632000231946583003F03CFF002808BFC2 +:10A4F000FFDFA06890F88E1011F0020F04BF012159 +:10A5000080F8631005D0002180F88610D0F8F8009C +:10A510000170A0680023194690F86420583003F0B9 +:10A5200021FF002808BF10BD58E7A0680023194686 +:10A5300090F86320583003F015FF002808BFFFDFB4 +:10A540000A20A16881F8630010BDA06800231946A5 +:10A5500090F86320583003F005FF002808BFFFDFA4 +:10A560001A20A16881F8630010BD25E00EE001E02B +:10A570004CE05CE0A0680023194690F86420583055 +:10A5800003F0F0FE002808BFFFDF27E7A06890F87F +:10A590009800012818BFFFDFA0680023194690F833 +:10A5A0006320583003F0DEFE002808BFFFDF1D20C7 +:10A5B000A16881F86300D7E7A06890F864101E29AD +:10A5C00012D090F86310202918BFFFDFCCD1B0F86B +:10A5D000061100291CBF212180F863100DD0A1684D +:10A5E000002081F88600BFE7B0F80611002918BFE7 +:10A5F000212180F864100021E2E6002180F8631038 +:10A6000080F898100846FFF712FCE8E7A06890F879 +:10A6100063001D2818BF072802D0082818BFFFDFD5 +:10A620000021A06880F8641080F88A109CE7FFDFA2 +:10A630009AE70000F80000202DE9F041FE4C0646A4 +:10A64000606904F06CFBE168002701F163020125F9 +:10A6500081F8C9004FF0050896420ED105FA00F0C6 +:10A6600010F0807F08BFFFDFE06880F86380A0F80B +:10A67000827080F88650BDE8F08101F16400864266 +:10A680001CBFFFDFBDE8F08181F86480A1F888700D +:10A6900081F88A50BDE8F081F0B4E748C06890F8CE +:10A6A0004E30478EC68E458FB0F84010C28FB0F83E +:10A6B00042C0022B1FD08D4238BF29460186624519 +:10A6C00028BF62468286018FB0F84430994238BF75 +:10A6D0000B464386818FB0F84640A14238BF0C46F6 +:10A6E000C486BB4228BF1F464786B44228BF2646C1 +:10A6F000C686F0BC7047038E9D4228BF1D46838EE0 +:10A700009A4228BF1A46A94298BF0D46058694452D +:10A7100098BF62468286002180F84E10D3E7F0B5DC +:10A72000C54C83B0207910F0010F04BF03B0F0BD19 +:10A73000606901230521C578E06890F864205830ED +:10A7400003F010FE002818BF022D0BD00A2D18BFF1 +:10A750000B2D07D0032D18BF062D03D0607840F0D5 +:10A7600008006070607800281CBF03B0F0BD60690D +:10A77000C078192880F0E483DFE800F04E280DC788 +:10A78000FBFBFAF9F8FBA3BCF7FBFBFBFBF6F5F4CC +:10A79000F3F2F1FBF000E0680123194690F8652020 +:10A7A000583003F0DFFD002840F0C083606904F0FA +:10A7B00011FBE16881F87001022081F8650000203A +:10A7C00081F88A0081F8860000F0B0BBE0680123C0 +:10A7D000002190F86420583003F0C4FD00287DD09B +:10A7E0006078002840F0A283606904F0EEFAE16826 +:10A7F000A1F88401B1F85820801A00B247F6FE7221 +:10A800008242A8BF002853DD01F5C371606904F0DE +:10A81000D3FA0620E16840E0E0680123002190F8C7 +:10A820006420583003F09EFD002857D0607800283F +:10A8300040F07C83606904F09BFA90B3606904F097 +:10A8400094FAE168A1F88401B1F85820801A00B2A6 +:10A8500047F6FE728242A8BF002829DD606904F035 +:10A860007EFAE16881F88601606904F073FAE168B4 +:10A87000A1F88801606904F058FAE168A1F88A013A +:10A88000606904F059FAE168A1F88C01606904F08C +:10A890005AFAE168A1F88E01082081F8640000F0FE +:10A8A00045BBFFE7E0686430FFF7C6FE00F03EBB43 +:10A8B000282081F87200012081F8710000F036BB79 +:10A8C0000CE0E0680123002190F86420583003F088 +:10A8D00049FD18B1607820B100F028BB012000F0DC +:10A8E00088B9E0680021A0F88810012180F88A105A +:10A8F0000D2106E0E06890F864100E2908BF0F21D2 +:10A9000059D180F8641000F011BBE06801230021E8 +:10A9100090F86420583003F025FD20B9E06890F8E5 +:10A920008C000028DAD06078002840F0FF82E068D0 +:10A9300000210125A0F8881080F88A5000F1E80174 +:10A94000606904F060FAE06800F1C001606904F039 +:10A9500065FAE06890F8B40100280BE0EAE1C5E18F +:10A9600074E106E1D5E0ECE059E22CE0A3E069E215 +:10A970001CE0E5E218BFFFDFE0680188A0F8B6112F +:10A9800000F5DC71606904F02CFAE06800F5E07114 +:10A99000606904F02EFAE06880F8B451112180F863 +:10A9A0006410E078EFF72CFC00F0C0BAE06890F893 +:10A9B0006410142902D0022000F01BB9002180F895 +:10A9C0008A1019219DE7E0680123002190F8642096 +:10A9D000583003F0C7FC50B9E0680123082190F813 +:10A9E0006320583003F0BEFC00283FF477AF607856 +:10A9F000002840F09B82E06890F88E0010F0020F73 +:10AA000017D1606904F028FAE16881F88F00606965 +:10AA100004F024FAE168A1F89000606904F021FADA +:10AA2000E168A1F8920091F88E0040F0020081F8F0 +:10AA30008E00E06802E000001801002090F88E10FF +:10AA400011F0010F15D190F8642001230021583036 +:10AA500003F088FC002808BFFFDF0121E068042222 +:10AA600080F8641080F8832180F88A100021A0F813 +:10AA70008810E06890F86310012907D1002180F860 +:10AA8000631080F88610E078EFF7BAFBE06890F882 +:10AA90008211042940F04A82002580F88251E07832 +:10AAA000EFF7AEFBE06890F86310002908BF80F86C +:10AAB000865000F03BBAE0680123002190F8642042 +:10AAC000583003F04FFC00283FF408AF60780028AE +:10AAD00040F02C826946606904F0D3F9E0689DF883 +:10AAE000002090F89410114001F02F0180F894108C +:10AAF00090F895109DF80120114001F02F0180F889 +:10AB000095100021A0F88810012180F88A100921F1 +:10AB1000F7E6E0680123092190F86320583003F03C +:10AB200021FC00283FF4DAAE6078002840F0FE8176 +:10AB3000E16881F87A0081F8860081F8630000F00E +:10AB4000F5B9E0680123002190F86420583003F043 +:10AB500009FC00283FF4C2AE6078002840F0E6818E +:10AB6000E0680021A0F88810012180F88A100B21EC +:10AB7000C7E6E0680123002190F86420583003F014 +:10AB8000F1FB00287ED0606904F098F9002804BF2A +:10AB9000E068643000F02281606904F08BF9E168BC +:10ABA0000887606904F082F9E1684887606904F009 +:10ABB00083F9E1688887606904F07AF9E168C887F9 +:10ABC000207910F0020F03D02069C078142813D028 +:10ABD00091F863001A280FD091F84E0001280ED08A +:10ABE00091F89101002804BF91F8900100280AD043 +:10ABF00005E0607000F09AB9012081F84E001C2039 +:10AC000081F8640018E01B2081F864000A88A1F82C +:10AC1000D4210A8FA1F8D6214A8FA1F8D8218A8F92 +:10AC200001F5D070A1F8DA21C98F8187012180F860 +:10AC30003210E078EFF7E4FAE0680021A0F888101D +:10AC40005FF0010180F88A1000F070B9E06801231C +:10AC50000A2190F86320583003F084FB90B16069BA +:10AC600004F02CF9B8B1606904F024F9E1680887B0 +:10AC7000606904F01BF9E1684887606904F01CF919 +:10AC8000E16800E02EE08887606904F011F9E1686E +:10AC9000C887FFF701FDE068002180F8861080F882 +:10ACA00063100521FDF705FCE06890F84E100129BE +:10ACB00000F029810288A0F8C821028EA0F8CA21DC +:10ACC000828EA0F8CC21428E00F5D071A0F8CE2162 +:10ACD000C08E0886012081F82600E078EFF790FA10 +:10ACE00000F024B9607840F0010082E7E0680123B9 +:10ACF000002190F86420583003F034FB00283FF422 +:10AD0000EDADE06890F8630021283FF4E7AD60788E +:10AD1000002865D1606904F0F2F800F00701E068EE +:10AD200080F86D110021A0F88810012180F88A10A8 +:10AD30001E21E6E5E06890F8641090F863201F2972 +:10AD400002D01D2A32D036E61D2A2FD01F290FBF70 +:10AD500000F16405FFDFE06800F16305606904F05D +:10AD6000DEF858B36169E06803F0A0FC064610F015 +:10AD7000FF0704BFC6F30720002832D0606904F043 +:10AD8000CCF8E168A1F88401B1F85820801A00B22B +:10AD900047F6FE728242A8BF00282FDD81F8867137 +:10ADA000300A81F88701212028702DE01E291CBF60 +:10ADB0001F2900F163053FF4FEADCFE7E06890F88E +:10ADC00063101D2909D1002180F89810302000F06F +:10ADD00077FFE168182081F8CA002846FFF72CFCAD +:10ADE000A4E000212970E06800F1630295420BD1D4 +:10ADF00080F89810002000F063FF05E0282081F81B +:10AE00007200012081F87100E06800F164018D4258 +:10AE10004FF0000118BF80F886104CD112E760692E +:10AE200004F099F8162846D1E06890F863101D29BF +:10AE30007CD1002180F8631080F8981080F886108B +:10AE4000232071E0E0680921012390F86320583045 +:10AE500003F088FA20B1606904F00CF8122813D0CE +:10AE6000E0680A21012390F86320583003F07AFA51 +:10AE700020B1606903F0FEFF14281DD0606903F063 +:10AE8000F9FF162852D142E0E06801252B4690F8E0 +:10AE900063200921583003F065FA002808BF657067 +:10AEA00044D0607838B9E068002180F87A1080F8E2 +:10AEB000861080F8631039E0E0680021012580F8F1 +:10AEC0006310A0F8821080F886100521FDF7F1FAD2 +:10AED000E06890F84E10012915D00288A0F8C8212A +:10AEE000028EA0F8CA21828EA0F8CC21428E00F5F5 +:10AEF000D071A0F8CE21C08E088681F82650E07867 +:10AF0000EFF77EF912E0022180F84E100EE0E068C3 +:10AF100090F863101D2909D1002180F8981080F85D +:10AF2000631080F886101A2000F0CAFEE068D0E9AD +:10AF30002A12491C42F10002C0E92A1203B0F0BDF6 +:10AF4000E0680123002190F86420583003F00AFAE9 +:10AF5000002801BF0120607003B0F0BD60780028B8 +:10AF60003FF4A0AC03B0F0BD30B585B004466846F0 +:10AF7000F9F7B0F9002808BFFFDF009803F00FFED3 +:10AF80000321009803F022FE0098017821F01001BF +:10AF90000170214603F097FEA01E162878D2DFE844 +:10AFA00000F00BAE23AFAF1BAE47AEAF3631AEAE47 +:10AFB000AEAEAFAF5D7892A0FE48C06890F8961034 +:10AFC00021B10621009803F003FF99E090F86F117A +:10AFD000009803F0FDFE93E0F648C06890F8C910B1 +:10AFE000009803F045FF8BE0F24DE86800F1F001B6 +:10AFF000009803F017FFE86800F1C401009803F01F +:10B000001BFF7DE00621009803F02EFF78E0E94D5C +:10B01000A8680178009803F015FFA8688188009857 +:10B0200003F012FFA8684188009803F011FF67E061 +:10B03000002002900390DF48C06890F8941001F05F +:10B04000F5018DF8081090F8950002A900F00900AC +:10B050008DF80900009803F042FF51E0D54DE868F3 +:10B06000B0F84410009803F011FFE868B0F84610FB +:10B07000009803F00FFFE868B0F84010009803F064 +:10B080000DFFE868B0F84210009803F00BFF37E0BE +:10B0900035E0C84DE868B0F84010009803F0FEFEB7 +:10B0A000E868B0F84210009803F0FCFEE868B0F8D9 +:10B0B0004410009803F0EAFEE868B0F846100098E3 +:10B0C00003F0E8FE1CE0BB4DE86890F89D11009885 +:10B0D00003F00FFFE86890F89E11009803F00DFF51 +:10B0E0000EE0B44DE86890F84F10009803F001FFAF +:10B0F000E86890F85010009803F0FFFE00E0FFDFD2 +:10B10000F9F7FBF8002808BFFFDF0C2C12BF072C53 +:10B1100005B030BD122C1CBF142C162C0DD0022CE7 +:10B1200004BF05B030BD0021A248C068A0F8881057 +:10B13000012180F88A1005B030BD9E480021C0680A +:10B14000A0F88210012180F8861005B030BD70B5DE +:10B150000C4605464FF4F871204605F0A8FB258003 +:10B1600070BDF4F789BD2DE9F0410D460746072172 +:10B17000F4F7A0FC040047D094F8A0010026D8B151 +:10B180006E700820287094F8A00188B1268484F895 +:10B19000A061D4F8A201C5F80200D4F8A601C5F850 +:10B1A0000600B4F8AA01688194F8A0010028EDD146 +:10B1B000AE700120BDE8F08194F8AC01002837D0D2 +:10B1C00094F8AC010C2818D00D2818BFFFDF4CD123 +:10B1D0002088F4F77AFD0746F4F7B6FAA0B96E7046 +:10B1E0000D20287094F8AE01A8702088A88084F8FB +:10B1F000AC613846F4F7A2FA37E02088F4F765FD31 +:10B200000746F4F7A1FA10B10020BDE8F0816E7096 +:10B210000C20287094F8AE01A8702088A88094F8BB +:10B22000B201A87184F8AC613846F4F787FA1CE0E3 +:10B2300094F8E40130B16E700F20287084F8E46156 +:10B240006F8012E094F8B40190B16E7009202870FC +:10B2500020886880D4F8B801D4F8BC116860A9606F +:10B26000B4F8C001A88184F8B4610120BDE8F08180 +:10B2700094F8C20140B16E7017202870B4F8C40170 +:10B28000688084F8C261F0E794F8DE0188B16E70DE +:10B290001820287094F8DE010028E6D084F8DE61DA +:10B2A000D4F8E001C5F8020094F8DE010028F5D1D9 +:10B2B000DBE794F8C601C8B16E701420287094F8CA +:10B2C000C6010028D1D000BF84F8C661D4F8C801F7 +:10B2D000C5F80200D4F8CC01C5F80600B4F8D001D6 +:10B2E000688194F8C6010028EED1BEE794F8D20137 +:10B2F00080B16E701A20287084F8D261D4F8D4011D +:10B30000C5F80200D4F8D801C5F80600B4F8DC018D +:10B310006881AAE794F8E601002808BFBDE8F0813B +:10B320006E701520287094F8E60100289DD000BFAB +:10B3300084F8E661D4F8E801C5F80200B4F8EC013D +:10B34000E88094F8E6010028F2D18EE7194A90606F +:10B35000D1707047002180F8631080F8641080F885 +:10B36000661090F8DE1011B10221FDF7A2B803219A +:10B37000FDF79FB82DE9F0470E4C80460D46E0687A +:10B380000088F4F7B4FC060008BFFFDF60782843AC +:10B39000607020794FF0000510F0200FE0681CBFAE +:10B3A000A0F87C5080F8E45008D1B0F87C10491C1B +:10B3B00002E0000018010020A0F87C10E0680127DE +:10B3C00090F8681039B990F86420012306215830AC +:10B3D00002F0C8FF48B3A08810F4006F07D0E068FF +:10B3E00090F86810002918BFA0F874501DD1E068CB +:10B3F000B0F87410491C8AB2A0F87420B0F8761026 +:10B4000091422CBF8B1A0023B4F806C00CF1050C36 +:10B41000634598BF80F87A708A4206D3A0F87450CA +:10B4200080F8E471E078EEF7EBFE20794FF0020946 +:10B4300010F0600F11D0E06890F8661011B1032988 +:10B4400006D00AE080F866700121FDF732F804E0CA +:10B4500080F866900121FDF72CF8E06890F86610FE +:10B46000012905D1A18811F4807F18BF80F866906A +:10B47000B8F1000F7DD1A18811F4007F18BFA0F8AA +:10B48000F85004D1B0F8F810491CA0F8F81000F0FA +:10B490004BFC00F004FE01F0D5FB0028E06818BF6B +:10B4A000A0F8D85004D1B0F8D810491CA0F8D81092 +:10B4B00001F0CBFB40B1E16891F8E40002289CBFA9 +:10B4C000401C81F8E40004D8E06890F8E400022809 +:10B4D00006D9E068A0F8D850A0F8DA5080F8E45017 +:10B4E000E0680123002190F86420583002F03AFF10 +:10B4F00020B9E06890F86400072859D1E06801237A +:10B50000002190F86320583002F02CFF00284FD023 +:10B51000E0680123002190F86520583002F022FFF6 +:10B52000002845D0E06890F86610022904BF90F822 +:10B53000E40000283CD13046F3F78CFEB8B3F8F7AE +:10B5400010FFA0B3E068B0F8D210012930D980F81C +:10B55000DD70B0F87E10B0F87C208B1E9A42AFBF31 +:10B560000121891A491E89B2B0F8D820E3889A428D +:10B5700000E034E02FBF01229A1A521C92B291428D +:10B5800088BF1146012908BF80F8DD5090F8692175 +:10B5900092B1B0F8DA20B0F86A0182422FBF0120E0 +:10B5A000801A401C80B2814288BF014604E0FFE758 +:10B5B000E068012180F8DD50D4F80CC0BCF85820B8 +:10B5C000501880B2ACF8D4009CF86610002918BF5F +:10B5D00001290ED002291CBF0329FFDF0CD0A0884F +:10B5E000C0F340200028E06818BFA0F8E6505FD103 +:10B5F00057E0ACF8D000F2E79CF86510032922D0A0 +:10B60000BCF87C00BCF87E100026821C914206D358 +:10B61000081A801E0604360C1CBF701E86B29CF8E9 +:10B620007A0058B19CF86320012309210CF15800DD +:10B6300002F098FE002808BF00262BD0E06890F8A2 +:10B64000681099B90AE0BCF87C100329D1D3BCF882 +:10B650007E001044401CACF8D000C0E790F8642095 +:10B6600001230621583002F07DFE78B1E268002007 +:10B67000B2F87610B2F87420931C994203D3881A5A +:10B68000801E18BF401EB04238BF86B2002E1CBFBD +:10B69000701E86B2E068B0F8D4103144A0F8D01023 +:10B6A0009DE7B0F8E610B0F8D6201144A0F8E610F7 +:10B6B000E06890F86E1139B990F8652001231946B9 +:10B6C000583002F04FFE38B1E068B0F88010B0F8A2 +:10B6D000D6201144A0F88010E06890F8863033B18D +:10B6E000B0F88210B0F8D6201144A0F8821090F87B +:10B6F0008AC0BCF1000F06D0B0F88810B0F8D62090 +:10B700001144A0F888103D22B8F1000F03D000BF0B +:10B7100080F8722010E02178022910D0012908BF9A +:10B7200090F8701106D06178F1B111F0140F18BFC4 +:10B730001E210BD080F8721080F871704DE090F8E7 +:10B740009610002914BF06211621F3E711F0080F07 +:10B75000DED111F0030F08BFFFDF2A21E06880F877 +:10B76000721080F8717038E02BB1B0F88210B0F828 +:10B770008420914211D2BCF1000F05D0B0F888109E +:10B78000B0F88420914208D2B0F88020B0F87E1042 +:10B790008A4208D390F86E212AB1222180F87210D3 +:10B7A00080F8717019E090F866204AB1B0F87C20FA +:10B7B0008A420FD3082180F8721080F871700CE073 +:10B7C000B0F87C10062905D33E2180F8721080F86D +:10B7D000717002E090F8711079B1E06880F8635000 +:10B7E00080F8645080F8665090F8DE10002914BF8D +:10B7F00002210321FCF75DFE02E00021FCF759FE67 +:10B80000E06880F8DE50BDE8F087FC4902464878E1 +:10B810008B7818430ED10846C0684AB1097911F0F7 +:10B82000080F03D090F86500032803D0012070476B +:10B83000FCF776BD002070472DE9F041EF4C05463E +:10B840000E46A0882843A08015F0020F04D015F002 +:10B85000010F18BFFFDF266115F0010F4FF0000840 +:10B860004FF001071CD03046666103F058FA0628F5 +:10B8700002D00B280BD013E0E06890F86410142974 +:10B880000ED10021C0E9281180F8677008E0E06857 +:10B8900090F864100E2904BF80F8678080F88C70DF +:10B8A00015F0020F18D02069C078052802D00B28A7 +:10B8B0000BD011E0E06890F8641012290CD100213F +:10B8C000C0E92A1180F8687006E0E06890F864101A +:10B8D0000D2908BF80F8688015F0800F1CBF082074 +:10B8E000A070BDE8F0812DE9F047C44C82B000257E +:10B8F00021690191A5806570A5704FF00108257040 +:10B90000E06068F30709074680F8DE800088F4F7F6 +:10B91000EEF95FEA000A08BFFFDFE0680088F8F789 +:10B92000D6FCE0680088F8F7F8FCE068B0F8D200D0 +:10B93000D0B101A8F8F7CEFCB0B1E06890F86E1174 +:10B9400091B190F8652001231946583002F00AFDA4 +:10B9500050B9E068A0F8805080F896500220FFF7B8 +:10B9600003FBE06880F8DD50D4F80CC09CF8DF00E1 +:10B97000002818BFE5800DD19CF8A00138B9BCF8AB +:10B980002000BCF80410884288BFE08002D8BCF8D0 +:10B990000400E080BCF8D600401E86B2BCF8D80097 +:10B9A0003044ACF8D8009CF8DC0000281CBFACF890 +:10B9B000DA508CF8DC5004D1BCF8DA003044ACF832 +:10B9C000DA00BCF87C003044ACF87C009CF86800DD +:10B9D00040B99CF86420012306210CF1580002F0C4 +:10B9E000C1FC28B1E068B0F874103144A0F87410BC +:10B9F000E068B0F8D21001299CBF491CA0F8D21011 +:10BA0000002E18BF80F8E45090F8DD10A1B1B0F816 +:10BA1000D800E18888420FD25046F3F71BFC58B19A +:10BA2000E06890F8691139B1B0F8DA10B0F86A013D +:10BA3000814228BF01F00CF9E26882F8DD5092F8EB +:10BA40006400062818BF072819D1B2F85810B2F8B8 +:10BA50008431C91A09B2002911DB02F5C37102F160 +:10BA6000080005F02EF80221E06802F0F7F8E0681F +:10BA700080F8835180F8645080F8978048E021284E +:10BA800020D1B2F85800B2F88411401A00B2002850 +:10BA900018DB92F88601002808BF92F8510082F85E +:10BAA000510092F88701002808BF92F8520082F8EE +:10BAB0005200002000F004F9E06880F8835180F81B +:10BAC000645025E092F86300212821D1B2F8580093 +:10BAD000B2F88411401A00B2002819DB92F88601EE +:10BAE000002808BF92F8510082F8510092F88701AF +:10BAF000002808BF92F8520082F85200002000F09F +:10BB0000DFF8E06880F8985080F8835180F863503F +:10BB1000E16801F15800B1F8D62002F0C8FAE068F7 +:10BB200090F86911002918BFA0F8DA503448009045 +:10BB3000344B354A3946484600F00AFFE068012395 +:10BB4000052190F86420583002F00CFC002818BF42 +:10BB500000F074FCE0680123072190F8642058305D +:10BB600002F000FC002818BF0C203AD000F06AFC5C +:10BB7000E06890F89A11002904BF02B0BDE8F08790 +:10BB800090F89C11002907BF90F89810002902B086 +:10BB9000BDE8F08790F8632001230B21583002F0B4 +:10BBA000E1FB00281CBF02B0BDE8F087E06801237C +:10BBB0000B2190F86420583002F0D4FB00281CBF01 +:10BBC00002B0BDE8F087E06890F8512090F89D1130 +:10BBD000012A1BD0022A1CD0032A08BF04291AD02C +:10BBE0002BE0E0680123082190F86420583002F02F +:10BBF000B9FB002818BF0820B8D1B9E71801002008 +:10BC000075B301000BB8010039B80100012914D146 +:10BC100001E0022911D190F8522090F89E11012ADA +:10BC200006D0022A07D0032A08BF042915D004E051 +:10BC3000012902D111E002290FD080F89880E06834 +:10BC400090F89B1100291CBFB0F89D11A0F84F106F +:10BC500080F89A5102B0BDE8F087002000F030F87B +:10BC6000EDE700F068BF10B50446B0F88A214388BC +:10BC7000B0F88C11B0F88E019A4201BFA3889942A6 +:10BC8000E38898420FD02388A4F8A431A4F8A62111 +:10BC9000A4F8A811A4F8AA01012084F8A001FC4886 +:10BCA000C078EEF7ADFA0121204601F0D7FF002061 +:10BCB00084F8830184F86400032084F8660010BDD2 +:10BCC00010B5F34CE1680A88A1F8EA2181F8E8018F +:10BCD00091F85100012808BF012108D0022808BFAF +:10BCE000022104D003281ABFFFDF00210321E068EE +:10BCF00080F8EC1190F85200012808BF012108D00B +:10BD0000022808BF022104D003281ABFFFDF002148 +:10BD10000321E06880F8ED11012180F8E611E07858 +:10BD2000BDE81040EEF76CBA2DE9F041D84C4FF069 +:10BD300002084FF00005207910F0080F14D0607849 +:10BD400090B9E06890F86410162905D180F88B50FE +:10BD500080F88A5080F8645090F86510032904BF79 +:10BD600084F8008080F86550FEF7D9FCA1884FF078 +:10BD7000010611F0040F4FF0070719D06078B8B929 +:10BD8000E06890F86420062A08BF80F8836108D034 +:10BD9000082A08BF80F8838103D0212A08BF80F8D1 +:10BDA000837190F86520022A04BF267080F86550E0 +:10BDB00011F0020F00F048816078002840F04481C3 +:10BDC0002069C078801E162880F03D81DFE800F0F1 +:10BDD0000BF9646F851EF948F955B97AF9F9F9F943 +:10BDE000E4F8FDF6F5F4E0680123194690F86520C3 +:10BDF000583002F0B7FA002840F02681E0680321AD +:10BE000080F8651080F8865000F0DCB8206903F0F7 +:10BE100031F80646E06890F86410052905D090F8DE +:10BE20006300052818BFFFDF04D0E06890F86300C6 +:10BE300005280AD1E06890F8CA10B14204BF80F822 +:10BE4000635080F8865000F0FF80E06890F864103E +:10BE500005290CBF80F86450FFDF40F0F580B1E0A9 +:10BE6000E06890F86400092818BFFFDFE06880F8F8 +:10BE70008A5080F8645000F0E7B8E06890F86400F9 +:10BE80000D2818BFFFDFE0685FF00E0180F88B60BF +:10BE900080F8641000F0D8B8E06890F864001128C9 +:10BEA00018BFFFDFE068122180F88B60F0E7E068E0 +:10BEB00090F86400122818BFFFDF1420E16881F8B1 +:10BEC0006400C1E0E06890F86400122818BFFFDF4A +:10BED0001620E16881F86400B6E0E06890F864003C +:10BEE000192818BFFFDFE06880F88B5080F88A506F +:10BEF00090F8AC01002818BFFFDFE06890F88C10C4 +:10BF000041B180F88C500188A0F8B01180F8AE5192 +:10BF10000D2107E00188A0F8B01180F8AE5180F83B +:10BF2000B2610C2180F8AC110088F3F7CEFEF3F774 +:10BF3000F5FBE078EEF764F9D4F80C0080F8645073 +:10BF400082E0E06890F8821104290ED0E0680123B5 +:10BF5000082190F86420583002F004FA00281CBF31 +:10BF6000E06880F88A506FD0E8E790F863200123FA +:10BF70000021583002F0F6F9002808BFFFDFE06822 +:10BF800090F88E1011F0020F0EBF80F8636080F8F9 +:10BF9000865080F88251D9E7E0680123002190F8AB +:10BFA0006320583002F0DEF9002808BFFFDF0A20C6 +:10BFB000E16881F8630047E03AE023E015E004E03F +:10BFC0001EE040E080F88A503EE0E0680123002156 +:10BFD00090F86320583002F0C5F9002808BFFFDF51 +:10BFE0001A20E16881F863002EE0E0680123002157 +:10BFF00090F86420583002F0B5F9002808BFFFDF40 +:10C00000E068DFE7E06890F89800012818BFFFDFDC +:10C01000E0680123002190F86320583002F0A2F973 +:10C02000002808BFFFDF1D20E16881F863000BE0F6 +:10C03000E06890F864001E2818BFFFDF1F20E16849 +:10C0400081F8640000E0FFDF207910F0100F08D0C5 +:10C05000607830B9E06890F86410062908BF80F86D +:10C060006470A07810F0080F08BFBDE8F081E068A8 +:10C070000123052190F86420583002F073F948B18B +:10C0800008206070E06880F8AC51BDE8F0810000E5 +:10C0900018010020BDE8F041002000F0DDBDF8B53A +:10C0A0006846F8F717F9002808BFF8BDDB4C607840 +:10C0B000002818BFF8BDE0680123194690F86520F4 +:10C0C000583002F04FF9002818BFF8BDE06800258D +:10C0D00090F86E1129B1A0F8805080F89650022097 +:10C0E00080E090F8632001230021583002F03AF9F3 +:10C0F00078B1E0680123042190F86420583002F000 +:10C1000031F930B9E06890F87A00002818BF1220A1 +:10C1100068D1E06890F86310052910D090F8642089 +:10C1200002270126112A4AD017DC092A08BF092054 +:10C1300058D00BDC012A7DD0052A39D017E0072022 +:10C14000FEF712FFE068A0F88250F8BD0B2A72D00B +:10C150000D2A08BF0B2045D009E0122A45D0192A24 +:10C1600072D01C2A69D01E2A08BF17203AD001239A +:10C170000421583002F0F6F8002818BFF8BDE06836 +:10C1800090F88211002973D090F8632001230021D8 +:10C19000583002F0E7F800286AD0E06890F8821181 +:10C1A000042904BF90F88E0010F0030F7DD0BDE08D +:10C1B0000720FEF7D9FEE068A0F88850F8BDF6F732 +:10C1C00095FB0C2838BFF8BD0821E068F030F6F781 +:10C1D0008EFB28B1E0680421C430F6F788FB00B973 +:10C1E000FFDF0420FEF7C0FEF8BD90F871110129B1 +:10C1F00010D0022918BFF8BD90F88C1000291ABF82 +:10C2000080F8966002200D20FEF7AEFEE06880F810 +:10C210007151F8BD90F8AC11002918BFF8BD00F1BC +:10C22000B00300F1E801002200F5B97002F02FF828 +:10C23000052003E00FE01CE006E021E0FEF794FE9D +:10C24000E06880F87151F8BD0620FEF78DFEE068C9 +:10C2500080F88A50F8BD0C20FEF786FEE068A0F852 +:10C26000885090F88E1041F0010180F88E10F8BDD2 +:10C270005CE01320FEF778FEE068A0F88850C9E083 +:10C2800090F89111002918BFF8BD90F8901199B15C +:10C29000B0F89211A0F84010B0F89411A0F8421034 +:10C2A000B0F89611A0F8441000E031E0B0F8981111 +:10C2B000A0F8461080F89051FEF7EEF90521E068ED +:10C2C000FCF7F7F8E06890F84E10012908BF80F8F5 +:10C2D0004E7014D00288A0F8C821028EA0F8CA219E +:10C2E000828EA0F8CC21428E00F5D071A0F8CE212C +:10C2F000C08E088681F82660E078EDF781FF152072 +:10C30000FEF732FEE068A0F8885080F86450F8BD6F +:10C310000C20FEF729FEE068A0F8825080F88660C5 +:10C3200090F88E1041F0010180F88E106846F7F702 +:10C33000D1FF002808BFF8BDE0680123002190F874 +:10C340006320583002F00EF830B1E06890F8901198 +:10C3500011B190F89111E9B1E0680123002190F842 +:10C360006320583001F0FEFF002808BFF8BDE068E8 +:10C3700090F89810002908BFF8BD90F864200123B8 +:10C380000B21583001F0EEFF002808BF16203FF4C3 +:10C3900029AFF8BDB0F89211A0F84010B0F8941190 +:10C3A000A0F84210B0F89611A0F84410B0F8981117 +:10C3B000A0F8461080F8905190F864001B2818BF30 +:10C3C00014207FF40FAFFEF767F90521E068FCF752 +:10C3D00070F8E06890F84E10012908BF80F84E70A0 +:10C3E00014D00288A0F8C821028EA0F8CA21828E3B +:10C3F000A0F8CC21428E00F5D071A0F8CE21C08EDD +:10C40000088681F82660E078EDF7FAFE1520FEF741 +:10C41000ABFDE06880F86450F8BD00001801002012 +:10C4200030B5F74C05462078002818BFFFDFA5720D +:10C430000020207330BDF24908737047F049012095 +:10C4400048727047EE49C872704770B4ED480121D8 +:10C45000426890F800C0406892F86360154690F812 +:10C46000510002F15803212E1CBF1C7B212C22D02D +:10C4700003231D2E40D01F2C1CBF70BC704700BF73 +:10C48000BCF1000F04BF70BC704795F84FC092F824 +:10C490006D210CEA020212F0040F14BF194612F0CB +:10C4A000010F4CD0032818BF032954D0012818BF0E +:10C4B000012953D04CE0BCF1000F0ED092F8861148 +:10C4C000002904BF70BC7047032818BF032942D05D +:10C4D000012818BF012941D03AE092F8041100293F +:10C4E00004BF70BC7047032818BF032933D001284C +:10C4F00018BF012932D02BE01F2CC1D0BCF1000F96 +:10C5000004BF70BC704792F89D2112F0040F14BF55 +:10C51000194612F0010F08D0032818BF03291AD0BA +:10C52000012818BF012919D012E012F0020F04BF30 +:10C5300070BC704703280ED001280FD008E012F01D +:10C54000020F04BF70BC7047032804D0012805D037 +:10C5500070BC0220704770BC0320704770BC012083 +:10C5600070472DE9F047A74F4FF0000839464FF0CC +:10C5700001094D6895F85210E88E01F086FF95F894 +:10C58000521080B26FF00D02032967D0022907BF55 +:10C590006FF00E0101EB900002EBD00086B268D084 +:10C5A000688EB04238BF0646954C3146606BF2F754 +:10C5B0008DFEDFF854A2E062002819BF84F80280E3 +:10C5C000A06284F80290C4F828A03878786800F156 +:10C5D0005808012000F009FE98F8100000284AD001 +:10C5E00008F15801884891E80E1000F5027989E8B1 +:10C5F0000E10D8F86810C0F82112D8F86C10C0F8E6 +:10C60000251200F58170F7F70AFA387800280CBF78 +:10C610000120002080F001017C480176D8E9141245 +:10C62000C0E90412C4F828A05146E681A0F583723F +:10C63000F6F72BFE95F85200012808BF002208D01B +:10C64000022808BF012204D003281ABFFFDF0022FE +:10C650000222A17B0120F6F726FE11E0B0F5747FDF +:10C6600038BF46469CD35038C11700EB916002EBAF +:10C67000A01086B294E7A06AF7F7D1F9F6F738FE72 +:10C6800001210020F7F75FFB02202070BDE8F08752 +:10C690002DE9F04FDFF86C9183B049464FF0000A66 +:10C6A0004E684FF0010806F1580496F85D00A1F1BC +:10C6B0001407A1F1380570B3012878D0022877D08B +:10C6C000032818BFFFDF74D0686A0823017821F0BF +:10C6D00008010170A27903EAC202114321F00401AA +:10C6E0000170E279042303EA8202114321F0100170 +:10C6F000017094F805A0286BF2F7BAFD0746F7F72A +:10C7000030FEBAF1020F79D0BAF1010F77D0BAF149 +:10C71000030F7DD08DE0FFE7FFF797FE014630461F +:10C7200001F0BCFE1FFA80FBFFF78FFE6FF00D01DA +:10C7300003281ED0022807BF6FF00E0000EB9B00FD +:10C7400001EBDB0080B220D0318E814238BF084639 +:10C75000ADF80400A6F84C003846F7F7E1FDB0B19B +:10C76000696A85F80380AA694FF4806090470320C6 +:10C7700030E0BBF5747F38BF5046E5D3ABF15000D5 +:10C78000C21700EB926001EBA01080B2DCE76A46B2 +:10C7900001A9286BF2F74FFC686210B194F83310CE +:10C7A00041B13846F7F790FD84F805808CE713E037 +:10C7B00016E02EE09DF8001031B9A0F800A080F836 +:10C7C00002A0012102F002FABDF80410686A02F02A +:10C7D000C6FB0220607177E73846F7F775FD73E70F +:10C7E000B6F84C00ADF804006A4601A9286BF2F7D0 +:10C7F00022FC6862002808BFFFDF65E710E012E056 +:10C800003001002068010020700E00207810002008 +:10C810000CE03846F7F784FD002808BFFFDF53E738 +:10C82000B84306D103E0B84303D100E00FB10121C2 +:10C8300000E00021686A027842EA01110170E17BA0 +:10C8400000291CBF6179012937D004F15801F8484B +:10C8500091E80E1000F5027787E80E10A16EC0F87F +:10C860002112E16EC0F8251200F58170F7F7D7F8B4 +:10C8700099F8000000280CBF01210021ED48017645 +:10C88000D4E91212C0E90412A0F583716A6AF6F7BE +:10C89000FCFC96F85100012808BF002208D00228AD +:10C8A00008BF012204D003281ABFFFDF00220222A2 +:10C8B000FB210020F6F7F7FC03E0F7F7B0F8F6F7F6 +:10C8C00017FD99F8000028B1686A007810F0100F81 +:10C8D00005D00CE001210846F7F735FA0AE0D64802 +:10C8E000007810F0100F04BF6879002802D0E878B3 +:10C8F0000028EFD0A87908BB85F8068096F852008A +:10C90000012808BF002408D0022808BF012404D051 +:10C9100003281ABFFFDF0024032496F851000128E2 +:10C9200008BF002007D0022808BF012003D0032839 +:10C930001CBFFFDF00202146F7F7D9F8686A01889D +:10C9400069828078287585F8008003B0BDE8F08F93 +:10C950002DE9F05FB94E8146DDF8288030781C461D +:10C9600017460D4628B9002F1CBF002CB8F1000F48 +:10C9700000D1FFDFC6F82080C6E90674C6E90E952F +:10C9800000247472FF20F072347274713471B471C7 +:10C99000F471AB4FF4703482387805F15808288868 +:10C9A000F3F7A5F930632888F3F78FF97063F7F789 +:10C9B0002BF8F6F7B6FDF7F7F8F805F11100F7F7E1 +:10C9C0000CF805F10D00F6F72EFE387800280CBFA4 +:10C9D00003200120F7F715F898F81800F6F72BFE5A +:10C9E000F7F709F895F85200012808BF002007D092 +:10C9F000022808BF012003D003281CBFFFDF00204E +:10CA0000F7F7DFFB38786FF00D066FF00E0920B3F3 +:10CA100098F81080B5F832A095F85210E88E01F021 +:10CA200034FD81B295F8520003286BD002280EBF66 +:10CA300009EB910106EBD1018CB26CD0A24538BF55 +:10CA40005446B8F1000F1CBF211D8CB2012864D0E0 +:10CA5000022865D0032865D027E098F80F80B5F844 +:10CA600030A0FFF7F2FC0146284601F017FD1FFA3F +:10CA700080FBFFF7EAFC032838D002280EBF09EB41 +:10CA80009B0006EBDB0084B23AD0A24538BF544687 +:10CA9000B8F1000F1CBF201D84B295F85100012889 +:10CAA0003BD002283CD003283CD0FFDF002528469D +:10CAB000F6F722FD29462046F6F7FBFC387870B3DE +:10CAC000786890F86801002818BFF6F75FFD01212B +:10CAD0000846F6F725FE7868D0F8E000F6F7A2FFE2 +:10CAE000FFF73FFDBDE8F05FF6F796BFBBF5747F3B +:10CAF000CBD3ABF15000C11700EB916006EBA01057 +:10CB000084B2C2E7B1F5747F98D35039CA1701EBEC +:10CB1000926106EBA1118CB290E70025C7E703E014 +:10CB20000125C4E70325C2E701210020F6F7F8FD3F +:10CB3000FFF7AEFDD6E770B54148404D05F138012D +:10CB400000784C68002840D094F85100012808BFB4 +:10CB5000002608D0022808BF012604D003281ABFE7 +:10CB6000FFDF0026032694F85200012808BF0021A9 +:10CB700008D0022808BF012104D003281ABFFFDF14 +:10CB80000021032132469620F7F72CF82878022856 +:10CB900018BFFFDF94F85150F6F736FF94F82C00D9 +:10CBA000012808BFF7F7ACF8012D08BF002008D016 +:10CBB000022D08BF012004D0032D1ABFFFDF002083 +:10CBC0000320BDE87040F6F797BC94F852000128A6 +:10CBD00008BF002608D0022808BF012604D0032879 +:10CBE0001ABFFFDF0026032694F85100012808BF72 +:10CBF000002108D0022808BF012104D003281ABF51 +:10CC0000FFDF0021032132469620F7F701F828784C +:10CC1000012818BFFFDF94F85250BDE7074810B550 +:10CC20000078022818BFFFDFBDE8104000F056BBB7 +:10CC3000700E0020781000204501002030010020F7 +:10CC400068010020FE4880797047FD4840797047B0 +:10CC5000FB490120C87170472DE9F0470600F948EB +:10CC6000F74D4FF0010740684FF0000800F15804FD +:10CC7000A86A90F8019018BF012E03D1696B03F0E8 +:10CC80003BFA68706878A0B1012830D0022848D0FB +:10CC900003281CBFFFDFBDE8F087012E08BFBDE8F9 +:10CCA000F087686BF2F723FDA87ABDE8F047EDF74F +:10CCB000A7BA012E08D001224946686BF2F764FB3F +:10CCC000022E08BFBDE8F087D4E91402411C42F1EE +:10CCD0000000C4E91410E079012802D184F807802B +:10CCE00000E0E771A87ABDE8F047EDF789BA012EB8 +:10CCF00008D000224946686BF2F746FB022E08BFB7 +:10CD0000BDE8F087D4E91401401C41F10001C4E9F9 +:10CD10001401E07901280CBF84F80780E771BDE8B1 +:10CD2000F087012E06D0686BF2F7E1FC022E08BFF7 +:10CD3000BDE8F087D4E91401401C41F10001C4E9C9 +:10CD40001401E0790128CCD1C8E72DE9F041BD4FAD +:10CD50004FF000083846A7F138044068012600F17A +:10CD600058052078012818BFFFDFA87850B185F852 +:10CD70000280E670A2694146042090473878002876 +:10CD800018BF2E71606A0321007831EA000004BFE9 +:10CD9000E878002805D1EE70616AE670A269022089 +:10CDA00090470121002000F0BCFA002808BF7C68F1 +:10CDB00003D0BDE8F04100F091BAFFF7D2FB94F840 +:10CDC0005100012808BF002007D0022808BF012019 +:10CDD00003D003281CBFFFDF0020F6F78DFB94F87B +:10CDE0005100012808BF002508D0022808BF0125EE +:10CDF00004D003281ABFFFDF0025032594F8520052 +:10CE0000012808BF002108D0022808BF012104D052 +:10CE100003281ABFFFDF002103212A46BDE8F041A5 +:10CE20009620F6F7DFBE2DE9F84F864E8346304652 +:10CE3000A6F138054068317800F1580A00272878B3 +:10CE40004FF00108B946022818BFFFDF288A40F4D6 +:10CE500000702882002000F0C8F99AF81000BBF199 +:10CE6000000F00F0F880F6F769FAF6F757FA90B974 +:10CE70009AF8100078B1A86A417861B100789AF800 +:10CE80000710C0F3C000884205D185F80480BDE8D2 +:10CE9000F84F00F023BAA86A0188A5F81510807829 +:10CEA000E875288A40F0200028826F713078706819 +:10CEB00058300090746894F82C00012818D1F6F7C7 +:10CEC00015FF2046009901F022FA88B13078002839 +:10CED00070680CBF00F58C7000F5EF702188418000 +:10CEE0000099097A017180F80080A87AEDF788F935 +:10CEF000A86A9AF806100078C0F38000884233D000 +:10CF00003078706800F1580490F85D0040B3022852 +:10CF100044D06771307840B12079394628B1217109 +:10CF200085F80380AA6910209047E07890B1E770F7 +:10CF3000F7F705FA002808BFFFDF082085F803800F +:10CF4000AA6900219047D4E91201401C41F1000177 +:10CF5000C4E91201A07901280CBFA77184F80680EA +:10CF6000288A40F480702882A86A9AF807300178ED +:10CF7000C1F3C0029A4256D13278726801F00301BF +:10CF800002F15804012918BF022939D003291CBF16 +:10CF9000287A40F0040012D0287244E0286BF2F79F +:10CFA00084F8002808BFFFDFD4E91210491C40F1C3 +:10CFB0000000C4E91210A87AEDF722F9A9E7297B4D +:10CFC00019B1C178EA7A91422DD001F020FE98B1D2 +:10CFD00084F80280298A404641F400612982A96AC6 +:10CFE00085F80380AA699047E079012801D1E771AB +:10CFF00019E084F8078016E0287A40F01000CBE7AB +:10D00000407820B3298A41F400612982A97851B976 +:10D01000FB28F1D8687A002808BFC14603D08020D9 +:10D02000AA69002190475946012000F07AF988B397 +:10D030009AF81000002818BFBBF1000F20D003E0C1 +:10D040003001002068010020A87868B118E0E0797C +:10D050000128CED1CBE7002818BFF6F7A8F9288A17 +:10D0600040F040002882DEE7A96AEA8948789042C9 +:10D0700088BF1046C21CE86A03F080FBE86AA86219 +:10D08000B9F1000F1CBF0020FFF7E6FDBDE8F84F27 +:10D0900000F024B930787468B9F1000F1CBF01208A +:10D0A000FFF7DAFDFFF7F4FA9AF81000002818BF2E +:10D0B000BBF1000F0DD0A87858B9A96AEA89487861 +:10D0C000904288BF1046C21CE86A03F057FBE86A2A +:10D0D000A862B9F1000F1CBF0220FFF7BDFD94F854 +:10D0E0005200012808BF002007D0022808BF0120F5 +:10D0F00003D003281CBFFFDF0020F6F7FDF994F8EA +:10D100005200012808BF002508D0022808BF0125C9 +:10D1100004D003281ABFFFDF0025032594F851002F +:10D12000012808BF002108D0022808BF012104D02F +:10D1300003281ABFFFDF002103212A46BDE8F84F6C +:10D140009620F6F765BD2DE9F0410D469549064656 +:10D1500094484C68007894F85220002822D0012A84 +:10D1600008BF002708D0022A08BF012704D0032ADD +:10D170001ABFFFDF0027032794F85100012808BFDA +:10D18000002208D0022808BF012204D003281ABFB9 +:10D19000FFDF002203223B4629463046BDE8F0412E +:10D1A000FBF7FFBA012A08BF002708D0022A08BFF0 +:10D1B000012704D0032A1ABFFFDF0027032794F8B2 +:10D1C0005100012808BF002208D0022808BF012210 +:10D1D00004D003281ABFFFDF002203223B46294662 +:10D1E0003046BDE8F041FAF723B92DE9F047014692 +:10D1F0006C4800246FF00D084568027805F158006E +:10D200006FF00E0909B3077C6E8E95F85210E88E08 +:10D2100001F03BF981B295F8520003284DD0022865 +:10D220000EBF09EB910108EBD1018CB24ED0A642A2 +:10D2300038BF3446002F1CBF211D8CB2012847D0B7 +:10D24000022847D0032847D024E0C77B2E8EFFF763 +:10D25000FCF80146284601F021F91FFA80FAFFF791 +:10D26000F4F803281DD002280EBF09EB9A0008EB42 +:10D27000DA0084B21FD0A64238BF3446002F1CBF4C +:10D28000201D84B295F85100012821D0022821D018 +:10D29000032821D0FFDF00212046BDE8F047F6F744 +:10D2A00008B9BAF5747FE6D3AAF15000C11700EBB4 +:10D2B000916008EBA01084B2DDE7B1F5747FB6D3BE +:10D2C0005039CA1701EB926108EBA1118CB2AEE79D +:10D2D0000021E1E70121DFE70321DDE770B53149F6 +:10D2E00000254C68F6F7AAFCF6F770FCF6F716FB7B +:10D2F000F6F779FBF5F7FCFFF6F764FCF6F78CFB25 +:10D3000094F82C00012808BFF6F7F0FC264C002109 +:10D31000A269208A9047226A217A20799047257055 +:10D3200070BD70B5204C0546002908BF012D05D100 +:10D330006079401CC0B26071012830D8E16928468C +:10D34000884700282BD0E179184839B1012D01BF59 +:10D3500041780029017811F0100F20D0217AF1B91D +:10D3600010490978002918BF002102D0294304D0B0 +:10D3700013E0012D18BF0121F8D10D49097811F0F2 +:10D38000100F04BF007810F0100F08D0E07830B90B +:10D39000A07810B111F0100F01D0002070BD012055 +:10D3A00070BD000068010020300100204501002010 +:10D3B0004201002010B540F2BB11F74803F055FAC6 +:10D3C000F648002141704FF46171418010BD2DE994 +:10D3D000F0410F46064600F0D6FAEF4C102817D061 +:10D3E00004EBC00191F8421111F0010F1CBF0120A4 +:10D3F000BDE8F081617808291FD2617804EBC00094 +:10D40000491C6170012180F842110846BDE8F08195 +:10D410006178082911D22578681C207004EBC508B2 +:10D420003868C8F83C01B888A8F84001102D28BF1A +:10D43000FFDF88F83B612846DFE70020BDE8F08188 +:10D44000D5480178491E4BB2002BB8BF704770B465 +:10D450005FF0000500EBC30191F8421111F0010FDC +:10D460003BD04278D9B2521E427000EBC10282F822 +:10D47000425190F802C00022BCF1000F0BD9841871 +:10D4800094F803618E4202D1102A26D103E0521C87 +:10D49000D2B29445F3D80278521ED2B202708A42B8 +:10D4A0001BD000EBC20200EBC10CD2F83B41CCF820 +:10D4B0003B41D2F83F21CCF83F21847890F800C05E +:10D4C0000022002C09D9861896F8036166450AD116 +:10D4D000102A1CBF024482F80311591E4BB2002BC4 +:10D4E000B8DA70BC7047521CD2B29442EBD8F4E761 +:10D4F0002DE9F0471E4617468846814600F043FA5C +:10D50000A54C0546102831D0A078002100280ED95E +:10D51000621892F80331AB4205D110291CBF1220CA +:10D52000BDE8F08703E0491CC9B28842F0D808285A +:10D5300032D2102D1DD000BF94F80280102208F1C5 +:10D540000100A07004EB081909F10300394600F04E +:10D550008DFE09F183001022314600F087FE04EBB6 +:10D56000080080F803510020BDE8F087A078082863 +:10D5700012D22578681C207004EBC50AD8F8000088 +:10D58000CAF83C01B8F80400AAF84001102D28BFE1 +:10D59000FFDF8AF83B91CFE70720BDE8F08770B442 +:10D5A0007D488178491E4BB2002BBCBF70BC7047D0 +:10D5B00003F0FF0C8178491ECAB2827050FA83F1E1 +:10D5C00091F8031194453AD000EB021400EB0C15CE +:10D5D000D4F80360C5F80360D4F80760C5F80760A5 +:10D5E000D4F80B60C5F80B60D4F80F60C5F80F6075 +:10D5F000D4F88360C5F88360D4F88760C5F8876085 +:10D60000D4F88B60C5F88B60D4F88F40C5F88F4094 +:10D61000841800EB0C0502EB420294F803410CEB7A +:10D620004C0C00EB420285F8034100EB4C0CD2F8A5 +:10D630000B41CCF80B41B2F80F21ACF80F2100EBF5 +:10D64000C10292F8422112F0010F35D190F802C0C8 +:10D6500000220C46BCF1000F0BD9851895F8035138 +:10D660008D4202D1102A27D103E0521CD2B2944538 +:10D67000F3D80178491EC9B20170A1421CD000EB59 +:10D68000C10100EBC402D1F83BC1C2F83BC1D1F8E3 +:10D690003F11C2F83F1190F802C002780021BCF19E +:10D6A000000F09D9451895F8035195420BD110295F +:10D6B0001CBF014481F80341591E4BB2002BBFF639 +:10D6C00077AF70BC7047491CC9B28C45EAD8F3E704 +:10D6D00032494870704731484078704738B14AF253 +:10D6E000B811884203D82D49488001207047002096 +:10D6F00070472A484088704710B500F044F9102858 +:10D7000014D0254A0146002092F802C0BCF1000F57 +:10D710000CD9131893F803318B4203D1102818BF8A +:10D7200010BD03E0401CC0B28445F2D8082010BDF3 +:10D7300019498A78824286BF01EB001083300020AD +:10D74000704715498A78824286BF01EB0010C01CE1 +:10D7500000207047104B93F802C084459CBF002006 +:10D760007047184490F8030103EBC00090F83B3178 +:10D770000B70D0F83C111160B0F84001908001208E +:10D780007047054A114491F8032104490A70026860 +:10D790004A60808808817047A01000207001002036 +:10D7A00010B5F5F721FD002804BFFF2010BDBDE82E +:10D7B0001040F5F73FBDF1498A7882429CBF0020B6 +:10D7C0007047084490F8030101EBC00090F8420153 +:10D7D00000F00100704770B5E84E0024254630780F +:10D7E000002814D906EBC50090F8421111F0010F82 +:10D7F00008D090F83B2100F59E712046631CDCB2F6 +:10D80000F5F7D9FE681CC5B23078A842EAD870781E +:10D81000A04218BFFFDF70BD70B5D84C002635465A +:10D82000A078002812D96019731C90F8030104EB4A +:10D83000C00000F59E7190F83B213046DEB2F5F74E +:10D84000BAFE681CC5B2A078A842ECD8C0B2B042FB +:10D8500018BFFFDF70BD10B5F5F7DDFE58B300242B +:10D86000F5F7DDFEC54A00211378002B23D900BF50 +:10D8700002EBC10C9CF842C11CF0010F17D084428E +:10D880001CBF04F1010C0CF0FF0410D193780020B0 +:10D89000002B0AD902EB000C9CF803C18C4508BF91 +:10D8A00010BD401CC0B28342F4D8102010BD491CEA +:10D8B000C9B28B42DCD8082010BD10B5F5F7ABFE1D +:10D8C000002804BF082010BDBDE81040F5F7A7BE32 +:10D8D000AB4910B5497841B1A84B997829B1C21C20 +:10D8E000D81CF5F71EFC012010BD002010BDA34A76 +:10D8F00001EB410102EB41010268C1F80B21808874 +:10D90000A1F80F01704770B59C4D0024A87800283D +:10D9100098BF70BDC0B2A04212D905EB041010F13F +:10D9200083060DD01021304600F07DFC40B904EB99 +:10D93000440005EB400000F20B113046F6F78FFD76 +:10D94000601CC4B2A878A042E4D870BD0146102281 +:10D950008C4800F08BBC8B48704770B5874D0446EF +:10D96000A878A04206D905EB04101021833000F0FE +:10D970005AFC08B1002070BD04EB440005EB4000E8 +:10D9800000F20B1070BD2DE9F0417C4D06460024DD +:10D9900028780F46002811D905EBC40090F83B11F8 +:10D9A000B14206D10622394600F59E7002F0BAFE59 +:10D9B00038B1601CC4B22878A042EDD81020BDE870 +:10D9C000F0812046BDE8F0816C4910B44A7801EB43 +:10D9D000C003521E4A70002283F8422191F802C00F +:10D9E000BCF1000F0DD98B1893F80341844204D188 +:10D9F000102A1CBF10BC704703E0521CD2B29445E1 +:10DA0000F1D80A78521ED2B20A70824204BF10BC0A +:10DA1000704701EBC00301EBC202D2F83BC1C3F86F +:10DA20003BC1D2F83F21C3F83F218C7891F800C068 +:10DA30000022002C9CBF10BC70478B1893F8033158 +:10DA4000634506D1102A1CBF114481F8030110BCA4 +:10DA50007047521CD2B29442EFD810BC704770B4D9 +:10DA600046490D188A78521ED3B28B7095F803215F +:10DA7000984239D001EB001C01EB031400EB40008D +:10DA8000D4F80360CCF80360D4F80760CCF80760E2 +:10DA9000D4F80B60CCF80B60D4F80F60CCF80F60B2 +:10DAA000D4F88360CCF88360D4F88760CCF88760C2 +:10DAB000D4F88B60CCF88B60D4F88F40CCF88F40D2 +:10DAC00001EB030C03EB43039CF803C101EB43039D +:10DAD00085F803C101EB4000D3F80BC1C0F80BC1BE +:10DAE000B3F80F31A0F80F3101EBC20090F84201FA +:10DAF00010F0010F1CBF70BC704700208C78002C08 +:10DB00000DD90B1893F803C1944504D110281CBFFC +:10DB100070BC704703E0401CC0B28442F1D8087862 +:10DB2000401EC0B20870904204BF70BC704701EB49 +:10DB3000C20301EBC000D0F83BC1C3F83BC1D0F831 +:10DB40003F01C3F83F018C780B780020002C9CBF6C +:10DB500070BC704701EB000C9CF803C19C4506D1DA +:10DB600010281CBF084480F8032170BC7047401C7B +:10DB7000C0B28442EED870BC70470000A0100020F4 +:10DB8000700100205B12002010B50A7B02F01F021A +:10DB90000A73002282758B181B7A03F0010C5B0854 +:10DBA00003F00104A4445B0803F00104A4445B08EF +:10DBB00003F00104A4445B0803F0010464444FEA49 +:10DBC000530C0CF0010323444FEA5C0C0CF00104ED +:10DBD000234403EB5C0300EB020C521C8CF8113065 +:10DBE00090F816C0D2B263448375052AD3D3D8B255 +:10DBF000252888BFFFDF10BD00238383028401EB4B +:10DC0000C202521EB2FBF1F1C183704770B46FF0D3 +:10DC10001F01050C01EA9024012000224FF01F0C87 +:10DC20001146134682EA0506F6430E43B6F1FF3F5E +:10DC300011D004F00106520842EAC63249080CF03D +:10DC4000010664085B1C41EAC6314FEA5C0C162BE6 +:10DC5000E8D370BC704770BC002070472DE9F0031A +:10DC60000A460021032A10D04FF4FA4C002A7CD037 +:10DC7000012A00F0FF80022A1CBFBDE8F0037047B4 +:10DC80000146BDE8F00358307EE7A0F8581080F850 +:10DC90005E1080F85F1080F8631080F8641080F8E0 +:10DCA000651080F8661080F85A1080F85B1080F8D4 +:10DCB0005C1080F85D1080F87110A0F8741080F886 +:10DCC0007A10A0F87C10A0F8821080F88610A0F8D6 +:10DCD000881080F88A1080F86F1080F8701080F833 +:10DCE000671080F8681080F88B1080F88C1080F82E +:10DCF0008E10F52280F89420092280F89520A0F853 +:10DD0000801080F89710A0F8D010A0F8D210A0F8DA +:10DD1000D410A0F8D610A0F8D810A0F8DA1080F827 +:10DD2000DD1080F8DF10A0F8E61080F8E410A0F80D +:10DD3000F810A0F8FA1080F82C1001844FF00108B8 +:10DD400080F8518080F852804FF4486242801B2254 +:10DD5000028742874FF4A473C38783870286428673 +:10DD6000C3868386A0F8442000E045E0A0F8463052 +:10DD7000A0F84020A0F84230A0F84820A0F84A209F +:10DD8000A0F84C2080F8901180F8981080F89A1133 +:10DD900080F8691180F86E1180F87111D0F80D20AB +:10DDA0006FF01F03140C03EA92271F2600231A4664 +:10DDB0004FEA030C83EA0405ED431543B5F1FF3F39 +:10DDC00015D007F001055B0843EAC53306F00105ED +:10DDD00052087F0876080CF1010C42EAC532BCF10A +:10DDE000160FE7D380F86811BDE8F003704780F89C +:10DDF0006881BDE8F0037047A0F8E61080F8DE10F7 +:10DE00004288FE4B1344B3FBF2F3A0F876304BF696 +:10DE10008033A0F87830C488A0F87C10B0F8801067 +:10DE200000F15803514391FBF2F1A0F88010E1009A +:10DE3000B1FBF2F1491C89B201FB02F4A0F87E109B +:10DE4000B4F5C84FC4BF491ED984BCFBF2F1491CCC +:10DE5000998502F5802101F5EE31A1F1010CBCFBA1 +:10DE6000F2F1D983B3F81CC00CFB02F1B1FBF2F163 +:10DE7000998305E7A0F8E61000F158024488B0F84D +:10DE80008A31B0F88E019184118DC0006143B0FBDE +:10DE9000F3F091FBF3F1401C118580B200FB03F11C +:10DEA000D084B1F5C84FC4BF401ED084BCFBF3F092 +:10DEB000401C9085108C03EBC000401EB0FBF3F0BB +:10DEC000D083908B6043B0FBF3F09083BDE8F00308 +:10DED00070470A4630B40021032A0DD04FF4FA4CA3 +:10DEE000002A7ED0012A7BD0022A1CBF30BC70479A +:10DEF000014630BC583047E6A0F8581080F85E1054 +:10DF000080F85F1080F8631080F8641080F8651066 +:10DF100080F8661080F85A1080F85B1080F85C106A +:10DF200080F85D1080F87110A0F8741080F87A10F5 +:10DF3000A0F87C10A0F8821080F88610A0F8881055 +:10DF400080F88A1080F86F1080F8701080F86710E1 +:10DF500080F8681080F88B1080F88C1080F88E1094 +:10DF6000F52280F89420092280F89520A0F88010EE +:10DF700080F89710A0F8D810202280F8DA2080F8D6 +:10DF8000D010C0F8D41080F82C10012280F8512055 +:10DF900080F852201B22028742874FF4A473C38764 +:10DFA000838702864286C3868386A0F84420A0F831 +:10DFB0004630A0F84020A0F84230A0F84820A0F851 +:10DFC0004A20A0F84C2080F8081180F8981080F8BA +:10DFD000121180F8F01080F8001130BC704700E09A +:10DFE00039E04288854B1344B3FBF2F3A0F8763056 +:10DFF0004BF68033A0F87830C488A0F87C10B0F8D5 +:10E00000801000F15803514391FBF2F1A0F8801009 +:10E01000E100B1FBF2F1491C89B201FB02F4A0F866 +:10E020007E10B4F5C84FC4BF491ED984BCFBF2F1C1 +:10E03000491C998502F5802101F5EE31A1F1010C11 +:10E04000BCFBF2F1D983B3F81CC00CFB02F1B1FBAD +:10E05000F2F199834CE7D0F8F84000F15802438878 +:10E060006089E4899184118D594391FBF0F1118508 +:10E07000E100B1FBF0F1491C89B201FB00F4D1844D +:10E08000B4F5C84FC4BF491ED184BCFBF0F1491C94 +:10E090009185118C00EBC101491EB1FBF0F1D183D8 +:10E0A000918B5943B1FBF0F0908330BC7047837D76 +:10E0B0000BB1252B01D912207047002A04BF002084 +:10E0C000704770B490F817C00C7E4D4D04FB02C22F +:10E0D0002C464FF0000CE2FB054C4FEA1C1C6FF085 +:10E0E00024040CFB0422D2B201EBD20CC27502F064 +:10E0F00007059CF808C0012404FA05F51CEA050F81 +:10E1000018BF02762CD1B2FBF3FC03FB1C22521C7D +:10E11000D2B24FF0000C00BF00EB0C035B7C9342CB +:10E120003CBFD21AD2B20ED301EB0C0500232D7ADC +:10E1300004FA03F635421CBF521ED2B26AB15B1C10 +:10E14000DBB2082BF4D30CF1010303F0FF0CBCF19C +:10E15000050FE1D370BC1F20704703EBCC010176A3 +:10E1600070BC00207047274A016812681140264A97 +:10E17000126811430160704730B42449214B0024D8 +:10E180004FF0010C0A78521CD2B20A70202A08BF44 +:10E190000C700D781A680CFA05F52A42F2D009784D +:10E1A00002680CFA01F15140016030BC70470179FE +:10E1B00031F01F0113BF002000221146704710B438 +:10E1C000435C03F0010C5B0803F00104A4445B080A +:10E1D00003F00104A4445B0803F00104A4445B08B9 +:10E1E00003F00104A4445B0803F00104A4445B08A9 +:10E1F00003F00104A4440CEB530309E0FFDB05002A +:10E2000053E4B36EB40F0200B80F02007A0100208D +:10E210001A44491CD2B20529D2DB012A8CBF012045 +:10E22000002010BC704730B40022A1F1010CBCF1F9 +:10E23000000F11DD431E11F0010F08BF13F8012F6D +:10E240005C785FEA6C0C07D013F8025F22435C78BD +:10E250002A43BCF1010CF7D1491E5CBF405C02436C +:10E26000002A0CBF0120002030BC7047130008BFFB +:10E27000704710B401EB030CD41A1CF801CC5B1EE0 +:10E2800000F804C013F0FF03F4D110BC7047F0B5E0 +:10E290008DB0164610251C466A46AC4600EB0C03B2 +:10E2A000A5EB0C0713F8013CD355ACF1010313F0B7 +:10E2B000FF0CF3D115461032102084460B18ACEB3E +:10E2C000000713F8013C401ED35510F0FF00F5D1B4 +:10E2D000284601F0DDFA86B1102005F12002014642 +:10E2E0001318A1EB000C13F8013C401E04F80C308D +:10E2F00010F0FF00F4D10DB0F0BD0898206009982F +:10E3000060600A98A0600B98E0600DB0F0BD38B571 +:10E3100005460C466846F5F7FEFC002808BF38BDE8 +:10E320009DF90020227294F909100020511A48BF6B +:10E33000494295F82D308B42C8BF38BDFF2B08BF2E +:10E3400038BDA17A491CC9B2A17295F82E30994204 +:10E3500003D8617A7F2918BF38BD62720020A0728D +:10E36000012038BD0C2950D2DFE801F006090E1358 +:10E37000161B323C3F4D4248002A48D045E0022A55 +:10E3800018BF032A43D040E0072A18BF062A3ED010 +:10E390003BE0082A3BD038E0A2F10C000D2836D92A +:10E3A00033E023B1A2F10D000C2830D92DE00F2A63 +:10E3B00018BF0E2A2BD090F8340020B10F2A24D396 +:10E3C000182A24D921E0132A1FD3182A1FD91CE0A8 +:10E3D000A2F10C0103291AD990F83400A8B1192A26 +:10E3E00015D912E0092A12D00FE0012A0FD00CE053 +:10E3F0001A2A1CBF1B2A1C2A09D006E0A2F11D0004 +:10E40000042804D901E00A2A01D000207047012025 +:10E4100070472DE9F04187680D4604462046F3F722 +:10E4200004FD98B1D5B13846A168F3F743FF002841 +:10E4300014DD401EB0FBF5F0461C06FB05F1384626 +:10E44000F3F75FF8A0603046BDE8F081F3F74AFBD0 +:10E4500040F22E71F3F755F8A060DFE70020BDE829 +:10E46000F081904228BF704770B50446101B6428A5 +:10E4700038BF642025188D4205D8F3F742FF0028E5 +:10E480001CBF284670BD204670BD032918BF7047C9 +:10E49000B0F5296F38BF4FF4296070470246808E6F +:10E4A000032918BF7047D18E92F85230032B04D144 +:10E4B000B1F5296F38BF4FF42961538840F2E24C1F +:10E4C00003FB0CF3528E4FF4747C0CEB821C8C45D6 +:10E4D0009CBF910101F57471591AA1F5967188429A +:10E4E00028BF0846B0F5296F38BF4FF42960704740 +:10E4F000CA8EB2F5296F38BF4FF42962498E4FF4A6 +:10E50000747303EB811393429CBF890101F574720C +:10E5100091B200280CBF0120002001F6283100280C +:10E5200018BF0420084470472DE9F00191F85160AC +:10E530000A8E4FF47477032E04BF07EB821294B255 +:10E5400006D0022E07BF92003C32D200703294B245 +:10E55000CB8E4D8E8A8E91F852C0032E16D0A242D9 +:10E5600028BF224692B2BCF1030F04BF07EB85110E +:10E5700089B207D0BCF1020F07BFA9003C31E90006 +:10E58000703189B2BCF1030F26D120E01E46BCF1E8 +:10E59000030F04D1B6F5296F38BF4FF429664988B7 +:10E5A00040F2E24801FB08F107EB8518B0459CBF3B +:10E5B000AE0106F57476891BA1F596718A4228BFD3 +:10E5C0000A46B2F5296F38BF4FF42962C7E7B3F5A1 +:10E5D000296F38BF4FF429638B4228BF0B460028B0 +:10E5E0000CBF01210021D0189830002918BF042148 +:10E5F0000844BDE8F001704770B48388B0F808C0E3 +:10E6000003EB0C049834002A18BF042222444C6AFD +:10E61000944224BF70BC7047121B0124521E04EBAD +:10E6200052029B1A9BB2ACEB0202838092B202812F +:10E6300091F851506FF00E06741C4FF0000C032D32 +:10E640001AD0022D0EBF06EB930304EBD3039BB24B +:10E650001DD0438091F8521003291AD002290EBF11 +:10E6600006EB920104EBD2011FFA81FC1BD000BF24 +:10E67000A0F806C070BC7047B3F5747F38BF63461E +:10E68000E7D3503BDD1703EB956304EBA3139BB279 +:10E69000DFE7B2F5747FEBD3A2F15001CA1701EBAB +:10E6A000926104EBA1111FFA81FCE1E7F8B5054680 +:10E6B0000E46084600F027FC0446304600F027FCD2 +:10E6C000014610F0010F18BF012008D111F0020F10 +:10E6D00018BF022003D111F0040018BF03208DF8E9 +:10E6E000000014F0010F18BF012208D114F0020F2E +:10E6F00018BF022203D114F0040218BF03228DF8C0 +:10E70000012011F0070F08BF00208DF8000014F061 +:10E71000070F08BF00228DF8012095F8511088429C +:10E7200008BF00208DF8000095F85200824208BF13 +:10E7300000228DF80120BDF80000F8BD012814BFAB +:10E740000228704703280CBF04200020704718B42B +:10E75000CBB2C1F3072CC1B2C0F30720012B07D005 +:10E76000022B09D0042B08BFBCF1040F23D006E014 +:10E77000BCF1010F03D11EE0BCF1020F1BD0012937 +:10E7800006D0022907D0042908BF042813D004E0CA +:10E79000012802D10FE002280DD001EA0C0161F33B +:10E7A0000702184060F30F22D0B210F0020F18BF1A +:10E7B000022010D106E0084003EA0C01084060F393 +:10E7C0000702EFE710F0010F18BF012003D110F08E +:10E7D000040018BF03208DF80000C2F3072010F0DA +:10E7E000020F18BF022008D110F0010F18BF01203E +:10E7F00003D110F0040018BF03208DF80100BDF80C +:10E80000000018BC7047072816BF08280120002008 +:10E8100070470000282102F028B830B5054600787E +:10E8200001F00F0220F00F0010432870092910D2C8 +:10E83000DFE801F0050705070509050B0D000624B3 +:10E8400009E00C2407E0222405E0012403E00E2463 +:10E8500001E00024FFDF6C7030BD007800F00F0095 +:10E8600070470A68C0F803208988A0F8071070472D +:10E87000D0F803200A60B0F80700888070470A6863 +:10E88000C0F809208988A0F80D107047D0F8092039 +:10E890000A60B0F80D00888070470278402322F0AB +:10E8A000400203EA81111143017070470078C0F300 +:10E8B000801070470278802322F0800203EAC111A1 +:10E8C0001143017070470078C0097047027802F068 +:10E8D0000F02072A16BF082AD0F80520D0F8032017 +:10E8E000C1F809200CBFB0F80920B0F80720A1F842 +:10E8F0000D200A7822F080020A700078800942EA2E +:10E90000C0100870704770B515460E4604461F2AA1 +:10E9100088BFFFDF2A46314604F1090001F02EFFCF +:10E92000A81D607070BD70B544780E460546062C73 +:10E9300038BFFFDFA01F84B21F2C88BF1F242246D0 +:10E9400005F10901304601F019FF204670BD70B590 +:10E9500015460E4604461F2A88BFFFDF2A46314669 +:10E9600004F1090001F00AFFA81D607070BD70B5C8 +:10E9700044780E460546062C38BFFFDFA01F84B240 +:10E980001F2C88BFFFDF224605F10901304601F048 +:10E99000F5FE204670BD0968C0F80F1070470A8860 +:10E9A000A0F813208978417570474176090A81766D +:10E9B0007047C176090A017770474177090A817764 +:10E9C0007047C175090A017670478175704790F8E4 +:10E9D000242001F01F0122F01F02114380F82410AF +:10E9E0007047072988BF072190F82420E02322F0F0 +:10E9F000E00203EA4111114380F8241070471F30F0 +:10EA000002F05FB8C17811F03F0F1BBF027912F01E +:10EA1000010F0022012211F03F0F1BBF037913F0F9 +:10EA2000020F002301231A4402EB4202530011F0AB +:10EA30003F0F1BBF027912F0080F0022012203EBE7 +:10EA4000420311F03F0F1BBF027912F0040F0022A6 +:10EA50000122134411F03F0F1BBF027912F0200F67 +:10EA60000022012202EBC20203EB420311F03F0F2E +:10EA70001BBF027912F0100F0022012202EB4202AA +:10EA80001A4411F03F0F1BBF007910F0400F002017 +:10EA90000120104410F0FF0014BF012100210844A0 +:10EAA000C0B2704710B50278417802F00F02082A10 +:10EAB0002ED2DFE802F004080B2D2D2D0F13881F36 +:10EAC0001F2823D924E00C2920D021E0881F1F28EB +:10EAD0001CD91DE0881F1F2818D919E04B1E242BB4 +:10EAE00016D80024072A18BF082A01D0204610BDD6 +:10EAF000C2789309032BF9D002F03F0C0CF101020C +:10EB00008A42F3D8FFF77EFF6045EFD8012010BDA1 +:10EB1000002010BD0278417802F00F02082A02BFDF +:10EB20000E29C0785FEA901005D0042A05D1062985 +:10EB300003D3252901D8012070470020704710B465 +:10EB4000017801F00F01032920D0052921D1447853 +:10EB5000B0F81910B0F81BC0B0F81730827D222C25 +:10EB600017D1062915D3B1F5486F98BFBCF5FA7FC8 +:10EB70000FD272B1082A98BF8A420AD28B429CBF38 +:10EB8000B0F81D00B0F5486F03D805E040780C28B8 +:10EB900002D010BC0020704710BC01207047222119 +:10EBA00001F063BE00B5027801F0030322F0030216 +:10EBB0001A43027000224270012914BF022900BDCD +:10EBC000032912BFFFDF0121417000BD01F00303E3 +:10EBD00000B5027822F003021A430270002242704C +:10EBE000012914BF022900BD032912BFFFDF012143 +:10EBF000417000BD007800F00300704702781023D8 +:10EC000022F0100203EA01111143017070474178AC +:10EC1000F9B1C078192850D2DFE800F00D101316B2 +:10EC2000191C1F2225282B2E31344F4F4F4C373AB9 +:10EC30003D40434649000C2941D042E008293ED0DE +:10EC40003FE002293BD03CE0172938D039E00D29BC +:10EC500035D036E0012932D033E001292FD030E021 +:10EC600002292CD02DE0092929D02AE0092926D013 +:10EC700027E0012923D024E0012920D021E0062922 +:10EC80001DD01EE002291AD01BE0012917D018E080 +:10EC9000012914D015E0092911D012E009290ED05C +:10ECA0000FE003290BD00CE0032908D009E0052967 +:10ECB00005D006E0032902D003E0FB2901D801209A +:10ECC00070470020704730B50546C170192922D21F +:10ECD000DFE801F00D0F1113151717111919171788 +:10ECE0001B112121211D171719191D1D1F000C248F +:10ECF00013E0082411E002240FE017240DE00D2496 +:10ED00000BE0012409E0092407E0062405E00324C0 +:10ED100003E0052401E00024FFDF6C7030BDC07803 +:10ED20007047C171090A01727047B0F80700704757 +:10ED30004172090A81727047B0F809007047C172C8 +:10ED4000090A01737047B0F80B0070474171090A56 +:10ED500081717047B0F80500704701717047007904 +:10ED600070474173090A81737047B0F80D0070470E +:10ED700030B4B0F807207E4DB0F809C0B0F80530C7 +:10ED80000179941F2D1998BFBCF5FA7F0ED269B195 +:10ED9000082998BF914209D293429FBFB0F80B0057 +:10EDA000B0F5486F012030BC98BF7047002030BCE0 +:10EDB0007047001D01F085BE021D0846114601F096 +:10EDC00080BE4172090A81727047B0F8090070472D +:10EDD00001717047007970470A6842604968816034 +:10EDE000704742680A60806848607047098881817E +:10EDF00070478089088070470A68C0F80E2049680B +:10EE0000C0F812107047D0F80E200A60D0F8120037 +:10EE1000486070470968C0F816107047D0F81600AF +:10EE2000086070470A6842604968816070474268BC +:10EE30000A608068486070470968C1607047C068B0 +:10EE400008607047017170474171090A817170470C +:10EE5000C171090A0172704700797047B0F8050066 +:10EE60007047B0F80700704701717047007970472C +:10EE700001717047007970470A6842604968816093 +:10EE8000704742680A608068486070470171090AEB +:10EE9000417170478171090AC17170470172090A95 +:10EEA000417270478172090AC17270478088704749 +:10EEB000C0887047008970474089704701891B29C5 +:10EEC00024BF4189B1F5A47F07D381881B2921BFC5 +:10EED000C088B0F5A47F01207047002070470A6801 +:10EEE000426049688160704742680A608068486093 +:10EEF00070470171704700797047417170474079E0 +:10EF000070470171704700797047417170474079CF +:10EF100070478171090AC1717047C088704715A296 +:10EF200082B0D2E90012CDE900120179407901F0F6 +:10EF3000070269461DF80220012A07D800F00700E1 +:10EF4000085C01289EBF012002B07047002002B07B +:10EF5000704701717047007970474171704730B553 +:10EF60000C460546FB2988BFFFDF6C7030BD0000F2 +:10EF700086F3FFFF000101020102020370B504469F +:10EF8000C2F11005281901F0F9FB15F0FF0108D0B6 +:10EF9000491EC9B2802060542046BDE8704001F08F +:10EFA00064BC70BD30B505E05B1EDBB2CC5CD55CEB +:10EFB0006C40C454002BF7D130BD10B5002409E0DB +:10EFC0000B78521E44EA430300F8013B11F8013B61 +:10EFD000D2B2DC09002AF3D110BD2DE9F0410C4674 +:10EFE00001200978FF4E92B0154602274FF006081F +:10EFF0004FF0040C71B101291ED0022945D003291C +:10F0000005D12978042902D105201070002012B002 +:10F01000BDE8F081606850B1CDE9010601202070A3 +:10F020008DF80080606A04901146684663E027709E +:10F0300085F800C0566026E029780429E7D1696880 +:10F0400010222069FFF7B9FF6868C07B000606D56B +:10F05000E44A2069102310320146FFF7A3FFD4E9E8 +:10F0600004101022FFF7A9FF2069C07B000606D517 +:10F07000DC4A6069102310320146FFF793FF2770C6 +:10F0800085F800C06E600320C1E729780429BED14D +:10F09000A08910280CD9A0F1100080B2A081A1682D +:10F0A0004FF01003014468466A68FFF77BFF18E0E1 +:10F0B00004D14FF010032269A16807E0C2B20DA885 +:10F0C000A168FFF75BFF626910230DA909A8FFF78C +:10F0D00069FF102309A968466A68FFF763FF0320E8 +:10F0E000207060680590CDF818D08DF81080606AA7 +:10F0F0000890294604A8F1F7FBFF88E72DE9F041C5 +:10F1000007460D4601200B7806213BB1012B04D1A7 +:10F110001378052B01D11170002079E76C69012665 +:10F1200020226170E8686060686A6062A168287C7B +:10F130000870A681A068A968401C01F01FFBA08987 +:10F1400020222030A081A0686968213001F016FBE0 +:10F15000A08921462030A0812E703846BDE8F041BC +:10F16000F1F7DDBF2DE9F05F0D46834601200978F8 +:10F17000174606464FF00608D1B1DFF868A24FF0F7 +:10F180000009AAF1080A012923D002297ED0032907 +:10F190000CD13978052909D179681022E86901F084 +:10F1A000EDFA07203870183500207D60BDE8F09F2B +:10F1B0002C6A8C48202284F8018020306060202056 +:10F1C000A081686A60626968A06801F0D7FA2E7051 +:10F1D000D4E039780529E9D12C6A84F80180686A7D +:10F1E000606251681022E86901F0C8FAE86960605D +:10F1F000A0684F4680F80090A681A0684670A0895C +:10F20000401C80B2A081A1680844696951F8012FAF +:10F21000026089888180A089801D80B2A08169698F +:10F22000A2680978C1F340011154A089401C80B242 +:10F23000A081A1680844296951F8012F02608988DA +:10F240008180A089801D80B2A0812969A268097887 +:10F25000C1F340011154A0891022401C80B2A0814A +:10F26000A1680844E96801F089FAA08910221030E9 +:10F2700080B2A081A1680844A96801F07FFAA08942 +:10F28000103080B2A081A168014400E00DE0DAF8FE +:10F2900004000860A089001D80B2A081A1680F54FD +:10F2A000A089401CA081022067E03978052992D10D +:10F2B00051681022A86901F061FA2C6A84F8018073 +:10F2C000E8696060686A6062A16881F80090A68160 +:10F2D000A0684670A089401C80B2A081A168084443 +:10F2E000696951F8012F026089888180A089801D99 +:10F2F00080B2A0816969A2680978C1F34001115404 +:10F30000A089401C80B2A081A1680844296951F8F5 +:10F31000012F026089888180A089801D80B2A08130 +:10F320002969A2680978C1F340011154A08910220B +:10F33000401C80B2A081A1680844E96801F01EFA6F +:10F34000A0891022103080B2A081A1680844A96869 +:10F3500001F014FAA089103080B2A081A1680144A4 +:10F36000DAF804000860A089001D80B2A081A168BD +:10F370000E54A089401CA0810320287021465846C5 +:10F38000BDE8F05FF1F7CBBE70B50D4606460978D3 +:10F39000012041B1012905D11178052902D10820A8 +:10F3A0001070002070BD2C6A062060706968616072 +:10F3B000696A6162EA69A16852F8013F0B6092884C +:10F3C0008A80A081E869A1680078C0F34000887154 +:10F3D000A089401C80B2A081A1680844A96951F8A5 +:10F3E000012F01E0C40F0200026089888180A0899A +:10F3F000801D80B2A081A969A2680978C1F340018B +:10F400001154A089401C80B2A081A1680844696998 +:10F410000A88028089788170A0891022C01C80B27D +:10F42000A081A1680844296901F0A8F9A0891022E7 +:10F43000103080B2A081A1680844E96801F09EF90B +:10F44000A0891022103080B2A081A1680844A96868 +:10F4500001F094F9A08921461030A0810120287084 +:10F460003046BDE87040F1F75ABE70B50D4606460D +:10F470000978012059B1012908D11178052905D150 +:10F4800009201070506800685060002070BD6C69E1 +:10F49000062010226070E8686060686A606229690E +:10F4A000A06801F06BF91020A081A0682022103024 +:10F4B000A96801F063F9A0892022203080B2A081E0 +:10F4C000A1680844696801F059F9A08921462030F3 +:10F4D000A081012028703046BDE87040F1F71FBEC2 +:10F4E00070B50C46012009788EB01546062659B134 +:10F4F000012934D0022905D12978042902D10A2012 +:10F50000107000200EB070BD606910236A4600784C +:10F51000C0F340008DF80000A0690078C0F34000FF +:10F520008DF80100E0680168CDF802108188ADF81F +:10F53000061080798DF8080020690168CDF809105F +:10F540008188ADF80D1080798DF80F006068059006 +:10F5500009A80690A168FFF725FD01201DE0297884 +:10F560000429CFD1A06910236A4650F8011F0091E9 +:10F570008088ADF80400606950F8011FCDF80610CE +:10F580008088ADF80A00002003906068059009A803 +:10F5900006906968FFF706FD022020708DF8106064 +:10F5A000606A0890294604A8F1F7A2FDAAE700B511 +:10F5B0000B7889B001204BB1012B05D111780429BA +:10F5C00002D10B201070002009B000BD48680190E6 +:10F5D00005A80290C868036805934068069088688B +:10F5E00003680793406808900120087006208DF892 +:10F5F0000000486A049011466846F1F779FDE3E798 +:10F6000000B50B7889B0012043B1012BDCD1117812 +:10F610000429D9D10C2010700020D5E7486801904A +:10F6200005A802908868036805934068069000204A +:10F63000079008900120087006208DF80000486AA5 +:10F64000049011466846F1F753FDBDE700B50B780D +:10F6500089B0012043B1012BB6D111780429B3D16F +:10F660000D2010700020AFE748680590CDF818D045 +:10F6700088680088ADF80000C8680088ADF802000E +:10F6800000200190029003900120087006208DF860 +:10F690001000486A0890114604A8F1F729FD93E785 +:10F6A00030B403460C7801205CB1012C15D0022C3B +:10F6B00005D111780C2902D10E201070002030BC29 +:10F6C000704701200870C868042242704A6842608E +:10F6D0000B4A8260921EC2600BE014780D2CEED1B2 +:10F6E00002200870C86803244470526842608A6827 +:10F6F0008260496A4162014630BC1846F1F70FBD8D +:10F70000BE0F02002DE9F0410C4611490D68104A68 +:10F71000104908321160A0F120012A2901D30120EB +:10F720000CE03E2810D040CC0B4F94E80E0007EBC5 +:10F730008000241F50F8807C3046B8472060044881 +:10F74000001D0560BDE8F0812046E1F739FDF5E7D1 +:10F750001005024001000001F40F020010B55248EC +:10F7600000F02AFA00B1FFDF4F48401C00F024FAF5 +:10F77000002800D0FFDF10BD2DE9F14F4B4ED6F829 +:10F7800000B00127484800F01FFADFF81C8128B9B3 +:10F790005FF0000708F1010000F02CFA444C00254E +:10F7A0004FF0030901206060C4F80051C4F804510F +:10F7B000009931602060DFF8FCA018E0DAF8000062 +:10F7C000C00614D50E2000F064F8EFF3108010F09E +:10F7D000010072B600D00120C4F80493D4F80011DF +:10F7E00019B9D4F8041101B920BF00B962B6D4F830 +:10F7F000000118B9D4F804010028DFD0D4F80401BE +:10F800000028CFD137B1C6F800B008F1010000F0F0 +:10F81000DBF911E008F1010000F0D6F90028B9D1B8 +:10F82000C4F80893C4F80451C4F800510E2000F045 +:10F8300030F81D4800F0DEF90020BDE8F88F2DE912 +:10F84000F0438DB00D46064600240DF110090DF170 +:10F85000200817E004EB4407102255F827106846EB +:10F8600000F08CFF05EB870710224846796800F00E +:10F8700085FF6846FFF780FF10224146B86800F018 +:10F880007DFF641CB442E5DB0DB00020BDE8F083D1 +:10F8900072E700F01F02012191404009800000F151 +:10F8A000E020C0F8801270477B01002004E5004092 +:10F8B00000E0004010ED00E0B548002101708170CB +:10F8C000704770B5B34D01232B60B34B1C68002CFF +:10F8D000FCD0002407E00E6806601E68002EFCD0F5 +:10F8E000001D091D641C9442F5D30020286018688F +:10F8F0000028FCD070BD70B5A54E0446A74D3078E9 +:10F90000022800D0FFDFAC4200D3FFDF7169A448BA +:10F91000012903D847F23052944201DD032242719B +:10F92000491C7161291BC1609D497078F2F7CBFABF +:10F93000002800D1FFDF70BD70B5954C0D46617891 +:10F94000884200D0FFDF954E082D4ED2DFE805F04B +:10F950004D0421304D4D4D3B2078022800D0FFDF73 +:10F9600003202070A078022802D0012804D008E0EB +:10F97000A06800F0FDFB04E004F1080007C8FFF7F1 +:10F98000A0FF052020700020A070BDE87040F1F7B6 +:10F99000B4BFF2F7A7F801466068F2F78BFCB042FB +:10F9A00002D2616902290BD30320F2F7E7FE12E0CD +:10F9B000F2F798F801466068F2F77CFCB042F3D2A7 +:10F9C000BDE8704097E7207802280AD0052806D0C5 +:10F9D000FFDF04202070BDE8704000F0CEB80220A8 +:10F9E00000E00320F2F7CAFEF3E7FFDF70BD70B559 +:10F9F0000546F2F777F8664C60602078012800D061 +:10FA0000FFDF674901200870002008718D60042025 +:10FA100048716248C860022020706078F2F753FA9B +:10FA2000002800D1FFDF70BD10B5594CA07808B98F +:10FA3000207808B1112010BD5A48F1F7D9FF607045 +:10FA40006078202804D0012020700020606110BD63 +:10FA5000032010BD002070472DE9F041144600EB53 +:10FA600084070E4605463F1F00F095FB4FF080527D +:10FA70001169484306EB8401091FB14201D20121FB +:10FA800000E000211CB11269B4EB920F02D90920E9 +:10FA9000BDE8F081444A95420ED3AF420CD3854273 +:10FAA00005D2874203D245EA0600800701D0102024 +:10FAB000EEE7964200D309B10F20E9E73B483C4905 +:10FAC0000068884205D0224631462846FFF7F9FEF5 +:10FAD00010E0FFF7A9FF0028DAD12D480121856049 +:10FAE000C0E9036481704FF4A97104FB01F0183080 +:10FAF000FFF77DFF0020CBE770B54FF0805504463F +:10FB000028692949B1FBF0F0844201D20F2070BD71 +:10FB100000F041FBA04201D8102070BD28692348A5 +:10FB200023490068884204D02869604300F020FB24 +:10FB30000CE0FFF779FF0028EFD1296914486143F1 +:10FB40008160022181701B48FFF751FF002070BDCA +:10FB50001548010B01208840401E704770B50D46C6 +:10FB60000446FFF7F5FF204201D00F2070BD294663 +:10FB70002046BDE8704000F0B4BD10B5044C60787C +:10FB8000F1F791FF00B9FFDF00202070A07010BDD9 +:10FB90008001002004E5014000E40140105C0C00FD +:10FBA0006C12002039F9010000200200A0000020A2 +:10FBB000BEBAFECA7C5E0100002101700846704793 +:10FBC0000146002008707047EFF3108101F0010139 +:10FBD00072B60278012A01D0012200E0002201233E +:10FBE000037001B962B60AB1002070474FF40050AB +:10FBF0007047E9E7EFF3108111F0010F72B64FF093 +:10FC00000002027000D162B600207047F2E70000E7 +:10FC10004C4909680160002070474A49086000208B +:10FC2000704701218A0720B1012804D042F2040064 +:10FC30007047916700E0D16700207047424901207A +:10FC4000086042F20600704708B504233E4A1907CF +:10FC5000103230B1C1F80433106840F00100106078 +:10FC60000BE0106820F001001060C1F8083300209C +:10FC7000C1F80801354800680090002008BD011F48 +:10FC80000B2909D8304910310A6822F01E0242EAD5 +:10FC9000400008600020704742F2050070470001F4 +:10FCA00000F18040C0F8041900207047000100F105 +:10FCB0008040C0F8081900207047000100F1804022 +:10FCC000D0F80009086000207047012801D90720FA +:10FCD00070471F4A52F8200002680A430260002061 +:10FCE0007047012801D907207047194A52F82000AF +:10FCF00002688A43026000207047012801D907206A +:10FD00007047134A52F820000068086000207047CE +:10FD1000020010494FF0000003D0012A01D0072053 +:10FD200070470A6070474FF080410020C1F8080119 +:10FD30004FF0E020802180F800140121C0F800116C +:10FD4000704700000004004000050040080100402A +:10FD50009C100200780500406249634B0A686349C1 +:10FD60009A42096801D1C1F3100101600020704777 +:10FD70005C495D4B0A685D49091D9A4201D1C0F397 +:10FD800010000860002070475649574B0A685749D1 +:10FD900008319A4201D1C0F310000860002070477A +:10FDA00030B5504B504D1C6842F20803AC4202D0B3 +:10FDB000142802D203E0112801D3184630BDC30035 +:10FDC0004B481844C0F81015C0F81425002030BD69 +:10FDD0004449454B0A6842F209019A4202D006287A +:10FDE00002D203E0042801D308467047404A0121AB +:10FDF00042F83010002070473A493B4B0A6842F203 +:10FE000009019A4202D0062802D203E0042801D355 +:10FE100008467047364A012102EBC00041600020CD +:10FE2000704770B52F4A304E314C156842F20903C5 +:10FE300004EB8002B54204D0062804D2C2F80018B0 +:10FE400007E0042801D3184670BDC1F31000C2F8C2 +:10FE50000008002070BD70B5224A234E244C15685E +:10FE600042F2090304EB8002B54204D0062804D212 +:10FE7000D2F8000807E0042801D3184670BDD2F874 +:10FE80000008C0F310000860002070BD174910B5CD +:10FE90000831184808601120154A002102EBC00300 +:10FEA000C3F81015C3F81415401C1428F6D300200D +:10FEB00006E0042804D302EB8003C3F8001807E02F +:10FEC00002EB8003D3F80048C4F31004C3F80048E1 +:10FED000401C0628EDD310BD0449064808310860CF +:10FEE00070470000A0000020BEBAFECA00F5014025 +:10FEF00000F001400000FEFF754B1B6803B19847FE +:10FF0000BFF34F8F73480168734A01F4E0611143F6 +:10FF10000160BFF34F8FFEE710B572B600F0CEF868 +:10FF200050B1E1F7E7F9F1F7B0FBF2F7CDFBE2F7FB +:10FF30008EFF6A490020086062B6002010BD70B5CF +:10FF40000C46054672B600F0B9F810B162B608204A +:10FF500070BDE1F74BF9E1F7CFF902460020430904 +:10FF60009B0003F1E02300F01F01D3F80031CB40E8 +:10FF7000D9071DD0202803D222FA00F1C90724D1C5 +:10FF800041B2002906DA01F00F0101F1E02191F8F8 +:10FF9000141D03E001F1E02191F80014490908293A +:10FFA00013D291B1012910D004290ED005290CD00B +:10FFB000401C6428D3D3E2F721FF48494848086031 +:10FFC0002046F3F73BF858B903E062B641F201006E +:10FFD00070BD3F4804602DB12846F3F77CF818B196 +:10FFE00010242BE03F4D18E02878022802D94FF466 +:10FFF000805423E007240028687801D058B908E02D +:020000040002F8 +:10000000E0B120281AD8A878212817D8012815D0BF +:1000100003E0A87808B162B612E03349802081F885 +:10002000140DE1F769F92946F2F734FBF1F7EBFA21 +:1000300000F0E4F82846E1F72FF9044662B61CB157 +:10004000FFF76AFF204670BD002070BD10B5044662 +:1000500000F034F800B101202070002010BD2349C9 +:1000600008600020704770B50C4621490D68204992 +:10007000204E08310E60102807D011280CD012280D +:100080000FD0132811D0012013E0D4E90001FFF7AD +:1000900056FF354620600DE0FFF73EFF002520604B +:1000A00008E02068FFF7D2FF03E0104920680860ED +:1000B000002020600E48001D056070BD07480849FB +:1000C0000068884201D1012070470020704700007D +:1000D000980100200CED00E00400FA05A0000020CB +:1000E000BEBAFECAA41002000BE000E0040000202B +:1000F00010050240010000012DE9F04184B088465E +:100100000746FEF777FD05467E786A4601A9404618 +:10011000EFF7F4FA04000ED0012D1EBF032004B047 +:10012000BDE8F08102AA40460199EFF7E6F902988E +:10013000B0F803000AE0022D14D1042E12D3B7F850 +:100140000300BDF80020011D8A420BD3001D80B2C0 +:10015000A119814238BF012008BF00209CBF04B014 +:10016000BDE8F0814FF0020004B0BDE8F08100006E +:100170000B4A022111600B490B68002BFCD0084B85 +:100180001B1D186008680028FCD00020106008685B +:100190000028FCD070474FF0805040697047000045 +:1001A00004E5014000E4014002000B464FF000006E +:1001B000014620D0012A04D0022A04D0032A0DD1FE +:1001C00003E0012002E0022015E00320072B05D206 +:1001D000DFE803F00406080A0C0E10000720704741 +:1001E000012108E0022106E0032104E0042102E0ED +:1001F000052100E00621F1F718BC0000FB480521AD +:100200008170002101704170C17081607047F849B0 +:100210000A78012A06D0CA681044C860C868323813 +:10022000F2F715B88A68104488608868F7E710B557 +:10023000EE4CE078F1F737FC00B9FFDF0820F2F769 +:100240009DFA0520A07000202070607010BD03781A +:10025000E849E94A13B1012B0ED011E00379012BD3 +:1002600000D06BB943790BB1012B09D18368643B92 +:100270008B4205D2C0680EE00379012B02D00BB18E +:100280000020704743790BB1012BF9D1C368643B5F +:100290008B42F5D280689042F2D8012070472DE958 +:1002A000F04104460227F1F7F4FE006800B1FFDFD9 +:1002B000CE4D01263CB12078B0B1012805D00228EE +:1002C00010D0032813D02E710CE06068C82807D323 +:1002D000F2F717F820B16068FFF799FF012703E0F4 +:1002E000002701E000F0CCF93846BDE8F08128781D +:1002F0000028F7D16068FFF7AAFF0028E3D0606804 +:10030000DFF8EC82007828B3A878042800D0FFDF5B +:100310000020464688F8000060680079C8B30020D5 +:10032000307160684079A8B304207071606881689A +:10033000E868F1F7E6F8B0606068C0683230F060F5 +:100340000320A870AA49E878F1F7BDFD0028C9D1BB +:10035000FFDFC7E7404688F8006061680979D1B1DE +:100360000021017161684979B9B104214171616865 +:100370008968323181606168C968C160C0689B4C1E +:1003800014346060F1F7AEFB20606E700220A8703C +:10039000A8E704E005E00321E3E70321E6E7012005 +:1003A000BEE70320C1E72DE9F047904C8846E1788D +:1003B000884200D0FFDFDFF83492002501278C4E01 +:1003C00009F11409B8F1080F79D2DFE808F0040D3B +:1003D0002A557E849199A078032803D0A07802281A +:1003E00000D0FFDFBDE8F087A078032803D0A07815 +:1003F000022800D0FFDF0420A0702571207800289B +:100400007AD1FFF704FF3078012806D0B068E060A9 +:1004100000F07BF92061002062E0E078F1F781FCD8 +:10042000F5E7A078032803D0A078022800D0FFDFEA +:10043000207800286FD1A078032816D0F1F752FB5E +:1004400001464F46D9F80000F1F734FF00280EDBD3 +:10045000796881420BDB081AF0606549E078F1F7B2 +:1004600032FD0028BED1FFDFBCE7042029E00420D4 +:10047000F2F784F9A570B5E7A078032803D0A07837 +:10048000022800D0FFDF207888BBA078032817D08F +:10049000F1F728FB01464F46D9F80000F1F70AFFB3 +:1004A0000028E4DB79688142E1DB081AF0605049FA +:1004B000E078F1F708FD002894D1FFDF92E740E0F3 +:1004C0000520F2F75BF9A7708CE7A078042800D02C +:1004D000FFDF022004E0A078042800D0FFDF012025 +:1004E000A1688847FFF7DBFE054630E004E012E034 +:1004F000A078042800D0FFDFBDE8F04700F0C0B8C6 +:10050000A078042805D0607810B1A078022800D027 +:10051000FFDF207810B1BDE8F04788E6207920B1F0 +:100520000620F2F72BF92571CDE7607838B1304914 +:10053000E078F1F7C8FC00B9FFDF657052E70720EB +:10054000BFE7FFDF4EE73DB1012D03D0FFDF022DF6 +:10055000F9D147E70420C3E70320C1E770B50500E0 +:1005600005D0224CA078052803D0112070BD1020A2 +:1005700070BD2248F1F73CFAE070E078202803D003 +:10058000A5600020A07070BD032070BD174810B595 +:10059000017809B1112010BD817805290CD081782E +:1005A00001290BD0817849B101210170817801299D +:1005B00004D0807810B103E00F2010BDFFF737FEA4 +:1005C000002010BD70B5094E0446B07808B101286E +:1005D0000AD1ACB12046FFF73AFE98B12078044D1D +:1005E00090B1B07801282AD00F2070BD9C01002066 +:1005F0007C1200203D860100FF1FA107A703020017 +:100600001020F2E70720F0E701202870207990B150 +:1006100000202871607980B104206871A0683230B0 +:10062000A860E068E860E8681A4C6060F1F75AFA80 +:100630002060022016E00320EBE70320EDE7002016 +:1006400028702079A8B100202871607998B1042021 +:100650006871A168F068F0F754FFA860E068323074 +:10066000E8600320B0700C49F078F1F72CFC28B951 +:1006700003E00320E8E70320EAE7FFDF0020B4E718 +:10068000044810B51438006900F037F8BDE8104090 +:10069000F1F733B9B00100207C1200201F4909682E +:1006A000014201D001207047002070471B49091DFD +:1006B0000968014201D001207047002070471749A6 +:1006C00010310968014201D00120704700207047B5 +:1006D000124914310968014201D0012070470020FD +:1006E000704710B50D4C2060201D01600B48103084 +:1006F0000260001D0360002010BD09490A6848F22D +:1007000002139A4302430A607047054A116848F28F +:10071000021301EA0300994311607047000600408C +:10072000C806024040EA010310B59B070FD1042A16 +:100730000DD310C808C9121F9C42F8D020BA19BAAC +:10074000884201D9012010BD4FF0FF3010BD1AB111 +:10075000D30703D0521C07E0002010BD10F8013B66 +:1007600011F8014B1B1B07D110F8013B11F8014B8D +:100770001B1B01D1921EF1D1184610BD032A40F275 +:10078000308010F0030C00F0158011F8013BBCF133 +:10079000020F624498BF11F801CB00F8013B38BF4B +:1007A00011F8013BA2F1040298BF00F801CB38BF59 +:1007B00000F8013B11F0030300F02580083AC0F077 +:1007C000088051F8043B083A51F804CBA0E808101F +:1007D000F5E7121D5CBF51F8043B40F8043BAFF352 +:1007E0000080D20724BF11F8013B11F801CB48BFAC +:1007F00011F8012B24BF00F8013B00F801CB48BFE2 +:1008000000F8012B704710B5203AC0F00B80B1E81A +:100810001850203AA0E81850B1E81850A0E8185035 +:10082000BFF4F5AF5FEA027C24BFB1E81850A0E83E +:10083000185044BF18C918C0BDE810405FEA827C58 +:1008400024BF51F8043B40F8043B08BF7047D2076F +:1008500028BF31F8023B48BF11F8012B28BF20F810 +:10086000023B48BF00F8012B70474FF000020429FB +:10087000C0F0128010F0030C00F01B80CCF1040CCF +:10088000BCF1020F18BF00F8012BA8BF20F8022B03 +:10089000A1EB0C0100F00DB85FEAC17C24BF00F8A9 +:1008A000012B00F8012B48BF00F8012B70474FF0D7 +:1008B000000200B5134694469646203922BFA0E8B0 +:1008C0000C50A0E80C50B1F12001BFF4F7AF0907BC +:1008D00028BFA0E80C5048BF0CC05DF804EB8900AD +:1008E00028BF40F8042B08BF704748BF20F8022BF0 +:1008F00011F0804F18BF00F8012B7047FEDF042075 +:100900007146084219D10699134A914215DC06999D +:1009100002394878DF2810D10878FE2807D0FF2850 +:100920000BD14FF001004FF000020C4B184741F281 +:1009300001000099019A094B184706980599084B40 +:10094000002B02D01B68DB6818474FF0FF304FF0D8 +:1009500000017246014B184700200200F9FE010019 +:1009600004000020184819497047FFF7FBFFE0F723 +:1009700015FC00BD4FF4805015490968884203D129 +:10098000144A13605B68184700BD000020BFFDE7F4 +:100990004FF480500E490968884210D10E4B1868F8 +:1009A0004FF0FF318842F1D080F308884FF02021CA +:1009B000884204DD0948026802210A4302600848AF +:1009C000804708488047FFDF9012002090120020E7 +:1009D0000000002004000020002002002405004048 +:1009E000B52F00007509020004207146084202D0AC +:1009F000EFF3098101E0EFF308818869023800789C +:100A0000102813DB20280FDB2B280BDB0A4A126887 +:100A10000A4B9A4203D1602804DB094A104702209E +:100A200008607047074A1047074A1047074A12688C +:100A30002C32126810470000A0000020BEBAFECA87 +:100A4000FD12000005F7010067000200040000200D +:100A50000D4B0E4908470E4B0C4908470D4B0B49EF +:100A600008470D4B094908470C4B084908470C4BF0 +:100A7000064908470B4B054908470B4B03490847F4 +:100A80000A4B02490847000071A00000392F0000FE +:100A9000B12C00004D2B0000DB2A0000532D00007C +:100AA000191300009728000035A20000A9110000CA +:100AB0000021016081807047002101604160017266 +:100AC00070470A6802600B7903717047D79600007F +:100AD000EF980000F5990000199A0000539A000061 +:100AE000879A0000CD9A0000FD9A00004F9B0000FD +:100AF000059800008712000087120000C94000001E +:100B00000F41000031410000EB410000274300008D +:100B1000F943000031440000F5440000A73C000008 +:100B2000494700002B4800004B480000BD1500005D +:100B3000E1150000111500006515000013160000F6 +:100B4000A7160000F5600000BB62000063660000AD +:100B50007D670000016800007B680000ED68000010 +:100B6000096A0000D76A0000576B00006548000062 +:100B70006B48000075480000693C00004B490000CC +:100B8000353C0000A94A0000014B0000814B0000E9 +:100B9000871200008712000087120000F72400006F +:100BA0007D25000099250000B525000043270000A1 +:100BB000DF250000E92500002B2600004D2600005F +:100BC000292700006B27000087120000A98400007D +:100BD000C9840000CB840000058500003385000037 +:100BE00021860000AF860000C38600001187000048 +:100BF000F787000099890000C18A00006D7300002A +:100C0000D98A0000871200008712000087120000B6 +:100C10005300000000000000000000000000000081 +:100C200000000000000000000000000000000000C4 +:100C30000000000000000000000000005200000062 +:100C400000000000000000000000000000000000A4 +:100C50000000000000000000000000000000000094 +:100C60000000000000000000100110013A02000026 +:100C70001A0200007591000035910000FFFFFFFF90 +:100C80000000FFFFA5C900007938000065200000C2 +:100C9000B7730000918F00000000000097810000F2 +:100CA00077810000138200004B2400000D24000017 +:100CB0002D24000083C8000011C90000D75900008E +:100CC000338200000000000063820000C72400009F +:100CD0000000000000000000000000000000000014 +:100CE000875A000000000000000000000000000023 +:100CF00000000000000000000000000000000000F4 +:100D00000000000000000000000000004DD20000C4 +:100D1000D1D2000000000000000000000000000030 +:100D2000D1D300000000000000000000000000001F +:100D3000E3E80000000000000000000000000000E8 +:100D4000D7D5000085E2000000000000A5E4000007 +:100D5000D7E6000000000000B3DB000079DC0000F3 +:100D60000000000061E5000071DD00008FDF000081 +:100D700001E00000F5E0000081D700000000000065 +:100D80000000000091D6000000000000AFD4000079 +:100D90000DD4000071E1000015E7000083E70000BA +:100DA000000000001FD300004FD300007FD20000DE +:100DB0000000000099D300000000000000000000C7 +:100DC00000000000DBE70000000000000000000061 +:100DD0000000000000000000000000000000000013 +:100DE000DBD900000000000055E4000027E500000A +:100DF000C1E6000095D5000039D400005DD50000A3 +:100E000000000000E3D4000000000000000000002B +:100E10004DE8000031E9000035EB0000B1E90000C9 +:100E20000FD60000EBEA00000000000021D800000F +:100E3000F5D80000FBE9000045EA000069DB00008E +:100E40001BD50000A1E800007FEA00005157000018 +:100E500051570000A54000002FC90000797600001E +:100E6000851F0000F39901004FB101009557000064 +:100E700095570000C740000063C9000003770000D9 +:100E8000EF1F0000219A010063B10100D001D001E1 +:100E90003E0034005C0024004801F0010100000025 +:100EA0000001020304000F101112000000130000E3 +:100EB000E1F40100AFF5010001F601004DF601007B +:100EC000A1F60100DBEF0100FDF0010065F101007A +:100ED00089F301006BF40100DFFD0000B90E010091 +:100EE00000000000060000000A00000032000000C0 +:100EF00073000000B4000000598701002F74010046 +:100F0000894C01001DCC01007D6001001DCC010059 +:100F1000FB4C010027CE0100B958010027CE01008B +:100F2000FB4B01004BCD0100335F01004BCD0100B5 +:100F30004F50010047D101001161010047D101006C +:100F40000004F4F4FE00F1F1FF000000131708089C +:100F50000000E8E8FC02E8E800000000F8FF0808EC +:100F6000555555D6BE898E0000009806250DB21342 +:100F700000000208F80FEF1700003C036D069E0901 +:100F8000000088040509820D555555252627D6BE33 +:100F9000898EF401FA00960064004B0032001E00B6 +:100FA00014000A00050002000100000025090000ED +:100FB00000000000AAAED7AB1541201000000300CE +:100FC000656C74620000000000000000000000007A +:100FD000000000008700000000000000000000008A +:100FE00000000000BE83605ADB0B376038A5F5AA0D +:100FF0009183886C59FD010071FD010089FD01009C +:10100000A1FD0100D1FD0100F9FD010023FE010059 +:1010100057FE0100F9FA010059FA01005DFB0100D9 +:10102000B9FB0100C9FB0100F5FB010033290100F8 +:101030003B2901004929010023FC01003DFC01007E +:1010400011FC01001BFC010049FC01007FFC0100B8 +:101050009FFC0100ADFC0100BBFC0100CBFC0100CA +:10106000E3FC0100FBFC010011FD01000000000099 +:10107000039E0000599E00006F9E0000A90102001F +:1010800079F701003FF801005D0502008D050200BF +:10109000C5050200292701000D2C01001C05004098 +:1010A0002005004000100200C810020008000020C7 +:1010B000B001000044110000F8100200B801002047 +:1010C000D8100000801100000119054910130020FC +:1010D0003601000100743720FB349B5F80041B80C5 +:1010E0000010022501540B0020337F0106A45C0C84 +:0810F000002029024810000055 +:00000001FF diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json new file mode 100644 index 0000000000..f72a514443 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json @@ -0,0 +1,46 @@ +{ + "name": "softdevice", + "macros": [ + "SOFTDEVICE_PRESENT=1", + "NRF_SDH_CLOCK_LF_SRC=1", + "NRF_SDH_CLOCK_LF_RC_CTIV=0", + "NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0", + "NRF_SDH_CLOCK_LF_XTAL_ACCURACY=7", + "BLE_STACK_SUPPORT_REQD", + "NRF_SD_BLE_API_VERSION=5", + "S140", + "NRF_SDH_ENABLED=1", + "NRF_SDH_BLE_ENABLED=1", + "PEER_MANAGER_ENABLED=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", + "NRF_SDH_BLE_SERVICE_CHANGED=1", + "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23", + "NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE=0x600", + "NRF_SDH_BLE_VS_UUID_COUNT=4", + "NRF_SDH_BLE_OBSERVER_PRIO_LEVELS=4", + "NRF_SDH_BLE_GAP_EVENT_LENGTH=3", + "BLE_ADV_BLE_OBSERVER_PRIO=1", + "BLE_CONN_STATE_BLE_OBSERVER_PRIO=0", + "BLE_CONN_PARAMS_BLE_OBSERVER_PRIO=1", + "NRF_BLE_GATT_BLE_OBSERVER_PRIO=1", + "NRF_SDH_DISPATCH_MODEL=2", + "NRF_SDH_SOC_ENABLED=1", + "NRF_SDH_STACK_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_STATE_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_SOC_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_REQ_OBSERVER_PRIO_LEVELS=2", + "NRF_SDH_BLE_STACK_OBSERVER_PRIO=0", + "NRF_SDH_SOC_STACK_OBSERVER_PRIO=0", + "FDS_BACKEND=2", + "SWI_DISABLE1=1", + "S140" + ], + "target_overrides": { + "*": { + "target.features_add": ["BLE"], + "target.bootloader_img": "hex/s140_nrf52840_5.0.0-2.alpha_softdevice.hex" + } + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/README.md new file mode 100644 index 0000000000..8217ae3c0f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/README.md @@ -0,0 +1,9 @@ +# Folder origin + +components/boards + +# Modifications + +Removed: + * d52_starterkit.h + * n5_starterkit.h diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/arduino_primo.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/arduino_primo.h new file mode 100644 index 0000000000..00c0390977 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/arduino_primo.h @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 ARDUINO_PRIMO_H +#define ARDUINO_PRIMO_H + +#ifdef __cplusplus +extern "C" { +#endif + +// LEDs definitions +#define LEDS_NUMBER 1 + +#define LED_1 20 + +#define LEDS_ACTIVE_STATE 0 + +#define LEDS_LIST { LED_1} + +#define BSP_LED_0 LED_1 + +#define LEDS_INV_MASK 0 + +#define BUTTONS_NUMBER 1 + +#define BUTTON_START 7 +#define BUTTON_1 7 +#define BUTTON_STOP 7 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BUTTONS_LIST { BUTTON_1 } + +#define BSP_BUTTON_0 BUTTON_1 + +#define RX_PIN_NUMBER 11 +#define TX_PIN_NUMBER 12 +#define CTS_PIN_NUMBER UART_PIN_DISCONNECTED +#define RTS_PIN_NUMBER UART_PIN_DISCONNECTED +#define HWFC false + +#define BUZZER_PIN_NUMBER 8 + +// Arduino board mappings +#define ARDUINO_SCL_PIN 27 // SCL signal pin +#define ARDUINO_SDA_PIN 26 // SDA signal pin +#define ARDUINO_AREF_PIN 2 // Aref pin +#define ARDUINO_13_PIN 25 // Digital pin 13 +#define ARDUINO_12_PIN 24 // Digital pin 12 +#define ARDUINO_11_PIN 23 // Digital pin 11 +#define ARDUINO_10_PIN 22 // Digital pin 10 +#define ARDUINO_9_PIN 20 // Digital pin 9 +#define ARDUINO_8_PIN 19 // Digital pin 8 + +#define ARDUINO_7_PIN 18 // Digital pin 7 +#define ARDUINO_6_PIN 17 // Digital pin 6 +#define ARDUINO_5_PIN 16 // Digital pin 5 +#define ARDUINO_4_PIN 15 // Digital pin 4 +#define ARDUINO_3_PIN 14 // Digital pin 3 +#define ARDUINO_2_PIN 13 // Digital pin 2 +#define ARDUINO_1_PIN 12 // Digital pin 1 +#define ARDUINO_0_PIN 11 // Digital pin 0 + +#define ARDUINO_A0_PIN 3 // Analog channel 0 +#define ARDUINO_A1_PIN 4 // Analog channel 1 +#define ARDUINO_A2_PIN 28 // Analog channel 2 +#define ARDUINO_A3_PIN 29 // Analog channel 3 +#define ARDUINO_A4_PIN 30 // Analog channel 4 +#define ARDUINO_A5_PIN 31 // Analog channel 5 + +// Low frequency clock source to be used by the SoftDevice +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} + + +#ifdef __cplusplus +} +#endif + +#endif // ARDUINO_PRIMO_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.c new file mode 100644 index 0000000000..511a14e84c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.c @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "boards.h" +#include +#include + +#if LEDS_NUMBER > 0 +static const uint8_t m_board_led_list[LEDS_NUMBER] = LEDS_LIST; +#endif + +#if BUTTONS_NUMBER > 0 +static const uint8_t m_board_btn_list[BUTTONS_NUMBER] = BUTTONS_LIST; +#endif + +#if LEDS_NUMBER > 0 +bool bsp_board_led_state_get(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + bool pin_set = nrf_gpio_pin_out_read(m_board_led_list[led_idx]) ? true : false; + return (pin_set == (LEDS_ACTIVE_STATE ? true : false)); +} + +void bsp_board_led_on(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 1 : 0); +} + +void bsp_board_led_off(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 0 : 1); +} + +void bsp_board_leds_off(void) +{ + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + bsp_board_led_off(i); + } +} + +void bsp_board_leds_on(void) +{ + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + bsp_board_led_on(i); + } +} + +void bsp_board_led_invert(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + nrf_gpio_pin_toggle(m_board_led_list[led_idx]); +} + +void bsp_board_leds_init(void) +{ + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + nrf_gpio_cfg_output(m_board_led_list[i]); + } + bsp_board_leds_off(); +} + +uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx) +{ + ASSERT(led_idx < LEDS_NUMBER); + return m_board_led_list[led_idx]; +} + +uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number) +{ + uint32_t ret = 0xFFFFFFFF; + uint32_t i; + for (i = 0; i < LEDS_NUMBER; ++i) + { + if (m_board_led_list[i] == pin_number) + { + ret = i; + break; + } + } + return ret; +} +#endif //LEDS_NUMBER > 0 + +#if BUTTONS_NUMBER > 0 +bool bsp_board_button_state_get(uint32_t button_idx) +{ + ASSERT(button_idx < BUTTONS_NUMBER); + bool pin_set = nrf_gpio_pin_read(m_board_btn_list[button_idx]) ? true : false; + return (pin_set == (BUTTONS_ACTIVE_STATE ? true : false)); +} + +void bsp_board_buttons_init(void) +{ + uint32_t i; + for (i = 0; i < BUTTONS_NUMBER; ++i) + { + nrf_gpio_cfg_input(m_board_btn_list[i], BUTTON_PULL); + } +} + +uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number) +{ + uint32_t i; + uint32_t ret = 0xFFFFFFFF; + for (i = 0; i < BUTTONS_NUMBER; ++i) + { + if (m_board_btn_list[i] == pin_number) + { + ret = i; + break; + } + } + return ret; +} + +uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx) +{ + ASSERT(button_idx < BUTTONS_NUMBER); + return m_board_btn_list[button_idx]; +} +#endif //BUTTONS_NUMBER > 0 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.h new file mode 100644 index 0000000000..87fca8023b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/boards.h @@ -0,0 +1,319 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 BOARDS_H +#define BOARDS_H + +#include "nrf_gpio.h" + +#if defined(BOARD_NRF6310) + #include "nrf6310.h" +#elif defined(BOARD_PCA10000) + #include "pca10000.h" +#elif defined(BOARD_PCA10001) + #include "pca10001.h" +#elif defined(BOARD_PCA10002) + #include "pca10000.h" +#elif defined(BOARD_PCA10003) + #include "pca10003.h" +#elif defined(BOARD_PCA20006) + #include "pca20006.h" +#elif defined(BOARD_PCA10028) + #include "pca10028.h" +#elif defined(BOARD_PCA10031) + #include "pca10031.h" +#elif defined(BOARD_PCA10036) + #include "pca10036.h" +#elif defined(BOARD_PCA10040) + #include "pca10040.h" +#elif defined(BOARD_PCA10056) + #include "pca10056.h" +#elif defined(BOARD_WT51822) + #include "wt51822.h" +#elif defined(BOARD_N5DK1) + #include "n5_starterkit.h" +#elif defined (BOARD_D52DK1) + #include "d52_starterkit.h" +#elif defined (BOARD_ARDUINO_PRIMO) + #include "arduino_primo.h" +#elif defined(BOARD_CUSTOM) + #include "custom_board.h" +#else +#error "Board is not defined" + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Function for returning the state of an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + * + * @return True if the LED is turned on. + */ +bool bsp_board_led_state_get(uint32_t led_idx); + +/** + * Function for turning on an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_on(uint32_t led_idx); + +/** + * Function for turning off an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_off(uint32_t led_idx); + +/** + * Function for inverting the state of an LED. + * + * @param led_idx LED index (starting from 0), as defined in the board-specific header. + */ +void bsp_board_led_invert(uint32_t led_idx); +/** + * Function for turning off all LEDs. + */ +void bsp_board_leds_off(void); + +/** + * Function for turning on all LEDs. + */ +void bsp_board_leds_on(void); + +/** + * Function for initializing LEDs. + */ +void bsp_board_leds_init(void); + +/** + * Function for converting pin number to LED index. + * + * @param pin_number Pin number. + * + * @return LED index of the given pin or 0xFFFFFFFF if invalid pin provided. + */ +uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number); + +/** + * Function for converting LED index to pin number. + * + * @param led_idx LED index. + * + * @return Pin number. + */ +uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx); + +/** + * Function for returning the state of a button. + * + * @param button_idx Button index (starting from 0), as defined in the board-specific header. + * + * @return True if the button is pressed. + */ +bool bsp_board_button_state_get(uint32_t button_idx); + +/** + * Function for initializing buttons. + */ +void bsp_board_buttons_init(void); + +/** + * Function for converting pin number to button index. + * + * @param pin_number Pin number. + * + * @return Button index of the given pin or 0xFFFFFFFF if invalid pin provided. + */ +uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number); + + +/** + * Function for converting button index to pin number. + * + * @param button_idx Button index. + * + * @return Pin number. + */ +uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx); + +#define BSP_BOARD_LED_0 0 +#define BSP_BOARD_LED_1 1 +#define BSP_BOARD_LED_2 2 +#define BSP_BOARD_LED_3 3 +#define BSP_BOARD_LED_4 4 +#define BSP_BOARD_LED_5 5 +#define BSP_BOARD_LED_6 6 +#define BSP_BOARD_LED_7 7 + +#ifdef BSP_LED_0 +#define BSP_LED_0_MASK (1<OUTSET = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ + NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) + +#define LEDS_ON(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \ + NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \ + NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0) + +#define LED_IS_ON(leds_mask) ((leds_mask) & (NRF_GPIO->OUT ^ LEDS_INV_MASK) ) + +#define LEDS_INVERT(leds_mask) do { uint32_t gpio_state = NRF_GPIO->OUT; \ + ASSERT(sizeof(leds_mask) == 4); \ + NRF_GPIO->OUTSET = ((leds_mask) & ~gpio_state); \ + NRF_GPIO->OUTCLR = ((leds_mask) & gpio_state); } while (0) + +#define LEDS_CONFIGURE(leds_mask) do { uint32_t pin; \ + ASSERT(sizeof(leds_mask) == 4); \ + for (pin = 0; pin < 32; pin++) \ + if ( (leds_mask) & (1 << pin) ) \ + nrf_gpio_cfg_output(pin); } while (0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/nrf6310.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/nrf6310.h new file mode 100644 index 0000000000..86698ecfa5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/nrf6310.h @@ -0,0 +1,186 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRF6310_H__ +#define NRF6310_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_START 8 +#define LED_0 8 +#define LED_1 9 +#define LED_2 10 +#define LED_3 11 +#define LED_4 12 +#define LED_5 13 +#define LED_6 14 +#define LED_7 15 +#define LED_STOP 15 + +#define BSP_LED_0 LED_0 +#define BSP_LED_1 LED_1 +#define BSP_LED_2 LED_2 +#define BSP_LED_3 LED_3 +#define BSP_LED_4 LED_4 +#define BSP_LED_5 LED_5 +#define BSP_LED_6 LED_6 +#define BSP_LED_7 LED_7 + +#define LEDS_ACTIVE_STATE 1 + +#define BUTTON_START 0 +#define BUTTON_0 0 +#define BUTTON_1 1 +#define BUTTON_2 2 +#define BUTTON_3 3 +#define BUTTON_4 4 +#define BUTTON_5 5 +#define BUTTON_6 6 +#define BUTTON_7 7 +#define BUTTON_STOP 7 +#define BUTTON_PULL NRF_GPIO_PIN_NOPULL + +#define BSP_BUTTON_0 BUTTON_0 +#define BSP_BUTTON_1 BUTTON_1 +#define BSP_BUTTON_2 BUTTON_2 +#define BSP_BUTTON_3 BUTTON_3 +#define BSP_BUTTON_4 BUTTON_4 +#define BSP_BUTTON_5 BUTTON_5 +#define BSP_BUTTON_6 BUTTON_6 +#define BSP_BUTTON_7 BUTTON_7 + +#define BUTTONS_ACTIVE_STATE 1 + +#define BUTTONS_LIST {BUTTON_0, BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4, BUTTON_5, BUTTON_6, BUTTON_7} +#define LEDS_LIST {LED_0, LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7} + +#define LEDS_INV_MASK 0x00000000 + +#define BUTTONS_NUMBER 8 +#define LEDS_NUMBER 8 + +#define RX_PIN_NUMBER 16 // UART RX pin number. +#define TX_PIN_NUMBER 17 // UART TX pin number. +#define CTS_PIN_NUMBER 18 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define RTS_PIN_NUMBER 19 // UART Request To Send pin number. Not used if HWFC is set to false. +#define HWFC false // UART hardware flow control. + +#define SPIS_MISO_PIN 20 // SPI MISO signal. +#define SPIS_CSN_PIN 21 // SPI CSN signal. +#define SPIS_MOSI_PIN 22 // SPI MOSI signal. +#define SPIS_SCK_PIN 23 // SPI SCK signal. + +#define SPIM0_SCK_PIN 23u /**< SPI clock GPIO pin number. */ +#define SPIM0_MOSI_PIN 20u /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM0_MISO_PIN 22u /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM0_SS_PIN 21u /**< SPI Slave Select GPIO pin number. */ + +#define SPIM1_SCK_PIN 16u /**< SPI clock GPIO pin number. */ +#define SPIM1_MOSI_PIN 18u /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM1_MISO_PIN 17u /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM1_SS_PIN 19u /**< SPI Slave Select GPIO pin number. */ + +// serialization APPLICATION board +#define SER_APP_RX_PIN 16 // UART RX pin number. +#define SER_APP_TX_PIN 17 // UART TX pin number. +#define SER_APP_CTS_PIN 18 // UART Clear To Send pin number. +#define SER_APP_RTS_PIN 19 // UART Request To Send pin number. + +#if 0 +#define SER_APP_SPIM0_SCK_PIN 20 // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN 17 // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN 16 // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN 21 // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN 19 // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN 18 // SPI REQUEST GPIO pin number +#else +#define SER_APP_SPIM0_SCK_PIN 23 // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN 20 // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN 22 // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN 21 // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN 29 // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN 28 // SPI REQUEST GPIO pin number + +#endif + +// serialization CONNECTIVITY board +#if 0 +#define SER_CON_RX_PIN 17 // UART RX pin number. +#define SER_CON_TX_PIN 16 // UART TX pin number. +#define SER_CON_CTS_PIN 19 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN 18 // UART Request To Send pin number. Not used if HWFC is set to false. +#else +#define SER_CON_RX_PIN 16 // UART RX pin number. +#define SER_CON_TX_PIN 17 // UART TX pin number. +#define SER_CON_CTS_PIN 18 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN 19 // UART Request To Send pin number. Not used if HWFC is set to false. +#endif + +#if 0 +#define SER_CON_SPIS_SCK_PIN 20 // SPI SCK signal. +#define SER_CON_SPIS_MISO_PIN 16 // SPI MISO signal. +#define SER_CON_SPIS_MOSI_PIN 17 // SPI MOSI signal. +#define SER_CON_SPIS_CSN_PIN 21 // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN 19 // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN 18 // SPI REQUEST GPIO pin number. +#else +#define SER_CON_SPIS_SCK_PIN 23 // SPI SCK signal. +#define SER_CON_SPIS_MOSI_PIN 22 // SPI MOSI signal. +#define SER_CON_SPIS_MISO_PIN 20 // SPI MISO signal. +#define SER_CON_SPIS_CSN_PIN 21 // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN 29 // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN 28 // SPI REQUEST GPIO pin number. +#endif + +#define SER_CONN_ASSERT_LED_PIN LED_2 + +// Low frequency clock source to be used by the SoftDevice +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} + + +#ifdef __cplusplus +} +#endif + +#endif // NRF6310_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10000.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10000.h new file mode 100644 index 0000000000..eb5ea139f8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10000.h @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PCA10000_H +#define PCA10000_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +// Definitions for PCA10000 v2.0.0 or higher +#if 1 + +#define LEDS_NUMBER 3 + +// there is RGB LED on this board +#define LED_RGB_RED 21 +#define LED_RGB_GREEN 22 +#define LED_RGB_BLUE 23 + +#define LED_START LED_RGB_RED +#define BSP_LED_0 LED_RGB_RED +#define BSP_LED_1 LED_RGB_GREEN +#define BSP_LED_2 LED_RGB_BLUE +#define LED_STOP LED_RGB_BLUE + +#define LEDS_ACTIVE_STATE 0 + +#define BUTTONS_LIST {} +#define LEDS_LIST { LED_RGB_RED, LED_RGB_GREEN, LED_RGB_BLUE } + +#define LEDS_INV_MASK LEDS_MASK + +// there are no buttons on this board +#define BUTTONS_NUMBER 0 + +// UART pins connected to J-Link +#define RX_PIN_NUMBER 11 +#define TX_PIN_NUMBER 9 +#define CTS_PIN_NUMBER 10 +#define RTS_PIN_NUMBER 8 +#define HWFC true + +// Definitions for PCA10000 v1.0 +#else + +#define RX_PIN_NUMBER 3 +#define TX_PIN_NUMBER 1 +#define CTS_PIN_NUMBER 2 +#define RTS_PIN_NUMBER 0 +#define HWFC true + +#endif + +// Low frequency clock source to be used by the SoftDevice +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10001.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10001.h new file mode 100644 index 0000000000..58a9c05e8d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10001.h @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PCA10001_H +#define PCA10001_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +#define LED_START 18 +#define LED_0 18 +#define LED_1 19 +#define LED_STOP 19 + +#define LEDS_ACTIVE_STATE 1 + +#define BSP_LED_0 LED_0 +#define BSP_LED_1 LED_1 + +#define LEDS_INV_MASK 0x00000000 + +#define BUTTON_START 16 +#define BUTTON_0 16 +#define BUTTON_1 17 +#define BUTTON_STOP 17 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BSP_BUTTON_0 BUTTON_0 +#define BSP_BUTTON_1 BUTTON_1 + +#define BUTTONS_NUMBER 2 +#define LEDS_NUMBER 2 + +#define BUTTONS_LIST { BUTTON_0, BUTTON_1 } +#define LEDS_LIST { LED_0, LED_1 } + +#define RX_PIN_NUMBER 11 +#define TX_PIN_NUMBER 9 +#define CTS_PIN_NUMBER 10 +#define RTS_PIN_NUMBER 8 +#define HWFC true + +#define SPIS_MISO_PIN 20 // SPI MISO signal. +#define SPIS_CSN_PIN 21 // SPI CSN signal. +#define SPIS_MOSI_PIN 22 // SPI MOSI signal. +#define SPIS_SCK_PIN 23 // SPI SCK signal. + +#define SPIM0_SCK_PIN 23u /**< SPI clock GPIO pin number. */ +#define SPIM0_MOSI_PIN 20u /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM0_MISO_PIN 22u /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM0_SS_PIN 21u /**< SPI Slave Select GPIO pin number. */ + +#define SPIM1_SCK_PIN 29u /**< SPI clock GPIO pin number. */ +#define SPIM1_MOSI_PIN 24u /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM1_MISO_PIN 28u /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM1_SS_PIN 25u /**< SPI Slave Select GPIO pin number. */ + +// serialization APPLICATION board + +// UART +// this configuration works with the SPI wires setup +#define SER_APP_RX_PIN 20 // UART RX pin number. +#define SER_APP_TX_PIN 22 // UART TX pin number. +#define SER_APP_CTS_PIN 23 // UART Clear To Send pin number. +#define SER_APP_RTS_PIN 21 // UART Request To Send pin number. + +// SPI +#if 0 +#define SER_APP_SPIM0_SCK_PIN 20 // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN 17 // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN 16 // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN 21 // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN 19 // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN 18 // SPI REQUEST GPIO pin number +#else +#define SER_APP_SPIM0_SCK_PIN 23 // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN 20 // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN 22 // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN 21 // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN 25 // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN 24 // SPI REQUEST GPIO pin number +#endif + +// serialization CONNECTIVITY board + +// UART +#if 0 +#define SER_CON_RX_PIN 22 // UART RX pin number. +#define SER_CON_TX_PIN 20 // UART TX pin number. +#define SER_CON_CTS_PIN 21 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN 23 // UART Request To Send pin number. Not used if HWFC is set to false. +#else +// this configuration works with the SPI wires setup +#define SER_CON_RX_PIN 20 // UART RX pin number. +#define SER_CON_TX_PIN 22 // UART TX pin number. +#define SER_CON_CTS_PIN 21 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN 23 // UART Request To Send pin number. Not used if HWFC is set to false. +#endif + +//SPI +#if 0 +#define SER_CON_SPIS_SCK_PIN 20 // SPI SCK signal. +#define SER_CON_SPIS_MISO_PIN 16 // SPI MISO signal. +#define SER_CON_SPIS_MOSI_PIN 17 // SPI MOSI signal. +#define SER_CON_SPIS_CSN_PIN 21 // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN 19 // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN 18 // SPI REQUEST GPIO pin number. +#else +#define SER_CON_SPIS_SCK_PIN 23 // SPI SCK signal. +#define SER_CON_SPIS_MOSI_PIN 22 // SPI MOSI signal. +#define SER_CON_SPIS_MISO_PIN 20 // SPI MISO signal. +#define SER_CON_SPIS_CSN_PIN 21 // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN 25 // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN 24 // SPI REQUEST GPIO pin number. +#endif + +#define SER_CONN_ASSERT_LED_PIN LED_0 + +// Low frequency clock source to be used by the SoftDevice +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10003.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10003.h new file mode 100644 index 0000000000..8a1b239f06 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10003.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PCA10003_H +#define PCA10003_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +#define LED_START 18 +#define LED_0 18 +#define LED_1 19 +#define LED_STOP 19 + +#define LEDS_ACTIVE_STATE 1 + +#define LEDS_INV_MASK 0x00000000 + +#define BSP_LED_0 LED_0 +#define BSP_LED_1 LED_1 + +#define BUTTON_START 16 +#define BUTTON_0 16 +#define BUTTON_1 17 +#define BUTTON_STOP 17 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BSP_BUTTON_0 BUTTON_0 +#define BSP_BUTTON_1 BUTTON_1 + +#define BUTTONS_NUMBER 2 +#define LEDS_NUMBER 2 +#define LEDS_LIST { LED_0, LED_1 } + +#define BUTTONS_LIST { BUTTON_0, BUTTON_1 } + +#define RX_PIN_NUMBER 11 +#define TX_PIN_NUMBER 9 +#define CTS_PIN_NUMBER 10 +#define RTS_PIN_NUMBER 8 +#define HWFC true + +// Low frequency clock source to be used by the SoftDevice +#ifdef S210 +#define NRF_CLOCK_LFCLKSRC NRF_CLOCK_LFCLKSRC_XTAL_20_PPM +#else +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10028.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10028.h new file mode 100644 index 0000000000..6d736ab027 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10028.h @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PCA10028_H +#define PCA10028_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +// LEDs definitions for PCA10028 +#define LEDS_NUMBER 4 + +#define LED_START 21 +#define LED_1 21 +#define LED_2 22 +#define LED_3 23 +#define LED_4 24 +#define LED_STOP 24 + +#define LEDS_ACTIVE_STATE 0 + +#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4 } + +#define LEDS_INV_MASK LEDS_MASK + +#define BSP_LED_0 LED_1 +#define BSP_LED_1 LED_2 +#define BSP_LED_2 LED_3 +#define BSP_LED_3 LED_4 + +#define BUTTONS_NUMBER 4 + +#define BUTTON_START 17 +#define BUTTON_1 17 +#define BUTTON_2 18 +#define BUTTON_3 19 +#define BUTTON_4 20 +#define BUTTON_STOP 20 +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +#define BUTTONS_ACTIVE_STATE 0 + +#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 } + +#define BSP_BUTTON_0 BUTTON_1 +#define BSP_BUTTON_1 BUTTON_2 +#define BSP_BUTTON_2 BUTTON_3 +#define BSP_BUTTON_3 BUTTON_4 + +#define RX_PIN_NUMBER 11 +#define TX_PIN_NUMBER 9 +#define CTS_PIN_NUMBER 10 +#define RTS_PIN_NUMBER 8 +#define HWFC true + +#define SPIS_MISO_PIN 28 // SPI MISO signal. +#define SPIS_CSN_PIN 12 // SPI CSN signal. +#define SPIS_MOSI_PIN 25 // SPI MOSI signal. +#define SPIS_SCK_PIN 29 // SPI SCK signal. + +#define SPIM0_SCK_PIN 4 /**< SPI clock GPIO pin number. */ +#define SPIM0_MOSI_PIN 1 /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM0_MISO_PIN 3 /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM0_SS_PIN 2 /**< SPI Slave Select GPIO pin number. */ + +#define SPIM1_SCK_PIN 15 /**< SPI clock GPIO pin number. */ +#define SPIM1_MOSI_PIN 12 /**< SPI Master Out Slave In GPIO pin number. */ +#define SPIM1_MISO_PIN 14 /**< SPI Master In Slave Out GPIO pin number. */ +#define SPIM1_SS_PIN 13 /**< SPI Slave Select GPIO pin number. */ + +// serialization APPLICATION board +#define SER_CONN_CHIP_RESET_PIN 12 // Pin used to reset connectivity chip + +#define SER_APP_RX_PIN 25 // UART RX pin number. +#define SER_APP_TX_PIN 28 // UART TX pin number. +#define SER_APP_CTS_PIN 0 // UART Clear To Send pin number. +#define SER_APP_RTS_PIN 29 // UART Request To Send pin number. + +#define SER_APP_SPIM0_SCK_PIN 7 // SPI clock GPIO pin number. +#define SER_APP_SPIM0_MOSI_PIN 0 // SPI Master Out Slave In GPIO pin number +#define SER_APP_SPIM0_MISO_PIN 30 // SPI Master In Slave Out GPIO pin number +#define SER_APP_SPIM0_SS_PIN 25 // SPI Slave Select GPIO pin number +#define SER_APP_SPIM0_RDY_PIN 29 // SPI READY GPIO pin number +#define SER_APP_SPIM0_REQ_PIN 28 // SPI REQUEST GPIO pin number + +// serialization CONNECTIVITY board +#define SER_CON_RX_PIN 28 // UART RX pin number. +#define SER_CON_TX_PIN 25 // UART TX pin number. +#define SER_CON_CTS_PIN 29 // UART Clear To Send pin number. Not used if HWFC is set to false. +#define SER_CON_RTS_PIN 0 // UART Request To Send pin number. Not used if HWFC is set to false. + + +#define SER_CON_SPIS_SCK_PIN 7 // SPI SCK signal. +#define SER_CON_SPIS_MOSI_PIN 0 // SPI MOSI signal. +#define SER_CON_SPIS_MISO_PIN 30 // SPI MISO signal. +#define SER_CON_SPIS_CSN_PIN 25 // SPI CSN signal. +#define SER_CON_SPIS_RDY_PIN 29 // SPI READY GPIO pin number. +#define SER_CON_SPIS_REQ_PIN 28 // SPI REQUEST GPIO pin number. + +// Arduino board mappings +#define ARDUINO_SCL_PIN 7 // SCL signal pin +#define ARDUINO_SDA_PIN 30 // SDA signal pin +#define ARDUINO_AREF_PIN 0 // Aref pin +#define ARDUINO_13_PIN 29 // Digital pin 13 +#define ARDUINO_12_PIN 28 // Digital pin 12 +#define ARDUINO_11_PIN 25 // Digital pin 11 +#define ARDUINO_10_PIN 24 // Digital pin 10 +#define ARDUINO_9_PIN 23 // Digital pin 9 +#define ARDUINO_8_PIN 20 // Digital pin 8 + +#define ARDUINO_7_PIN 19 // Digital pin 7 +#define ARDUINO_6_PIN 18 // Digital pin 6 +#define ARDUINO_5_PIN 17 // Digital pin 5 +#define ARDUINO_4_PIN 16 // Digital pin 4 +#define ARDUINO_3_PIN 15 // Digital pin 3 +#define ARDUINO_2_PIN 14 // Digital pin 2 +#define ARDUINO_1_PIN 13 // Digital pin 1 +#define ARDUINO_0_PIN 12 // Digital pin 0 + +#define ARDUINO_A0_PIN 1 // Analog channel 0 +#define ARDUINO_A1_PIN 2 // Analog channel 1 +#define ARDUINO_A2_PIN 3 // Analog channel 2 +#define ARDUINO_A3_PIN 4 // Analog channel 3 +#define ARDUINO_A4_PIN 5 // Analog channel 4 +#define ARDUINO_A5_PIN 6 // Analog channel 5 + +// Low frequency clock source to be used by the SoftDevice +#ifdef S210 +#define NRF_CLOCK_LFCLKSRC NRF_CLOCK_LFCLKSRC_XTAL_20_PPM +#else +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} +#endif + +#ifdef __cplusplus +} +#endif + +#endif // PCA10028_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10031.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10031.h new file mode 100644 index 0000000000..35d7301c21 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/boards/pca10031.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 PCA10031_H +#define PCA10031_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_gpio.h" + +// LEDs definitions for PCA10031 +#define LEDS_NUMBER 3 + +#define LED_START 21 +#define LED_RGB_RED 21 +#define LED_RGB_GREEN 22 +#define LED_RGB_BLUE 23 +#define LED_STOP 23 + +#define LEDS_ACTIVE_STATE 1 + +#define LEDS_INV_MASK LEDS_MASK + +#define LED_RGB_RED_MASK (1< +#include +#include +#include "nrf_soc.h" +#include "nordic_common.h" +#include "nrf_error.h" +#include "nrf.h" +#include "app_util.h" + + +static volatile bool m_radio_active = false; /**< TRUE if radio is active (or about to become active), FALSE otherwise. */ + + +uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc) +{ + uint16_t i; + uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc; + + for (i = 0; i < size; i++) + { + crc = (unsigned char)(crc >> 8) | (crc << 8); + crc ^= p_data[i]; + crc ^= (unsigned char)(crc & 0xff) >> 4; + crc ^= (crc << 8) << 4; + crc ^= ((crc & 0xff) << 4) << 1; + } + return crc; +} + + +/**@brief Function for erasing a page in flash. + * + * @param[in] p_page Pointer to first word in page to be erased. + */ +static void flash_page_erase(uint32_t * p_page) +{ + // Turn on flash erase enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + + // Erase page. + NRF_NVMC->ERASEPAGE = (uint32_t)p_page; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + + // Turn off flash erase enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing + } +} + + +/**@brief Function for writing one word to flash. Unprotected write, which can interfere with radio communication. + * + * @details This function DOES NOT use the m_radio_active variable, but will force the write even + * when the radio is active. To be used only from @ref ble_flash_page_write. + * + * @note Flash location to be written must have been erased previously. + * + * @param[in] p_address Pointer to flash location to be written. + * @param[in] value Value to write to flash. + */ +static void flash_word_unprotected_write(uint32_t * p_address, uint32_t value) +{ + // Turn on flash write enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + *p_address = value; + + // Wait flash write to finish + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + + // Turn off flash write enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } +} + + +/**@brief Function for writing one word to flash. + * + * @note Flash location to be written must have been erased previously. + * + * @param[in] p_address Pointer to flash location to be written. + * @param[in] value Value to write to flash. + */ +static void flash_word_write(uint32_t * p_address, uint32_t value) +{ + // If radio is active, wait for it to become inactive. + while (m_radio_active) + { + // Do nothing (just wait for radio to become inactive). + (void) sd_app_evt_wait(); + } + + // Turn on flash write enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + + *p_address = value; + // Wait flash write to finish + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing. + } + // Turn off flash write enable and wait until the NVMC is ready. + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) + { + // Do nothing + } +} + + +uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value) +{ + flash_word_write(p_address, value); + return NRF_SUCCESS; +} + + +uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count) +{ + uint16_t i; + + for (i = 0; i < word_count; i++) + { + flash_word_write(p_address, p_in_array[i]); + p_address++; + } + + return NRF_SUCCESS; +} + + +uint32_t ble_flash_page_erase(uint8_t page_num) +{ + uint32_t * p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); + flash_page_erase(p_page); + + return NRF_SUCCESS; +} + + +uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count) +{ + int i; + uint32_t * p_page; + uint32_t * p_curr_addr; + uint16_t in_data_crc; + uint16_t flash_crc; + uint32_t flash_header; + + p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); + p_curr_addr = p_page; + + // Calculate CRC of the data to write. + in_data_crc = ble_flash_crc16_compute((uint8_t *)p_in_array, + word_count * sizeof(uint32_t), + NULL); + + // Compare the calculated to the one in flash. + flash_header = *p_curr_addr; + flash_crc = (uint16_t)flash_header; + + if (flash_crc == in_data_crc) + { + // Data is the same as the data already stored in flash, return without modifying flash. + return NRF_SUCCESS; + } + + // Erase flash page + flash_page_erase(p_page); + + // Reserve space for magic number (for detecting if flash content is valid). + p_curr_addr++; + + // Reserve space for saving word_count. + p_curr_addr++; + + // Write data + for (i = 0; i < word_count; i++) + { + flash_word_unprotected_write(p_curr_addr, p_in_array[i]); + p_curr_addr++; + } + + // Write number of elements. + flash_word_write(p_page + 1, (uint32_t)(word_count)); + + // Write magic number and CRC to indicate that flash content is valid. + flash_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)in_data_crc; + flash_word_write(p_page, flash_header); + + return NRF_SUCCESS; +} + + +uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count) +{ + int byte_count; + uint32_t * p_page; + uint32_t * p_curr_addr; + uint32_t flash_header; + uint32_t calc_header; + uint16_t calc_crc; + uint32_t tmp; + + p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); + p_curr_addr = p_page; + + // Check if block is valid + flash_header = *p_curr_addr; + tmp = flash_header & 0xFFFF0000; + if (tmp != BLE_FLASH_MAGIC_NUMBER) + { + *p_word_count = 0; + return NRF_ERROR_NOT_FOUND; + } + p_curr_addr++; + + // Read number of elements + *p_word_count = (uint8_t)(*(p_curr_addr)); + p_curr_addr++; + + // Read data + byte_count = (*p_word_count) * sizeof(uint32_t); + memcpy(p_out_array, p_curr_addr, byte_count); + + // Check CRC + calc_crc = ble_flash_crc16_compute((uint8_t *)p_out_array, + (*p_word_count) * sizeof(uint32_t), + NULL); + calc_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)calc_crc; + + if (calc_header != flash_header) + { + return NRF_ERROR_NOT_FOUND; + } + + return NRF_SUCCESS; +} + + +uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr) +{ + *pp_page_addr = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); + return NRF_SUCCESS; +} + + +void ble_flash_on_radio_active_evt(bool radio_active) +{ + m_radio_active = radio_active; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ble_flash/ble_flash.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ble_flash/ble_flash.h new file mode 100644 index 0000000000..8fffeb62a7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ble_flash/ble_flash.h @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_flash_module Flash Manager + * @{ + * @ingroup ble_sdk_lib + * @brief Module for accessing flash memory. + * + * @details It contains functions for reading, writing and erasing one page in flash. + * + * The module uses the first 32 bits of the flash page to write a magic number in order to + * determine if the page has been written or not. + * + * @note Be careful not to use a page number in the SoftDevice area (which currently occupies the + * range 0 to 127), or in your application space! In both cases, this would end up + * with a hard fault. + */ + +#ifndef BLE_FLASH_H__ +#define BLE_FLASH_H__ + +#include +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_FLASH_PAGE_SIZE ((uint16_t)NRF_FICR->CODEPAGESIZE) /**< Size of one flash page. */ +#define BLE_FLASH_MAGIC_NUMBER 0x45DE0000 /**< Magic value to identify if flash contains valid data. */ +#define BLE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */ + + +/**@brief Macro for getting the end of the flash available for application. + * + * @details The result flash page number indicates the end boundary of the flash available + * to the application. If a bootloader is used, the end will be the start of the + * bootloader region. Otherwise, the end will be the size of the flash. + */ +#define BLE_FLASH_PAGE_END \ + ((NRF_UICR->NRFFW[0] != BLE_FLASH_EMPTY_MASK) \ + ? (NRF_UICR->NRFFW[0] / BLE_FLASH_PAGE_SIZE) \ + : NRF_FICR->CODESIZE) + +/**@brief Function for erasing the specified flash page, and then writes the given data to this page. + * + * @warning This operation blocks the CPU. DO NOT use while in a connection! + * + * @param[in] page_num Page number to update. + * @param[in] p_in_array Pointer to a RAM area containing the elements to write in flash. + * This area has to be 32 bits aligned. + * @param[in] word_count Number of 32 bits words to write in flash. + * + * @return NRF_SUCCESS on successful flash write, otherwise an error code. + */ +uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count); + +/**@brief Function for reading data from flash to RAM. + * + * @param[in] page_num Page number to read. + * @param[out] p_out_array Pointer to a RAM area where the found data will be written. + * This area has to be 32 bits aligned. + * @param[out] p_word_count Number of 32 bits words read. + * + * @return NRF_SUCCESS on successful upload, NRF_ERROR_NOT_FOUND if no valid data has been found + * in flash (first 32 bits not equal to the MAGIC_NUMBER + CRC). + */ +uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count); + +/**@brief Function for erasing a flash page. + * + * @note This operation blocks the CPU, so it should not be done while the radio is running! + * + * @param[in] page_num Page number to erase. + * + * @return NRF_SUCCESS on success, an error_code otherwise. + */ +uint32_t ble_flash_page_erase(uint8_t page_num); + +/**@brief Function for writing one word to flash. + * + * @note Flash location to be written must have been erased previously. + * + * @param[in] p_address Pointer to flash location to be written. + * @param[in] value Value to write to flash. + * + * @return NRF_SUCCESS. + */ +uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value); + +/**@brief Function for writing a data block to flash. + * + * @note Flash locations to be written must have been erased previously. + * + * @param[in] p_address Pointer to start of flash location to be written. + * @param[in] p_in_array Pointer to start of flash block to be written. + * @param[in] word_count Number of words to be written. + * + * @return NRF_SUCCESS. + */ +uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count); + +/**@brief Function for computing pointer to start of specified flash page. + * + * @param[in] page_num Page number. + * @param[out] pp_page_addr Pointer to start of flash page. + * + * @return NRF_SUCCESS. + */ +uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr); + +/**@brief Function for calculating a 16 bit CRC using the CRC-16-CCITT scheme. + * + * @param[in] p_data Pointer to data on which the CRC is to be calculated. + * @param[in] size Number of bytes on which the CRC is to be calculated. + * @param[in] p_crc Initial CRC value (if NULL, a preset value is used as the initial value). + * + * @return Calculated CRC. + */ +uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc); + +/**@brief Function for handling flashing module Radio Notification event. + * + * @note For flash writing to work safely while in a connection or while advertising, this function + * MUST be called from the Radio Notification module's event handler (see + * @ref ble_radio_notification for details). + * + * @param[in] radio_active TRUE if radio is active (or about to become active), FALSE otherwise. + */ +void ble_flash_on_radio_active_evt(bool radio_active); + + +#ifdef __cplusplus +} +#endif + +#endif // BLE_FLASH_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.c new file mode 100644 index 0000000000..cb02c3c7d7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.c @@ -0,0 +1,627 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(CLOCK) + +#include "nrf_drv_clock.h" +#include "nrf_error.h" +#include "app_util_platform.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +#define NRF_LOG_MODULE_NAME clock + +#if CLOCK_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \ + (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \ + (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : "UNKNOWN EVENT")))) +#else //CLOCK_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //CLOCK_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(CLOCK_CONFIG_IRQ_PRIORITY); + +/*lint -save -e652 */ +#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC +#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal +#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth +/*lint -restore */ + +#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT) +#define CALIBRATION_SUPPORT 1 +#else +#define CALIBRATION_SUPPORT 0 +#endif +typedef enum +{ + CAL_STATE_IDLE, + CAL_STATE_CT, + CAL_STATE_HFCLK_REQ, + CAL_STATE_CAL, + CAL_STATE_ABORT, +} nrf_drv_clock_cal_state_t; + +/**@brief CLOCK control block. */ +typedef struct +{ + bool module_initialized; /*< Indicate the state of module */ + volatile bool hfclk_on; /*< High-frequency clock state. */ + volatile bool lfclk_on; /*< Low-frequency clock state. */ + volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_hf_head; + volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */ + volatile nrf_drv_clock_handler_item_t * p_lf_head; +#if CALIBRATION_SUPPORT + nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item; + nrf_drv_clock_event_handler_t cal_done_handler; + volatile nrf_drv_clock_cal_state_t cal_state; +#endif // CALIBRATION_SUPPORT +} nrf_drv_clock_cb_t; + +static nrf_drv_clock_cb_t m_clock_cb; + + +/**@brief Function for starting LFCLK. This function will return immediately without waiting for start. + */ +static void lfclk_start(void) +{ + nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART); +} + +/**@brief Function for stopping LFCLK and calibration (if it was set up). + */ +static void lfclk_stop(void) +{ +#if CALIBRATION_SUPPORT + (void)nrf_drv_clock_calibration_abort(); +#endif + +#ifdef SOFTDEVICE_PRESENT + // If LFCLK is requested to stop while SD is still enabled, + // it indicates an error in the application. + // Enabling SD should increment the LFCLK request. + ASSERT(!nrf_sdh_is_enabled()); +#endif // SOFTDEVICE_PRESENT + + nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP); + while (nrf_clock_lf_is_running()) + {} + m_clock_cb.lfclk_on = false; +} + +static void hfclk_start(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_request(); + return; + } +#endif // SOFTDEVICE_PRESENT + + nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); +} + +static void hfclk_stop(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void)sd_clock_hfclk_release(); + return; + } +#endif // SOFTDEVICE_PRESENT + + nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); + while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY)) + {} + m_clock_cb.hfclk_on = false; +} + +bool nrf_drv_clock_init_check(void) +{ + return m_clock_cb.module_initialized; +} + +ret_code_t nrf_drv_clock_init(void) +{ + ret_code_t err_code = NRF_SUCCESS; + if (m_clock_cb.module_initialized) + { + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + else + { + m_clock_cb.p_hf_head = NULL; + m_clock_cb.hfclk_requests = 0; + m_clock_cb.p_lf_head = NULL; + m_clock_cb.lfclk_requests = 0; + nrf_drv_common_power_clock_irq_init(); +#ifdef SOFTDEVICE_PRESENT + if (!nrf_sdh_is_enabled()) +#endif + { + nrf_clock_lf_src_set((nrf_clock_lfclk_t)CLOCK_CONFIG_LF_SRC); + } + +#if CALIBRATION_SUPPORT + m_clock_cb.cal_state = CAL_STATE_IDLE; +#endif + + m_clock_cb.module_initialized = true; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_clock_uninit(void) +{ + ASSERT(m_clock_cb.module_initialized); + nrf_drv_common_clock_irq_disable(); + nrf_clock_int_disable(0xFFFFFFFF); + + lfclk_stop(); + hfclk_stop(); + m_clock_cb.module_initialized = false; + NRF_LOG_INFO("Uninitialized."); +} + +static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head, + nrf_drv_clock_handler_item_t * p_item) +{ + nrf_drv_clock_handler_item_t * p_next = *p_head; + while (p_next) + { + if (p_next == p_item) + { + return; + } + p_next = p_next->p_next; + } + + p_item->p_next = (*p_head ? *p_head : NULL); + *p_head = p_item; +} + +static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head) +{ + nrf_drv_clock_handler_item_t * p_item = *p_head; + if (p_item) + { + *p_head = p_item->p_next; + } + return p_item; +} + +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.lfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, + p_handler_item); + } + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_start(); + } + ++(m_clock_cb.lfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.lfclk_requests > 0); +} + +void nrf_drv_clock_lfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.lfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.lfclk_requests); + if (m_clock_cb.lfclk_requests == 0) + { + lfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_lfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return true; + } +#endif // SOFTDEVICE_PRESENT + + return nrf_clock_lf_is_running(); +} + +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item) +{ + ASSERT(m_clock_cb.module_initialized); + + if (m_clock_cb.hfclk_on) + { + if (p_handler_item) + { + p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + CRITICAL_REGION_ENTER(); + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + if (p_handler_item) + { + item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, + p_handler_item); + } + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_start(); + } + ++(m_clock_cb.hfclk_requests); + CRITICAL_REGION_EXIT(); + } + + ASSERT(m_clock_cb.hfclk_requests > 0); +} + +void nrf_drv_clock_hfclk_release(void) +{ + ASSERT(m_clock_cb.module_initialized); + ASSERT(m_clock_cb.hfclk_requests > 0); + + CRITICAL_REGION_ENTER(); + --(m_clock_cb.hfclk_requests); + if (m_clock_cb.hfclk_requests == 0) + { + hfclk_stop(); + } + CRITICAL_REGION_EXIT(); +} + +bool nrf_drv_clock_hfclk_is_running(void) +{ + ASSERT(m_clock_cb.module_initialized); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + uint32_t is_running; + UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running)); + return (is_running ? true : false); + } +#endif // SOFTDEVICE_PRESENT + + return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); +} + +#if CALIBRATION_SUPPORT +static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event) +{ + if (m_clock_cb.cal_state == CAL_STATE_ABORT) + { + nrf_drv_clock_hfclk_release(); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + } + else + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE); + nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK); + m_clock_cb.cal_state = CAL_STATE_CAL; + nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL); + } +} +#endif // CALIBRATION_SUPPORT + +ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE); + if (m_clock_cb.lfclk_on == false) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_clock_cb.cal_state == CAL_STATE_IDLE) + { + m_clock_cb.cal_done_handler = handler; + m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started; + if (interval == 0) + { + m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ; + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + else + { + m_clock_cb.cal_state = CAL_STATE_CT; + nrf_clock_cal_timer_timeout_set(interval); + nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO); + nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART); + } + } + else + { + err_code = NRF_ERROR_BUSY; + } + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_calibration_abort(void) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + CRITICAL_REGION_ENTER(); + switch (m_clock_cb.cal_state) + { + case CAL_STATE_CT: + nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK); + nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED); + } + break; + case CAL_STATE_HFCLK_REQ: + /* fall through. */ + case CAL_STATE_CAL: + m_clock_cb.cal_state = CAL_STATE_ABORT; + break; + default: + break; + } + CRITICAL_REGION_EXIT(); + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating) +{ + ret_code_t err_code = NRF_SUCCESS; +#if CALIBRATION_SUPPORT + ASSERT(m_clock_cb.module_initialized); + *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE); + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_FORBIDDEN; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif // CALIBRATION_SUPPORT +} + +__STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type) +{ + nrf_drv_clock_handler_item_t **p_head; + if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED) + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head; + } + else + { + p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head; + } + + while (1) + { + nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head); + if (!p_item) + { + break; + } + + p_item->event_handler(evt_type); + } +} + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void nrf_drv_clock_onIRQ(void) +#else +void POWER_CLOCK_IRQHandler(void) +#endif +{ + if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_HFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK); + m_clock_cb.hfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } + if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_LFCLKSTARTED)); + nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK); + m_clock_cb.lfclk_on = true; + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED); + } +#if CALIBRATION_SUPPORT + if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_CTTO)); + nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK); + nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item); + } + + if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE)) + { + nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_CLOCK_EVENT_DONE)); + nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK); + nrf_drv_clock_hfclk_release(); + bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT); + m_clock_cb.cal_state = CAL_STATE_IDLE; + if (m_clock_cb.cal_done_handler) + { + m_clock_cb.cal_done_handler(aborted ? + NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE); + } + } +#endif // CALIBRATION_SUPPORT +} + +#ifdef SOFTDEVICE_PRESENT +/** + * @brief SoftDevice SoC event handler. + * + * @param[in] evt_id SoC event. + * @param[in] p_context Context. + */ +static void soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_HFCLKSTARTED) + { + clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED); + } +} + +NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL); + +/** + * @brief SoftDevice enable/disable state handler. + * + * @param[in] state State. + * @param[in] p_context Context. + */ +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + NVIC_DisableIRQ(POWER_CLOCK_IRQn); + break; + + case NRF_SDH_EVT_STATE_ENABLED: + CRITICAL_REGION_ENTER(); + /* Make sure that nrf_drv_clock module is initialized */ + if (!m_clock_cb.module_initialized) + { + (void)nrf_drv_clock_init(); + } + /* SD is one of the LFCLK requesters, but it will enable it by itself. */ + ++(m_clock_cb.lfclk_requests); + m_clock_cb.lfclk_on = true; + CRITICAL_REGION_EXIT(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + /* Reinit interrupts */ + ASSERT(m_clock_cb.module_initialized); + nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + + /* SD leaves LFCLK enabled - disable it if it is no longer required. */ + nrf_drv_clock_lfclk_release(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +#undef NRF_CLOCK_LFCLK_RC +#undef NRF_CLOCK_LFCLK_Xtal +#undef NRF_CLOCK_LFCLK_Synth + +#endif // NRF_MODULE_ENABLED(CLOCK) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.h new file mode 100644 index 0000000000..be2831bee6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/clock/nrf_drv_clock.h @@ -0,0 +1,285 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_CLOCK_H__ +#define NRF_DRV_CLOCK_H__ + +#include +#include +#include "sdk_errors.h" +#include "nrf_assert.h" +#include "nrf_clock.h" +#include "sdk_config.h" +#include "nrf_drv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @addtogroup nrf_clock Clock HAL and driver + * @ingroup nrf_drivers + * @brief Clock APIs. + * @details The clock HAL provides basic APIs for accessing the registers of the clock. + * The clock driver provides APIs on a higher level. + * + * @defgroup nrf_drv_clock Clock driver + * @{ + * @ingroup nrf_clock + * @brief Driver for managing the low-frequency clock (LFCLK) and the high-frequency clock (HFCLK). + */ + +/** + * @brief Clock events. + */ +typedef enum +{ + NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started. + NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started. + NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done. + NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted. +} nrf_drv_clock_evt_type_t; + +/** + * @brief Clock event handler. + * + * @param[in] event Event. + */ +typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event); + +// Forward declaration of the nrf_drv_clock_handler_item_t type. +typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t; + +struct nrf_drv_clock_handler_item_s +{ + nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started. + nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started. +}; + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whatever common POWER_CLOCK common interrupt + * should be disabled or not if @ref nrf_drv_power tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + */ +bool nrf_drv_clock_init_check(void); + +/** + * @brief Function for initializing the nrf_drv_clock module. + * + * After initialization, the module is in power off state (clocks are not requested). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized. + */ +ret_code_t nrf_drv_clock_init(void); + +/** + * @brief Function for uninitializing the clock module. + * + */ +void nrf_drv_clock_uninit(void); + +/** + * @brief Function for requesting the LFCLK. + * + * The low-frequency clock can be requested by different modules + * or contexts. The driver ensures that the clock will be started only when it is requested + * the first time. If the clock is not ready but it was already started, the handler item that is + * provided as an input parameter is added to the list of handlers that will be notified + * when the clock is started. If the clock is already enabled, user callback is called from the + * current context. + * + * The first request will start the selected LFCLK source. If an event handler is + * provided, it will be called once the LFCLK is started. If the LFCLK was already started at this + * time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started. + * + * @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it. + * + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the LFCLK. + * + * If there are no more requests, the LFCLK source will be stopped. + * + * @note When a SoftDevice is enabled, the LFCLK is always running. + */ +void nrf_drv_clock_lfclk_release(void); + +/** + * @brief Function for checking the LFCLK state. + * + * @retval true If the LFCLK is running. + * @retval false If the LFCLK is not running. + */ +bool nrf_drv_clock_lfclk_is_running(void); + +/** + * @brief Function for requesting the high-accuracy source HFCLK. + * + * The high-accuracy source + * can be requested by different modules or contexts. The driver ensures that the high-accuracy + * clock will be started only when it is requested the first time. If the clock is not ready + * but it was already started, the handler item that is provided as an input parameter is added + * to the list of handlers that will be notified when the clock is started. + * + * If an event handler is provided, it will be called once the clock is started. If the clock was already + * started at this time, the event handler will be called from the context of this function. Additionally, + * the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started. + * + * @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by + * the SoftDevice. This function cannot be called from all interrupt priority levels in that case. + * @note The handler item provided by the user cannot be an automatic variable. + * + * @param[in] p_handler_item A pointer to the event handler structure. + */ +void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item); + +/** + * @brief Function for releasing the high-accuracy source HFCLK. + * + * If there are no more requests, the high-accuracy source will be released. + */ +void nrf_drv_clock_hfclk_release(void); + +/** + * @brief Function for checking the HFCLK state. + * + * @retval true If the HFCLK is running (for \nRFXX XTAL source). + * @retval false If the HFCLK is not running. + */ +bool nrf_drv_clock_hfclk_is_running(void); + +/** + * @brief Function for starting a single calibration process. + * + * This function can also delay the start of calibration by a user-specified value. The delay will use + * a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to + * check if calibration is still in progress. If a handler is provided, the user can be notified when + * calibration is completed. The ext calibration can be started from the handler context. + * + * The calibration process consists of three phases: + * - Delay (optional) + * - Requesting the high-accuracy HFCLK + * - Hardware-supported calibration + * + * @param[in] delay Time after which the calibration will be started (in 0.25 s units). + * @param[in] handler NULL or user function to be called when calibration is completed or aborted. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + * @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off. + * @retval NRF_ERROR_BUSY If calibration is in progress. + */ +ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler); + +/** + * @brief Function for aborting calibration. + * + * This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler + * was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once + * aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check + * if the system is calibrating. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_calibration_abort(void); + +/** + * @brief Function for checking if calibration is in progress. + * + * This function indicates that the system is + * in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start). + * + * @param[out] p_is_calibrating True if calibration is in progress, false if not. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator. + */ +ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating); + +/**@brief Function for returning a requested task address for the clock driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task); + +/**@brief Function for returning a requested event address for the clock driver module. + * + * @param[in] event One of the peripheral events. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event); +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task) +{ + return nrf_clock_task_address_get(task); +} + +__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event) +{ + return nrf_clock_event_address_get(event); +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +/*lint --flb "Leave library region" */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CLOCK_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.c new file mode 100644 index 0000000000..8d93e97f60 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.c @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "nrf_drv_common.h" +#include "nrf_assert.h" +#include "app_util_platform.h" +#include "nrf_peripherals.h" + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +#include "nrf_drv_power.h" +#include "nrf_drv_clock.h" +#endif +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#endif + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +#define NRF_LOG_MODULE_NAME common + +#if COMMON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL COMMON_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR COMMON_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR COMMON_CONFIG_DEBUG_COLOR +#else //COMMON_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //COMMON_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +typedef struct { + nrf_drv_irq_handler_t handler; + bool acquired; +} shared_resource_t; + +// SPIM0, SPIS0, SPI0, TWIM0, TWIS0, TWI0 +#if (NRF_MODULE_ENABLED(SPI0) || NRF_MODULE_ENABLED(SPIS0) || NRF_MODULE_ENABLED(TWI0) || NRF_MODULE_ENABLED(TWIS0)) + #define SERIAL_BOX_0_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_0 + #define IS_SERIAL_BOX_0(p_per_base) (p_per_base == NRF_SPI0) + #endif + + static shared_resource_t m_serial_box_0 = { .acquired = false }; + void SPI0_TWI0_IRQHandler(void) + { + ASSERT(m_serial_box_0.handler); + m_serial_box_0.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI0) || NRF_MODULE_ENABLED(SPIS0) || NRF_MODULE_ENABLED(TWI0) || NRF_MODULE_ENABLED(TWIS0)) + +// SPIM1, SPIS1, SPI1, TWIM1, TWIS1, TWI1 +#if (NRF_MODULE_ENABLED(SPI1) || NRF_MODULE_ENABLED(SPIS1) || NRF_MODULE_ENABLED(TWI1) || NRF_MODULE_ENABLED(TWIS1)) + #define SERIAL_BOX_1_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_1 + #define IS_SERIAL_BOX_1(p_per_base) (p_per_base == NRF_SPI1) + #endif + + static shared_resource_t m_serial_box_1 = { .acquired = false }; +#ifdef TWIM_PRESENT + void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void) +#else + void SPI1_TWI1_IRQHandler(void) +#endif + { + ASSERT(m_serial_box_1.handler); + m_serial_box_1.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI1) || NRF_MODULE_ENABLED(SPIS1) || NRF_MODULE_ENABLED(TWI1) || NRF_MODULE_ENABLED(TWIS1)) + +// SPIM2, SPIS2, SPI2 +#if (NRF_MODULE_ENABLED(SPI2) || NRF_MODULE_ENABLED(SPIS2)) + #define SERIAL_BOX_2_IN_USE + // [this checking may need a different form in unit tests, hence macro] + #ifndef IS_SERIAL_BOX_2 + #define IS_SERIAL_BOX_2(p_per_base) (p_per_base == NRF_SPI2) + #endif + + static shared_resource_t m_serial_box_2 = { .acquired = false }; + void SPIM2_SPIS2_SPI2_IRQHandler(void) + { + ASSERT(m_serial_box_2.handler); + m_serial_box_2.handler(); + } +#endif // (NRF_MODULE_ENABLED(SPI2) || NRF_MODULE_ENABLED(SPIS2)) + +// COMP, LPCOMP +#if (NRF_MODULE_ENABLED(COMP) || NRF_MODULE_ENABLED(LPCOMP)) + #define COMP_LPCOMP_IN_USE + + #ifndef IS_COMP_LPCOMP + #define IS_COMP_LPCOMP(p_per_base) ((p_per_base) == NRF_LPCOMP) + #endif + + static shared_resource_t m_comp_lpcomp = { .acquired = false }; + void LPCOMP_IRQHandler(void) + { + ASSERT(m_comp_lpcomp.handler); + m_comp_lpcomp.handler(); + } +#endif // (NRF_MODULE_ENABLED(COMP) || NRF_MODULE_ENABLED(LPCOMP)) + +#if defined(SERIAL_BOX_0_IN_USE) || \ + defined(SERIAL_BOX_1_IN_USE) || \ + defined(SERIAL_BOX_2_IN_USE) || \ + defined(COMP_LPCOMP_IN_USE) +static ret_code_t acquire_shared_resource(shared_resource_t * p_resource, + nrf_drv_irq_handler_t handler) +{ + ret_code_t err_code; + + bool busy = false; + + CRITICAL_REGION_ENTER(); + if (p_resource->acquired) + { + busy = true; + } + else + { + p_resource->acquired = true; + } + CRITICAL_REGION_EXIT(); + + if (busy) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + p_resource->handler = handler; + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} +#endif + +ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base, + nrf_drv_irq_handler_t handler) +{ +#ifdef SERIAL_BOX_0_IN_USE + if (IS_SERIAL_BOX_0(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_0, handler); + } +#endif + +#ifdef SERIAL_BOX_1_IN_USE + if (IS_SERIAL_BOX_1(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_1, handler); + } +#endif + +#ifdef SERIAL_BOX_2_IN_USE + if (IS_SERIAL_BOX_2(p_per_base)) + { + return acquire_shared_resource(&m_serial_box_2, handler); + } +#endif + +#ifdef COMP_LPCOMP_IN_USE + if (IS_COMP_LPCOMP(p_per_base)) + { + return acquire_shared_resource(&m_comp_lpcomp, handler); + } +#endif + ret_code_t err_code; + + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_common_per_res_release(void const * p_per_base) +{ +#ifdef SERIAL_BOX_0_IN_USE + if (IS_SERIAL_BOX_0(p_per_base)) + { + m_serial_box_0.acquired = false; + } + else +#endif + +#ifdef SERIAL_BOX_1_IN_USE + if (IS_SERIAL_BOX_1(p_per_base)) + { + m_serial_box_1.acquired = false; + } + else +#endif + +#ifdef SERIAL_BOX_2_IN_USE + if (IS_SERIAL_BOX_2(p_per_base)) + { + m_serial_box_2.acquired = false; + } + else +#endif + +#ifdef COMP_LPCOMP_IN_USE + if (IS_COMP_LPCOMP(p_per_base)) + { + m_comp_lpcomp.acquired = false; + } + else +#endif + + {} +} + +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +#if NRF_MODULE_ENABLED(POWER) +void nrf_drv_common_power_irq_disable(void) +{ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + if (!nrf_drv_clock_init_check()) +#endif + { + nrf_drv_common_irq_disable(POWER_CLOCK_IRQn); + } +} +#endif + +#if NRF_MODULE_ENABLED(CLOCK) +void nrf_drv_common_clock_irq_disable(void) +{ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + if (!nrf_drv_power_init_check()) +#endif + { + nrf_drv_common_irq_disable(POWER_CLOCK_IRQn); + } +} +#endif + +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void POWER_CLOCK_IRQHandler(void) +{ + extern void nrf_drv_clock_onIRQ(void); + extern void nrf_drv_power_onIRQ(void); + + nrf_drv_clock_onIRQ(); + nrf_drv_power_onIRQ(); +} +#endif // NRF_DRV_COMMON_POWER_CLOCK_ISR + + +void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority) +{ + INTERRUPT_PRIORITY_ASSERT(priority); + + NVIC_SetPriority(IRQn, priority); + NVIC_ClearPendingIRQ(IRQn); + NVIC_EnableIRQ(IRQn); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.h new file mode 100644 index 0000000000..cdf866a5cc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/common/nrf_drv_common.h @@ -0,0 +1,358 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_COMMON_H__ +#define NRF_DRV_COMMON_H__ + +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "sdk_common.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NRF51 +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) (((pri) == 1) || ((pri) == 3)) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 4) +#endif //SOFTDEVICE_PRESENT +#else +#ifdef SOFTDEVICE_PRESENT +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((((pri) > 1) && ((pri) < 4)) || \ + (((pri) > 4) && ((pri) < 8))) +#else +#define INTERRUPT_PRIORITY_IS_VALID(pri) ((pri) < 8) +#endif //SOFTDEVICE_PRESENT +#endif //NRF52 + +#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) +#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri))) + +/** + * @defgroup nrf_drv_common Peripheral drivers common module + * @{ + * @ingroup nrf_drivers + */ + +/** + * @brief Offset of event registers in every peripheral instance. + * + * This is the offset where event registers start in every peripheral. + */ +#define NRF_DRV_COMMON_EVREGS_OFFSET 0x100U + +/** + * @brief The flag that is set when POWER_CLOCK ISR is implemented in common module + * + * This flag means that the function POWER_CLOCK_IRQHandler is implemented in + * nrf_drv_common.c file. In the @c clock and @c power modules functions + * nrf_drv_clock_onIRQ nrf_drv_power_onIRQ should be implemented + * and they would be called from common implementation. + * + * None of the checking is done here. + * The implementation functions in @c clock and @c power are required to handle + * correctly the case when they are called without any event bit set. + */ +#define NRF_DRV_COMMON_POWER_CLOCK_ISR (NRF_MODULE_ENABLED(CLOCK) && NRF_MODULE_ENABLED(POWER)) + +/** + * @brief Driver state. + */ +typedef enum +{ + NRF_DRV_STATE_UNINITIALIZED, /**< Uninitialized. */ + NRF_DRV_STATE_INITIALIZED, /**< Initialized but powered off. */ + NRF_DRV_STATE_POWERED_ON +} nrf_drv_state_t; + +/** + * @brief Driver power state selection. + */ +typedef enum +{ + NRF_DRV_PWR_CTRL_ON, /**< Power on request. */ + NRF_DRV_PWR_CTRL_OFF /**< Power off request. */ +} nrf_drv_pwr_ctrl_t; + +/** + * @brief IRQ handler type. + */ +typedef void (*nrf_drv_irq_handler_t)(void); + + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +/** + * @brief Function for acquiring shared peripheral resources associated with + * the specified peripheral. + * + * Certain resources and registers are shared among peripherals that have + * the same ID (for example: SPI0, SPIM0, SPIS0, TWI0, TWIM0, and TWIS0). + * Only one of them can be utilized at a given time. This function reserves + * proper resources to be used by the specified peripheral. + * If PERIPHERAL_RESOURCE_SHARING_ENABLED is set to a non-zero value, IRQ + * handlers for peripherals that are sharing resources with others are + * implemented by the nrf_drv_common module instead of individual drivers. + * The drivers must then specify their interrupt handling routines and + * register them by using this function. + * + * @param[in] p_per_base Requested peripheral base pointer. + * @param[in] handler Interrupt handler to register. May be NULL + * if interrupts are not used for the peripheral. + * + * @retval NRF_SUCCESS If resources were acquired successfully. + * @retval NRF_ERROR_BUSY If resources were already acquired. + * @retval NRF_ERROR_INVALID_PARAM If the specified peripheral is not enabled + * or the peripheral does not share resources + * with other peripherals. + */ +ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base, + nrf_drv_irq_handler_t handler); + +/** + * @brief Function for releasing shared resources reserved previously by + * @ref nrf_drv_common_per_res_acquire() for the specified peripheral. + * + * @param[in] p_per_base Requested peripheral base pointer. + */ +void nrf_drv_common_per_res_release(void const * p_per_base); + +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + + +/** + * @brief Function sets priority and enables NVIC interrupt + * + * @note Function checks if correct priority is used when softdevice is present + * + * @param[in] IRQn Interrupt id + * @param[in] priority Interrupt priority + */ +void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority); + +#if NRF_MODULE_ENABLED(POWER) +/** + * @brief Disable power IRQ + * + * Power and clock peripheral uses the same IRQ. + * This function disables POWER_CLOCK IRQ only if CLOCK driver + * is uninitialized. + * + * @sa nrf_drv_common_power_clock_irq_init + */ +void nrf_drv_common_power_irq_disable(void); +#endif + +#if NRF_MODULE_ENABLED(CLOCK) +/** + * @brief Disable clock IRQ + * + * Power and clock peripheral uses the same IRQ. + * This function disables POWER_CLOCK IRQ only if POWER driver + * is uninitialized. + * + * @sa nrf_drv_common_power_clock_irq_init + */ +void nrf_drv_common_clock_irq_disable(void); +#endif + +/** + * @brief Check if interrupt is enabled + * + * Function that checks if selected interrupt is enabled. + * + * @param[in] IRQn Interrupt id + * + * @retval true Selected IRQ is enabled. + * @retval false Selected IRQ is disabled. + */ +__STATIC_INLINE bool nrf_drv_common_irq_enable_check(IRQn_Type IRQn); + +/** + * @brief Function disables NVIC interrupt + * + * @param[in] IRQn Interrupt id + */ +__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn); + +/** + * @brief Convert bit position to event code + * + * Function for converting the bit position in INTEN register to event code + * that is equivalent to the offset of the event register from the beginning + * of peripheral instance. + * + * For example the result of this function can be casted directly to + * the types like @ref nrf_twis_event_t or @ref nrf_rng_event_t + * + * @param bit Bit position in INTEN register + * @return Event code to be casted to the right enum type or to be used in functions like + * @ref nrf_rng_event_get + * + * @sa nrf_drv_event_to_bitpos + */ +__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit); + +/** + * @brief Convert event code to bit position + * + * This function can be used to get bit position in INTEN register from event code. + * + * @param event Event code that may be casted from enum values from types like + * @ref nrf_twis_event_t or @ref nrf_rng_event_t + * @return Bit position in INTEN register that corresponds to the given code. + * + * @sa nrf_drv_bitpos_to_event + */ +__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event); + +/** + * @brief Get interrupt number connected with given instance + * + * Function returns interrupt number for a given instance of any peripheral. + * @param[in] pinst Pointer to peripheral registry + * @return Interrupt number + */ +__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst); + +#if NRF_MODULE_ENABLED(CLOCK) || NRF_MODULE_ENABLED(POWER) +/** + * @brief Enable and setup power clock IRQ + * + * This function would be called from @ref nrf_drv_clock and @ref nrf_drv_power + * to enable related interrupt. + * This function avoids multiple interrupt configuration. + * + * @note + * This function is aviable only if @ref nrf_drv_clock or @ref nrf_drv_power + * module is enabled. + * + * @note + * If both @ref nrf_drv_clock and @ref nrf_drv_power modules are enabled, + * during the compilation the check is made that + * @ref CLOCK_CONFIG_IRQ_PRIORITY equals @ref POWER_CONFIG_IRQ_PRIORITY. + * + * @sa nrf_drv_common_power_irq_disable + * @sa nrf_drv_common_clock_irq_disable + */ +__STATIC_INLINE void nrf_drv_common_power_clock_irq_init(void); +#endif + +/** + * @brief Check if given object is in RAM + * + * Function for analyzing if given location is placed in RAM. + * This function is used to determine if we have address that can be supported by EasyDMA. + * @param[in] ptr Pointer to the object + * @retval true Object is located in RAM + * @retval false Object is not located in RAM + */ +__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE bool nrf_drv_common_irq_enable_check(IRQn_Type IRQn) +{ + return 0 != (NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & + (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))); +} + +__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn) +{ + NVIC_DisableIRQ(IRQn); +} + +__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit) +{ + return NRF_DRV_COMMON_EVREGS_OFFSET + bit * sizeof(uint32_t); +} + +__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event) +{ + return (event - NRF_DRV_COMMON_EVREGS_OFFSET) / sizeof(uint32_t); +} + +__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst) +{ + uint8_t ret = (uint8_t)((uint32_t)pinst>>12U); + return (IRQn_Type) ret; +} + +#if NRF_MODULE_ENABLED(CLOCK) || NRF_MODULE_ENABLED(POWER) +__STATIC_INLINE void nrf_drv_common_power_clock_irq_init(void) +{ + if (!nrf_drv_common_irq_enable_check(POWER_CLOCK_IRQn)) + { + nrf_drv_common_irq_enable( + POWER_CLOCK_IRQn, +#if NRF_DRV_COMMON_POWER_CLOCK_ISR + #if CLOCK_CONFIG_IRQ_PRIORITY != POWER_CONFIG_IRQ_PRIORITY + #error CLOCK_CONFIG_IRQ_PRIORITY and POWER_CONFIG_IRQ_PRIORITY have to be the same. + #endif + CLOCK_CONFIG_IRQ_PRIORITY +#elif NRF_MODULE_ENABLED(CLOCK) + CLOCK_CONFIG_IRQ_PRIORITY +#elif NRF_MODULE_ENABLED(POWER) + POWER_CONFIG_IRQ_PRIORITY +#endif + ); + } +} +#endif + +__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr) +{ + return ((((uintptr_t)ptr) & 0xE0000000u) == 0x20000000u); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_COMMON_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.c new file mode 100644 index 0000000000..90d56e0730 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.c @@ -0,0 +1,239 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(COMP) +#include "nrf_drv_comp.h" + +#include "nrf_assert.h" +#include "nrf_error.h" +#include "nrf_soc.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" +#include +#include +#include + +#define NRF_LOG_MODULE_NAME comp + +#if COMP_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL COMP_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR COMP_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR COMP_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_COMP_EVENT_READY ? "NRF_COMP_EVENT_READY" : \ + (event == NRF_COMP_EVENT_DOWN ? "NRF_COMP_EVENT_DOWN" : \ + (event == NRF_COMP_EVENT_UP ? "NRF_COMP_EVENT_UP" : \ + (event == NRF_COMP_EVENT_CROSS ? "NRF_COMP_EVENT_CROSS" : "UNKNOWN ERROR")))) +#else //COMP_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //COMP_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + + +static comp_events_handler_t m_comp_events_handler = NULL; +static nrf_drv_state_t m_state = NRF_DRV_STATE_UNINITIALIZED; + +static const nrf_drv_comp_config_t m_default_config = NRF_DRV_COMP_DEFAULT_CONFIG(NRF_COMP_INPUT_0); + +static void comp_execute_handler(nrf_comp_event_t event, uint32_t event_mask) +{ + if ( nrf_comp_event_check(event) && nrf_comp_int_enable_check(event_mask) ) + { + nrf_comp_event_clear(event); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(event)); + + m_comp_events_handler(event); + } +} + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME irq_handler_for_comp + #define IRQ_HANDLER static void IRQ_HANDLER_NAME(void) + + IRQ_HANDLER; +#else + #define IRQ_HANDLER void COMP_LPCOMP_IRQHandler(void) +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +IRQ_HANDLER +{ + comp_execute_handler(NRF_COMP_EVENT_READY, COMP_INTENSET_READY_Msk); + comp_execute_handler(NRF_COMP_EVENT_DOWN, COMP_INTENSET_DOWN_Msk); + comp_execute_handler(NRF_COMP_EVENT_UP, COMP_INTENSET_UP_Msk); + comp_execute_handler(NRF_COMP_EVENT_CROSS, COMP_INTENSET_CROSS_Msk); +} + + +ret_code_t nrf_drv_comp_init(const nrf_drv_comp_config_t * p_config, + comp_events_handler_t event_handler) +{ + ret_code_t err_code; + + if (m_state != NRF_DRV_STATE_UNINITIALIZED) + { // COMP driver is already initialized + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(NRF_COMP, IRQ_HANDLER_NAME) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif + + nrf_comp_task_trigger(NRF_COMP_TASK_STOP); + nrf_comp_enable(); + + // Clear events to be sure there are no leftovers. + nrf_comp_event_clear(NRF_COMP_EVENT_READY); + nrf_comp_event_clear(NRF_COMP_EVENT_DOWN); + nrf_comp_event_clear(NRF_COMP_EVENT_UP); + nrf_comp_event_clear(NRF_COMP_EVENT_CROSS); + + nrf_comp_ref_set(p_config->reference); + + //If external source is chosen, write to appropriate register. + if (p_config->reference == COMP_REFSEL_REFSEL_ARef) + { + nrf_comp_ext_ref_set(p_config->ext_ref); + } + + nrf_comp_th_set(p_config->threshold); + nrf_comp_main_mode_set(p_config->main_mode); + nrf_comp_speed_mode_set(p_config->speed_mode); + nrf_comp_hysteresis_set(p_config->hyst); +#if defined (COMP_ISOURCE_ISOURCE_Msk) + nrf_comp_isource_set(p_config->isource); +#endif + nrf_comp_shorts_disable(NRF_DRV_COMP_SHORT_STOP_AFTER_CROSS_EVT | NRF_DRV_COMP_SHORT_STOP_AFTER_UP_EVT | + NRF_DRV_COMP_SHORT_STOP_AFTER_DOWN_EVT); + nrf_comp_int_disable(COMP_INTENCLR_CROSS_Msk | COMP_INTENCLR_UP_Msk | + COMP_INTENCLR_DOWN_Msk | COMP_INTENCLR_READY_Msk); + + if (event_handler) + { + m_comp_events_handler = event_handler; + } + else + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_comp_input_select(p_config->input); + + nrf_drv_common_irq_enable(COMP_LPCOMP_IRQn, p_config->interrupt_priority); + + m_state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_comp_uninit(void) +{ + ASSERT(m_state != NRF_DRV_STATE_UNINITIALIZED); + nrf_drv_common_irq_disable(COMP_LPCOMP_IRQn); + nrf_comp_disable(); +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(NRF_COMP); +#endif + m_state = NRF_DRV_STATE_UNINITIALIZED; + m_comp_events_handler = NULL; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_comp_pin_select(nrf_comp_input_t psel) +{ + bool comp_enable_state = nrf_comp_enable_check(); + nrf_comp_task_trigger(NRF_COMP_TASK_STOP); + if (m_state == NRF_DRV_STATE_POWERED_ON) + { + m_state = NRF_DRV_STATE_INITIALIZED; + } + nrf_comp_disable(); + nrf_comp_input_select(psel); + if (comp_enable_state == true) + { + nrf_comp_enable(); + } +} + +void nrf_drv_comp_start(uint32_t comp_int_mask, uint32_t comp_shorts_mask) +{ + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + nrf_comp_int_enable(comp_int_mask); + nrf_comp_shorts_enable(comp_shorts_mask); + nrf_comp_task_trigger(NRF_COMP_TASK_START); + m_state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled."); +} + +void nrf_drv_comp_stop(void) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_comp_shorts_disable(UINT32_MAX); + nrf_comp_int_disable(UINT32_MAX); + nrf_comp_task_trigger(NRF_COMP_TASK_STOP); + m_state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled."); +} + +uint32_t nrf_drv_comp_sample() +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_comp_task_trigger(NRF_COMP_TASK_SAMPLE); + return nrf_comp_result_get(); +} +#endif //NRF_MODULE_ENABLED(COMP) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.h new file mode 100644 index 0000000000..3c03c1d8d2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/comp/nrf_drv_comp.h @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_COMP_H__ +#define NRF_DRV_COMP_H__ + +#include "sdk_config.h" +#include "nrf_comp.h" +#include "sdk_errors.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup nrf_comp COMP HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52 Comparator (COMP) APIs. + * @details The COMP HAL provides basic APIs for accessing the registers of Comparator. + * The COMP driver provides APIs on a higher level. + * + * @defgroup nrf_drv_comp COMP driver + * @{ + * @ingroup nrf_comp + * @brief @tagAPI52 Comparator (COMP) driver. + */ + +/** + * @brief Macro to convert the threshold voltage to an integer value (needed by the COMP_TH register). + * + * @param[in] vol Voltage to be changed to COMP_TH register value. This value must not be smaller than + * reference voltage divided by 64. + * @param[in] ref Reference voltage. + */ +#define VOLTAGE_THRESHOLD_TO_INT(vol, ref) (uint8_t)(((vol) > ((ref) / 64)) ? (ROUNDED_DIV((vol) * 64,(ref)) - 1) : 0) + +/**@brief COMP event handler function type. + * @param[in] event COMP event. + */ +typedef void (* comp_events_handler_t)(nrf_comp_event_t event); + +/** + * @enum nrf_drv_comp_short_mask_t + * @brief COMP shortcut masks. + */ +typedef enum +{ + NRF_DRV_COMP_SHORT_STOP_AFTER_CROSS_EVT = COMP_SHORTS_CROSS_STOP_Msk, /*!< Shortcut between the CROSS event and the STOP task. */ + NRF_DRV_COMP_SHORT_STOP_AFTER_UP_EVT = COMP_SHORTS_UP_STOP_Msk, /*!< Shortcut between the UP event and the STOP task. */ + NRF_DRV_COMP_SHORT_STOP_AFTER_DOWN_EVT = COMP_SHORTS_DOWN_STOP_Msk /*!< Shortcut between the DOWN event and the STOP task. */ +}nrf_drv_comp_short_mask_t; + +/** + * @enum nrf_drv_comp_evt_en_mask_t + * @brief COMP events masks. + */ +typedef enum +{ + NRF_DRV_COMP_EVT_EN_CROSS_MASK = COMP_INTENSET_CROSS_Msk, /*!< CROSS event (generated after VIN+ == VIN-). */ + NRF_DRV_COMP_EVT_EN_UP_MASK = COMP_INTENSET_UP_Msk, /*!< UP event (generated when VIN+ crosses VIN- while increasing). */ + NRF_DRV_COMP_EVT_EN_DOWN_MASK = COMP_INTENSET_DOWN_Msk, /*!< DOWN event (generated when VIN+ crosses VIN- while decreasing). */ + NRF_DRV_COMP_EVT_EN_READY_MASK = COMP_INTENSET_READY_Msk /*!< READY event (generated when the module is ready). */ +}nrf_drv_comp_evt_en_mask_t; + +/**@brief COMP configuration. + */ +typedef struct +{ + nrf_comp_ref_t reference; /**< Reference selection. */ + nrf_comp_ext_ref_t ext_ref; /**< External analog reference selection. */ + nrf_comp_main_mode_t main_mode; /**< Main operation mode. */ + nrf_comp_th_t threshold; /**< Structure holding THDOWN and THUP values needed by the COMP_TH register. */ + nrf_comp_sp_mode_t speed_mode; /**< Speed and power mode. */ + nrf_comp_hyst_t hyst; /**< Comparator hysteresis.*/ +#if defined (COMP_ISOURCE_ISOURCE_Msk) || defined (__SDK_DOXYGEN__) + nrf_isource_t isource; /**< Current source selected on analog input. */ +#endif + nrf_comp_input_t input; /**< Input to be monitored. */ + uint8_t interrupt_priority; /**< Interrupt priority. */ +} nrf_drv_comp_config_t; + +/** @brief COMP threshold default configuration. */ +#define COMP_CONFIG_TH \ +{ \ + .th_down = VOLTAGE_THRESHOLD_TO_INT(0.5, 1.8), \ + .th_up = VOLTAGE_THRESHOLD_TO_INT(1.5, 1.8) \ +} + +/** @brief COMP driver default configuration including the COMP HAL configuration. */ +#if defined (COMP_ISOURCE_ISOURCE_Msk) +#define NRF_DRV_COMP_DEFAULT_CONFIG(INPUT) \ +{ \ + .reference = (nrf_comp_ref_t)COMP_CONFIG_REF, \ + .main_mode = (nrf_comp_main_mode_t)COMP_CONFIG_MAIN_MODE, \ + .threshold = COMP_CONFIG_TH, \ + .speed_mode = (nrf_comp_sp_mode_t)COMP_CONFIG_SPEED_MODE, \ + .hyst = (nrf_comp_hyst_t)COMP_CONFIG_HYST, \ + .isource = (nrf_isource_t)COMP_CONFIG_ISOURCE, \ + .input = (nrf_comp_input_t)INPUT, \ + .interrupt_priority = COMP_CONFIG_IRQ_PRIORITY \ +} +#else +#define NRF_DRV_COMP_DEFAULT_CONFIG(INPUT) \ +{ \ + .reference = (nrf_comp_ref_t)COMP_CONFIG_REF, \ + .main_mode = (nrf_comp_main_mode_t)COMP_CONFIG_MAIN_MODE, \ + .threshold = COMP_CONFIG_TH, \ + .speed_mode = (nrf_comp_sp_mode_t)COMP_CONFIG_SPEED_MODE, \ + .hyst = (nrf_comp_hyst_t)COMP_CONFIG_HYST, \ + .input = (nrf_comp_input_t)INPUT, \ + .interrupt_priority = COMP_CONFIG_IRQ_PRIORITY \ +} +#endif + +/** + * @brief Function for initializing the COMP driver. + * + * This function initializes the COMP driver, but does not enable the peripheral or any interrupts. + * To start the driver, call the function @ref nrf_drv_comp_start() after initialization. + * + * If no configuration structure is provided, the driver is initialized with the default settings. + * + * @param[in] p_config Initial configuration. If NULL, the default configuration is used. + * @param[in] event_handler Handler function. + * + * @retval NRF_ERROR_INVALID_PARAM If the configuration is invalid. + * @retval NRF_ERROR_INVALID_STATE If the driver has already been initialized. + * @retval NRF_ERROR_BUSY If the LPCOMP driver is initialized. + */ +ret_code_t nrf_drv_comp_init(const nrf_drv_comp_config_t * p_config, + comp_events_handler_t event_handler); + + +/** + * @brief Function for uninitializing the COMP driver. + * + * This function uninitializes the COMP driver. The COMP peripheral and + * its interrupts are disabled, and local variables are cleaned. After this call, you must + * initialize the driver again by calling nrf_drv_comp_init() if you want to use it. + * + * @sa nrf_drv_comp_stop() + */ +void nrf_drv_comp_uninit(void); + +/** + * @brief Function for setting the analog input. + * + * @param[in] psel COMP analog pin selection. + */ +void nrf_drv_comp_pin_select(nrf_comp_input_t psel); + +/** + * @brief Function for starting the COMP peripheral and interrupts. + * + * Before calling this function, the driver must be initialized. This function + * enables the COMP peripheral and its interrupts. + * + * @param[in] comp_evt_en_mask Mask of events to be enabled. This parameter should be built as + * 'or' of elements from @ref nrf_drv_comp_evt_en_mask_t. + * @param[in] comp_shorts_mask Mask of shorts to be enabled. This parameter should be built as + * 'or' of elements from @ref nrf_drv_comp_short_mask_t. + * + * @sa nrf_drv_comp_init() + * + */ +void nrf_drv_comp_start(uint32_t comp_evt_en_mask, uint32_t comp_shorts_mask); + +/**@brief Function for stopping the COMP peripheral. + * + * Before calling this function, the driver must be enabled. This function disables the COMP + * peripheral and its interrupts. + * + * @sa nrf_drv_comp_uninit() + * + */ +void nrf_drv_comp_stop(void); + +/** + * @brief Function for copying the current state of the comparator result to the RESULT register. + * + * @retval 0 If the input voltage is below the threshold (VIN+ < VIN-). + * @retval 1 If the input voltage is above the threshold (VIN+ > VIN-). + */ +uint32_t nrf_drv_comp_sample(void); + +/** + * @brief Function for getting the task address. + * + * Before calling this function, the driver must be enabled. + * + * @param[in] comp_task COMP task. + * + * @return Address of the given COMP task. + */ +__STATIC_INLINE uint32_t nrf_drv_comp_task_address_get(nrf_comp_task_t comp_task) +{ + return (uint32_t)nrf_comp_task_address_get(comp_task); +} + +/** + * @brief Function for getting the event address. + * + * @param[in] comp_event COMP event. + * + * @return Address of the given COMP event. + */ +__STATIC_INLINE uint32_t nrf_drv_comp_event_address_get(nrf_comp_event_t comp_event) +{ + return (uint32_t)nrf_comp_event_address_get(comp_event); +} + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif +#endif /* NRF_DRV_COMP_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/delay/nrf_delay.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/delay/nrf_delay.h new file mode 100644 index 0000000000..0a62f7db25 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/delay/nrf_delay.h @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DELAY_H +#define _NRF_DELAY_H + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CLOCK_FREQ_16MHz (16000000UL) + +#ifdef NRF52_SERIES + #define CPU_FREQ_64MHz +#endif + +/** + * @brief Function for delaying execution for number of microseconds. + * + * @note NRF52 has instruction cache and because of that delay is not precise. + * + * @param number_of_us + * + */ +/*lint -e{438, 522, 40, 10, 563} */ +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us); + + +/** + * @brief Function for delaying execution for number of miliseconds. + * + * @note NRF52 has instruction cache and because of that delay is not precise. + * + * @note Function internally calls @ref nrf_delay_us so the maximum delay is the + * same as in case of @ref nrf_delay_us, approx. 71 minutes. + * + * @param number_of_ms + * + */ + +/*lint -e{438, 522, 40, 10, 563} */ +__STATIC_INLINE void nrf_delay_ms(uint32_t number_of_ms); + +#if defined ( __CC_ARM ) +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{ + if (!number_of_us) + return; +__asm + { +loop: + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + CMP SystemCoreClock, CLOCK_FREQ_16MHz + BEQ cond + NOP +#ifdef CPU_FREQ_64MHz + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP + NOP +#endif //CPU_FREQ_64MHz +cond: + SUBS number_of_us, #1 + BNE loop + } +} + +#elif defined ( _WIN32 ) || defined ( __unix ) || defined( __APPLE__ ) + + +#ifndef CUSTOM_NRF_DELAY_US +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{} +#endif + +#elif defined ( __GNUC__ ) || ( __ICCARM__ ) + +__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) +{ + const uint32_t clock16MHz = CLOCK_FREQ_16MHz; + if (number_of_us) + { +__ASM volatile ( +#if ( defined(__GNUC__) && (__CORTEX_M == (0x00U) ) ) + ".syntax unified\n" +#endif +"1:\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " CMP %[SystemCoreClock], %[clock16MHz]\n" + " BEQ.N 2f\n" + " NOP\n" +#ifdef CPU_FREQ_64MHz + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" +#endif //CPU_FREQ_64MHz +"2:\n" + " SUBS %[number_of_us], %[number_of_us], #1\n" + " BNE.N 1b\n" +#if ( defined(__GNUC__) && (__CORTEX_M == (0x00U) ) ) + ".syntax divided\n" +#endif +#if ( __CORTEX_M == (0x00U) ) + // The SUBS instruction in Cortex-M0 is available only in 16-bit encoding, + // hence it requires a "lo" register (r0-r7) as an operand. + : [number_of_us] "=l" (number_of_us) +#else + : [number_of_us] "=r" (number_of_us) +#endif + : [SystemCoreClock] "r" (SystemCoreClock), + [clock16MHz] "r" (clock16MHz), + "[number_of_us]" (number_of_us) + : "cc" + ); + } +} +#endif + +__STATIC_INLINE void nrf_delay_ms(uint32_t number_of_ms) +{ + nrf_delay_us(1000*number_of_ms); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.c new file mode 100644 index 0000000000..4fde3f1445 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.c @@ -0,0 +1,808 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(GPIOTE) +#include "nrf_drv_gpiote.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" +#include "nrf_assert.h" +#include "nrf_bitmask.h" +#include + +#define NRF_LOG_MODULE_NAME gpiote + +#if GPIOTE_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL GPIOTE_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR GPIOTE_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR GPIOTE_CONFIG_DEBUG_COLOR +#else // GPIOTE_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif // GPIOTE_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(GPIOTE_CONFIG_IRQ_PRIORITY); + +#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX) +#define PIN_NOT_USED (-1) +#define PIN_USED (-2) +#define NO_CHANNELS (-1) +#define SENSE_FIELD_POS (6) +#define SENSE_FIELD_MASK (0xC0) + +/** + * @brief Macro for converting task-event index to an address of an event register. + * + * Macro utilizes the fact that registers are grouped together in ascending order. + */ +#define TE_IDX_TO_EVENT_ADDR(idx) (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0 + \ + (sizeof(uint32_t) * (idx))) + +/** + * @brief Macro for converting task-event index of OUT task to an address of a task register. + * + * Macro utilizes the fact that registers are grouped together in ascending order. + */ +#define TE_OUT_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0 + \ + (sizeof(uint32_t) * (idx))) + +#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__SDK_DOXYGEN__) +/** + * @brief Macro for converting task-event index of SET task to an address of a task register. + * + * Macro utilizes the fact that registers are grouped together in ascending order. + */ +#define TE_SET_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_SET_0 + \ + (sizeof(uint32_t) * (idx))) + +#endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__SDK_DOXYGEN__) + +#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__SDK_DOXYGEN__) +/** + * @brief Macro for converting task-event index of CLR task to an address of a task register. + * + * Macro utilizes the fact that registers are grouped together in ascending order. + */ +#define TE_CLR_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_CLR_0 + \ + (sizeof(uint32_t) * (idx))) + +#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__SDK_DOXYGEN__) + +/*lint -save -e661*/ +typedef struct +{ + nrf_drv_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; + int8_t pin_assignments[NUMBER_OF_PINS]; + int8_t port_handlers_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS]; + nrf_drv_state_t state; +} gpiote_control_block_t; + +static gpiote_control_block_t m_cb; + +__STATIC_INLINE bool pin_in_use(uint32_t pin) +{ + return (m_cb.pin_assignments[pin] != PIN_NOT_USED); +} + + +__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin) +{ + return (m_cb.pin_assignments[pin] == PIN_USED); +} + + +__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin) +{ + return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < + GPIOTE_CH_NUM) ? true : false; +} + + +__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin) +{ + return (m_cb.pin_assignments[pin] >= GPIOTE_CH_NUM); +} + + +__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin) +{ + return (m_cb.pin_assignments[pin] >= 0); +} + + +__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin, + uint32_t channel_id, + nrf_drv_gpiote_evt_handler_t handler, + bool is_channel) +{ + m_cb.pin_assignments[pin] = channel_id; + m_cb.handlers[channel_id] = handler; + if (!is_channel) + { + m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)pin; + } +} + + +__STATIC_INLINE void pin_in_use_set(uint32_t pin) +{ + m_cb.pin_assignments[pin] = PIN_USED; +} + + +__STATIC_INLINE void pin_in_use_clear(uint32_t pin) +{ + m_cb.pin_assignments[pin] = PIN_NOT_USED; +} + + +__STATIC_INLINE int8_t channel_port_get(uint32_t pin) +{ + return m_cb.pin_assignments[pin]; +} + + +__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel) +{ + return m_cb.handlers[channel]; +} + + +static int8_t channel_port_alloc(uint32_t pin, nrf_drv_gpiote_evt_handler_t handler, bool channel) +{ + int8_t channel_id = NO_CHANNELS; + uint32_t i; + + uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM; + uint32_t end_idx = + channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); + + // critical section + + for (i = start_idx; i < end_idx; i++) + { + if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS) + { + pin_in_use_by_te_set(pin, i, handler, channel); + channel_id = i; + break; + } + } + // critical section + return channel_id; +} + + +static void channel_free(uint8_t channel_id) +{ + m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS; + if (channel_id >= GPIOTE_CH_NUM) + { + m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)PIN_NOT_USED; + } +} + + +ret_code_t nrf_drv_gpiote_init(void) +{ + ret_code_t err_code; + + if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + uint8_t i; + + for (i = 0; i < NUMBER_OF_PINS; i++) + { + pin_in_use_clear(i); + } + + for (i = 0; i < (GPIOTE_CH_NUM + GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++) + { + channel_free(i); + } + + nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY); + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); + nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk); + m_cb.state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +bool nrf_drv_gpiote_is_init(void) +{ + return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false; +} + + +void nrf_drv_gpiote_uninit(void) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + uint32_t i; + + for (i = 0; i < NUMBER_OF_PINS; i++) + { + if (pin_in_use_as_non_task_out(i)) + { + nrf_drv_gpiote_out_uninit(i); + } + else if ( pin_in_use_by_gpiote(i)) + { + /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on + * so it can be called on all pins used by GPIOTE. + */ + nrf_drv_gpiote_in_uninit(i); + } + } + m_cb.state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + + +ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, + nrf_drv_gpiote_out_config_t const * p_config) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED); + ASSERT(p_config); + + ret_code_t err_code = NRF_SUCCESS; + + if (pin_in_use(pin)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + if (p_config->task_pin) + { + int8_t channel = channel_port_alloc(pin, NULL, true); + + if (channel != NO_CHANNELS) + { + nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state); + } + else + { + err_code = NRF_ERROR_NO_MEM; + } + } + else + { + pin_in_use_set(pin); + } + + if (err_code == NRF_SUCCESS) + { + if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH) + { + nrf_gpio_pin_set(pin); + } + else + { + nrf_gpio_pin_clear(pin); + } + + nrf_gpio_cfg_output(pin); + } + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + + if (pin_in_use_by_te(pin)) + { + channel_free((uint8_t)channel_port_get(pin)); + nrf_gpiote_te_default(channel_port_get(pin)); + } + pin_in_use_clear(pin); + + nrf_gpio_cfg_default(pin); +} + + +void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(!pin_in_use_by_te(pin)) + + nrf_gpio_pin_set(pin); +} + + +void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(!pin_in_use_by_te(pin)) + + nrf_gpio_pin_clear(pin); +} + + +void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(!pin_in_use_by_te(pin)) + + nrf_gpio_pin_toggle(pin); +} + + +void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)) + + nrf_gpiote_task_enable(m_cb.pin_assignments[pin]); +} + + +void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)) + + nrf_gpiote_task_disable(m_cb.pin_assignments[pin]); +} + + +uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR(channel_port_get(pin)); + return nrf_gpiote_task_addr_get(task); +} + + +#if defined(GPIOTE_FEATURE_SET_PRESENT) +uint32_t nrf_drv_gpiote_set_task_addr_get(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR(channel_port_get(pin)); + return nrf_gpiote_task_addr_get(task); +} + + +#endif // defined(GPIOTE_FEATURE_SET_PRESENT) + +#if defined(GPIOTE_FEATURE_CLR_PRESENT) +uint32_t nrf_drv_gpiote_clr_task_addr_get(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR(channel_port_get(pin)); + return nrf_gpiote_task_addr_get(task); +} + + +#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) + +void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_outinit_t init_val = + state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW; + nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val); +} + + +void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR(channel_port_get(pin)); + nrf_gpiote_task_set(task); +} + + +#if defined(GPIOTE_FEATURE_SET_PRESENT) +void nrf_drv_gpiote_set_task_trigger(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR(channel_port_get(pin)); + nrf_gpiote_task_set(task); +} + + +#endif // defined(GPIOTE_FEATURE_SET_PRESENT) + +#if defined(GPIOTE_FEATURE_CLR_PRESENT) +void nrf_drv_gpiote_clr_task_trigger(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use(pin)); + ASSERT(pin_in_use_by_te(pin)); + + nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR(channel_port_get(pin)); + nrf_gpiote_task_set(task); +} + + +#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) + +ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin, + nrf_drv_gpiote_in_config_t const * p_config, + nrf_drv_gpiote_evt_handler_t evt_handler) +{ + ASSERT(pin < NUMBER_OF_PINS); + ret_code_t err_code = NRF_SUCCESS; + + /* Only one GPIOTE channel can be assigned to one physical pin. */ + if (pin_in_use_by_gpiote(pin)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy); + if (channel != NO_CHANNELS) + { + if (p_config->is_watcher) + { + nrf_gpio_cfg_watcher(pin); + } + else + { + nrf_gpio_cfg_input(pin, p_config->pull); + } + + if (p_config->hi_accuracy) + { + nrf_gpiote_event_configure(channel, pin, p_config->sense); + } + else + { + m_cb.port_handlers_pins[channel - + GPIOTE_CH_NUM] |= (p_config->sense) << SENSE_FIELD_POS; + } + } + else + { + err_code = NRF_ERROR_NO_MEM; + } + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_gpiote(pin)); + if (pin_in_use_by_port(pin)) + { + uint8_t pin_and_sense = + m_cb.port_handlers_pins[channel_port_get(pin) - GPIOTE_CH_NUM]; + nrf_gpiote_polarity_t polarity = + (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS); + nrf_gpio_pin_sense_t sense; + if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) + { + /* read current pin state and set for next sense to oposit */ + sense = (nrf_gpio_pin_read(pin)) ? + NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH; + } + else + { + sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ? + NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW; + } + nrf_gpio_cfg_sense_set(pin, sense); + } + else if (pin_in_use_by_te(pin)) + { + int32_t channel = (int32_t)channel_port_get(pin); + nrf_gpiote_events_t event = TE_IDX_TO_EVENT_ADDR(channel); + + nrf_gpiote_event_enable(channel); + + nrf_gpiote_event_clear(event); + if (int_enable) + { + nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin)); + // Enable the interrupt only if event handler was provided. + if (handler) + { + nrf_gpiote_int_enable(1 << channel); + } + } + } +} + + +void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_gpiote(pin)); + if (pin_in_use_by_port(pin)) + { + nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE); + } + else if (pin_in_use_by_te(pin)) + { + int32_t channel = (int32_t)channel_port_get(pin); + nrf_gpiote_event_disable(channel); + nrf_gpiote_int_disable(1 << channel); + } +} + + +void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_gpiote(pin)); + nrf_drv_gpiote_in_event_disable(pin); + if (pin_in_use_by_te(pin)) + { + nrf_gpiote_te_default(channel_port_get(pin)); + } + nrf_gpio_cfg_default(pin); + channel_free((uint8_t)channel_port_get(pin)); + pin_in_use_clear(pin); +} + + +bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + return nrf_gpio_pin_read(pin) ? true : false; +} + + +uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin) +{ + ASSERT(pin < NUMBER_OF_PINS); + ASSERT(pin_in_use_by_port(pin) || pin_in_use_by_te(pin)); + + nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_PORT; + + if (pin_in_use_by_te(pin)) + { + event = TE_IDX_TO_EVENT_ADDR(channel_port_get(pin)); + } + return nrf_gpiote_event_addr_get(event); +} + + +void GPIOTE_IRQHandler(void) +{ + uint32_t status = 0; + uint32_t input[GPIO_COUNT] = {0}; + + /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/ + uint32_t i; + nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0; + uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK; + + for (i = 0; i < GPIOTE_CH_NUM; i++) + { + if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask)) + { + nrf_gpiote_event_clear(event); + status |= mask; + } + mask <<= 1; + /* Incrementing to next event, utilizing the fact that events are grouped together + * in ascending order. */ + event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t)); + } + + /* collect PORT status event, if event is set read pins state. Processing is postponed to the + * end of interrupt. */ + if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT)) + { + nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); + status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK; + nrf_gpio_ports_read(0, GPIO_COUNT, input); + } + + /* Process pin events. */ + if (status & NRF_GPIOTE_INT_IN_MASK) + { + mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK; + + for (i = 0; i < GPIOTE_CH_NUM; i++) + { + if (mask & status) + { + nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i); + NRF_LOG_DEBUG("Event in number: %d.", i); + nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i); + nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i); + NRF_LOG_DEBUG("Pin: %d, polarity: %d.", pin, polarity); + if (handler) + { + handler(pin, polarity); + } + } + mask <<= 1; + } + } + + if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK) + { + /* Process port event. */ + uint32_t port_idx; + uint8_t repeat = 0; + uint32_t toggle_mask[GPIO_COUNT] = {0}; + uint32_t pins_to_check[GPIO_COUNT]; + + // Faster way of doing memset because in interrupt context. + for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++) + { + pins_to_check[port_idx] = 0xFFFFFFFF; + } + + do + { + repeat = 0; + + for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++) + { + uint8_t pin_and_sense = m_cb.port_handlers_pins[i]; + nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK); + + if ((m_cb.port_handlers_pins[i] != PIN_NOT_USED) + && nrf_bitmask_bit_is_set(pin, pins_to_check)) + { + nrf_gpiote_polarity_t polarity = + (nrf_gpiote_polarity_t)((pin_and_sense & + SENSE_FIELD_MASK) >> SENSE_FIELD_POS); + nrf_drv_gpiote_evt_handler_t handler = + channel_handler_get(channel_port_get(pin)); + if (handler || (polarity == NRF_GPIOTE_POLARITY_TOGGLE)) + { + if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) + { + nrf_bitmask_bit_set(pin, toggle_mask); + } + nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin); + uint32_t pin_state = nrf_bitmask_bit_is_set(pin, input); + if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) || + (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) ) + { + NRF_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, + polarity); + if (polarity == NRF_GPIOTE_POLARITY_TOGGLE) + { + nrf_gpio_pin_sense_t next_sense = + (sense == NRF_GPIO_PIN_SENSE_HIGH) ? + NRF_GPIO_PIN_SENSE_LOW : + NRF_GPIO_PIN_SENSE_HIGH; + nrf_gpio_cfg_sense_set(pin, next_sense); + ++repeat; + + } + if (handler) + { + handler(pin, polarity); + } + } + } + } + } + + if (repeat) + { + // When one of the pins in low-accuracy and toggle mode becomes active, + // it's sense mode is inverted to clear the internal SENSE signal. + // State of any other enabled low-accuracy input in toggle mode must be checked + // explicitly, because it does not trigger the interrput when SENSE signal is active. + // For more information about SENSE functionality, refer to Product Specification. + + uint32_t new_input[GPIO_COUNT]; + bool input_unchanged = true; + nrf_gpio_ports_read(0, GPIO_COUNT, new_input); + + // Faster way of doing memcmp because in interrupt context. + for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++) + { + if (new_input[port_idx] != input[port_idx]) + { + input_unchanged = false; + break; + } + } + + if (input_unchanged) + { + // No change. + repeat = 0; + } + else + { + // Faster way of doing memcpy because in interrupt context. + for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++) + { + input[port_idx] = new_input[port_idx]; + pins_to_check[port_idx] = toggle_mask[port_idx]; + } + } + } + } + while (repeat); + } +} + + +/*lint -restore*/ +#endif // NRF_MODULE_ENABLED(GPIOTE) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.h new file mode 100644 index 0000000000..6c5f627b8c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/gpiote/nrf_drv_gpiote.h @@ -0,0 +1,385 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_GPIOTE__ +#define NRF_DRV_GPIOTE__ + +/** + * @addtogroup nrf_gpiote GPIOTE abstraction and driver + * @ingroup nrf_drivers + * @brief GPIOTE APIs. + * @defgroup nrf_drv_gpiote GPIOTE driver + * @{ + * @ingroup nrf_gpiote + * @brief GPIOTE driver for managing input and output pins. + */ + +#include "nrf_gpiote.h" +#include "nrf_gpio.h" +#include "sdk_errors.h" +#include +#include +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Input pin configuration. */ +typedef struct +{ + nrf_gpiote_polarity_t sense; /**< Transition that triggers interrupt. */ + nrf_gpio_pin_pull_t pull; /**< Pulling mode. */ + bool is_watcher; /**< True when the input pin is tracking an output pin. */ + bool hi_accuracy;/**< True when high accuracy (IN_EVENT) is used. */ +} nrf_drv_gpiote_in_config_t; + +/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition. + * @details Set hi_accu to true to use IN_EVENT. */ +#define GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \ + { \ + .is_watcher = false, \ + .hi_accuracy = hi_accu, \ + .pull = NRF_GPIO_PIN_NOPULL, \ + .sense = NRF_GPIOTE_POLARITY_LOTOHI, \ + } + +/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition. + * @details Set hi_accu to true to use IN_EVENT. */ +#define GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \ + { \ + .is_watcher = false, \ + .hi_accuracy = hi_accu, \ + .pull = NRF_GPIO_PIN_NOPULL, \ + .sense = NRF_GPIOTE_POLARITY_HITOLO, \ + } + +/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin. + * @details Set hi_accu to true to use IN_EVENT.*/ +#define GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \ + { \ + .is_watcher = false, \ + .hi_accuracy = hi_accu, \ + .pull = NRF_GPIO_PIN_NOPULL, \ + .sense = NRF_GPIOTE_POLARITY_TOGGLE, \ + } + +/**@brief Output pin configuration. */ +typedef struct +{ + nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */ + nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */ + bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */ +} nrf_drv_gpiote_out_config_t; + +/**@brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */ +#define GPIOTE_CONFIG_OUT_SIMPLE(init_high) \ + { \ + .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ + .task_pin = false, \ + } + +/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low. + * @details The task will clear the pin. Therefore, the pin is set initially. */ +#define GPIOTE_CONFIG_OUT_TASK_LOW \ + { \ + .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \ + .task_pin = true, \ + .action = NRF_GPIOTE_POLARITY_HITOLO, \ + } + +/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high. + * @details The task will set the pin. Therefore, the pin is cleared initially. */ +#define GPIOTE_CONFIG_OUT_TASK_HIGH \ + { \ + .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \ + .task_pin = true, \ + .action = NRF_GPIOTE_POLARITY_LOTOHI, \ + } + +/**@brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state. + * @details The initial pin state must be provided. */ +#define GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \ + { \ + .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ + .task_pin = true, \ + .action = NRF_GPIOTE_POLARITY_TOGGLE, \ + } + +/** @brief Pin. */ +typedef uint32_t nrf_drv_gpiote_pin_t; + +/** + * @brief Pin event handler prototype. + * @param pin Pin that triggered this event. + * @param action Action that lead to triggering this event. + */ +typedef void (*nrf_drv_gpiote_evt_handler_t)(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action); + +/** + * @brief Function for initializing the GPIOTE module. + * + * @details Only static configuration is supported to prevent the shared + * resource being customized by the initiator. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + */ +ret_code_t nrf_drv_gpiote_init(void); + +/** + * @brief Function for checking if the GPIOTE module is initialized. + * + * @details The GPIOTE module is a shared module. Therefore, you should check if + * the module is already initialized and skip initialization if it is. + * + * @retval true If the module is already initialized. + * @retval false If the module is not initialized. + */ +bool nrf_drv_gpiote_is_init(void); + +/** + * @brief Function for uninitializing the GPIOTE module. + */ +void nrf_drv_gpiote_uninit(void); + +/** + * @brief Function for initializing a GPIOTE output pin. + * @details The output pin can be controlled by the CPU or by PPI. The initial + * configuration specifies which mode is used. If PPI mode is used, the driver + * attempts to allocate one of the available GPIOTE channels. If no channel is + * available, an error is returned. + * + * @param[in] pin Pin. + * @param[in] p_config Initial configuration. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used. + * @retval NRF_ERROR_NO_MEM If no GPIOTE channel is available. + */ +ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin, + nrf_drv_gpiote_out_config_t const * p_config); + +/** + * @brief Function for uninitializing a GPIOTE output pin. + * @details The driver frees the GPIOTE channel if the output pin was using one. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for setting a GPIOTE output pin. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for clearing a GPIOTE output pin. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for toggling a GPIOTE output pin. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for enabling a GPIOTE output pin task. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for disabling a GPIOTE output pin task. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for getting the address of a configurable GPIOTE task. + * + * @param[in] pin Pin. + * + * @return Address of OUT task. + */ +uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin); + +#if defined(GPIOTE_FEATURE_SET_PRESENT) +/** + * @brief Function for getting the address of a configurable GPIOTE task. + * + * @param[in] pin Pin. + * + * @return Address of SET task. + */ +uint32_t nrf_drv_gpiote_set_task_addr_get(nrf_drv_gpiote_pin_t pin); +#endif // defined(GPIOTE_FEATURE_SET_PRESENT) + +#if defined(GPIOTE_FEATURE_CLR_PRESENT) +/** + * @brief Function for getting the address of a configurable GPIOTE task. + * + * @param[in] pin Pin. + * + * @return Address of CLR task. + */ +uint32_t nrf_drv_gpiote_clr_task_addr_get(nrf_drv_gpiote_pin_t pin); +#endif // defined(GPIOTE_FEATURE_CLR_PRESENT) + +/** + * @brief Function for initializing a GPIOTE input pin. + * @details The input pin can act in two ways: + * - lower accuracy but low power (high frequency clock not needed) + * - higher accuracy (high frequency clock required) + * + * The initial configuration specifies which mode is used. + * If high-accuracy mode is used, the driver attempts to allocate one + * of the available GPIOTE channels. If no channel is + * available, an error is returned. + * In low accuracy mode SENSE feature is used. In this case only one active pin + * can be detected at a time. It can be worked around by setting all of the used + * low accuracy pins to toggle mode. + * For more information about SENSE functionality, refer to Product Specification. + * + * @param[in] pin Pin. + * @param[in] p_config Initial configuration. + * @param[in] evt_handler User function to be called when the configured transition occurs. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used. + * @retval NRF_ERROR_NO_MEM If no GPIOTE channel is available. + */ +ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin, + nrf_drv_gpiote_in_config_t const * p_config, + nrf_drv_gpiote_evt_handler_t evt_handler); + +/** + * @brief Function for uninitializing a GPIOTE input pin. + * @details The driver frees the GPIOTE channel if the input pin was using one. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for enabling sensing of a GPIOTE input pin. + * + * @details If the input pin is configured as high-accuracy pin, the function + * enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism. + * Note that a PORT event is shared between multiple pins, therefore the + * interrupt is always enabled. + * + * @param[in] pin Pin. + * @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin. + */ +void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable); + +/** + * @brief Function for disabling a GPIOTE input pin. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for checking if a GPIOTE input pin is set. + * + * @param[in] pin Pin. + * @retval true If the input pin is set. + * @retval false If the input pin is not set. + */ +bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for getting the address of a GPIOTE input pin event. + * @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned. + * + * @param[in] pin Pin. + */ +uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for forcing a specific state on the pin configured as task. + * + * @param[in] pin Pin. + * @param[in] state Pin state. + */ +void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state); + +/** + * @brief Function for triggering the task OUT manually. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin); + +#ifdef NRF52_SERIES +/** + * @brief Function for triggering the task SET manually. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_set_task_trigger(nrf_drv_gpiote_pin_t pin); + +/** + * @brief Function for triggering the task CLR manually. + * + * @param[in] pin Pin. + */ +void nrf_drv_gpiote_clr_task_trigger(nrf_drv_gpiote_pin_t pin); +#endif + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + +#endif //NRF_DRV_GPIOTE__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_clock.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_clock.h new file mode 100644 index 0000000000..50a7271a9d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_clock.h @@ -0,0 +1,401 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_CLOCK_H__ +#define NRF_CLOCK_H__ + +#include +#include + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_clock_hal Clock HAL + * @{ + * @ingroup nrf_clock + * @brief Hardware access layer for managing the low-frequency clock (LFCLK) and the high-frequency clock (HFCLK). + */ + +#define NRF_CLOCK_TASK_TRIGGER (1UL) +#define NRF_CLOCK_EVENT_CLEAR (0UL) + +/** + * @brief Low-frequency clock sources. + * @details Used by LFCLKSRC, LFCLKSTAT, and LFCLKSRCCOPY registers. + */ +typedef enum +{ + NRF_CLOCK_LFCLK_RC = CLOCK_LFCLKSRC_SRC_RC, /**< Internal 32 kHz RC oscillator. */ + NRF_CLOCK_LFCLK_Xtal = CLOCK_LFCLKSRC_SRC_Xtal, /**< External 32 kHz crystal. */ + NRF_CLOCK_LFCLK_Synth = CLOCK_LFCLKSRC_SRC_Synth /**< Internal 32 kHz synthesizer from HFCLK system clock. */ +} nrf_clock_lfclk_t; + +/** + * @brief High-frequency clock sources. + */ +typedef enum +{ + NRF_CLOCK_HFCLK_LOW_ACCURACY = CLOCK_HFCLKSTAT_SRC_RC, /**< Internal 16 MHz RC oscillator. */ + NRF_CLOCK_HFCLK_HIGH_ACCURACY = CLOCK_HFCLKSTAT_SRC_Xtal /**< External 16 MHz/32 MHz crystal oscillator. */ +} nrf_clock_hfclk_t; + +/** + * @brief Trigger status of task LFCLKSTART/HFCLKSTART. + * @details Used by LFCLKRUN and HFCLKRUN registers. + */ +typedef enum +{ + NRF_CLOCK_START_TASK_NOT_TRIGGERED = CLOCK_LFCLKRUN_STATUS_NotTriggered, /**< Task LFCLKSTART/HFCLKSTART has not been triggered. */ + NRF_CLOCK_START_TASK_TRIGGERED = CLOCK_LFCLKRUN_STATUS_Triggered /**< Task LFCLKSTART/HFCLKSTART has been triggered. */ +} nrf_clock_start_task_status_t; + +/** + * @brief Interrupts. + */ +typedef enum +{ + NRF_CLOCK_INT_HF_STARTED_MASK = CLOCK_INTENSET_HFCLKSTARTED_Msk, /**< Interrupt on HFCLKSTARTED event. */ + NRF_CLOCK_INT_LF_STARTED_MASK = CLOCK_INTENSET_LFCLKSTARTED_Msk, /**< Interrupt on LFCLKSTARTED event. */ + NRF_CLOCK_INT_DONE_MASK = CLOCK_INTENSET_DONE_Msk, /**< Interrupt on DONE event. */ + NRF_CLOCK_INT_CTTO_MASK = CLOCK_INTENSET_CTTO_Msk /**< Interrupt on CTTO event. */ +} nrf_clock_int_mask_t; + +/** + * @brief Tasks. + * + * @details The NRF_CLOCK_TASK_LFCLKSTOP task cannot be set when the low-frequency clock is not running. + * The NRF_CLOCK_TASK_HFCLKSTOP task cannot be set when the high-frequency clock is not running. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_CLOCK_TASK_HFCLKSTART = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTART), /**< Start HFCLK clock source.*/ + NRF_CLOCK_TASK_HFCLKSTOP = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTOP), /**< Stop HFCLK clock source.*/ + NRF_CLOCK_TASK_LFCLKSTART = offsetof(NRF_CLOCK_Type, TASKS_LFCLKSTART), /**< Start LFCLK clock source.*/ + NRF_CLOCK_TASK_LFCLKSTOP = offsetof(NRF_CLOCK_Type, TASKS_LFCLKSTOP), /**< Stop LFCLK clock source.*/ + NRF_CLOCK_TASK_CAL = offsetof(NRF_CLOCK_Type, TASKS_CAL), /**< Start calibration of LFCLK RC oscillator.*/ + NRF_CLOCK_TASK_CTSTART = offsetof(NRF_CLOCK_Type, TASKS_CTSTART), /**< Start calibration timer.*/ + NRF_CLOCK_TASK_CTSTOP = offsetof(NRF_CLOCK_Type, TASKS_CTSTOP) /**< Stop calibration timer.*/ +} nrf_clock_task_t; /*lint -restore */ + +/** + * @brief Events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_CLOCK_EVENT_HFCLKSTARTED = offsetof(NRF_CLOCK_Type, EVENTS_HFCLKSTARTED), /**< HFCLK oscillator started.*/ + NRF_CLOCK_EVENT_LFCLKSTARTED = offsetof(NRF_CLOCK_Type, EVENTS_LFCLKSTARTED), /**< LFCLK oscillator started.*/ + NRF_CLOCK_EVENT_DONE = offsetof(NRF_CLOCK_Type, EVENTS_DONE), /**< Calibration of LFCLK RC oscillator completed.*/ + NRF_CLOCK_EVENT_CTTO = offsetof(NRF_CLOCK_Type, EVENTS_CTTO) /**< Calibration timer time-out.*/ +} nrf_clock_event_t; /*lint -restore */ + +/** + * @brief Function for enabling a specific interrupt. + * + * @param[in] int_mask Interrupt. + */ +__STATIC_INLINE void nrf_clock_int_enable(uint32_t int_mask); + +/** + * @brief Function for disabling a specific interrupt. + * + * @param[in] int_mask Interrupt. + */ +__STATIC_INLINE void nrf_clock_int_disable(uint32_t int_mask); + +/** + * @brief Function for retrieving the state of a specific interrupt. + * + * @param[in] int_mask Interrupt. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_clock_int_enable_check(nrf_clock_int_mask_t int_mask); + +/** + * @brief Function for retrieving the address of a specific task. + * @details This function can be used by the PPI module. + * + * @param[in] task Task. + * + * @return Address of the requested task register. + */ +__STATIC_INLINE uint32_t nrf_clock_task_address_get(nrf_clock_task_t task); + +/** + * @brief Function for setting a specific task. + * + * @param[in] task Task. + */ +__STATIC_INLINE void nrf_clock_task_trigger(nrf_clock_task_t task); + +/** + * @brief Function for retrieving the address of a specific event. + * @details This function can be used by the PPI module. + * + * @param[in] event Event. + * + * @return Address of the requested event register. + */ +__STATIC_INLINE uint32_t nrf_clock_event_address_get(nrf_clock_event_t event); + +/** + * @brief Function for clearing a specific event. + * + * @param[in] event Event. + */ +__STATIC_INLINE void nrf_clock_event_clear(nrf_clock_event_t event); + +/** + * @brief Function for retrieving the state of a specific event. + * + * @param[in] event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_clock_event_check(nrf_clock_event_t event); + +/** + * @brief Function for changing the low-frequency clock source. + * @details This function cannot be called when the low-frequency clock is running. + * + * @param[in] source New low-frequency clock source. + * + */ +__STATIC_INLINE void nrf_clock_lf_src_set(nrf_clock_lfclk_t source); + +/** + * @brief Function for retrieving the selected source for the low-frequency clock. + * + * @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is the selected source for the low-frequency clock. + * @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is the selected source for the low-frequency clock. + * @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is the selected source for the low-frequency clock. + */ +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_src_get(void); + +/** + * @brief Function for retrieving the active source of the low-frequency clock. + * + * @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is the active source of the low-frequency clock. + * @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is the active source of the low-frequency clock. + * @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is the active source of the low-frequency clock. + */ +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_actv_src_get(void); + +/** + * @brief Function for retrieving the clock source for the LFCLK clock when the task LKCLKSTART is triggered. + * + * @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is running and generating the LFCLK clock. + * @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is running and generating the LFCLK clock. + * @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is running and generating the LFCLK clock. + */ +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_srccopy_get(void); + +/** + * @brief Function for retrieving the state of the LFCLK clock. + * + * @retval false If the LFCLK clock is not running. + * @retval true If the LFCLK clock is running. + */ +__STATIC_INLINE bool nrf_clock_lf_is_running(void); + +/** + * @brief Function for retrieving the trigger status of the task LFCLKSTART. + * + * @retval NRF_CLOCK_START_TASK_NOT_TRIGGERED If the task LFCLKSTART has not been triggered. + * @retval NRF_CLOCK_START_TASK_TRIGGERED If the task LFCLKSTART has been triggered. + */ +__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_lf_start_task_status_get(void); + +/** + * @brief Function for retrieving the active source of the high-frequency clock. + * + * @retval NRF_CLOCK_HFCLK_LOW_ACCURACY If the internal 16 MHz RC oscillator is the active source of the high-frequency clock. + * @retval NRF_CLOCK_HFCLK_HIGH_ACCURACY If an external 16 MHz/32 MHz crystal oscillator is the active source of the high-frequency clock. + */ +__STATIC_INLINE nrf_clock_hfclk_t nrf_clock_hf_src_get(void); + +/** + * @brief Function for retrieving the state of the HFCLK clock. + * + * @param[in] clk_src Clock source to be checked. + * + * @retval false If the HFCLK clock is not running. + * @retval true If the HFCLK clock is running. + */ +__STATIC_INLINE bool nrf_clock_hf_is_running(nrf_clock_hfclk_t clk_src); + +/** + * @brief Function for retrieving the trigger status of the task HFCLKSTART. + * + * @retval NRF_CLOCK_START_TASK_NOT_TRIGGERED If the task HFCLKSTART has not been triggered. + * @retval NRF_CLOCK_START_TASK_TRIGGERED If the task HFCLKSTART has been triggered. + */ +__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_hf_start_task_status_get(void); + +/** + * @brief Function for changing the calibration timer interval. + * + * @param[in] interval New calibration timer interval in 0.25 s resolution (range: 0.25 seconds to 31.75 seconds). + */ +__STATIC_INLINE void nrf_clock_cal_timer_timeout_set(uint32_t interval); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_clock_int_enable(uint32_t int_mask) +{ + NRF_CLOCK->INTENSET = int_mask; +} + +__STATIC_INLINE void nrf_clock_int_disable(uint32_t int_mask) +{ + NRF_CLOCK->INTENCLR = int_mask; +} + +__STATIC_INLINE bool nrf_clock_int_enable_check(nrf_clock_int_mask_t int_mask) +{ + return (bool)(NRF_CLOCK->INTENCLR & int_mask); +} + +__STATIC_INLINE uint32_t nrf_clock_task_address_get(nrf_clock_task_t task) +{ + return ((uint32_t )NRF_CLOCK + task); +} + +__STATIC_INLINE void nrf_clock_task_trigger(nrf_clock_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + task)) = NRF_CLOCK_TASK_TRIGGER; +} + +__STATIC_INLINE uint32_t nrf_clock_event_address_get(nrf_clock_event_t event) +{ + return ((uint32_t)NRF_CLOCK + event); +} + +__STATIC_INLINE void nrf_clock_event_clear(nrf_clock_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event)) = NRF_CLOCK_EVENT_CLEAR; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_clock_event_check(nrf_clock_event_t event) +{ + return (bool)*((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event)); +} + +__STATIC_INLINE void nrf_clock_lf_src_set(nrf_clock_lfclk_t source) +{ + NRF_CLOCK->LFCLKSRC = + (uint32_t)((source << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk); +} + +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_src_get(void) +{ + return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSRC & + CLOCK_LFCLKSRC_SRC_Msk) >> CLOCK_LFCLKSRC_SRC_Pos); +} + +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_actv_src_get(void) +{ + return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSTAT & + CLOCK_LFCLKSTAT_SRC_Msk) >> CLOCK_LFCLKSTAT_SRC_Pos); +} + +__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_srccopy_get(void) +{ + return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSRCCOPY & + CLOCK_LFCLKSRCCOPY_SRC_Msk) >> CLOCK_LFCLKSRCCOPY_SRC_Pos); +} + +__STATIC_INLINE bool nrf_clock_lf_is_running(void) +{ + return ((NRF_CLOCK->LFCLKSTAT & + CLOCK_LFCLKSTAT_STATE_Msk) >> CLOCK_LFCLKSTAT_STATE_Pos); +} + +__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_lf_start_task_status_get(void) +{ + return (nrf_clock_start_task_status_t)((NRF_CLOCK->LFCLKRUN & + CLOCK_LFCLKRUN_STATUS_Msk) >> + CLOCK_LFCLKRUN_STATUS_Pos); +} + +__STATIC_INLINE nrf_clock_hfclk_t nrf_clock_hf_src_get(void) +{ + return (nrf_clock_hfclk_t)((NRF_CLOCK->HFCLKSTAT & + CLOCK_HFCLKSTAT_SRC_Msk) >> CLOCK_HFCLKSTAT_SRC_Pos); +} + +__STATIC_INLINE bool nrf_clock_hf_is_running(nrf_clock_hfclk_t clk_src) +{ + return (NRF_CLOCK->HFCLKSTAT & (CLOCK_HFCLKSTAT_STATE_Msk | CLOCK_HFCLKSTAT_SRC_Msk)) == + (CLOCK_HFCLKSTAT_STATE_Msk | (clk_src << CLOCK_HFCLKSTAT_SRC_Pos)); +} + +__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_hf_start_task_status_get(void) +{ + return (nrf_clock_start_task_status_t)((NRF_CLOCK->HFCLKRUN & + CLOCK_HFCLKRUN_STATUS_Msk) >> + CLOCK_HFCLKRUN_STATUS_Pos); +} + +__STATIC_INLINE void nrf_clock_cal_timer_timeout_set(uint32_t interval) +{ + NRF_CLOCK->CTIV = ((interval << CLOCK_CTIV_CTIV_Pos) & CLOCK_CTIV_CTIV_Msk); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_CLOCK_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_comp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_comp.h new file mode 100644 index 0000000000..31e2ff3cd5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_comp.h @@ -0,0 +1,518 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief COMP HAL API. + */ + +#ifndef NRF_COMP_H_ +#define NRF_COMP_H_ + +/** + * @defgroup nrf_comp_hal COMP HAL + * @{ + * @ingroup nrf_comp + * @brief @tagAPI52 Hardware access layer for managing the Comparator (COMP). + */ + +#include "nrf.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @enum nrf_comp_input_t + * @brief COMP analog pin selection. + */ +typedef enum +{ + NRF_COMP_INPUT_0 = COMP_PSEL_PSEL_AnalogInput0, /*!< AIN0 selected as analog input. */ + NRF_COMP_INPUT_1 = COMP_PSEL_PSEL_AnalogInput1, /*!< AIN1 selected as analog input. */ + NRF_COMP_INPUT_2 = COMP_PSEL_PSEL_AnalogInput2, /*!< AIN2 selected as analog input. */ + NRF_COMP_INPUT_3 = COMP_PSEL_PSEL_AnalogInput3, /*!< AIN3 selected as analog input. */ + NRF_COMP_INPUT_4 = COMP_PSEL_PSEL_AnalogInput4, /*!< AIN4 selected as analog input. */ + NRF_COMP_INPUT_5 = COMP_PSEL_PSEL_AnalogInput5, /*!< AIN5 selected as analog input. */ + NRF_COMP_INPUT_6 = COMP_PSEL_PSEL_AnalogInput6, /*!< AIN6 selected as analog input. */ +#if defined (COMP_PSEL_PSEL_AnalogInput7) || defined (__SDK_DOXYGEN__) + NRF_COMP_INPUT_7 = COMP_PSEL_PSEL_AnalogInput7, /*!< AIN7 selected as analog input. */ +#endif +#if defined (COMP_PSEL_PSEL_VddDiv2) || defined (__SDK_DOXYGEN__) + NRF_COMP_VDD_DIV2 = COMP_PSEL_PSEL_VddDiv2, /*!< VDD/2 selected as analog input. */ +#endif +}nrf_comp_input_t; + +/** + * @enum nrf_comp_ref_t + * @brief COMP reference selection. + */ +typedef enum +{ + NRF_COMP_REF_Int1V2 = COMP_REFSEL_REFSEL_Int1V2, /*!< VREF = internal 1.2 V reference (VDD >= 1.7 V). */ + NRF_COMP_REF_Int1V8 = COMP_REFSEL_REFSEL_Int1V8, /*!< VREF = internal 1.8 V reference (VDD >= VREF + 0.2 V). */ + NRF_COMP_REF_Int2V4 = COMP_REFSEL_REFSEL_Int2V4, /*!< VREF = internal 2.4 V reference (VDD >= VREF + 0.2 V). */ + NRF_COMP_REF_VDD = COMP_REFSEL_REFSEL_VDD, /*!< VREF = VDD. */ + NRF_COMP_REF_ARef = COMP_REFSEL_REFSEL_ARef /*!< VREF = AREF (VDD >= VREF >= AREFMIN). */ +}nrf_comp_ref_t; + +/** + * @enum nrf_comp_ext_ref_t + * @brief COMP external analog reference selection. + */ +typedef enum +{ + NRF_COMP_EXT_REF_0 = COMP_EXTREFSEL_EXTREFSEL_AnalogReference0, /*!< Use AIN0 as external analog reference. */ + NRF_COMP_EXT_REF_1 = COMP_EXTREFSEL_EXTREFSEL_AnalogReference1 /*!< Use AIN1 as external analog reference. */ +}nrf_comp_ext_ref_t; + +/** + * @brief COMP THDOWN and THUP values that are used to calculate the threshold voltages VDOWN and VUP. + */ +typedef struct +{ + uint8_t th_down; /*!< THDOWN value. */ + uint8_t th_up; /*!< THUP value. */ +}nrf_comp_th_t; + +/** + * @enum nrf_comp_main_mode_t + * @brief COMP main operation mode. + */ +typedef enum +{ + NRF_COMP_MAIN_MODE_SE = COMP_MODE_MAIN_SE, /*!< Single ended mode. */ + NRF_COMP_MAIN_MODE_Diff = COMP_MODE_MAIN_Diff /*!< Differential mode. */ +}nrf_comp_main_mode_t; + +/** + * @enum nrf_comp_sp_mode_t + * @brief COMP speed and power mode. + */ +typedef enum +{ + NRF_COMP_SP_MODE_Low = COMP_MODE_SP_Low, /*!< Low power mode. */ + NRF_COMP_SP_MODE_Normal = COMP_MODE_SP_Normal, /*!< Normal mode. */ + NRF_COMP_SP_MODE_High = COMP_MODE_SP_High /*!< High speed mode. */ +}nrf_comp_sp_mode_t; + +/** + * @enum nrf_comp_hyst_t + * @brief COMP comparator hysteresis. + */ +typedef enum +{ + NRF_COMP_HYST_NoHyst = COMP_HYST_HYST_NoHyst, /*!< Comparator hysteresis disabled. */ + NRF_COMP_HYST_50mV = COMP_HYST_HYST_Hyst50mV /*!< Comparator hysteresis enabled. */ +}nrf_comp_hyst_t; + +#if defined (COMP_ISOURCE_ISOURCE_Msk) +/** + * @brief COMP current source selection on analog input. + */ +typedef enum +{ + NRF_COMP_ISOURCE_Off = COMP_ISOURCE_ISOURCE_Off, /*!< Current source disabled. */ + NRF_COMP_ISOURCE_Ien2uA5 = COMP_ISOURCE_ISOURCE_Ien2mA5, /*!< Current source enabled (+/- 2.5 uA). */ + NRF_COMP_ISOURCE_Ien5uA = COMP_ISOURCE_ISOURCE_Ien5mA, /*!< Current source enabled (+/- 5 uA). */ + NRF_COMP_ISOURCE_Ien10uA = COMP_ISOURCE_ISOURCE_Ien10mA /*!< Current source enabled (+/- 10 uA). */ +}nrf_isource_t; +#endif + +/** + * @enum nrf_comp_task_t + * @brief COMP tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_COMP_TASK_START = offsetof(NRF_COMP_Type, TASKS_START), /*!< COMP start sampling task. */ + NRF_COMP_TASK_STOP = offsetof(NRF_COMP_Type, TASKS_STOP), /*!< COMP stop sampling task. */ + NRF_COMP_TASK_SAMPLE = offsetof(NRF_COMP_Type, TASKS_SAMPLE) /*!< Sample comparator value. */ + /*lint -restore*/ +}nrf_comp_task_t; + +/** + * @enum nrf_comp_event_t + * @brief COMP events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_COMP_EVENT_READY = offsetof(NRF_COMP_Type, EVENTS_READY), /*!< COMP is ready and output is valid. */ + NRF_COMP_EVENT_DOWN = offsetof(NRF_COMP_Type, EVENTS_DOWN), /*!< Input voltage crossed the threshold going down. */ + NRF_COMP_EVENT_UP = offsetof(NRF_COMP_Type, EVENTS_UP), /*!< Input voltage crossed the threshold going up. */ + NRF_COMP_EVENT_CROSS = offsetof(NRF_COMP_Type, EVENTS_CROSS) /*!< Input voltage crossed the threshold in any direction. */ + /*lint -restore*/ +}nrf_comp_event_t; + +/** + * @brief COMP reference configuration. + */ +typedef struct +{ + nrf_comp_ref_t reference; /*!< COMP reference selection. */ + nrf_comp_ext_ref_t external; /*!< COMP external analog reference selection. */ +}nrf_comp_ref_conf_t; + + +/** + * @brief Function for enabling the COMP peripheral. + */ +__STATIC_INLINE void nrf_comp_enable(void); + + +/** + * @brief Function for disabling the COMP peripheral. + */ + +__STATIC_INLINE void nrf_comp_disable(void); + +/** + * @brief Function for checking if the COMP peripheral is enabled. + * + * @retval true If the COMP peripheral is enabled. + * @retval false If the COMP peripheral is not enabled. + */ +__STATIC_INLINE bool nrf_comp_enable_check(void); + +/** + * @brief Function for setting the reference source. + * + * @param[in] reference COMP reference selection. + */ +__STATIC_INLINE void nrf_comp_ref_set(nrf_comp_ref_t reference); + + +/** + * @brief Function for setting the external analog reference source. + * + * @param[in] ext_ref COMP external analog reference selection. + */ +__STATIC_INLINE void nrf_comp_ext_ref_set(nrf_comp_ext_ref_t ext_ref); + + +/** + * @brief Function for setting threshold voltages. + * + * @param[in] threshold COMP VDOWN and VUP thresholds. + */ +__STATIC_INLINE void nrf_comp_th_set(nrf_comp_th_t threshold); + + +/** + * @brief Function for setting the main mode. + * + * @param[in] main_mode COMP main operation mode. + */ +__STATIC_INLINE void nrf_comp_main_mode_set(nrf_comp_main_mode_t main_mode); + + +/** + * @brief Function for setting the speed mode. + * + * @param[in] speed_mode COMP speed and power mode. + */ +__STATIC_INLINE void nrf_comp_speed_mode_set(nrf_comp_sp_mode_t speed_mode); + + +/** + * @brief Function for setting the hysteresis. + * + * @param[in] hyst COMP comparator hysteresis. + */ +__STATIC_INLINE void nrf_comp_hysteresis_set(nrf_comp_hyst_t hyst); + +#if defined (COMP_ISOURCE_ISOURCE_Msk) +/** + * @brief Function for setting the current source on the analog input. + * + * @param[in] isource COMP current source selection on analog input. + */ +__STATIC_INLINE void nrf_comp_isource_set(nrf_isource_t isource); +#endif + +/** + * @brief Function for selecting the active input of the COMP. + * + * @param[in] input Input to be selected. + */ +__STATIC_INLINE void nrf_comp_input_select(nrf_comp_input_t input); + + +/** + * @brief Function for getting the last COMP compare result. + * + * @return The last compare result. If 0, then VIN+ < VIN-. If 1, then VIN+ > VIN-. + * + * @note If VIN+ == VIN-, the return value depends on the previous result. + */ +__STATIC_INLINE uint32_t nrf_comp_result_get(void); + + +/** + * @brief Function for enabling interrupts from COMP. + * + * @param[in] comp_int_mask Mask of interrupts to be enabled. + * + * @sa nrf_comp_int_enable_check() + */ +__STATIC_INLINE void nrf_comp_int_enable(uint32_t comp_int_mask); + +/** + * @brief Function for disabling interrupts from COMP. + * + * @param[in] comp_int_mask Mask of interrupts to be disabled. + * + * @sa nrf_comp_int_enable_check() + */ +__STATIC_INLINE void nrf_comp_int_disable(uint32_t comp_int_mask); + + +/** + * @brief Function for getting the enabled interrupts of COMP. + * + * @param[in] comp_int_mask Mask of interrupts to be checked. + * + * @retval true If any interrupts of the specified mask are enabled. + */ +__STATIC_INLINE bool nrf_comp_int_enable_check(uint32_t comp_int_mask); + + + +/** + * @brief Function for getting the address of a specific COMP task register. + * + * @param[in] comp_task COMP task. + * + * @return Address of the specified COMP task. + */ +__STATIC_INLINE uint32_t * nrf_comp_task_address_get(nrf_comp_task_t comp_task); + + +/** + * @brief Function for getting the address of a specific COMP event register. + * + * @param[in] comp_event COMP event. + * + * @return Address of the specified COMP event. + */ +__STATIC_INLINE uint32_t * nrf_comp_event_address_get(nrf_comp_event_t comp_event); + + +/** + * @brief Function for setting COMP shorts. + * + * @param[in] comp_short_mask COMP shorts by mask. + * + */ +__STATIC_INLINE void nrf_comp_shorts_enable(uint32_t comp_short_mask); + + +/** + * @brief Function for clearing COMP shorts by mask. + * + * @param[in] comp_short_mask COMP shorts to be cleared. + * + */ +__STATIC_INLINE void nrf_comp_shorts_disable(uint32_t comp_short_mask); + + +/** + * @brief Function for setting a specific COMP task. + * + * @param[in] comp_task COMP task to be set. + * + */ +__STATIC_INLINE void nrf_comp_task_trigger(nrf_comp_task_t comp_task); + + +/** + * @brief Function for clearing a specific COMP event. + * + * @param[in] comp_event COMP event to be cleared. + * + */ +__STATIC_INLINE void nrf_comp_event_clear(nrf_comp_event_t comp_event); + + +/** + * @brief Function for getting the state of a specific COMP event. + * + * @retval true If the specified COMP event is active. + * + */ +__STATIC_INLINE bool nrf_comp_event_check(nrf_comp_event_t comp_event); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_comp_enable(void) +{ + NRF_COMP->ENABLE = (COMP_ENABLE_ENABLE_Enabled << COMP_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_comp_disable(void) +{ + NRF_COMP->ENABLE = (COMP_ENABLE_ENABLE_Disabled << COMP_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE bool nrf_comp_enable_check(void) +{ + return ((NRF_COMP->ENABLE) & COMP_ENABLE_ENABLE_Enabled); +} + +__STATIC_INLINE void nrf_comp_ref_set(nrf_comp_ref_t reference) +{ + NRF_COMP->REFSEL = (reference << COMP_REFSEL_REFSEL_Pos); +} + +__STATIC_INLINE void nrf_comp_ext_ref_set(nrf_comp_ext_ref_t ext_ref) +{ + NRF_COMP->EXTREFSEL = (ext_ref << COMP_EXTREFSEL_EXTREFSEL_Pos); +} + +__STATIC_INLINE void nrf_comp_th_set(nrf_comp_th_t threshold) +{ + NRF_COMP->TH = + ((threshold.th_down << COMP_TH_THDOWN_Pos) & COMP_TH_THDOWN_Msk) | + ((threshold.th_up << COMP_TH_THUP_Pos) & COMP_TH_THUP_Msk); +} + +__STATIC_INLINE void nrf_comp_main_mode_set(nrf_comp_main_mode_t main_mode) +{ + NRF_COMP->MODE |= (main_mode << COMP_MODE_MAIN_Pos); +} + +__STATIC_INLINE void nrf_comp_speed_mode_set(nrf_comp_sp_mode_t speed_mode) +{ + NRF_COMP->MODE |= (speed_mode << COMP_MODE_SP_Pos); +} + +__STATIC_INLINE void nrf_comp_hysteresis_set(nrf_comp_hyst_t hyst) +{ + NRF_COMP->HYST = (hyst << COMP_HYST_HYST_Pos) & COMP_HYST_HYST_Msk; +} + +#if defined (COMP_ISOURCE_ISOURCE_Msk) +__STATIC_INLINE void nrf_comp_isource_set(nrf_isource_t isource) +{ + NRF_COMP->ISOURCE = (isource << COMP_ISOURCE_ISOURCE_Pos) & COMP_ISOURCE_ISOURCE_Msk; +} +#endif + +__STATIC_INLINE void nrf_comp_input_select(nrf_comp_input_t input) +{ + NRF_COMP->PSEL = ((uint32_t)input << COMP_PSEL_PSEL_Pos); +} + +__STATIC_INLINE uint32_t nrf_comp_result_get(void) +{ + return (uint32_t)NRF_COMP->RESULT; +} + +__STATIC_INLINE void nrf_comp_int_enable(uint32_t comp_int_mask) +{ + NRF_COMP->INTENSET = comp_int_mask; +} + +__STATIC_INLINE void nrf_comp_int_disable(uint32_t comp_int_mask) +{ + NRF_COMP->INTENCLR = comp_int_mask; +} + +__STATIC_INLINE bool nrf_comp_int_enable_check(uint32_t comp_int_mask) +{ + return (NRF_COMP->INTENSET & comp_int_mask); // when read this register will return the value of INTEN. +} + +__STATIC_INLINE uint32_t * nrf_comp_task_address_get(nrf_comp_task_t comp_task) +{ + return (uint32_t *)((uint8_t *)NRF_COMP + (uint32_t)comp_task); +} + +__STATIC_INLINE uint32_t * nrf_comp_event_address_get(nrf_comp_event_t comp_event) +{ + return (uint32_t *)((uint8_t *)NRF_COMP + (uint32_t)comp_event); +} + +__STATIC_INLINE void nrf_comp_shorts_enable(uint32_t comp_short_mask) +{ + NRF_COMP->SHORTS |= comp_short_mask; +} + +__STATIC_INLINE void nrf_comp_shorts_disable(uint32_t comp_short_mask) +{ + NRF_COMP->SHORTS &= ~comp_short_mask; +} + +__STATIC_INLINE void nrf_comp_task_trigger(nrf_comp_task_t comp_task) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_COMP + comp_task) ) = 1; +} + +__STATIC_INLINE void nrf_comp_event_clear(nrf_comp_event_t comp_event) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_COMP + (uint32_t)comp_event) ) = 0; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_COMP + (uint32_t)comp_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_comp_event_check(nrf_comp_event_t comp_event) +{ + return (bool) (*(volatile uint32_t *)( (uint8_t *)NRF_COMP + comp_event)); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_COMP_H_ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.c new file mode 100644 index 0000000000..d8c96d4ce8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.c @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Implementation of AES ECB driver + */ + + +//lint -e438 + +#include +#include +#include +#include "nrf.h" +#include "nrf_ecb.h" + +static uint8_t ecb_data[48]; ///< ECB data structure for RNG peripheral to access. +static uint8_t* ecb_key; ///< Key: Starts at ecb_data +static uint8_t* ecb_cleartext; ///< Cleartext: Starts at ecb_data + 16 bytes. +static uint8_t* ecb_ciphertext; ///< Ciphertext: Starts at ecb_data + 32 bytes. + +bool nrf_ecb_init(void) +{ + ecb_key = ecb_data; + ecb_cleartext = ecb_data + 16; + ecb_ciphertext = ecb_data + 32; + + NRF_ECB->ECBDATAPTR = (uint32_t)ecb_data; + return true; +} + + +bool nrf_ecb_crypt(uint8_t * dest_buf, const uint8_t * src_buf) +{ + uint32_t counter = 0x1000000; + if (src_buf != ecb_cleartext) + { + memcpy(ecb_cleartext,src_buf,16); + } + NRF_ECB->EVENTS_ENDECB = 0; + NRF_ECB->TASKS_STARTECB = 1; + while (NRF_ECB->EVENTS_ENDECB == 0) + { + counter--; + if (counter == 0) + { + return false; + } + } + NRF_ECB->EVENTS_ENDECB = 0; + if (dest_buf != ecb_ciphertext) + { + memcpy(dest_buf,ecb_ciphertext,16); + } + return true; +} + +void nrf_ecb_set_key(const uint8_t * key) +{ + memcpy(ecb_key,key,16); +} + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.h new file mode 100644 index 0000000000..b9bf4fb0a8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ecb.h @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief ECB driver API. + */ + +#ifndef NRF_ECB_H__ +#define NRF_ECB_H__ + +/** + * @defgroup nrf_ecb AES ECB encryption + * @{ + * @ingroup nrf_drivers + * @brief Driver for the AES Electronic Code Book (ECB) peripheral. + * + * To encrypt data, the peripheral must first be powered on + * using @ref nrf_ecb_init. Next, the key must be set using @ref nrf_ecb_set_key. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing and powering on the ECB peripheral. + * + * This function allocates memory for the ECBDATAPTR. + * @retval true If initialization was successful. + * @retval false If powering on failed. + */ +bool nrf_ecb_init(void); + +/** + * @brief Function for encrypting 16-byte data using current key. + * + * This function avoids unnecessary copying of data if the parameters point to the + * correct locations in the ECB data structure. + * + * @param dst Result of encryption, 16 bytes will be written. + * @param src Source with 16-byte data to be encrypted. + * + * @retval true If the encryption operation completed. + * @retval false If the encryption operation did not complete. + */ +bool nrf_ecb_crypt(uint8_t * dst, const uint8_t * src); + +/** + * @brief Function for setting the key to be used for encryption. + * + * @param key Pointer to the key. 16 bytes will be read. + */ +void nrf_ecb_set_key(const uint8_t * key); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_ECB_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_egu.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_egu.h new file mode 100644 index 0000000000..7610516149 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_egu.h @@ -0,0 +1,367 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_EGU_H__ +#define NRF_EGU_H__ + +/** +* @defgroup nrf_egu EGU (Event Generator Unit) abstraction +* @{ +* @ingroup nrf_drivers +* @brief @tagAPI52 EGU (Event Generator Unit) module functions. +* +*/ + +#include +#include +#include +#include "nrf_assert.h" +#include "nrf.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @enum nrf_egu_task_t + * @brief EGU tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_EGU_TASK_TRIGGER0 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[0]), /**< Trigger 0 for triggering the corresponding TRIGGERED[0] event. */ + NRF_EGU_TASK_TRIGGER1 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[1]), /**< Trigger 1 for triggering the corresponding TRIGGERED[1] event. */ + NRF_EGU_TASK_TRIGGER2 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[2]), /**< Trigger 2 for triggering the corresponding TRIGGERED[2] event. */ + NRF_EGU_TASK_TRIGGER3 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[3]), /**< Trigger 3 for triggering the corresponding TRIGGERED[3] event. */ + NRF_EGU_TASK_TRIGGER4 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[4]), /**< Trigger 4 for triggering the corresponding TRIGGERED[4] event. */ + NRF_EGU_TASK_TRIGGER5 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[5]), /**< Trigger 5 for triggering the corresponding TRIGGERED[5] event. */ + NRF_EGU_TASK_TRIGGER6 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[6]), /**< Trigger 6 for triggering the corresponding TRIGGERED[6] event. */ + NRF_EGU_TASK_TRIGGER7 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[7]), /**< Trigger 7 for triggering the corresponding TRIGGERED[7] event. */ + NRF_EGU_TASK_TRIGGER8 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[8]), /**< Trigger 8 for triggering the corresponding TRIGGERED[8] event. */ + NRF_EGU_TASK_TRIGGER9 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[9]), /**< Trigger 9 for triggering the corresponding TRIGGERED[9] event. */ + NRF_EGU_TASK_TRIGGER10 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[10]), /**< Trigger 10 for triggering the corresponding TRIGGERED[10] event. */ + NRF_EGU_TASK_TRIGGER11 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[11]), /**< Trigger 11 for triggering the corresponding TRIGGERED[11] event. */ + NRF_EGU_TASK_TRIGGER12 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[12]), /**< Trigger 12 for triggering the corresponding TRIGGERED[12] event. */ + NRF_EGU_TASK_TRIGGER13 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[13]), /**< Trigger 13 for triggering the corresponding TRIGGERED[13] event. */ + NRF_EGU_TASK_TRIGGER14 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[14]), /**< Trigger 14 for triggering the corresponding TRIGGERED[14] event. */ + NRF_EGU_TASK_TRIGGER15 = offsetof(NRF_EGU_Type, TASKS_TRIGGER[15]) /**< Trigger 15 for triggering the corresponding TRIGGERED[15] event. */ + /*lint -restore*/ +} nrf_egu_task_t; + + +/** + * @enum nrf_egu_event_t + * @brief EGU events. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_EGU_EVENT_TRIGGERED0 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[0]), /**< Event number 0 generated by triggering the corresponding TRIGGER[0] task. */ + NRF_EGU_EVENT_TRIGGERED1 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[1]), /**< Event number 1 generated by triggering the corresponding TRIGGER[1] task. */ + NRF_EGU_EVENT_TRIGGERED2 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[2]), /**< Event number 2 generated by triggering the corresponding TRIGGER[2] task. */ + NRF_EGU_EVENT_TRIGGERED3 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[3]), /**< Event number 3 generated by triggering the corresponding TRIGGER[3] task. */ + NRF_EGU_EVENT_TRIGGERED4 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[4]), /**< Event number 4 generated by triggering the corresponding TRIGGER[4] task. */ + NRF_EGU_EVENT_TRIGGERED5 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[5]), /**< Event number 5 generated by triggering the corresponding TRIGGER[5] task. */ + NRF_EGU_EVENT_TRIGGERED6 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[6]), /**< Event number 6 generated by triggering the corresponding TRIGGER[6] task. */ + NRF_EGU_EVENT_TRIGGERED7 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[7]), /**< Event number 7 generated by triggering the corresponding TRIGGER[7] task. */ + NRF_EGU_EVENT_TRIGGERED8 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[8]), /**< Event number 8 generated by triggering the corresponding TRIGGER[8] task. */ + NRF_EGU_EVENT_TRIGGERED9 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[9]), /**< Event number 9 generated by triggering the corresponding TRIGGER[9] task. */ + NRF_EGU_EVENT_TRIGGERED10 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[10]), /**< Event number 10 generated by triggering the corresponding TRIGGER[10] task. */ + NRF_EGU_EVENT_TRIGGERED11 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[11]), /**< Event number 11 generated by triggering the corresponding TRIGGER[11] task. */ + NRF_EGU_EVENT_TRIGGERED12 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[12]), /**< Event number 12 generated by triggering the corresponding TRIGGER[12] task. */ + NRF_EGU_EVENT_TRIGGERED13 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[13]), /**< Event number 13 generated by triggering the corresponding TRIGGER[13] task. */ + NRF_EGU_EVENT_TRIGGERED14 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[14]), /**< Event number 14 generated by triggering the corresponding TRIGGER[14] task. */ + NRF_EGU_EVENT_TRIGGERED15 = offsetof(NRF_EGU_Type, EVENTS_TRIGGERED[15]) /**< Event number 15 generated by triggering the corresponding TRIGGER[15] task. */ + /*lint -restore*/ +} nrf_egu_event_t; + + +/** + * @enum nrf_egu_int_mask_t + * @brief EGU interrupts. + */ +typedef enum +{ + NRF_EGU_INT_TRIGGERED0 = EGU_INTENSET_TRIGGERED0_Msk, /**< Interrupt on EVENTS_TRIGGERED[0] event. */ + NRF_EGU_INT_TRIGGERED1 = EGU_INTENSET_TRIGGERED1_Msk, /**< Interrupt on EVENTS_TRIGGERED[1] event. */ + NRF_EGU_INT_TRIGGERED2 = EGU_INTENSET_TRIGGERED2_Msk, /**< Interrupt on EVENTS_TRIGGERED[2] event. */ + NRF_EGU_INT_TRIGGERED3 = EGU_INTENSET_TRIGGERED3_Msk, /**< Interrupt on EVENTS_TRIGGERED[3] event. */ + NRF_EGU_INT_TRIGGERED4 = EGU_INTENSET_TRIGGERED4_Msk, /**< Interrupt on EVENTS_TRIGGERED[4] event. */ + NRF_EGU_INT_TRIGGERED5 = EGU_INTENSET_TRIGGERED5_Msk, /**< Interrupt on EVENTS_TRIGGERED[5] event. */ + NRF_EGU_INT_TRIGGERED6 = EGU_INTENSET_TRIGGERED6_Msk, /**< Interrupt on EVENTS_TRIGGERED[6] event. */ + NRF_EGU_INT_TRIGGERED7 = EGU_INTENSET_TRIGGERED7_Msk, /**< Interrupt on EVENTS_TRIGGERED[7] event. */ + NRF_EGU_INT_TRIGGERED8 = EGU_INTENSET_TRIGGERED8_Msk, /**< Interrupt on EVENTS_TRIGGERED[8] event. */ + NRF_EGU_INT_TRIGGERED9 = EGU_INTENSET_TRIGGERED9_Msk, /**< Interrupt on EVENTS_TRIGGERED[9] event. */ + NRF_EGU_INT_TRIGGERED10 = EGU_INTENSET_TRIGGERED10_Msk, /**< Interrupt on EVENTS_TRIGGERED[10] event. */ + NRF_EGU_INT_TRIGGERED11 = EGU_INTENSET_TRIGGERED11_Msk, /**< Interrupt on EVENTS_TRIGGERED[11] event. */ + NRF_EGU_INT_TRIGGERED12 = EGU_INTENSET_TRIGGERED12_Msk, /**< Interrupt on EVENTS_TRIGGERED[12] event. */ + NRF_EGU_INT_TRIGGERED13 = EGU_INTENSET_TRIGGERED13_Msk, /**< Interrupt on EVENTS_TRIGGERED[13] event. */ + NRF_EGU_INT_TRIGGERED14 = EGU_INTENSET_TRIGGERED14_Msk, /**< Interrupt on EVENTS_TRIGGERED[14] event. */ + NRF_EGU_INT_TRIGGERED15 = EGU_INTENSET_TRIGGERED15_Msk, /**< Interrupt on EVENTS_TRIGGERED[15] event. */ + NRF_EGU_INT_ALL = 0xFFFFuL +} nrf_egu_int_mask_t; + +/**@brief Function for getting max channel number of given EGU. + * + * @param NRF_EGUx EGU instance. + * + * @returns number of available channels. + */ +__STATIC_INLINE uint32_t nrf_egu_channel_count(NRF_EGU_Type * NRF_EGUx) +{ + if (NRF_EGUx == NRF_EGU0){ + return EGU0_CH_NUM; + } + if (NRF_EGUx == NRF_EGU1){ + return EGU1_CH_NUM; + } +#if EGU_COUNT > 2 + if (NRF_EGUx == NRF_EGU2){ + return EGU2_CH_NUM; + } + if (NRF_EGUx == NRF_EGU3){ + return EGU3_CH_NUM; + } + if (NRF_EGUx == NRF_EGU4){ + return EGU4_CH_NUM; + } + if (NRF_EGUx == NRF_EGU5){ + return EGU5_CH_NUM; + } +#endif + return 0; +} + +/** + * @brief Function for triggering a specific EGU task. + * + * @param NRF_EGUx EGU instance. + * @param egu_task EGU task. + */ +__STATIC_INLINE void nrf_egu_task_trigger(NRF_EGU_Type * NRF_EGUx, nrf_egu_task_t egu_task) +{ + ASSERT(NRF_EGUx); + *((volatile uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_task)) = 0x1UL; +} + + +/** + * @brief Function for returning the address of a specific EGU task register. + * + * @param NRF_EGUx EGU instance. + * @param egu_task EGU task. + */ +__STATIC_INLINE uint32_t * nrf_egu_task_address_get(NRF_EGU_Type * NRF_EGUx, + nrf_egu_task_t egu_task) +{ + ASSERT(NRF_EGUx); + return (uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_task); +} + + +/** + * @brief Function for returning the address of a specific EGU TRIGGER task register. + * + * @param NRF_EGUx EGU instance. + * @param channel Channel number. + */ +__STATIC_INLINE uint32_t * nrf_egu_task_trigger_address_get(NRF_EGU_Type * NRF_EGUx, + uint8_t channel) +{ + ASSERT(NRF_EGUx); + ASSERT(channel < nrf_egu_channel_count(NRF_EGUx)); + return (uint32_t*)&NRF_EGUx->TASKS_TRIGGER[channel]; +} + + +/** + * @brief Function for returning the specific EGU TRIGGER task. + * + * @param NRF_EGUx EGU instance. + * @param channel Channel number. + */ +__STATIC_INLINE nrf_egu_task_t nrf_egu_task_trigger_get(NRF_EGU_Type * NRF_EGUx, uint8_t channel) +{ + ASSERT(NRF_EGUx); + ASSERT(channel < nrf_egu_channel_count(NRF_EGUx)); + return (nrf_egu_task_t)((uint32_t) NRF_EGU_TASK_TRIGGER0 + (channel * sizeof(uint32_t))); +} + + +/** + * @brief Function for returning the state of a specific EGU event. + * + * @param NRF_EGUx EGU instance. + * @param egu_event EGU event to check. + */ +__STATIC_INLINE bool nrf_egu_event_check(NRF_EGU_Type * NRF_EGUx, + nrf_egu_event_t egu_event) +{ + ASSERT(NRF_EGUx); + return (bool)*(volatile uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_event); +} + + +/** + * @brief Function for clearing a specific EGU event. + * + * @param NRF_EGUx EGU instance. + * @param egu_event EGU event to clear. + */ +__STATIC_INLINE void nrf_egu_event_clear(NRF_EGU_Type * NRF_EGUx, + nrf_egu_event_t egu_event) +{ + ASSERT(NRF_EGUx); + *((volatile uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for returning the address of a specific EGU event register. + * + * @param NRF_EGUx EGU instance. + * @param egu_event EGU event. + */ +__STATIC_INLINE uint32_t * nrf_egu_event_address_get(NRF_EGU_Type * NRF_EGUx, + nrf_egu_event_t egu_event) +{ + ASSERT(NRF_EGUx); + return (uint32_t *)((uint8_t *)NRF_EGUx + (uint32_t)egu_event); +} + + +/** + * @brief Function for returning the address of a specific EGU TRIGGERED event register. + * + * @param NRF_EGUx EGU instance. + * @param channel Channel number. + */ +__STATIC_INLINE uint32_t * nrf_egu_event_triggered_address_get(NRF_EGU_Type * NRF_EGUx, + uint8_t channel) +{ + ASSERT(NRF_EGUx); + ASSERT(channel < nrf_egu_channel_count(NRF_EGUx)); + return (uint32_t*)&NRF_EGUx->EVENTS_TRIGGERED[channel]; +} + + +/** + * @brief Function for returning the specific EGU TRIGGERED event. + * + * @param NRF_EGUx EGU instance. + * @param channel Channel number. + */ +__STATIC_INLINE nrf_egu_event_t nrf_egu_event_triggered_get(NRF_EGU_Type * NRF_EGUx, + uint8_t channel) +{ + ASSERT(NRF_EGUx); + ASSERT(channel < nrf_egu_channel_count(NRF_EGUx)); + return (nrf_egu_event_t)((uint32_t) NRF_EGU_EVENT_TRIGGERED0 + (channel * sizeof(uint32_t))); +} + + +/** + * @brief Function for enabling one or more specific EGU interrupts. + * + * @param NRF_EGUx EGU instance. + * @param egu_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_egu_int_enable(NRF_EGU_Type * NRF_EGUx, uint32_t egu_int_mask) +{ + ASSERT(NRF_EGUx); + NRF_EGUx->INTENSET = egu_int_mask; +} + + +/** + * @brief Function for retrieving the state of one or more EGU interrupts. + * + * @param NRF_EGUx EGU instance. + * @param egu_int_mask Interrupts to check. + * + * @retval true If all of the specified interrupts are enabled. + * @retval false If at least one of the specified interrupts is disabled. + */ +__STATIC_INLINE bool nrf_egu_int_enable_check(NRF_EGU_Type * NRF_EGUx, uint32_t egu_int_mask) +{ + ASSERT(NRF_EGUx); + return (bool)(NRF_EGUx->INTENSET & egu_int_mask); +} + + +/** + * @brief Function for disabling one or more specific EGU interrupts. + * + * @param NRF_EGUx EGU instance. + * @param egu_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_egu_int_disable(NRF_EGU_Type * NRF_EGUx, uint32_t egu_int_mask) +{ + ASSERT(NRF_EGUx); + NRF_EGUx->INTENCLR = egu_int_mask; +} + +/** + * @brief Function for retrieving one or more specific EGU interrupts. + * + * @param NRF_EGUx EGU instance. + * @param channel Channel number. + * + * @returns EGU interrupt mask. + */ +__STATIC_INLINE nrf_egu_int_mask_t nrf_egu_int_get(NRF_EGU_Type * NRF_EGUx, uint8_t channel) +{ + ASSERT(NRF_EGUx); + ASSERT(channel < nrf_egu_channel_count(NRF_EGUx)); + return (nrf_egu_int_mask_t)((uint32_t) (EGU_INTENSET_TRIGGERED0_Msk << channel)); +} + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpio.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpio.h new file mode 100644 index 0000000000..ccd408c0ad --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpio.h @@ -0,0 +1,795 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_GPIO_H__ +#define NRF_GPIO_H__ + +#include "nrf.h" +#include "nrf_peripherals.h" +#include "nrf_assert.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_gpio GPIO abstraction + * @{ + * @ingroup nrf_drivers + * @brief GPIO pin abstraction and port abstraction for reading and writing byte-wise to GPIO ports. + */ + +#if (GPIO_COUNT == 1) +#define NUMBER_OF_PINS (P0_PIN_NUM) +#define GPIO_REG_LIST {NRF_GPIO} +#elif (GPIO_COUNT == 2) +#define NUMBER_OF_PINS (P0_PIN_NUM + P1_PIN_NUM) +#define GPIO_REG_LIST {NRF_P0, NRF_P1} +#else +#error "Not supported." +#endif + + +/** + * @brief Macro for mapping port and pin numbers to values understandable for nrf_gpio functions. + */ +#define NRF_GPIO_PIN_MAP(port, pin) ((port << 5) | (pin & 0x1F)) + +/** + * @brief Pin direction definitions. + */ +typedef enum +{ + NRF_GPIO_PIN_DIR_INPUT = GPIO_PIN_CNF_DIR_Input, ///< Input. + NRF_GPIO_PIN_DIR_OUTPUT = GPIO_PIN_CNF_DIR_Output ///< Output. +} nrf_gpio_pin_dir_t; + +/** + * @brief Connection of input buffer. + */ +typedef enum +{ + NRF_GPIO_PIN_INPUT_CONNECT = GPIO_PIN_CNF_INPUT_Connect, ///< Connect input buffer. + NRF_GPIO_PIN_INPUT_DISCONNECT = GPIO_PIN_CNF_INPUT_Disconnect ///< Disconnect input buffer. +} nrf_gpio_pin_input_t; + +/** + * @brief Enumerator used for selecting the pin to be pulled down or up at the time of pin configuration. + */ +typedef enum +{ + NRF_GPIO_PIN_NOPULL = GPIO_PIN_CNF_PULL_Disabled, ///< Pin pull-up resistor disabled. + NRF_GPIO_PIN_PULLDOWN = GPIO_PIN_CNF_PULL_Pulldown, ///< Pin pull-down resistor enabled. + NRF_GPIO_PIN_PULLUP = GPIO_PIN_CNF_PULL_Pullup, ///< Pin pull-up resistor enabled. +} nrf_gpio_pin_pull_t; + +/** + * @brief Enumerator used for selecting output drive mode. + */ +typedef enum +{ + NRF_GPIO_PIN_S0S1 = GPIO_PIN_CNF_DRIVE_S0S1, ///< !< Standard '0', standard '1'. + NRF_GPIO_PIN_H0S1 = GPIO_PIN_CNF_DRIVE_H0S1, ///< !< High-drive '0', standard '1'. + NRF_GPIO_PIN_S0H1 = GPIO_PIN_CNF_DRIVE_S0H1, ///< !< Standard '0', high-drive '1'. + NRF_GPIO_PIN_H0H1 = GPIO_PIN_CNF_DRIVE_H0H1, ///< !< High drive '0', high-drive '1'. + NRF_GPIO_PIN_D0S1 = GPIO_PIN_CNF_DRIVE_D0S1, ///< !< Disconnect '0' standard '1'. + NRF_GPIO_PIN_D0H1 = GPIO_PIN_CNF_DRIVE_D0H1, ///< !< Disconnect '0', high-drive '1'. + NRF_GPIO_PIN_S0D1 = GPIO_PIN_CNF_DRIVE_S0D1, ///< !< Standard '0', disconnect '1'. + NRF_GPIO_PIN_H0D1 = GPIO_PIN_CNF_DRIVE_H0D1, ///< !< High-drive '0', disconnect '1'. +} nrf_gpio_pin_drive_t; + +/** + * @brief Enumerator used for selecting the pin to sense high or low level on the pin input. + */ +typedef enum +{ + NRF_GPIO_PIN_NOSENSE = GPIO_PIN_CNF_SENSE_Disabled, ///< Pin sense level disabled. + NRF_GPIO_PIN_SENSE_LOW = GPIO_PIN_CNF_SENSE_Low, ///< Pin sense low level. + NRF_GPIO_PIN_SENSE_HIGH = GPIO_PIN_CNF_SENSE_High, ///< Pin sense high level. +} nrf_gpio_pin_sense_t; + + +#if (__LINT__ != 1) + +/** + * @brief Function for configuring the GPIO pin range as output pins with normal drive strength. + * This function can be used to configure pin range as simple output with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases). + * + * @param pin_range_start Specifies the start number (inclusive) in the range of pin numbers to be configured (allowed values 0-30). + * + * @param pin_range_end Specifies the end number (inclusive) in the range of pin numbers to be configured (allowed values 0-30). + * + * @note For configuring only one pin as output, use @ref nrf_gpio_cfg_output. + * Sense capability on the pin is disabled and input is disconnected from the buffer as the pins are configured as output. + */ +__STATIC_INLINE void nrf_gpio_range_cfg_output(uint32_t pin_range_start, uint32_t pin_range_end); + +/** + * @brief Function for configuring the GPIO pin range as input pins with given initial value set, hiding inner details. + * This function can be used to configure pin range as simple input. + * + * @param pin_range_start Specifies the start number (inclusive) in the range of pin numbers to be configured (allowed values 0-30). + * + * @param pin_range_end Specifies the end number (inclusive) in the range of pin numbers to be configured (allowed values 0-30). + * + * @param pull_config State of the pin range pull resistor (no pull, pulled down, or pulled high). + * + * @note For configuring only one pin as input, use @ref nrf_gpio_cfg_input. + * Sense capability on the pin is disabled and input is connected to buffer so that the GPIO->IN register is readable. + */ +__STATIC_INLINE void nrf_gpio_range_cfg_input(uint32_t pin_range_start, + uint32_t pin_range_end, + nrf_gpio_pin_pull_t pull_config); + +/** + * @brief Pin configuration function. + * + * The main pin configuration function. + * This function allows to set any aspect in PIN_CNF register. + * @param pin_number Specifies the pin number. + * @param dir Pin direction. + * @param input Connect or disconnect the input buffer. + * @param pull Pull configuration. + * @param drive Drive configuration. + * @param sense Pin sensing mechanism. + */ +__STATIC_INLINE void nrf_gpio_cfg( + uint32_t pin_number, + nrf_gpio_pin_dir_t dir, + nrf_gpio_pin_input_t input, + nrf_gpio_pin_pull_t pull, + nrf_gpio_pin_drive_t drive, + nrf_gpio_pin_sense_t sense); + +/** + * @brief Function for configuring the given GPIO pin number as output, hiding inner details. + * This function can be used to configure a pin as simple output with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases). + * + * @param pin_number Specifies the pin number. + * + * @note Sense capability on the pin is disabled and input is disconnected from the buffer as the pins are configured as output. + */ +__STATIC_INLINE void nrf_gpio_cfg_output(uint32_t pin_number); + +/** + * @brief Function for configuring the given GPIO pin number as input, hiding inner details. + * This function can be used to configure a pin as simple input. + * + * @param pin_number Specifies the pin number. + * @param pull_config State of the pin range pull resistor (no pull, pulled down, or pulled high). + * + * @note Sense capability on the pin is disabled and input is connected to buffer so that the GPIO->IN register is readable. + */ +__STATIC_INLINE void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config); + +/** + * @brief Function for resetting pin configuration to its default state. + * + * @param pin_number Specifies the pin number. + */ +__STATIC_INLINE void nrf_gpio_cfg_default(uint32_t pin_number); + +/** + * @brief Function for configuring the given GPIO pin number as a watcher. Only input is connected. + * + * @param pin_number Specifies the pin number. + * + */ +__STATIC_INLINE void nrf_gpio_cfg_watcher(uint32_t pin_number); + +/** + * @brief Function for disconnecting input for the given GPIO. + * + * @param pin_number Specifies the pin number. + * + */ +__STATIC_INLINE void nrf_gpio_input_disconnect(uint32_t pin_number); + +/** + * @brief Function for configuring the given GPIO pin number as input, hiding inner details. + * This function can be used to configure pin range as simple input. + * Sense capability on the pin is configurable and input is connected to buffer so that the GPIO->IN register is readable. + * + * @param pin_number Specifies the pin number. + * @param pull_config State of the pin pull resistor (no pull, pulled down, or pulled high). + * @param sense_config Sense level of the pin (no sense, sense low, or sense high). + */ +__STATIC_INLINE void nrf_gpio_cfg_sense_input(uint32_t pin_number, + nrf_gpio_pin_pull_t pull_config, + nrf_gpio_pin_sense_t sense_config); + +/** + * @brief Function for configuring sense level for the given GPIO. + * + * @param pin_number Specifies the pin number. + * @param sense_config Sense configuration. + * + */ +__STATIC_INLINE void nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config); + +/** + * @brief Function for setting the direction for a GPIO pin. + * + * @param pin_number Specifies the pin number for which to set the direction. + * + * @param direction Specifies the direction. + */ +__STATIC_INLINE void nrf_gpio_pin_dir_set(uint32_t pin_number, nrf_gpio_pin_dir_t direction); + +/** + * @brief Function for setting a GPIO pin. + * + * Note that the pin must be configured as an output for this function to have any effect. + * + * @param pin_number Specifies the pin number to set. + */ +__STATIC_INLINE void nrf_gpio_pin_set(uint32_t pin_number); + +/** + * @brief Function for clearing a GPIO pin. + * + * Note that the pin must be configured as an output for this + * function to have any effect. + * + * @param pin_number Specifies the pin number to clear. + */ +__STATIC_INLINE void nrf_gpio_pin_clear(uint32_t pin_number); + +/** + * @brief Function for toggling a GPIO pin. + * + * Note that the pin must be configured as an output for this + * function to have any effect. + * + * @param pin_number Specifies the pin number to toggle. + */ +__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number); + +/** + * @brief Function for writing a value to a GPIO pin. + * + * Note that the pin must be configured as an output for this + * function to have any effect. + * + * @param pin_number Specifies the pin number to write. + * + * @param value Specifies the value to be written to the pin. + * @arg 0 Clears the pin. + * @arg >=1 Sets the pin. + */ +__STATIC_INLINE void nrf_gpio_pin_write(uint32_t pin_number, uint32_t value); + +/** + * @brief Function for reading the input level of a GPIO pin. + * + * Note that the pin must have input connected for the value + * returned from this function to be valid. + * + * @param pin_number Specifies the pin number to read. + * + * @return 0 if the pin input level is low. Positive value if the pin is high. + */ +__STATIC_INLINE uint32_t nrf_gpio_pin_read(uint32_t pin_number); + +/** + * @brief Function for reading the output level of a GPIO pin. + * + * @param pin_number Specifies the pin number to read. + * + * @return 0 if the pin output level is low. Positive value if pin output is high. + */ +__STATIC_INLINE uint32_t nrf_gpio_pin_out_read(uint32_t pin_number); + +/** + * @brief Function for reading the sense configuration of a GPIO pin. + * + * @param pin_number Specifies the pin number to read. + * + * @retval Sense configuration. + */ +__STATIC_INLINE nrf_gpio_pin_sense_t nrf_gpio_pin_sense_get(uint32_t pin_number); + +/** + * @brief Function for setting output direction on selected pins on a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param out_mask Mask specifying the pins to set as output. + * + */ +__STATIC_INLINE void nrf_gpio_port_dir_output_set(NRF_GPIO_Type * p_reg, uint32_t out_mask); + +/** + * @brief Function for setting input direction on selected pins on a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param in_mask Mask specifying the pins to set as input. + * + */ +__STATIC_INLINE void nrf_gpio_port_dir_input_set(NRF_GPIO_Type * p_reg, uint32_t in_mask); + +/** + * @brief Function for writing the direction configuration of GPIO pins in a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param dir_mask Mask specifying the direction of pins. Bit set means that the given pin is configured as output. + * + */ +__STATIC_INLINE void nrf_gpio_port_dir_write(NRF_GPIO_Type * p_reg, uint32_t dir_mask); + +/** + * @brief Function for reading the direction configuration of a GPIO port. + * + * @param p_reg Pointer to the peripheral registers structure. + * + * @retval Pin configuration of the current direction settings. Bit set means that the given pin is configured as output. + */ +__STATIC_INLINE uint32_t nrf_gpio_port_dir_read(NRF_GPIO_Type const * p_reg); + +/** + * @brief Function for reading the input signals of GPIO pins on a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * + * @retval Port input values. + */ +__STATIC_INLINE uint32_t nrf_gpio_port_in_read(NRF_GPIO_Type const * p_reg); + +/** + * @brief Function for reading the output signals of GPIO pins of a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * + * @retval Port output values. + */ +__STATIC_INLINE uint32_t nrf_gpio_port_out_read(NRF_GPIO_Type const * p_reg); + +/** + * @brief Function for writing the GPIO pins output on a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param value Output port mask. + * + */ +__STATIC_INLINE void nrf_gpio_port_out_write(NRF_GPIO_Type * p_reg, uint32_t value); + +/** + * @brief Function for setting high level on selected GPIO pins of a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param set_mask Mask with pins to set as logical high level. + * + */ +__STATIC_INLINE void nrf_gpio_port_out_set(NRF_GPIO_Type * p_reg, uint32_t set_mask); + +/** + * @brief Function for setting low level on selected GPIO pins of a given port. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param clr_mask Mask with pins to set as logical low level. + * + */ +__STATIC_INLINE void nrf_gpio_port_out_clear(NRF_GPIO_Type * p_reg, uint32_t clr_mask); + +/** + * @brief Function for reading pins state of multiple consecutive ports. + * + * @param start_port Index of the first port to read. + * @param length Number of ports to read. + * @param p_masks Pointer to output array where port states will be stored. + */ +__STATIC_INLINE void nrf_gpio_ports_read(uint32_t start_port, uint32_t length, uint32_t * p_masks); + +#ifdef GPIO_DETECTMODE_DETECTMODE_LDETECT +/** + * @brief Function for reading latch state of multiple consecutive ports. + * + * @param start_port Index of the first port to read. + * @param length Number of ports to read. + * @param p_masks Pointer to output array where latch states will be stored. + */ +__STATIC_INLINE void nrf_gpio_latches_read(uint32_t start_port, uint32_t length, + uint32_t * p_masks); + +/** + * @brief Function for reading latch state of single pin. + * + * @param pin_number Pin number. + * @return 0 if latch is not set. Positive value otherwise. + * + */ +__STATIC_INLINE uint32_t nrf_gpio_pin_latch_get(uint32_t pin_number); + +/** + * @brief Function for clearing latch state of a single pin. + * + * @param pin_number Pin number. + * + */ +__STATIC_INLINE void nrf_gpio_pin_latch_clear(uint32_t pin_number); +#endif + + +#endif // #ifndef (__LINT__ != 1) + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/** + * @brief Function for extracting port and relative pin number from absolute pin number. + * + * @param[inout] Pointer to absolute pin number which is overriden by relative to port pin number. + * + * @return Pointer to port register set. + * + */ +__STATIC_INLINE NRF_GPIO_Type * nrf_gpio_pin_port_decode(uint32_t * p_pin) +{ + ASSERT(*p_pin < NUMBER_OF_PINS); +#if (GPIO_COUNT == 1) + // The oldest definition case + return NRF_GPIO; +#else + if (*p_pin < P0_PIN_NUM) + { + return NRF_P0; + } + else + { + *p_pin = *p_pin & (P0_PIN_NUM - 1); + return NRF_P1; + } +#endif +} + + +__STATIC_INLINE void nrf_gpio_range_cfg_output(uint32_t pin_range_start, uint32_t pin_range_end) +{ + /*lint -e{845} // A zero has been given as right argument to operator '|'" */ + for (; pin_range_start <= pin_range_end; pin_range_start++) + { + nrf_gpio_cfg_output(pin_range_start); + } +} + + +__STATIC_INLINE void nrf_gpio_range_cfg_input(uint32_t pin_range_start, + uint32_t pin_range_end, + nrf_gpio_pin_pull_t pull_config) +{ + /*lint -e{845} // A zero has been given as right argument to operator '|'" */ + for (; pin_range_start <= pin_range_end; pin_range_start++) + { + nrf_gpio_cfg_input(pin_range_start, pull_config); + } +} + + +__STATIC_INLINE void nrf_gpio_cfg( + uint32_t pin_number, + nrf_gpio_pin_dir_t dir, + nrf_gpio_pin_input_t input, + nrf_gpio_pin_pull_t pull, + nrf_gpio_pin_drive_t drive, + nrf_gpio_pin_sense_t sense) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + reg->PIN_CNF[pin_number] = ((uint32_t)dir << GPIO_PIN_CNF_DIR_Pos) + | ((uint32_t)input << GPIO_PIN_CNF_INPUT_Pos) + | ((uint32_t)pull << GPIO_PIN_CNF_PULL_Pos) + | ((uint32_t)drive << GPIO_PIN_CNF_DRIVE_Pos) + | ((uint32_t)sense << GPIO_PIN_CNF_SENSE_Pos); +} + + +__STATIC_INLINE void nrf_gpio_cfg_output(uint32_t pin_number) +{ + nrf_gpio_cfg( + pin_number, + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); +} + + +__STATIC_INLINE void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config) +{ + nrf_gpio_cfg( + pin_number, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + pull_config, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); +} + + +__STATIC_INLINE void nrf_gpio_cfg_default(uint32_t pin_number) +{ + nrf_gpio_cfg( + pin_number, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); +} + + +__STATIC_INLINE void nrf_gpio_cfg_watcher(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + /*lint -e{845} // A zero has been given as right argument to operator '|'" */ + uint32_t cnf = reg->PIN_CNF[pin_number] & ~GPIO_PIN_CNF_INPUT_Msk; + + reg->PIN_CNF[pin_number] = cnf | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos); +} + + +__STATIC_INLINE void nrf_gpio_input_disconnect(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + /*lint -e{845} // A zero has been given as right argument to operator '|'" */ + uint32_t cnf = reg->PIN_CNF[pin_number] & ~GPIO_PIN_CNF_INPUT_Msk; + + reg->PIN_CNF[pin_number] = cnf | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos); +} + + +__STATIC_INLINE void nrf_gpio_cfg_sense_input(uint32_t pin_number, + nrf_gpio_pin_pull_t pull_config, + nrf_gpio_pin_sense_t sense_config) +{ + nrf_gpio_cfg( + pin_number, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + pull_config, + NRF_GPIO_PIN_S0S1, + sense_config); +} + + +__STATIC_INLINE void nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + /*lint -e{845} // A zero has been given as right argument to operator '|'" */ + reg->PIN_CNF[pin_number] &= ~GPIO_PIN_CNF_SENSE_Msk; + reg->PIN_CNF[pin_number] |= (sense_config << GPIO_PIN_CNF_SENSE_Pos); +} + + +__STATIC_INLINE void nrf_gpio_pin_dir_set(uint32_t pin_number, nrf_gpio_pin_dir_t direction) +{ + if (direction == NRF_GPIO_PIN_DIR_INPUT) + { + nrf_gpio_cfg( + pin_number, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + } + else + { + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + reg->DIRSET = (1UL << pin_number); + } +} + + +__STATIC_INLINE void nrf_gpio_pin_set(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + nrf_gpio_port_out_set(reg, 1UL << pin_number); +} + + +__STATIC_INLINE void nrf_gpio_pin_clear(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + nrf_gpio_port_out_clear(reg, 1UL << pin_number); +} + + +__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + uint32_t pins_state = reg->OUT; + + reg->OUTSET = (~pins_state & (1UL << pin_number)); + reg->OUTCLR = (pins_state & (1UL << pin_number)); +} + + +__STATIC_INLINE void nrf_gpio_pin_write(uint32_t pin_number, uint32_t value) +{ + if (value == 0) + { + nrf_gpio_pin_clear(pin_number); + } + else + { + nrf_gpio_pin_set(pin_number); + } +} + + +__STATIC_INLINE uint32_t nrf_gpio_pin_read(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + return ((nrf_gpio_port_in_read(reg) >> pin_number) & 1UL); +} + + +__STATIC_INLINE uint32_t nrf_gpio_pin_out_read(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + return ((nrf_gpio_port_out_read(reg) >> pin_number) & 1UL); +} + + +__STATIC_INLINE nrf_gpio_pin_sense_t nrf_gpio_pin_sense_get(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + return (nrf_gpio_pin_sense_t)((reg->PIN_CNF[pin_number] & + GPIO_PIN_CNF_SENSE_Msk) >> GPIO_PIN_CNF_SENSE_Pos); +} + + +__STATIC_INLINE void nrf_gpio_port_dir_output_set(NRF_GPIO_Type * p_reg, uint32_t out_mask) +{ + p_reg->DIRSET = out_mask; +} + + +__STATIC_INLINE void nrf_gpio_port_dir_input_set(NRF_GPIO_Type * p_reg, uint32_t in_mask) +{ + p_reg->DIRCLR = in_mask; +} + + +__STATIC_INLINE void nrf_gpio_port_dir_write(NRF_GPIO_Type * p_reg, uint32_t value) +{ + p_reg->DIR = value; +} + + +__STATIC_INLINE uint32_t nrf_gpio_port_dir_read(NRF_GPIO_Type const * p_reg) +{ + return p_reg->DIR; +} + + +__STATIC_INLINE uint32_t nrf_gpio_port_in_read(NRF_GPIO_Type const * p_reg) +{ + return p_reg->IN; +} + + +__STATIC_INLINE uint32_t nrf_gpio_port_out_read(NRF_GPIO_Type const * p_reg) +{ + return p_reg->OUT; +} + + +__STATIC_INLINE void nrf_gpio_port_out_write(NRF_GPIO_Type * p_reg, uint32_t value) +{ + p_reg->OUT = value; +} + + +__STATIC_INLINE void nrf_gpio_port_out_set(NRF_GPIO_Type * p_reg, uint32_t set_mask) +{ + p_reg->OUTSET = set_mask; +} + + +__STATIC_INLINE void nrf_gpio_port_out_clear(NRF_GPIO_Type * p_reg, uint32_t clr_mask) +{ + p_reg->OUTCLR = clr_mask; +} + + +__STATIC_INLINE void nrf_gpio_ports_read(uint32_t start_port, uint32_t length, uint32_t * p_masks) +{ + NRF_GPIO_Type * gpio_regs[GPIO_COUNT] = GPIO_REG_LIST; + + ASSERT(start_port + length <= GPIO_COUNT); + uint32_t i; + + for (i = start_port; i < (start_port + length); i++) + { + *p_masks = nrf_gpio_port_in_read(gpio_regs[i]); + p_masks++; + } +} + + +#ifdef GPIO_DETECTMODE_DETECTMODE_LDETECT +__STATIC_INLINE void nrf_gpio_latches_read(uint32_t start_port, uint32_t length, uint32_t * p_masks) +{ + NRF_GPIO_Type * gpio_regs[GPIO_COUNT] = GPIO_REG_LIST; + uint32_t i; + + for (i = start_port; i < (start_port + length); i++) + { + *p_masks = gpio_regs[i]->LATCH; + p_masks++; + } +} + + +__STATIC_INLINE uint32_t nrf_gpio_pin_latch_get(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + return (reg->LATCH & (1 << pin_number)) ? 1 : 0; +} + + +__STATIC_INLINE void nrf_gpio_pin_latch_clear(uint32_t pin_number) +{ + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); + + reg->LATCH = (1 << pin_number); +} + + +#endif +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpiote.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpiote.h new file mode 100644 index 0000000000..df9bd35ce6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_gpiote.h @@ -0,0 +1,430 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_GPIOTE_H__ +#define NRF_GPIOTE_H__ + +#include "nrf_peripherals.h" +#include "nrf.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef GPIOTE_CONFIG_PORT_Msk +#define GPIOTE_CONFIG_PORT_PIN_Msk (GPIOTE_CONFIG_PORT_Msk | GPIOTE_CONFIG_PSEL_Msk) +#else +#define GPIOTE_CONFIG_PORT_PIN_Msk GPIOTE_CONFIG_PSEL_Msk +#endif +/** +* @defgroup nrf_gpiote_abs GPIOTE abstraction +* @{ +* @ingroup nrf_gpiote +* @brief GPIOTE abstraction for configuration of channels. +*/ + + /** + * @enum nrf_gpiote_polarity_t + * @brief Polarity for the GPIOTE channel. + */ +typedef enum +{ + NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi, ///< Low to high. + NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo, ///< High to low. + NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle ///< Toggle. +} nrf_gpiote_polarity_t; + + + /** + * @enum nrf_gpiote_outinit_t + * @brief Initial output value for the GPIOTE channel. + */ +typedef enum +{ + NRF_GPIOTE_INITIAL_VALUE_LOW = GPIOTE_CONFIG_OUTINIT_Low, ///< Low to high. + NRF_GPIOTE_INITIAL_VALUE_HIGH = GPIOTE_CONFIG_OUTINIT_High ///< High to low. +} nrf_gpiote_outinit_t; + +/** + * @brief Tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_GPIOTE_TASKS_OUT_0 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0.*/ + NRF_GPIOTE_TASKS_OUT_1 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1.*/ + NRF_GPIOTE_TASKS_OUT_2 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2.*/ + NRF_GPIOTE_TASKS_OUT_3 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3.*/ +#if (GPIOTE_CH_NUM > 4) || defined(__SDK_DOXYGEN__) + NRF_GPIOTE_TASKS_OUT_4 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4.*/ + NRF_GPIOTE_TASKS_OUT_5 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5.*/ + NRF_GPIOTE_TASKS_OUT_6 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6.*/ + NRF_GPIOTE_TASKS_OUT_7 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7.*/ +#endif +#if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__SDK_DOXYGEN__) + NRF_GPIOTE_TASKS_SET_0 = offsetof(NRF_GPIOTE_Type, TASKS_SET[0]), /**< Set task 0.*/ + NRF_GPIOTE_TASKS_SET_1 = offsetof(NRF_GPIOTE_Type, TASKS_SET[1]), /**< Set task 1.*/ + NRF_GPIOTE_TASKS_SET_2 = offsetof(NRF_GPIOTE_Type, TASKS_SET[2]), /**< Set task 2.*/ + NRF_GPIOTE_TASKS_SET_3 = offsetof(NRF_GPIOTE_Type, TASKS_SET[3]), /**< Set task 3.*/ + NRF_GPIOTE_TASKS_SET_4 = offsetof(NRF_GPIOTE_Type, TASKS_SET[4]), /**< Set task 4.*/ + NRF_GPIOTE_TASKS_SET_5 = offsetof(NRF_GPIOTE_Type, TASKS_SET[5]), /**< Set task 5.*/ + NRF_GPIOTE_TASKS_SET_6 = offsetof(NRF_GPIOTE_Type, TASKS_SET[6]), /**< Set task 6.*/ + NRF_GPIOTE_TASKS_SET_7 = offsetof(NRF_GPIOTE_Type, TASKS_SET[7]), /**< Set task 7.*/ +#endif +#if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__SDK_DOXYGEN__) + NRF_GPIOTE_TASKS_CLR_0 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[0]), /**< Clear task 0.*/ + NRF_GPIOTE_TASKS_CLR_1 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[1]), /**< Clear task 1.*/ + NRF_GPIOTE_TASKS_CLR_2 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[2]), /**< Clear task 2.*/ + NRF_GPIOTE_TASKS_CLR_3 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[3]), /**< Clear task 3.*/ + NRF_GPIOTE_TASKS_CLR_4 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[4]), /**< Clear task 4.*/ + NRF_GPIOTE_TASKS_CLR_5 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[5]), /**< Clear task 5.*/ + NRF_GPIOTE_TASKS_CLR_6 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[6]), /**< Clear task 6.*/ + NRF_GPIOTE_TASKS_CLR_7 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[7]), /**< Clear task 7.*/ +#endif + /*lint -restore*/ +} nrf_gpiote_tasks_t; + +/** + * @brief Events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_GPIOTE_EVENTS_IN_0 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]), /**< In event 0.*/ + NRF_GPIOTE_EVENTS_IN_1 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[1]), /**< In event 1.*/ + NRF_GPIOTE_EVENTS_IN_2 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[2]), /**< In event 2.*/ + NRF_GPIOTE_EVENTS_IN_3 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[3]), /**< In event 3.*/ +#if (GPIOTE_CH_NUM > 4) || defined(__SDK_DOXYGEN__) + NRF_GPIOTE_EVENTS_IN_4 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[4]), /**< In event 4.*/ + NRF_GPIOTE_EVENTS_IN_5 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[5]), /**< In event 5.*/ + NRF_GPIOTE_EVENTS_IN_6 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[6]), /**< In event 6.*/ + NRF_GPIOTE_EVENTS_IN_7 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[7]), /**< In event 7.*/ +#endif + NRF_GPIOTE_EVENTS_PORT = offsetof(NRF_GPIOTE_Type, EVENTS_PORT), /**< Port event.*/ + /*lint -restore*/ +} nrf_gpiote_events_t; + +/** + * @enum nrf_gpiote_int_t + * @brief GPIOTE interrupts. + */ +typedef enum +{ + NRF_GPIOTE_INT_IN0_MASK = GPIOTE_INTENSET_IN0_Msk, /**< GPIOTE interrupt from IN0. */ + NRF_GPIOTE_INT_IN1_MASK = GPIOTE_INTENSET_IN1_Msk, /**< GPIOTE interrupt from IN1. */ + NRF_GPIOTE_INT_IN2_MASK = GPIOTE_INTENSET_IN2_Msk, /**< GPIOTE interrupt from IN2. */ + NRF_GPIOTE_INT_IN3_MASK = GPIOTE_INTENSET_IN3_Msk, /**< GPIOTE interrupt from IN3. */ +#if (GPIOTE_CH_NUM > 4) || defined(__SDK_DOXYGEN__) + NRF_GPIOTE_INT_IN4_MASK = GPIOTE_INTENSET_IN4_Msk, /**< GPIOTE interrupt from IN4. */ + NRF_GPIOTE_INT_IN5_MASK = GPIOTE_INTENSET_IN5_Msk, /**< GPIOTE interrupt from IN5. */ + NRF_GPIOTE_INT_IN6_MASK = GPIOTE_INTENSET_IN6_Msk, /**< GPIOTE interrupt from IN6. */ + NRF_GPIOTE_INT_IN7_MASK = GPIOTE_INTENSET_IN7_Msk, /**< GPIOTE interrupt from IN7. */ +#endif + NRF_GPIOTE_INT_PORT_MASK = (int)GPIOTE_INTENSET_PORT_Msk, /**< GPIOTE interrupt from PORT event. */ +} nrf_gpiote_int_t; + +#define NRF_GPIOTE_INT_IN_MASK (NRF_GPIOTE_INT_IN0_MASK | NRF_GPIOTE_INT_IN1_MASK |\ + NRF_GPIOTE_INT_IN2_MASK | NRF_GPIOTE_INT_IN3_MASK) +#if (GPIOTE_CH_NUM > 4) +#undef NRF_GPIOTE_INT_IN_MASK +#define NRF_GPIOTE_INT_IN_MASK (NRF_GPIOTE_INT_IN0_MASK | NRF_GPIOTE_INT_IN1_MASK |\ + NRF_GPIOTE_INT_IN2_MASK | NRF_GPIOTE_INT_IN3_MASK |\ + NRF_GPIOTE_INT_IN4_MASK | NRF_GPIOTE_INT_IN5_MASK |\ + NRF_GPIOTE_INT_IN6_MASK | NRF_GPIOTE_INT_IN7_MASK) +#endif + +/** + * @brief Function for activating a specific GPIOTE task. + * + * @param[in] task Task. + */ +__STATIC_INLINE void nrf_gpiote_task_set(nrf_gpiote_tasks_t task); + +/** + * @brief Function for getting the address of a specific GPIOTE task. + * + * @param[in] task Task. + * + * @returns Address. + */ +__STATIC_INLINE uint32_t nrf_gpiote_task_addr_get(nrf_gpiote_tasks_t task); + +/** + * @brief Function for getting the state of a specific GPIOTE event. + * + * @param[in] event Event. + */ +__STATIC_INLINE bool nrf_gpiote_event_is_set(nrf_gpiote_events_t event); + +/** + * @brief Function for clearing a specific GPIOTE event. + * + * @param[in] event Event. + */ +__STATIC_INLINE void nrf_gpiote_event_clear(nrf_gpiote_events_t event); + +/** + * @brief Function for getting the address of a specific GPIOTE event. + * + * @param[in] event Event. + * + * @return Address + */ +__STATIC_INLINE uint32_t nrf_gpiote_event_addr_get(nrf_gpiote_events_t event); + +/**@brief Function for enabling interrupts. + * + * @param[in] mask Interrupt mask to be enabled. + */ +__STATIC_INLINE void nrf_gpiote_int_enable(uint32_t mask); + +/**@brief Function for disabling interrupts. + * + * @param[in] mask Interrupt mask to be disabled. + */ +__STATIC_INLINE void nrf_gpiote_int_disable(uint32_t mask); + +/**@brief Function for checking if interrupts are enabled. + * + * @param[in] mask Mask of interrupt flags to check. + * + * @return Mask with enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_gpiote_int_is_enabled(uint32_t mask); + +/**@brief Function for enabling a GPIOTE event. + * + * @param[in] idx Task-Event index. + */ +__STATIC_INLINE void nrf_gpiote_event_enable(uint32_t idx); + +/**@brief Function for disabling a GPIOTE event. + * + * @param[in] idx Task-Event index. + */ +__STATIC_INLINE void nrf_gpiote_event_disable(uint32_t idx); + +/**@brief Function for configuring a GPIOTE event. + * + * @param[in] idx Task-Event index. + * @param[in] pin Pin associated with event. + * @param[in] polarity Transition that should generate an event. + */ +__STATIC_INLINE void nrf_gpiote_event_configure(uint32_t idx, uint32_t pin, + nrf_gpiote_polarity_t polarity); + +/**@brief Function for getting the pin associated with a GPIOTE event. + * + * @param[in] idx Task-Event index. + * + * @return Pin number. + */ +__STATIC_INLINE uint32_t nrf_gpiote_event_pin_get(uint32_t idx); + +/**@brief Function for getting the polarity associated with a GPIOTE event. + * + * @param[in] idx Task-Event index. + * + * @return Polarity. + */ +__STATIC_INLINE nrf_gpiote_polarity_t nrf_gpiote_event_polarity_get(uint32_t idx); + +/**@brief Function for enabling a GPIOTE task. + * + * @param[in] idx Task-Event index. + */ +__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx); + +/**@brief Function for disabling a GPIOTE task. + * + * @param[in] idx Task-Event index. + */ +__STATIC_INLINE void nrf_gpiote_task_disable(uint32_t idx); + +/**@brief Function for configuring a GPIOTE task. + * @note Function is not configuring mode field so task is disabled after this function is called. + * + * @param[in] idx Task-Event index. + * @param[in] pin Pin associated with event. + * @param[in] polarity Transition that should generate an event. + * @param[in] init_val Initial value of the pin. + */ +__STATIC_INLINE void nrf_gpiote_task_configure(uint32_t idx, uint32_t pin, + nrf_gpiote_polarity_t polarity, + nrf_gpiote_outinit_t init_val); + +/**@brief Function for forcing a specific state on the pin connected to GPIOTE. + * + * @param[in] idx Task-Event index. + * @param[in] init_val Pin state. + */ +__STATIC_INLINE void nrf_gpiote_task_force(uint32_t idx, nrf_gpiote_outinit_t init_val); + +/**@brief Function for resetting a GPIOTE task event configuration to the default state. + * + * @param[in] idx Task-Event index. + */ +__STATIC_INLINE void nrf_gpiote_te_default(uint32_t idx); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_gpiote_task_set(nrf_gpiote_tasks_t task) +{ + *(__IO uint32_t *)((uint32_t)NRF_GPIOTE + task) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_gpiote_task_addr_get(nrf_gpiote_tasks_t task) +{ + return ((uint32_t)NRF_GPIOTE + task); +} + +__STATIC_INLINE bool nrf_gpiote_event_is_set(nrf_gpiote_events_t event) +{ + return (*(uint32_t *)nrf_gpiote_event_addr_get(event) == 0x1UL) ? true : false; +} + +__STATIC_INLINE void nrf_gpiote_event_clear(nrf_gpiote_events_t event) +{ + *(uint32_t *)nrf_gpiote_event_addr_get(event) = 0; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)nrf_gpiote_event_addr_get(event)); + (void)dummy; +#endif +} + +__STATIC_INLINE uint32_t nrf_gpiote_event_addr_get(nrf_gpiote_events_t event) +{ + return ((uint32_t)NRF_GPIOTE + event); +} + +__STATIC_INLINE void nrf_gpiote_int_enable(uint32_t mask) +{ + NRF_GPIOTE->INTENSET = mask; +} + +__STATIC_INLINE void nrf_gpiote_int_disable(uint32_t mask) +{ + NRF_GPIOTE->INTENCLR = mask; +} + +__STATIC_INLINE uint32_t nrf_gpiote_int_is_enabled(uint32_t mask) +{ + return (NRF_GPIOTE->INTENSET & mask); +} + +__STATIC_INLINE void nrf_gpiote_event_enable(uint32_t idx) +{ + NRF_GPIOTE->CONFIG[idx] |= GPIOTE_CONFIG_MODE_Event; +} + +__STATIC_INLINE void nrf_gpiote_event_disable(uint32_t idx) +{ + NRF_GPIOTE->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Event; +} + +__STATIC_INLINE void nrf_gpiote_event_configure(uint32_t idx, uint32_t pin, nrf_gpiote_polarity_t polarity) +{ + NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk | GPIOTE_CONFIG_POLARITY_Msk); + NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) | + ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk); +} + +__STATIC_INLINE uint32_t nrf_gpiote_event_pin_get(uint32_t idx) +{ + return ((NRF_GPIOTE->CONFIG[idx] & GPIOTE_CONFIG_PORT_PIN_Msk) >> GPIOTE_CONFIG_PSEL_Pos); +} + +__STATIC_INLINE nrf_gpiote_polarity_t nrf_gpiote_event_polarity_get(uint32_t idx) +{ + return (nrf_gpiote_polarity_t)((NRF_GPIOTE->CONFIG[idx] & GPIOTE_CONFIG_POLARITY_Msk) >> GPIOTE_CONFIG_POLARITY_Pos); +} + +__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx) +{ + uint32_t final_config = NRF_GPIOTE->CONFIG[idx] | GPIOTE_CONFIG_MODE_Task; +#ifdef NRF51 + /* Workaround for the OUTINIT PAN. When nrf_gpiote_task_config() is called a glitch happens + on the GPIO if the GPIO in question is already assigned to GPIOTE and the pin is in the + correct state in GPIOTE but not in the OUT register. */ + /* Configure channel to not existing, not connected to the pin, and configure as a tasks that will set it to proper level */ + NRF_GPIOTE->CONFIG[idx] = final_config | (((31) << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk); + __NOP(); + __NOP(); + __NOP(); +#endif + NRF_GPIOTE->CONFIG[idx] = final_config; +} + +__STATIC_INLINE void nrf_gpiote_task_disable(uint32_t idx) +{ + NRF_GPIOTE->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Task; +} + +__STATIC_INLINE void nrf_gpiote_task_configure(uint32_t idx, uint32_t pin, + nrf_gpiote_polarity_t polarity, + nrf_gpiote_outinit_t init_val) +{ + NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk | + GPIOTE_CONFIG_POLARITY_Msk | + GPIOTE_CONFIG_OUTINIT_Msk); + + NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) | + ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) | + ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk); +} + +__STATIC_INLINE void nrf_gpiote_task_force(uint32_t idx, nrf_gpiote_outinit_t init_val) +{ + NRF_GPIOTE->CONFIG[idx] = (NRF_GPIOTE->CONFIG[idx] & ~GPIOTE_CONFIG_OUTINIT_Msk) + | ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk); +} + +__STATIC_INLINE void nrf_gpiote_te_default(uint32_t idx) +{ + NRF_GPIOTE->CONFIG[idx] = 0; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_i2s.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_i2s.h new file mode 100644 index 0000000000..d5485572b5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_i2s.h @@ -0,0 +1,563 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_i2s_hal I2S HAL + * @{ + * @ingroup nrf_i2s + * + * @brief @tagAPI52 Hardware access layer for managing the Inter-IC Sound (I2S) peripheral. + */ + +#ifndef NRF_I2S_H__ +#define NRF_I2S_H__ + +#include +#include +#include + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be provided as a parameter for the @ref nrf_i2s_pins_set + * function call to specify that a given I2S signal (SDOUT, SDIN, or MCK) + * shall not be connected to a physical pin. + */ +#define NRF_I2S_PIN_NOT_CONNECTED 0xFFFFFFFF + + +/** + * @brief I2S tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_I2S_TASK_START = offsetof(NRF_I2S_Type, TASKS_START), ///< Starts continuous I2S transfer. Also starts the MCK generator if this is enabled. + NRF_I2S_TASK_STOP = offsetof(NRF_I2S_Type, TASKS_STOP) ///< Stops I2S transfer. Also stops the MCK generator. + /*lint -restore*/ +} nrf_i2s_task_t; + +/** + * @brief I2S events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_I2S_EVENT_RXPTRUPD = offsetof(NRF_I2S_Type, EVENTS_RXPTRUPD), ///< The RXD.PTR register has been copied to internal double-buffers. + NRF_I2S_EVENT_TXPTRUPD = offsetof(NRF_I2S_Type, EVENTS_TXPTRUPD), ///< The TXD.PTR register has been copied to internal double-buffers. + NRF_I2S_EVENT_STOPPED = offsetof(NRF_I2S_Type, EVENTS_STOPPED) ///< I2S transfer stopped. + /*lint -restore*/ +} nrf_i2s_event_t; + +/** + * @brief I2S interrupts. + */ +typedef enum +{ + NRF_I2S_INT_RXPTRUPD_MASK = I2S_INTENSET_RXPTRUPD_Msk, ///< Interrupt on RXPTRUPD event. + NRF_I2S_INT_TXPTRUPD_MASK = I2S_INTENSET_TXPTRUPD_Msk, ///< Interrupt on TXPTRUPD event. + NRF_I2S_INT_STOPPED_MASK = I2S_INTENSET_STOPPED_Msk ///< Interrupt on STOPPED event. +} nrf_i2s_int_mask_t; + +/** + * @brief I2S modes of operation. + */ +typedef enum +{ + NRF_I2S_MODE_MASTER = I2S_CONFIG_MODE_MODE_Master, ///< Master mode. + NRF_I2S_MODE_SLAVE = I2S_CONFIG_MODE_MODE_Slave ///< Slave mode. +} nrf_i2s_mode_t; + +/** + * @brief I2S master clock generator settings. + */ +typedef enum +{ + NRF_I2S_MCK_DISABLED = 0, ///< MCK disabled. + // [conversion to 'int' needed to prevent compilers from complaining + // that the provided value (0x80000000UL) is out of range of "int"] + NRF_I2S_MCK_32MDIV2 = (int)I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV2, ///< 32 MHz / 2 = 16.0 MHz. + NRF_I2S_MCK_32MDIV3 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV3, ///< 32 MHz / 3 = 10.6666667 MHz. + NRF_I2S_MCK_32MDIV4 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV4, ///< 32 MHz / 4 = 8.0 MHz. + NRF_I2S_MCK_32MDIV5 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV5, ///< 32 MHz / 5 = 6.4 MHz. + NRF_I2S_MCK_32MDIV6 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV6, ///< 32 MHz / 6 = 5.3333333 MHz. + NRF_I2S_MCK_32MDIV8 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV8, ///< 32 MHz / 8 = 4.0 MHz. + NRF_I2S_MCK_32MDIV10 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV10, ///< 32 MHz / 10 = 3.2 MHz. + NRF_I2S_MCK_32MDIV11 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11, ///< 32 MHz / 11 = 2.9090909 MHz. + NRF_I2S_MCK_32MDIV15 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV15, ///< 32 MHz / 15 = 2.1333333 MHz. + NRF_I2S_MCK_32MDIV16 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16, ///< 32 MHz / 16 = 2.0 MHz. + NRF_I2S_MCK_32MDIV21 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV21, ///< 32 MHz / 21 = 1.5238095 MHz. + NRF_I2S_MCK_32MDIV23 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV23, ///< 32 MHz / 23 = 1.3913043 MHz. + NRF_I2S_MCK_32MDIV31 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31, ///< 32 MHz / 31 = 1.0322581 MHz. + NRF_I2S_MCK_32MDIV42 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV42, ///< 32 MHz / 42 = 0.7619048 MHz. + NRF_I2S_MCK_32MDIV63 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV63, ///< 32 MHz / 63 = 0.5079365 MHz. + NRF_I2S_MCK_32MDIV125 = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV125 ///< 32 MHz / 125 = 0.256 MHz. +} nrf_i2s_mck_t; + +/** + * @brief I2S MCK/LRCK ratios. + */ +typedef enum +{ + NRF_I2S_RATIO_32X = I2S_CONFIG_RATIO_RATIO_32X, ///< LRCK = MCK / 32. + NRF_I2S_RATIO_48X = I2S_CONFIG_RATIO_RATIO_48X, ///< LRCK = MCK / 48. + NRF_I2S_RATIO_64X = I2S_CONFIG_RATIO_RATIO_64X, ///< LRCK = MCK / 64. + NRF_I2S_RATIO_96X = I2S_CONFIG_RATIO_RATIO_96X, ///< LRCK = MCK / 96. + NRF_I2S_RATIO_128X = I2S_CONFIG_RATIO_RATIO_128X, ///< LRCK = MCK / 128. + NRF_I2S_RATIO_192X = I2S_CONFIG_RATIO_RATIO_192X, ///< LRCK = MCK / 192. + NRF_I2S_RATIO_256X = I2S_CONFIG_RATIO_RATIO_256X, ///< LRCK = MCK / 256. + NRF_I2S_RATIO_384X = I2S_CONFIG_RATIO_RATIO_384X, ///< LRCK = MCK / 384. + NRF_I2S_RATIO_512X = I2S_CONFIG_RATIO_RATIO_512X ///< LRCK = MCK / 512. +} nrf_i2s_ratio_t; + +/** + * @brief I2S sample widths. + */ +typedef enum +{ + NRF_I2S_SWIDTH_8BIT = I2S_CONFIG_SWIDTH_SWIDTH_8Bit, ///< 8 bit. + NRF_I2S_SWIDTH_16BIT = I2S_CONFIG_SWIDTH_SWIDTH_16Bit, ///< 16 bit. + NRF_I2S_SWIDTH_24BIT = I2S_CONFIG_SWIDTH_SWIDTH_24Bit ///< 24 bit. +} nrf_i2s_swidth_t; + +/** + * @brief I2S alignments of sample within a frame. + */ +typedef enum +{ + NRF_I2S_ALIGN_LEFT = I2S_CONFIG_ALIGN_ALIGN_Left, ///< Left-aligned. + NRF_I2S_ALIGN_RIGHT = I2S_CONFIG_ALIGN_ALIGN_Right ///< Right-aligned. +} nrf_i2s_align_t; + +/** + * @brief I2S frame formats. + */ +typedef enum +{ + NRF_I2S_FORMAT_I2S = I2S_CONFIG_FORMAT_FORMAT_I2S, ///< Original I2S format. + NRF_I2S_FORMAT_ALIGNED = I2S_CONFIG_FORMAT_FORMAT_Aligned ///< Alternate (left- or right-aligned) format. +} nrf_i2s_format_t; + +/** + * @brief I2S enabled channels. + */ +typedef enum +{ + NRF_I2S_CHANNELS_STEREO = I2S_CONFIG_CHANNELS_CHANNELS_Stereo, ///< Stereo. + NRF_I2S_CHANNELS_LEFT = I2S_CONFIG_CHANNELS_CHANNELS_Left, ///< Left only. + NRF_I2S_CHANNELS_RIGHT = I2S_CONFIG_CHANNELS_CHANNELS_Right ///< Right only. +} nrf_i2s_channels_t; + + +/** + * @brief Function for activating a specific I2S task. + * + * @param[in] p_i2s I2S instance. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_i2s_task_trigger(NRF_I2S_Type * p_i2s, + nrf_i2s_task_t task); + +/** + * @brief Function for getting the address of a specific I2S task register. + * + * @param[in] p_i2s I2S instance. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t nrf_i2s_task_address_get(NRF_I2S_Type const * p_i2s, + nrf_i2s_task_t task); + +/** + * @brief Function for clearing a specific I2S event. + * + * @param[in] p_i2s I2S instance. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_i2s_event_clear(NRF_I2S_Type * p_i2s, + nrf_i2s_event_t event); + +/** + * @brief Function for checking the state of a specific I2S event. + * + * @param[in] p_i2s I2S instance. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_i2s_event_check(NRF_I2S_Type const * p_i2s, + nrf_i2s_event_t event); + +/** + * @brief Function for getting the address of a specific I2S event register. + * + * @param[in] p_i2s I2S instance. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t nrf_i2s_event_address_get(NRF_I2S_Type const * p_i2s, + nrf_i2s_event_t event); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_i2s I2S instance. + * @param[in] mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_i2s_int_enable(NRF_I2S_Type * p_i2s, uint32_t mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_i2s I2S instance. + * @param[in] mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_i2s_int_disable(NRF_I2S_Type * p_i2s, uint32_t mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_i2s I2S instance. + * @param[in] i2s_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_i2s_int_enable_check(NRF_I2S_Type const * p_i2s, + nrf_i2s_int_mask_t i2s_int); + +/** + * @brief Function for enabling the I2S peripheral. + * + * @param[in] p_i2s I2S instance. + */ +__STATIC_INLINE void nrf_i2s_enable(NRF_I2S_Type * p_i2s); + +/** + * @brief Function for disabling the I2S peripheral. + * + * @param[in] p_i2s I2S instance. + */ +__STATIC_INLINE void nrf_i2s_disable(NRF_I2S_Type * p_i2s); + +/** + * @brief Function for configuring I2S pins. + * + * Usage of the SDOUT, SDIN, and MCK signals is optional. + * If a given signal is not needed, pass the @ref NRF_I2S_PIN_NOT_CONNECTED + * value instead of its pin number. + * + * @param[in] p_i2s I2S instance. + * @param[in] sck_pin SCK pin number. + * @param[in] lrck_pin LRCK pin number. + * @param[in] mck_pin MCK pin number. + * @param[in] sdout_pin SDOUT pin number. + * @param[in] sdin_pin SDIN pin number. + */ +__STATIC_INLINE void nrf_i2s_pins_set(NRF_I2S_Type * p_i2s, + uint32_t sck_pin, + uint32_t lrck_pin, + uint32_t mck_pin, + uint32_t sdout_pin, + uint32_t sdin_pin); + +/** + * @brief Function for setting the I2S peripheral configuration. + * + * @param[in] p_i2s I2S instance. + * @param[in] mode Mode of operation (master or slave). + * @param[in] format I2S frame format. + * @param[in] alignment Alignment of sample within a frame. + * @param[in] sample_width Sample width. + * @param[in] channels Enabled channels. + * @param[in] mck_setup Master clock generator setup. + * @param[in] ratio MCK/LRCK ratio. + * + * @retval true If the configuration has been set successfully. + * @retval false If the requested configuration is not allowed. + */ +__STATIC_INLINE bool nrf_i2s_configure(NRF_I2S_Type * p_i2s, + nrf_i2s_mode_t mode, + nrf_i2s_format_t format, + nrf_i2s_align_t alignment, + nrf_i2s_swidth_t sample_width, + nrf_i2s_channels_t channels, + nrf_i2s_mck_t mck_setup, + nrf_i2s_ratio_t ratio); + +/** + * @brief Function for setting up the I2S transfer. + * + * This function sets up the RX and TX buffers and enables reception and/or + * transmission accordingly. If the transfer in a given direction is not + * required, pass NULL instead of the pointer to the corresponding buffer. + * + * @param[in] p_i2s I2S instance. + * @param[in] size Size of the buffers (in 32-bit words). + * @param[in] p_rx_buffer Pointer to the receive buffer. + * Pass NULL to disable reception. + * @param[in] p_tx_buffer Pointer to the transmit buffer. + * Pass NULL to disable transmission. + */ +__STATIC_INLINE void nrf_i2s_transfer_set(NRF_I2S_Type * p_i2s, + uint16_t size, + uint32_t * p_rx_buffer, + uint32_t const * p_tx_buffer); + +/** + * @brief Function for setting the pointer to the receive buffer. + * + * @note The size of the buffer can be set only by calling + * @ref nrf_i2s_transfer_set. + * + * @param[in] p_i2s I2S instance. + * @param[in] p_buffer Pointer to the receive buffer. + */ +__STATIC_INLINE void nrf_i2s_rx_buffer_set(NRF_I2S_Type * p_i2s, + uint32_t * p_buffer); + +/** + * @brief Function for getting the pointer to the receive buffer. + * + * @param[in] p_i2s I2S instance. + * + * @return Pointer to the receive buffer. + */ +__STATIC_INLINE uint32_t * nrf_i2s_rx_buffer_get(NRF_I2S_Type const * p_i2s); + +/** + * @brief Function for setting the pointer to the transmit buffer. + * + * @note The size of the buffer can be set only by calling + * @ref nrf_i2s_transfer_set. + * + * @param[in] p_i2s I2S instance. + * @param[in] p_buffer Pointer to the transmit buffer. + */ +__STATIC_INLINE void nrf_i2s_tx_buffer_set(NRF_I2S_Type * p_i2s, + uint32_t const * p_buffer); + +/** + * @brief Function for getting the pointer to the transmit buffer. + * + * @param[in] p_i2s I2S instance. + * + * @return Pointer to the transmit buffer. + */ +__STATIC_INLINE uint32_t * nrf_i2s_tx_buffer_get(NRF_I2S_Type const * p_i2s); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_i2s_task_trigger(NRF_I2S_Type * p_i2s, + nrf_i2s_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_i2s + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_i2s_task_address_get(NRF_I2S_Type const * p_i2s, + nrf_i2s_task_t task) +{ + return ((uint32_t)p_i2s + (uint32_t)task); +} + +__STATIC_INLINE void nrf_i2s_event_clear(NRF_I2S_Type * p_i2s, + nrf_i2s_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_i2s + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_i2s + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_i2s_event_check(NRF_I2S_Type const * p_i2s, + nrf_i2s_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_i2s + (uint32_t)event); +} + +__STATIC_INLINE uint32_t nrf_i2s_event_address_get(NRF_I2S_Type const * p_i2s, + nrf_i2s_event_t event) +{ + return ((uint32_t)p_i2s + (uint32_t)event); +} + +__STATIC_INLINE void nrf_i2s_int_enable(NRF_I2S_Type * p_i2s, uint32_t mask) +{ + p_i2s->INTENSET = mask; +} + +__STATIC_INLINE void nrf_i2s_int_disable(NRF_I2S_Type * p_i2s, uint32_t mask) +{ + p_i2s->INTENCLR = mask; +} + +__STATIC_INLINE bool nrf_i2s_int_enable_check(NRF_I2S_Type const * p_i2s, + nrf_i2s_int_mask_t i2s_int) +{ + return (bool)(p_i2s->INTENSET & i2s_int); +} + +__STATIC_INLINE void nrf_i2s_enable(NRF_I2S_Type * p_i2s) +{ + p_i2s->ENABLE = (I2S_ENABLE_ENABLE_Enabled << I2S_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_i2s_disable(NRF_I2S_Type * p_i2s) +{ + p_i2s->ENABLE = (I2S_ENABLE_ENABLE_Disabled << I2S_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_i2s_pins_set(NRF_I2S_Type * p_i2s, + uint32_t sck_pin, + uint32_t lrck_pin, + uint32_t mck_pin, + uint32_t sdout_pin, + uint32_t sdin_pin) +{ + p_i2s->PSEL.SCK = sck_pin; + p_i2s->PSEL.LRCK = lrck_pin; + p_i2s->PSEL.MCK = mck_pin; + p_i2s->PSEL.SDOUT = sdout_pin; + p_i2s->PSEL.SDIN = sdin_pin; +} + +__STATIC_INLINE bool nrf_i2s_configure(NRF_I2S_Type * p_i2s, + nrf_i2s_mode_t mode, + nrf_i2s_format_t format, + nrf_i2s_align_t alignment, + nrf_i2s_swidth_t sample_width, + nrf_i2s_channels_t channels, + nrf_i2s_mck_t mck_setup, + nrf_i2s_ratio_t ratio) +{ + if (mode == NRF_I2S_MODE_MASTER) + { + // The MCK/LRCK ratio shall be a multiple of 2 * sample width. + if (((sample_width == NRF_I2S_SWIDTH_16BIT) && + (ratio == NRF_I2S_RATIO_48X)) + || + ((sample_width == NRF_I2S_SWIDTH_24BIT) && + ((ratio == NRF_I2S_RATIO_32X) || + (ratio == NRF_I2S_RATIO_64X) || + (ratio == NRF_I2S_RATIO_128X) || + (ratio == NRF_I2S_RATIO_256X) || + (ratio == NRF_I2S_RATIO_512X)))) + { + return false; + } + } + + p_i2s->CONFIG.MODE = mode; + p_i2s->CONFIG.FORMAT = format; + p_i2s->CONFIG.ALIGN = alignment; + p_i2s->CONFIG.SWIDTH = sample_width; + p_i2s->CONFIG.CHANNELS = channels; + p_i2s->CONFIG.RATIO = ratio; + + if (mck_setup == NRF_I2S_MCK_DISABLED) + { + p_i2s->CONFIG.MCKEN = + (I2S_CONFIG_MCKEN_MCKEN_Disabled << I2S_CONFIG_MCKEN_MCKEN_Pos); + } + else + { + p_i2s->CONFIG.MCKFREQ = mck_setup; + p_i2s->CONFIG.MCKEN = + (I2S_CONFIG_MCKEN_MCKEN_Enabled << I2S_CONFIG_MCKEN_MCKEN_Pos); + } + + return true; +} + +__STATIC_INLINE void nrf_i2s_transfer_set(NRF_I2S_Type * p_i2s, + uint16_t size, + uint32_t * p_buffer_rx, + uint32_t const * p_buffer_tx) +{ + p_i2s->RXTXD.MAXCNT = size; + + nrf_i2s_rx_buffer_set(p_i2s, p_buffer_rx); + p_i2s->CONFIG.RXEN = (p_buffer_rx != NULL) ? 1 : 0; + + nrf_i2s_tx_buffer_set(p_i2s, p_buffer_tx); + p_i2s->CONFIG.TXEN = (p_buffer_tx != NULL) ? 1 : 0; +} + +__STATIC_INLINE void nrf_i2s_rx_buffer_set(NRF_I2S_Type * p_i2s, + uint32_t * p_buffer) +{ + p_i2s->RXD.PTR = (uint32_t)p_buffer; +} + +__STATIC_INLINE uint32_t * nrf_i2s_rx_buffer_get(NRF_I2S_Type const * p_i2s) +{ + return (uint32_t *)(p_i2s->RXD.PTR); +} + +__STATIC_INLINE void nrf_i2s_tx_buffer_set(NRF_I2S_Type * p_i2s, + uint32_t const * p_buffer) +{ + p_i2s->TXD.PTR = (uint32_t)p_buffer; +} + +__STATIC_INLINE uint32_t * nrf_i2s_tx_buffer_get(NRF_I2S_Type const * p_i2s) +{ + return (uint32_t *)(p_i2s->TXD.PTR); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_I2S_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_lpcomp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_lpcomp.h new file mode 100644 index 0000000000..4e241a9779 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_lpcomp.h @@ -0,0 +1,425 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief LPCOMP HAL API. + */ + +#ifndef NRF_LPCOMP_H_ +#define NRF_LPCOMP_H_ + +/** + * @defgroup nrf_lpcomp_hal LPCOMP HAL + * @{ + * @ingroup nrf_lpcomp + * @brief Hardware access layer for managing the Low Power Comparator (LPCOMP). + */ + +#include "nrf.h" +#include "nrf_peripherals.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @enum nrf_lpcomp_ref_t + * @brief LPCOMP reference selection. + */ +typedef enum +{ +#if (LPCOMP_REFSEL_RESOLUTION == 8) || defined(__SDK_DOXYGEN__) + NRF_LPCOMP_REF_SUPPLY_1_8 = LPCOMP_REFSEL_REFSEL_SupplyOneEighthPrescaling, /**< Use supply with a 1/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_2_8 = LPCOMP_REFSEL_REFSEL_SupplyTwoEighthsPrescaling, /**< Use supply with a 2/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_3_8 = LPCOMP_REFSEL_REFSEL_SupplyThreeEighthsPrescaling, /**< Use supply with a 3/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_4_8 = LPCOMP_REFSEL_REFSEL_SupplyFourEighthsPrescaling, /**< Use supply with a 4/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_5_8 = LPCOMP_REFSEL_REFSEL_SupplyFiveEighthsPrescaling, /**< Use supply with a 5/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_6_8 = LPCOMP_REFSEL_REFSEL_SupplySixEighthsPrescaling, /**< Use supply with a 6/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_7_8 = LPCOMP_REFSEL_REFSEL_SupplySevenEighthsPrescaling, /**< Use supply with a 7/8 prescaler as reference. */ +#elif (LPCOMP_REFSEL_RESOLUTION == 16) || defined(__SDK_DOXYGEN__) + NRF_LPCOMP_REF_SUPPLY_1_8 = LPCOMP_REFSEL_REFSEL_Ref1_8Vdd, /**< Use supply with a 1/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_2_8 = LPCOMP_REFSEL_REFSEL_Ref2_8Vdd, /**< Use supply with a 2/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_3_8 = LPCOMP_REFSEL_REFSEL_Ref3_8Vdd, /**< Use supply with a 3/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_4_8 = LPCOMP_REFSEL_REFSEL_Ref4_8Vdd, /**< Use supply with a 4/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_5_8 = LPCOMP_REFSEL_REFSEL_Ref5_8Vdd, /**< Use supply with a 5/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_6_8 = LPCOMP_REFSEL_REFSEL_Ref6_8Vdd, /**< Use supply with a 6/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_7_8 = LPCOMP_REFSEL_REFSEL_Ref7_8Vdd, /**< Use supply with a 7/8 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_1_16 = LPCOMP_REFSEL_REFSEL_Ref1_16Vdd, /**< Use supply with a 1/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_3_16 = LPCOMP_REFSEL_REFSEL_Ref3_16Vdd, /**< Use supply with a 3/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_5_16 = LPCOMP_REFSEL_REFSEL_Ref5_16Vdd, /**< Use supply with a 5/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_7_16 = LPCOMP_REFSEL_REFSEL_Ref7_16Vdd, /**< Use supply with a 7/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_9_16 = LPCOMP_REFSEL_REFSEL_Ref9_16Vdd, /**< Use supply with a 9/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_11_16 = LPCOMP_REFSEL_REFSEL_Ref11_16Vdd, /**< Use supply with a 11/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_13_16 = LPCOMP_REFSEL_REFSEL_Ref13_16Vdd, /**< Use supply with a 13/16 prescaler as reference. */ + NRF_LPCOMP_REF_SUPPLY_15_16 = LPCOMP_REFSEL_REFSEL_Ref15_16Vdd, /**< Use supply with a 15/16 prescaler as reference. */ +#endif + NRF_LPCOMP_REF_EXT_REF0 = LPCOMP_REFSEL_REFSEL_ARef | + (LPCOMP_EXTREFSEL_EXTREFSEL_AnalogReference0 << 16), /**< External reference 0. */ + NRF_LPCOMP_CONFIG_REF_EXT_REF1 = LPCOMP_REFSEL_REFSEL_ARef | + (LPCOMP_EXTREFSEL_EXTREFSEL_AnalogReference1 << 16), /**< External reference 1. */ +} nrf_lpcomp_ref_t; + +/** + * @enum nrf_lpcomp_input_t + * @brief LPCOMP input selection. + */ +typedef enum +{ + NRF_LPCOMP_INPUT_0 = LPCOMP_PSEL_PSEL_AnalogInput0, /**< Input 0. */ + NRF_LPCOMP_INPUT_1 = LPCOMP_PSEL_PSEL_AnalogInput1, /**< Input 1. */ + NRF_LPCOMP_INPUT_2 = LPCOMP_PSEL_PSEL_AnalogInput2, /**< Input 2. */ + NRF_LPCOMP_INPUT_3 = LPCOMP_PSEL_PSEL_AnalogInput3, /**< Input 3. */ + NRF_LPCOMP_INPUT_4 = LPCOMP_PSEL_PSEL_AnalogInput4, /**< Input 4. */ + NRF_LPCOMP_INPUT_5 = LPCOMP_PSEL_PSEL_AnalogInput5, /**< Input 5. */ + NRF_LPCOMP_INPUT_6 = LPCOMP_PSEL_PSEL_AnalogInput6, /**< Input 6. */ + NRF_LPCOMP_INPUT_7 = LPCOMP_PSEL_PSEL_AnalogInput7 /**< Input 7. */ +} nrf_lpcomp_input_t; + +/** + * @enum nrf_lpcomp_detect_t + * @brief LPCOMP detection type selection. + */ +typedef enum +{ + NRF_LPCOMP_DETECT_CROSS = LPCOMP_ANADETECT_ANADETECT_Cross, /**< Generate ANADETEC on crossing, both upwards and downwards crossing. */ + NRF_LPCOMP_DETECT_UP = LPCOMP_ANADETECT_ANADETECT_Up, /**< Generate ANADETEC on upwards crossing only. */ + NRF_LPCOMP_DETECT_DOWN = LPCOMP_ANADETECT_ANADETECT_Down /**< Generate ANADETEC on downwards crossing only. */ +} nrf_lpcomp_detect_t; + +/** + * @enum nrf_lpcomp_task_t + * @brief LPCOMP tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_LPCOMP_TASK_START = offsetof(NRF_LPCOMP_Type, TASKS_START), /**< LPCOMP start sampling task. */ + NRF_LPCOMP_TASK_STOP = offsetof(NRF_LPCOMP_Type, TASKS_STOP), /**< LPCOMP stop sampling task. */ + NRF_LPCOMP_TASK_SAMPLE = offsetof(NRF_LPCOMP_Type, TASKS_SAMPLE) /**< Sample comparator value. */ +} nrf_lpcomp_task_t; /*lint -restore*/ + + +/** + * @enum nrf_lpcomp_event_t + * @brief LPCOMP events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_LPCOMP_EVENT_READY = offsetof(NRF_LPCOMP_Type, EVENTS_READY), /**< LPCOMP is ready and output is valid. */ + NRF_LPCOMP_EVENT_DOWN = offsetof(NRF_LPCOMP_Type, EVENTS_DOWN), /**< Input voltage crossed the threshold going down. */ + NRF_LPCOMP_EVENT_UP = offsetof(NRF_LPCOMP_Type, EVENTS_UP), /**< Input voltage crossed the threshold going up. */ + NRF_LPCOMP_EVENT_CROSS = offsetof(NRF_LPCOMP_Type, EVENTS_CROSS) /**< Input voltage crossed the threshold in any direction. */ +} nrf_lpcomp_event_t; /*lint -restore*/ + +/** + * @enum nrf_lpcomp_short_mask_t + * @brief LPCOMP shorts masks. + */ +typedef enum +{ + NRF_LPCOMP_SHORT_CROSS_STOP_MASK = LPCOMP_SHORTS_CROSS_STOP_Msk, /*!< Short between CROSS event and STOP task. */ + NRF_LPCOMP_SHORT_UP_STOP_MASK = LPCOMP_SHORTS_UP_STOP_Msk, /*!< Short between UP event and STOP task. */ + NRF_LPCOMP_SHORT_DOWN_STOP_MASK = LPCOMP_SHORTS_DOWN_STOP_Msk, /*!< Short between DOWN event and STOP task. */ + NRF_LPCOMP_SHORT_READY_STOP_MASK = LPCOMP_SHORTS_READY_STOP_Msk, /*!< Short between READY event and STOP task. */ + NRF_LPCOMP_SHORT_READY_SAMPLE_MASK = LPCOMP_SHORTS_READY_SAMPLE_Msk /*!< Short between READY event and SAMPLE task. */ +} nrf_lpcomp_short_mask_t; + +#ifdef LPCOMP_FEATURE_HYST_PRESENT +/** + * @enum nrf_lpcomp_hysteresis_t + * @brief LPCOMP hysteresis. + */ +typedef enum +{ + NRF_LPCOMP_HYST_NOHYST = LPCOMP_HYST_HYST_NoHyst, /**< Comparator hysteresis disabled. */ + NRF_LPCOMP_HYST_50mV = LPCOMP_HYST_HYST_Hyst50mV /**< Comparator hysteresis enabled (typ. 50 mV). */ +}nrf_lpcomp_hysteresis_t; +#endif // LPCOMP_FEATURE_HYST_PRESENT + +/** @brief LPCOMP configuration. */ +typedef struct +{ + nrf_lpcomp_ref_t reference; /**< LPCOMP reference. */ + nrf_lpcomp_detect_t detection; /**< LPCOMP detection type. */ +#ifdef LPCOMP_FEATURE_HYST_PRESENT + nrf_lpcomp_hysteresis_t hyst; /**< LPCOMP hysteresis. */ +#endif // LPCOMP_FEATURE_HYST_PRESENT +} nrf_lpcomp_config_t; + +/** Default LPCOMP configuration. */ +#define NRF_LPCOMP_CONFIG_DEFAULT { NRF_LPCOMP_REF_SUPPLY_FOUR_EIGHT, NRF_LPCOMP_DETECT_DOWN } + +/** + * @brief Function for configuring LPCOMP. + * + * This function powers on LPCOMP and configures it. LPCOMP is in DISABLE state after configuration, + * so it must be enabled before using it. All shorts are inactive, events are cleared, and LPCOMP is stopped. + * + * @param[in] p_config Configuration. + */ +__STATIC_INLINE void nrf_lpcomp_configure(const nrf_lpcomp_config_t * p_config) +{ + NRF_LPCOMP->TASKS_STOP = 1; + NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Disabled << LPCOMP_ENABLE_ENABLE_Pos; + NRF_LPCOMP->REFSEL = + (p_config->reference << LPCOMP_REFSEL_REFSEL_Pos) & LPCOMP_REFSEL_REFSEL_Msk; + + //If external source is choosen extract analog reference index. + if ((p_config->reference & LPCOMP_REFSEL_REFSEL_ARef)==LPCOMP_REFSEL_REFSEL_ARef) + { + uint32_t extref = p_config->reference >> 16; + NRF_LPCOMP->EXTREFSEL = (extref << LPCOMP_EXTREFSEL_EXTREFSEL_Pos) & LPCOMP_EXTREFSEL_EXTREFSEL_Msk; + } + + NRF_LPCOMP->ANADETECT = + (p_config->detection << LPCOMP_ANADETECT_ANADETECT_Pos) & LPCOMP_ANADETECT_ANADETECT_Msk; +#ifdef LPCOMP_FEATURE_HYST_PRESENT + NRF_LPCOMP->HYST = ((p_config->hyst) << LPCOMP_HYST_HYST_Pos) & LPCOMP_HYST_HYST_Msk; +#endif //LPCOMP_FEATURE_HYST_PRESENT + NRF_LPCOMP->SHORTS = 0; + NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | + LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk; +} + + +/** + * @brief Function for selecting the LPCOMP input. + * + * This function selects the active input of LPCOMP. + * + * @param[in] input Input to be selected. + */ +__STATIC_INLINE void nrf_lpcomp_input_select(nrf_lpcomp_input_t input) +{ + uint32_t lpcomp_enable_state = NRF_LPCOMP->ENABLE; + + NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Disabled << LPCOMP_ENABLE_ENABLE_Pos; + NRF_LPCOMP->PSEL = + ((uint32_t)input << LPCOMP_PSEL_PSEL_Pos) | (NRF_LPCOMP->PSEL & ~LPCOMP_PSEL_PSEL_Msk); + NRF_LPCOMP->ENABLE = lpcomp_enable_state; +} + + +/** + * @brief Function for enabling the Low Power Comparator. + * + * This function enables LPCOMP. + * + */ +__STATIC_INLINE void nrf_lpcomp_enable(void) +{ + NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Enabled << LPCOMP_ENABLE_ENABLE_Pos; + NRF_LPCOMP->EVENTS_READY = 0; + NRF_LPCOMP->EVENTS_DOWN = 0; + NRF_LPCOMP->EVENTS_UP = 0; + NRF_LPCOMP->EVENTS_CROSS = 0; +} + + +/** + * @brief Function for disabling the Low Power Comparator. + * + * This function disables LPCOMP. + * + */ +__STATIC_INLINE void nrf_lpcomp_disable(void) +{ + NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Disabled << LPCOMP_ENABLE_ENABLE_Pos; +} + + +/** + * @brief Function for getting the last LPCOMP compare result. + * + * @return The last compare result. If 0 then VIN+ < VIN-, if 1 then the opposite. + */ +__STATIC_INLINE uint32_t nrf_lpcomp_result_get(void) +{ + return (uint32_t)NRF_LPCOMP->RESULT; +} + + +/** + * @brief Function for enabling interrupts from LPCOMP. + * + * @param[in] lpcomp_int_mask Mask of interrupts to be enabled. + * + * @sa nrf_lpcomp_int_disable() + * @sa nrf_lpcomp_int_enable_check() + */ +__STATIC_INLINE void nrf_lpcomp_int_enable(uint32_t lpcomp_int_mask) +{ + NRF_LPCOMP->INTENSET = lpcomp_int_mask; +} + + +/** + * @brief Function for disabling interrupts from LPCOMP. + * + * @param[in] lpcomp_int_mask Mask of interrupts to be disabled. + * + * @sa nrf_lpcomp_int_enable() + * @sa nrf_lpcomp_int_enable_check() + */ +__STATIC_INLINE void nrf_lpcomp_int_disable(uint32_t lpcomp_int_mask) +{ + NRF_LPCOMP->INTENCLR = lpcomp_int_mask; +} + + +/** + * @brief Function for getting the enabled interrupts of LPCOMP. + * + * @param[in] lpcomp_int_mask Mask of interrupts to be checked. + * + * @retval true If any of interrupts of the specified mask are enabled. + * + * @sa nrf_lpcomp_int_enable() + * @sa nrf_lpcomp_int_disable() + */ +__STATIC_INLINE bool nrf_lpcomp_int_enable_check(uint32_t lpcomp_int_mask) +{ + return (NRF_LPCOMP->INTENSET & lpcomp_int_mask); // when read this register will return the value of INTEN. +} + + +/** + * @brief Function for getting the address of a specific LPCOMP task register. + * + * @param[in] lpcomp_task LPCOMP task. + * + * @return The address of the specified LPCOMP task. + */ +__STATIC_INLINE uint32_t * nrf_lpcomp_task_address_get(nrf_lpcomp_task_t lpcomp_task) +{ + return (uint32_t *)((uint8_t *)NRF_LPCOMP + lpcomp_task); +} + + +/** + * @brief Function for getting the address of a specific LPCOMP event register. + * + * @param[in] lpcomp_event LPCOMP event. + * + * @return The address of the specified LPCOMP event. + */ +__STATIC_INLINE uint32_t * nrf_lpcomp_event_address_get(nrf_lpcomp_event_t lpcomp_event) +{ + return (uint32_t *)((uint8_t *)NRF_LPCOMP + lpcomp_event); +} + + +/** + * @brief Function for setting LPCOMP shorts. + * + * @param[in] lpcomp_short_mask LPCOMP shorts by mask. + * + */ +__STATIC_INLINE void nrf_lpcomp_shorts_enable(uint32_t lpcomp_short_mask) +{ + NRF_LPCOMP->SHORTS |= lpcomp_short_mask; +} + + +/** + * @brief Function for clearing LPCOMP shorts by mask. + * + * @param[in] lpcomp_short_mask LPCOMP shorts to be cleared. + * + */ +__STATIC_INLINE void nrf_lpcomp_shorts_disable(uint32_t lpcomp_short_mask) +{ + NRF_LPCOMP->SHORTS &= ~lpcomp_short_mask; +} + + +/** + * @brief Function for setting a specific LPCOMP task. + * + * @param[in] lpcomp_task LPCOMP task to be set. + * + */ +__STATIC_INLINE void nrf_lpcomp_task_trigger(nrf_lpcomp_task_t lpcomp_task) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_LPCOMP + lpcomp_task) ) = 1; +} + + +/** + * @brief Function for clearing a specific LPCOMP event. + * + * @param[in] lpcomp_event LPCOMP event to be cleared. + * + */ +__STATIC_INLINE void nrf_lpcomp_event_clear(nrf_lpcomp_event_t lpcomp_event) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_LPCOMP + lpcomp_event) ) = 0; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_LPCOMP + lpcomp_event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for getting the state of a specific LPCOMP event. + * + * @retval true If the specified LPCOMP event is active. + * + */ +__STATIC_INLINE bool nrf_lpcomp_event_check(nrf_lpcomp_event_t lpcomp_event) +{ + return (bool) (*(volatile uint32_t *)( (uint8_t *)NRF_LPCOMP + lpcomp_event)); +} + + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_LPCOMP_H_ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.c new file mode 100644 index 0000000000..ccae784b64 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.c @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + *@brief NMVC driver implementation + */ + +#include +#include "nrf.h" +#include "nrf_nvmc.h" + + +static inline void wait_for_flash_ready(void) +{ + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;} +} + + +void nrf_nvmc_page_erase(uint32_t address) +{ + // Enable erase. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een; + __ISB(); + __DSB(); + + // Erase the page + NRF_NVMC->ERASEPAGE = address; + wait_for_flash_ready(); + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + __ISB(); + __DSB(); +} + + +void nrf_nvmc_write_byte(uint32_t address, uint8_t value) +{ + uint32_t byte_shift = address & (uint32_t)0x03; + uint32_t address32 = address & ~byte_shift; // Address to the word this byte is in. + uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3))); + value32 = value32 + ((uint32_t)value << (byte_shift << 3)); + + // Enable write. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + __ISB(); + __DSB(); + + *(uint32_t*)address32 = value32; + wait_for_flash_ready(); + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + __ISB(); + __DSB(); +} + + +void nrf_nvmc_write_word(uint32_t address, uint32_t value) +{ + // Enable write. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + __ISB(); + __DSB(); + + *(uint32_t*)address = value; + wait_for_flash_ready(); + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + __ISB(); + __DSB(); +} + + +void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes) +{ + for (uint32_t i = 0; i < num_bytes; i++) + { + nrf_nvmc_write_byte(address + i, src[i]); + } +} + + +void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words) +{ + // Enable write. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + __ISB(); + __DSB(); + + for (uint32_t i = 0; i < num_words; i++) + { + ((uint32_t*)address)[i] = src[i]; + wait_for_flash_ready(); + } + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + __ISB(); + __DSB(); +} + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.h new file mode 100644 index 0000000000..b31c5b1b32 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_nvmc.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief NMVC driver API. + */ + +#ifndef NRF_NVMC_H__ +#define NRF_NVMC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup nrf_nvmc Non-volatile memory controller + * @{ + * @ingroup nrf_drivers + * @brief Driver for the NVMC peripheral. + * + * This driver allows writing to the non-volatile memory (NVM) regions + * of the chip. In order to write to NVM the controller must be powered + * on and the relevant page must be erased. + * + */ + + +/** + * @brief Erase a page in flash. This is required before writing to any + * address in the page. + * + * @param address Start address of the page. + */ +void nrf_nvmc_page_erase(uint32_t address); + + +/** + * @brief Write a single byte to flash. + * + * The function reads the word containing the byte, and then + * rewrites the entire word. + * + * @param address Address to write to. + * @param value Value to write. + */ +void nrf_nvmc_write_byte(uint32_t address , uint8_t value); + + +/** + * @brief Write a 32-bit word to flash. + * @param address Address to write to. + * @param value Value to write. + */ +void nrf_nvmc_write_word(uint32_t address, uint32_t value); + + +/** + * @brief Write consecutive bytes to flash. + * + * @param address Address to write to. + * @param src Pointer to data to copy from. + * @param num_bytes Number of bytes in src to write. + */ +void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes); + + +/** + * @brief Write consecutive words to flash. + * + * @param address Address to write to. + * @param src Pointer to data to copy from. + * @param num_words Number of words in src to write. + */ +void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words); + + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_NVMC_H__ +/** @} */ + + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pdm.h new file mode 100644 index 0000000000..7937d75687 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pdm.h @@ -0,0 +1,396 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_PDM_H_ +#define NRF_PDM_H_ + +/** + * @defgroup nrf_pdm_hal PDM HAL + * @{ + * @ingroup nrf_pdm + * + * @brief @tagAPI52 Hardware abstraction layer for accessing the pulse density modulation (PDM) peripheral. + */ + +#include +#include +#include "nrf.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_PDM_GAIN_MINIMUM 0x00 +#define NRF_PDM_GAIN_DEFAULT 0x28 +#define NRF_PDM_GAIN_MAXIMUM 0x50 + +typedef uint8_t nrf_pdm_gain_t; + + +/** + * @brief PDM tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_PDM_TASK_START = offsetof(NRF_PDM_Type, TASKS_START), ///< Starts continuous PDM transfer. + NRF_PDM_TASK_STOP = offsetof(NRF_PDM_Type, TASKS_STOP) ///< Stops PDM transfer. +} nrf_pdm_task_t; + + +/** + * @brief PDM events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_PDM_EVENT_STARTED = offsetof(NRF_PDM_Type, EVENTS_STARTED), ///< PDM transfer has started. + NRF_PDM_EVENT_STOPPED = offsetof(NRF_PDM_Type, EVENTS_STOPPED), ///< PDM transfer has finished. + NRF_PDM_EVENT_END = offsetof(NRF_PDM_Type, EVENTS_END) ///< The PDM has written the last sample specified by SAMPLE.MAXCNT (or the last sample after a STOP task has been received) to Data RAM. +} nrf_pdm_event_t; + + +/** + * @brief PDM interrupt masks. + */ +typedef enum +{ + NRF_PDM_INT_STARTED = PDM_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event. + NRF_PDM_INT_STOPPED = PDM_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event. + NRF_PDM_INT_END = PDM_INTENSET_END_Msk ///< Interrupt on EVENTS_END event. +} nrf_pdm_int_mask_t; + +/** + * @brief PDM clock frequency. + */ +typedef enum +{ + NRF_PDM_FREQ_1000K = PDM_PDMCLKCTRL_FREQ_1000K, ///< PDM_CLK = 1.000 MHz. + NRF_PDM_FREQ_1032K = PDM_PDMCLKCTRL_FREQ_Default, ///< PDM_CLK = 1.032 MHz. + NRF_PDM_FREQ_1067K = PDM_PDMCLKCTRL_FREQ_1067K ///< PDM_CLK = 1.067 MHz. +} nrf_pdm_freq_t; + + +/** + * @brief PDM operation mode. + */ +typedef enum +{ + NRF_PDM_MODE_STEREO = PDM_MODE_OPERATION_Stereo, ///< Sample and store one pair (Left + Right) of 16-bit samples per RAM word. + NRF_PDM_MODE_MONO = PDM_MODE_OPERATION_Mono ///< Sample and store two successive Left samples (16 bit each) per RAM word. +} nrf_pdm_mode_t; + + +/** + * @brief PDM sampling mode. + */ +typedef enum +{ + NRF_PDM_EDGE_LEFTFALLING = PDM_MODE_EDGE_LeftFalling, ///< Left (or mono) is sampled on falling edge of PDM_CLK. + NRF_PDM_EDGE_LEFTRISING = PDM_MODE_EDGE_LeftRising ///< Left (or mono) is sampled on rising edge of PDM_CLK. +} nrf_pdm_edge_t; + + +/** + * @brief Function for triggering a PDM task. + * + * @param[in] pdm_task PDM task. + */ +__STATIC_INLINE void nrf_pdm_task_trigger(nrf_pdm_task_t pdm_task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_task)) = 0x1UL; +} + + +/** + * @brief Function for getting the address of a PDM task register. + * + * @param[in] pdm_task PDM task. + * + * @return Address of the specified PDM task. + */ +__STATIC_INLINE uint32_t nrf_pdm_task_address_get(nrf_pdm_task_t pdm_task) +{ + return (uint32_t)((uint8_t *)NRF_PDM + (uint32_t)pdm_task); +} + + +/** + * @brief Function for getting the state of a PDM event. + * + * @param[in] pdm_event PDM event. + * + * @return State of the specified PDM event. + */ +__STATIC_INLINE bool nrf_pdm_event_check(nrf_pdm_event_t pdm_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event); +} + + +/** + * @brief Function for clearing a PDM event. + * + * @param[in] pdm_event PDM event. + */ +__STATIC_INLINE void nrf_pdm_event_clear(nrf_pdm_event_t pdm_event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for getting the address of a PDM event register. + * + * @param[in] pdm_event PDM event. + * + * @return Address of the specified PDM event. + */ +__STATIC_INLINE volatile uint32_t * nrf_pdm_event_address_get(nrf_pdm_event_t pdm_event) +{ + return (volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event); +} + + +/** + * @brief Function for enabling PDM interrupts. + * + * @param[in] pdm_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_pdm_int_enable(uint32_t pdm_int_mask) +{ + NRF_PDM->INTENSET = pdm_int_mask; +} + + +/** + * @brief Function for retrieving the state of PDM interrupts. + * + * @param[in] pdm_int_mask Interrupts to check. + * + * @retval true If all specified interrupts are enabled. + * @retval false If at least one of the given interrupts is not enabled. + */ +__STATIC_INLINE bool nrf_pdm_int_enable_check(uint32_t pdm_int_mask) +{ + return (bool)(NRF_PDM->INTENSET & pdm_int_mask); +} + + +/** + * @brief Function for disabling interrupts. + * + * @param pdm_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_pdm_int_disable(uint32_t pdm_int_mask) +{ + NRF_PDM->INTENCLR = pdm_int_mask; +} + + +/** + * @brief Function for enabling the PDM peripheral. + * + * The PDM peripheral must be enabled before use. + */ +__STATIC_INLINE void nrf_pdm_enable(void) +{ + NRF_PDM->ENABLE = (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos); +} + + +/** + * @brief Function for disabling the PDM peripheral. + */ +__STATIC_INLINE void nrf_pdm_disable(void) +{ + NRF_PDM->ENABLE = (PDM_ENABLE_ENABLE_Disabled << PDM_ENABLE_ENABLE_Pos); +} + + +/** + * @brief Function for checking if the PDM peripheral is enabled. + * + * @retval true If the PDM peripheral is enabled. + * @retval false If the PDM peripheral is not enabled. + */ +__STATIC_INLINE bool nrf_pdm_enable_check(void) +{ + return (NRF_PDM->ENABLE == (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos)); +} + + +/** + * @brief Function for setting the PDM operation mode. + * + * @param[in] pdm_mode PDM operation mode. + * @param[in] pdm_edge PDM sampling mode. + */ +__STATIC_INLINE void nrf_pdm_mode_set(nrf_pdm_mode_t pdm_mode, nrf_pdm_edge_t pdm_edge) +{ + NRF_PDM->MODE = ((pdm_mode << PDM_MODE_OPERATION_Pos) & PDM_MODE_OPERATION_Msk) + | ((pdm_edge << PDM_MODE_EDGE_Pos) & PDM_MODE_EDGE_Msk); +} + + +/** + * @brief Function for getting the PDM operation mode. + * + * @param[out] p_pdm_mode PDM operation mode. + * @param[out] p_pdm_edge PDM sampling mode. + */ +__STATIC_INLINE void nrf_pdm_mode_get(nrf_pdm_mode_t * p_pdm_mode, nrf_pdm_edge_t * p_pdm_edge) +{ + uint32_t mode = NRF_PDM->MODE; + *p_pdm_mode = (nrf_pdm_mode_t)((mode & PDM_MODE_OPERATION_Msk ) >> PDM_MODE_OPERATION_Pos); + *p_pdm_edge = (nrf_pdm_edge_t)((mode & PDM_MODE_EDGE_Msk ) >> PDM_MODE_EDGE_Pos); +} + + +/** + * @brief Function for setting the PDM clock frequency. + * + * @param[in] pdm_freq PDM clock frequency. + */ +__STATIC_INLINE void nrf_pdm_clock_set(nrf_pdm_freq_t pdm_freq) +{ + NRF_PDM->PDMCLKCTRL = ((pdm_freq << PDM_PDMCLKCTRL_FREQ_Pos) & PDM_PDMCLKCTRL_FREQ_Msk); +} + + +/** + * @brief Function for getting the PDM clock frequency. + */ +__STATIC_INLINE nrf_pdm_freq_t nrf_pdm_clock_get(void) +{ + return (nrf_pdm_freq_t) ((NRF_PDM->PDMCLKCTRL << PDM_PDMCLKCTRL_FREQ_Pos) & PDM_PDMCLKCTRL_FREQ_Msk); +} + + +/** + * @brief Function for setting up the PDM pins. + * + * @param[in] psel_clk CLK pin number. + * @param[in] psel_din DIN pin number. + */ +__STATIC_INLINE void nrf_pdm_psel_connect(uint32_t psel_clk, uint32_t psel_din) +{ + NRF_PDM->PSEL.CLK = psel_clk; + NRF_PDM->PSEL.DIN = psel_din; +} + +/** + * @brief Function for disconnecting the PDM pins. + */ +__STATIC_INLINE void nrf_pdm_psel_disconnect() +{ + NRF_PDM->PSEL.CLK = ((PDM_PSEL_CLK_CONNECT_Disconnected << PDM_PSEL_CLK_CONNECT_Pos) + & PDM_PSEL_CLK_CONNECT_Msk); + NRF_PDM->PSEL.DIN = ((PDM_PSEL_DIN_CONNECT_Disconnected << PDM_PSEL_DIN_CONNECT_Pos) + & PDM_PSEL_DIN_CONNECT_Msk); +} + + +/** + * @brief Function for setting the PDM gain. + * + * @param[in] gain_l Left channel gain. + * @param[in] gain_r Right channel gain. + */ +__STATIC_INLINE void nrf_pdm_gain_set(nrf_pdm_gain_t gain_l, nrf_pdm_gain_t gain_r) +{ + NRF_PDM->GAINL = gain_l; + NRF_PDM->GAINR = gain_r; +} + + +/** + * @brief Function for getting the PDM gain. + * + * @param[out] p_gain_l Left channel gain. + * @param[out] p_gain_r Right channel gain. + */ +__STATIC_INLINE void nrf_pdm_gain_get(nrf_pdm_gain_t * p_gain_l, nrf_pdm_gain_t * p_gain_r) +{ + *p_gain_l = NRF_PDM->GAINL; + *p_gain_r = NRF_PDM->GAINR; +} + + +/** + * @brief Function for setting the PDM sample buffer. + * + * @param[in] p_buffer Pointer to the RAM address where samples should be written with EasyDMA. + * @param[in] num Number of samples to allocate memory for in EasyDMA mode. + * + * The amount of allocated RAM depends on the operation mode. + * - For stereo mode: N 32-bit words. + * - For mono mode: Ceil(N/2) 32-bit words. + */ +__STATIC_INLINE void nrf_pdm_buffer_set(uint32_t * p_buffer, uint32_t num) +{ + NRF_PDM->SAMPLE.PTR = (uint32_t)p_buffer; + NRF_PDM->SAMPLE.MAXCNT = num; +} + +/** + * @brief Function for getting the current PDM sample buffer address. + * + * @return Pointer to the current sample buffer. + */ +__STATIC_INLINE uint32_t * nrf_pdm_buffer_get() +{ + return (uint32_t *)NRF_PDM->SAMPLE.PTR; +} + + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_PDM_H_ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_peripherals.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_peripherals.h new file mode 100644 index 0000000000..a1cdd3b4d8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_peripherals.h @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_PERIPHERALS_H +#define NRF_PERIPHERALS_H + +/*lint ++flb "Enter library region */ + +#ifdef NRF51422 +#include "nrf51422_peripherals.h" +#endif + +#ifdef NRF51802 +#include "nrf51802_peripherals.h" +#endif + +#ifdef NRF51822 +#include "nrf51822_peripherals.h" +#endif + +#ifdef NRF52810_XXAA +#include "nrf52810_peripherals.h" +#endif + +#ifdef NRF52832_XXAA +#include "nrf52832_peripherals.h" +#endif + +#ifdef NRF52840_XXAA +#include "nrf52840_peripherals.h" +#endif + + +/*lint --flb "Leave library region" */ + +#endif /* NRF_PERIPHERALS_H */ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_power.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_power.h new file mode 100644 index 0000000000..13116cfee7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_power.h @@ -0,0 +1,1065 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_POWER_H__ +#define NRF_POWER_H__ + +/** + * @ingroup nrf_power + * @defgroup nrf_power_hal POWER HAL + * @{ + * + * Hardware access layer for (POWER) peripheral. + */ +#include "nrf.h" +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_assert.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POWER_RAMSTATUS_RAMBLOCK0_Msk) +#define NRF_POWER_HAS_RAMSTATUS 1 +#else +#define NRF_POWER_HAS_RAMSTATUS 0 +#endif + +/** + * @name The implemented functionality + * @{ + * + * Macros that defines functionality that is implemented into POWER peripheral. + */ +#if defined(POWER_INTENSET_SLEEPENTER_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that sleep events are present + * + * In some MCUs there is possibility to process sleep entering and exiting + * events. + */ +#define NRF_POWER_HAS_SLEEPEVT 1 +#else +#define NRF_POWER_HAS_SLEEPEVT 0 +#endif + +#if defined(POWER_RAM_POWER_S0POWER_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that RAMPOWER registers are present + * + * After nRF51, new way to manage RAM power was implemented. + * Special registers, one for every RAM block that makes it possible to + * power ON or OFF RAM segments and turn ON and OFF RAM retention in system OFF + * state. + */ +#define NRF_POWER_HAS_RAMPOWER_REGS 1 +#else +#define NRF_POWER_HAS_RAMPOWER_REGS 0 +#endif + +#if defined(POWER_POFCON_THRESHOLDVDDH_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief Auxiliary definition to mark the fact that VDDH is present + * + * This definition can be used in a code to decide if the part with VDDH + * related settings should be implemented. + */ +#define NRF_POWER_HAS_VDDH 1 +#else +#define NRF_POWER_HAS_VDDH 0 +#endif + +#if defined(POWER_USBREGSTATUS_VBUSDETECT_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief The fact that power module manages USB regulator + * + * In devices that have USB, power peripheral manages also connection + * detection and USB power regulator, that converts 5 V to 3.3 V + * used by USBD peripheral. + */ +#define NRF_POWER_HAS_USBREG 1 +#else +#define NRF_POWER_HAS_USBREG 0 +#endif +/** @} */ + +/* ------------------------------------------------------------------------------------------------ + * Begin of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ + +/** + * @brief POWER tasks + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_POWER_TASK_CONSTLAT = offsetof(NRF_POWER_Type, TASKS_CONSTLAT), /**< Enable constant latency mode */ + NRF_POWER_TASK_LOWPWR = offsetof(NRF_POWER_Type, TASKS_LOWPWR ), /**< Enable low power mode (variable latency) */ +}nrf_power_task_t; /*lint -restore */ + +/** + * @brief POWER events + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_POWER_EVENT_POFWARN = offsetof(NRF_POWER_Type, EVENTS_POFWARN ), /**< Power failure warning */ +#if NRF_POWER_HAS_SLEEPEVT + NRF_POWER_EVENT_SLEEPENTER = offsetof(NRF_POWER_Type, EVENTS_SLEEPENTER ), /**< CPU entered WFI/WFE sleep */ + NRF_POWER_EVENT_SLEEPEXIT = offsetof(NRF_POWER_Type, EVENTS_SLEEPEXIT ), /**< CPU exited WFI/WFE sleep */ +#endif +#if NRF_POWER_HAS_USBREG + NRF_POWER_EVENT_USBDETECTED = offsetof(NRF_POWER_Type, EVENTS_USBDETECTED), /**< Voltage supply detected on VBUS */ + NRF_POWER_EVENT_USBREMOVED = offsetof(NRF_POWER_Type, EVENTS_USBREMOVED ), /**< Voltage supply removed from VBUS */ + NRF_POWER_EVENT_USBPWRRDY = offsetof(NRF_POWER_Type, EVENTS_USBPWRRDY ), /**< USB 3.3 V supply ready */ +#endif +}nrf_power_event_t; /*lint -restore */ + +/** + * @brief POWER interrupts + */ +typedef enum +{ + NRF_POWER_INT_POFWARN_MASK = POWER_INTENSET_POFWARN_Msk , /**< Write '1' to Enable interrupt for POFWARN event */ +#if NRF_POWER_HAS_SLEEPEVT + NRF_POWER_INT_SLEEPENTER_MASK = POWER_INTENSET_SLEEPENTER_Msk , /**< Write '1' to Enable interrupt for SLEEPENTER event */ + NRF_POWER_INT_SLEEPEXIT_MASK = POWER_INTENSET_SLEEPEXIT_Msk , /**< Write '1' to Enable interrupt for SLEEPEXIT event */ +#endif +#if NRF_POWER_HAS_USBREG + NRF_POWER_INT_USBDETECTED_MASK = POWER_INTENSET_USBDETECTED_Msk, /**< Write '1' to Enable interrupt for USBDETECTED event */ + NRF_POWER_INT_USBREMOVED_MASK = POWER_INTENSET_USBREMOVED_Msk , /**< Write '1' to Enable interrupt for USBREMOVED event */ + NRF_POWER_INT_USBPWRRDY_MASK = POWER_INTENSET_USBPWRRDY_Msk , /**< Write '1' to Enable interrupt for USBPWRRDY event */ +#endif +}nrf_power_int_mask_t; + +/** + * @brief Function for activating a specific POWER task. + * + * @param task Task. + */ +__STATIC_INLINE void nrf_power_task_trigger(nrf_power_task_t task); + +/** + * @brief Function for returning the address of a specific POWER task register. + * + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_power_task_address_get(nrf_power_task_t task); + +/** + * @brief Function for clearing a specific event. + * + * @param event Event. + */ +__STATIC_INLINE void nrf_power_event_clear(nrf_power_event_t event); + +/** + * @brief Function for returning the state of a specific event. + * + * @param event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_power_event_check(nrf_power_event_t event); + +/** + * @brief Function for getting and clearing the state of specific event + * + * This function checks the state of the event and clears it. + * + * @param event Event. + * + * @retval true If the event was set. + * @retval false If the event was not set. + */ +__STATIC_INLINE bool nrf_power_event_get_and_clear(nrf_power_event_t event); + +/** + * @brief Function for returning the address of a specific POWER event register. + * + * @param event Event. + * + * @return Address. + */ +__STATIC_INLINE uint32_t nrf_power_event_address_get(nrf_power_event_t event); + +/** + * @brief Function for enabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_power_int_enable(uint32_t int_mask); + +/** + * @brief Function for retrieving the state of selected interrupts. + * + * @param int_mask Interrupts mask. + * + * @retval true If any of selected interrupts is enabled. + * @retval false If none of selected interrupts is enabled. + */ +__STATIC_INLINE bool nrf_power_int_enable_check(uint32_t int_mask); + +/** + * @brief Function for retrieving the information about enabled interrupts. + * + * @return The flags of enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_power_int_enable_get(void); + +/** + * @brief Function for disabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_power_int_disable(uint32_t int_mask); + + +/** @} */ /* End of nrf_power_hal */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/* ------------------------------------------------------------------------------------------------ + * Internal functions + */ + +/** + * @internal + * @brief Internal function for getting task/event register address + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile uint32_t * nrf_power_regptr_get(uint32_t offset) +{ + return (volatile uint32_t *)(((uint8_t *)NRF_POWER) + (uint32_t)offset); +} + +/** + * @internal + * @brief Internal function for getting task/event register address - constant version + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile const uint32_t * nrf_power_regptr_get_c( + uint32_t offset) +{ + return (volatile const uint32_t *)(((uint8_t *)NRF_POWER) + + (uint32_t)offset); +} + +/* ------------------------------------------------------------------------------------------------ + * Interface functions definitions + */ + +void nrf_power_task_trigger(nrf_power_task_t task) +{ + *(nrf_power_regptr_get((uint32_t)task)) = 1UL; +} + +uint32_t nrf_power_task_address_get(nrf_power_task_t task) +{ + return (uint32_t)nrf_power_regptr_get_c((uint32_t)task); +} + +void nrf_power_event_clear(nrf_power_event_t event) +{ + *(nrf_power_regptr_get((uint32_t)event)) = 0UL; +} + +bool nrf_power_event_check(nrf_power_event_t event) +{ + return (bool)*nrf_power_regptr_get_c((uint32_t)event); +} + +bool nrf_power_event_get_and_clear(nrf_power_event_t event) +{ + bool ret = nrf_power_event_check(event); + if (ret) + { + nrf_power_event_clear(event); + } + return ret; +} + +uint32_t nrf_power_event_address_get(nrf_power_event_t event) +{ + return (uint32_t)nrf_power_regptr_get_c((uint32_t)event); +} + +void nrf_power_int_enable(uint32_t int_mask) +{ + NRF_POWER->INTENSET = int_mask; +} + +bool nrf_power_int_enable_check(uint32_t int_mask) +{ + return !!(NRF_POWER->INTENSET & int_mask); +} + +uint32_t nrf_power_int_enable_get(void) +{ + return NRF_POWER->INTENSET; +} + +void nrf_power_int_disable(uint32_t int_mask) +{ + NRF_POWER->INTENCLR = int_mask; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/* ------------------------------------------------------------------------------------------------ + * End of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ +/** + * @ingroup nrf_power_hal + * @{ + */ + +/** + * @brief Reset reason + */ +typedef enum +{ + NRF_POWER_RESETREAS_RESETPIN_MASK = POWER_RESETREAS_RESETPIN_Msk, /*!< Bit mask of RESETPIN field. *///!< NRF_POWER_RESETREAS_RESETPIN_MASK + NRF_POWER_RESETREAS_DOG_MASK = POWER_RESETREAS_DOG_Msk , /*!< Bit mask of DOG field. */ //!< NRF_POWER_RESETREAS_DOG_MASK + NRF_POWER_RESETREAS_SREQ_MASK = POWER_RESETREAS_SREQ_Msk , /*!< Bit mask of SREQ field. */ //!< NRF_POWER_RESETREAS_SREQ_MASK + NRF_POWER_RESETREAS_LOCKUP_MASK = POWER_RESETREAS_LOCKUP_Msk , /*!< Bit mask of LOCKUP field. */ //!< NRF_POWER_RESETREAS_LOCKUP_MASK + NRF_POWER_RESETREAS_OFF_MASK = POWER_RESETREAS_OFF_Msk , /*!< Bit mask of OFF field. */ //!< NRF_POWER_RESETREAS_OFF_MASK +#if defined(POWER_RESETREAS_LPCOMP_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_LPCOMP_MASK = POWER_RESETREAS_LPCOMP_Msk , /*!< Bit mask of LPCOMP field. */ //!< NRF_POWER_RESETREAS_LPCOMP_MASK +#endif + NRF_POWER_RESETREAS_DIF_MASK = POWER_RESETREAS_DIF_Msk , /*!< Bit mask of DIF field. */ //!< NRF_POWER_RESETREAS_DIF_MASK +#if defined(POWER_RESETREAS_NFC_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_NFC_MASK = POWER_RESETREAS_NFC_Msk , /*!< Bit mask of NFC field. */ +#endif +#if defined(POWER_RESETREAS_VBUS_Msk) || defined(__SDK_DOXYGEN__) + NRF_POWER_RESETREAS_VBUS_MASK = POWER_RESETREAS_VBUS_Msk , /*!< Bit mask of VBUS field. */ +#endif +}nrf_power_resetreas_mask_t; + +#if NRF_POWER_HAS_USBREG +/** + * @brief USBREGSTATUS register bit masks + * + * @sa nrf_power_usbregstatus_get + */ +typedef enum +{ + NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK = POWER_USBREGSTATUS_VBUSDETECT_Msk, /**< USB detected or removed */ + NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK = POWER_USBREGSTATUS_OUTPUTRDY_Msk /**< USB 3.3 V supply ready */ +}nrf_power_usbregstatus_mask_t; +#endif + +#if NRF_POWER_HAS_RAMSTATUS +/** + * @brief RAM blocks numbers + * + * @sa nrf_power_ramblock_mask_t + * @note + * Ram blocks has to been used in nrf51. + * In new CPU ram is divided into segments and this functionality is depreciated. + * For the newer MCU see the PS for mapping between internal RAM and RAM blocks, + * because this mapping is not 1:1, and functions related to old style blocks + * should not be used. + */ +typedef enum +{ + NRF_POWER_RAMBLOCK0 = POWER_RAMSTATUS_RAMBLOCK0_Pos, + NRF_POWER_RAMBLOCK1 = POWER_RAMSTATUS_RAMBLOCK1_Pos, + NRF_POWER_RAMBLOCK2 = POWER_RAMSTATUS_RAMBLOCK2_Pos, + NRF_POWER_RAMBLOCK3 = POWER_RAMSTATUS_RAMBLOCK3_Pos +}nrf_power_ramblock_t; + +/** + * @brief RAM blocks masks + * + * @sa nrf_power_ramblock_t + */ + +typedef enum +{ + NRF_POWER_RAMBLOCK0_MASK = POWER_RAMSTATUS_RAMBLOCK0_Msk, + NRF_POWER_RAMBLOCK1_MASK = POWER_RAMSTATUS_RAMBLOCK1_Msk, + NRF_POWER_RAMBLOCK2_MASK = POWER_RAMSTATUS_RAMBLOCK2_Msk, + NRF_POWER_RAMBLOCK3_MASK = POWER_RAMSTATUS_RAMBLOCK3_Msk +}nrf_power_ramblock_mask_t; +#endif // NRF_POWER_HAS_RAMSTATUS + +/** + * @brief RAM power state position of the bits + * + * @sa nrf_power_onoffram_mask_t + */ +typedef enum +{ + NRF_POWER_ONRAM0, /**< Keep RAM block 0 on or off in system ON Mode */ + NRF_POWER_OFFRAM0, /**< Keep retention on RAM block 0 when RAM block is switched off */ + NRF_POWER_ONRAM1, /**< Keep RAM block 1 on or off in system ON Mode */ + NRF_POWER_OFFRAM1, /**< Keep retention on RAM block 1 when RAM block is switched off */ + NRF_POWER_ONRAM2, /**< Keep RAM block 2 on or off in system ON Mode */ + NRF_POWER_OFFRAM2, /**< Keep retention on RAM block 2 when RAM block is switched off */ + NRF_POWER_ONRAM3, /**< Keep RAM block 3 on or off in system ON Mode */ + NRF_POWER_OFFRAM3, /**< Keep retention on RAM block 3 when RAM block is switched off */ +}nrf_power_onoffram_t; + +/** + * @brief RAM power state bit masks + * + * @sa nrf_power_onoffram_t + */ +typedef enum +{ + NRF_POWER_ONRAM0_MASK = 1U << NRF_POWER_ONRAM0, /**< Keep RAM block 0 on or off in system ON Mode */ + NRF_POWER_OFFRAM0_MASK = 1U << NRF_POWER_OFFRAM0, /**< Keep retention on RAM block 0 when RAM block is switched off */ + NRF_POWER_ONRAM1_MASK = 1U << NRF_POWER_ONRAM1, /**< Keep RAM block 1 on or off in system ON Mode */ + NRF_POWER_OFFRAM1_MASK = 1U << NRF_POWER_OFFRAM1, /**< Keep retention on RAM block 1 when RAM block is switched off */ + NRF_POWER_ONRAM2_MASK = 1U << NRF_POWER_ONRAM2, /**< Keep RAM block 2 on or off in system ON Mode */ + NRF_POWER_OFFRAM2_MASK = 1U << NRF_POWER_OFFRAM2, /**< Keep retention on RAM block 2 when RAM block is switched off */ + NRF_POWER_ONRAM3_MASK = 1U << NRF_POWER_ONRAM3, /**< Keep RAM block 3 on or off in system ON Mode */ + NRF_POWER_OFFRAM3_MASK = 1U << NRF_POWER_OFFRAM3, /**< Keep retention on RAM block 3 when RAM block is switched off */ +}nrf_power_onoffram_mask_t; + +/** + * @brief Power failure comparator thresholds + */ +typedef enum +{ + NRF_POWER_POFTHR_V21 = POWER_POFCON_THRESHOLD_V21, /**< Set threshold to 2.1 V */ + NRF_POWER_POFTHR_V23 = POWER_POFCON_THRESHOLD_V23, /**< Set threshold to 2.3 V */ + NRF_POWER_POFTHR_V25 = POWER_POFCON_THRESHOLD_V25, /**< Set threshold to 2.5 V */ + NRF_POWER_POFTHR_V27 = POWER_POFCON_THRESHOLD_V27, /**< Set threshold to 2.7 V */ +#if defined(POWER_POFCON_THRESHOLD_V17) || defined(__SDK_DOXYGEN__) + NRF_POWER_POFTHR_V17 = POWER_POFCON_THRESHOLD_V17, /**< Set threshold to 1.7 V */ + NRF_POWER_POFTHR_V18 = POWER_POFCON_THRESHOLD_V18, /**< Set threshold to 1.8 V */ + NRF_POWER_POFTHR_V19 = POWER_POFCON_THRESHOLD_V19, /**< Set threshold to 1.9 V */ + NRF_POWER_POFTHR_V20 = POWER_POFCON_THRESHOLD_V20, /**< Set threshold to 2.0 V */ + NRF_POWER_POFTHR_V22 = POWER_POFCON_THRESHOLD_V22, /**< Set threshold to 2.2 V */ + NRF_POWER_POFTHR_V24 = POWER_POFCON_THRESHOLD_V24, /**< Set threshold to 2.4 V */ + NRF_POWER_POFTHR_V26 = POWER_POFCON_THRESHOLD_V26, /**< Set threshold to 2.6 V */ + NRF_POWER_POFTHR_V28 = POWER_POFCON_THRESHOLD_V28, /**< Set threshold to 2.8 V */ +#endif +}nrf_power_pof_thr_t; + +#if NRF_POWER_HAS_VDDH +/** + * @brief Power failure comparator thresholds for VDDH + */ +typedef enum +{ + NRF_POWER_POFTHRVDDH_V27 = POWER_POFCON_THRESHOLDVDDH_V27, /**< Set threshold to 2.7 V */ + NRF_POWER_POFTHRVDDH_V28 = POWER_POFCON_THRESHOLDVDDH_V28, /**< Set threshold to 2.8 V */ + NRF_POWER_POFTHRVDDH_V29 = POWER_POFCON_THRESHOLDVDDH_V29, /**< Set threshold to 2.9 V */ + NRF_POWER_POFTHRVDDH_V30 = POWER_POFCON_THRESHOLDVDDH_V30, /**< Set threshold to 3.0 V */ + NRF_POWER_POFTHRVDDH_V31 = POWER_POFCON_THRESHOLDVDDH_V31, /**< Set threshold to 3.1 V */ + NRF_POWER_POFTHRVDDH_V32 = POWER_POFCON_THRESHOLDVDDH_V32, /**< Set threshold to 3.2 V */ + NRF_POWER_POFTHRVDDH_V33 = POWER_POFCON_THRESHOLDVDDH_V33, /**< Set threshold to 3.3 V */ + NRF_POWER_POFTHRVDDH_V34 = POWER_POFCON_THRESHOLDVDDH_V34, /**< Set threshold to 3.4 V */ + NRF_POWER_POFTHRVDDH_V35 = POWER_POFCON_THRESHOLDVDDH_V35, /**< Set threshold to 3.5 V */ + NRF_POWER_POFTHRVDDH_V36 = POWER_POFCON_THRESHOLDVDDH_V36, /**< Set threshold to 3.6 V */ + NRF_POWER_POFTHRVDDH_V37 = POWER_POFCON_THRESHOLDVDDH_V37, /**< Set threshold to 3.7 V */ + NRF_POWER_POFTHRVDDH_V38 = POWER_POFCON_THRESHOLDVDDH_V38, /**< Set threshold to 3.8 V */ + NRF_POWER_POFTHRVDDH_V39 = POWER_POFCON_THRESHOLDVDDH_V39, /**< Set threshold to 3.9 V */ + NRF_POWER_POFTHRVDDH_V40 = POWER_POFCON_THRESHOLDVDDH_V40, /**< Set threshold to 4.0 V */ + NRF_POWER_POFTHRVDDH_V41 = POWER_POFCON_THRESHOLDVDDH_V41, /**< Set threshold to 4.1 V */ + NRF_POWER_POFTHRVDDH_V42 = POWER_POFCON_THRESHOLDVDDH_V42, /**< Set threshold to 4.2 V */ +}nrf_power_pof_thrvddh_t; + +/** + * @brief Main regulator status + */ +typedef enum +{ + NRF_POWER_MAINREGSTATUS_NORMAL = POWER_MAINREGSTATUS_MAINREGSTATUS_Normal, /**< Normal voltage mode. Voltage supplied on VDD. */ + NRF_POWER_MAINREGSTATUS_HIGH = POWER_MAINREGSTATUS_MAINREGSTATUS_High /**< High voltage mode. Voltage supplied on VDDH. */ +}nrf_power_mainregstatus_t; + +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_RAMPOWER_REGS +/** + * @brief Bit positions for RAMPOWER register + * + * All possible bits described, even if they are not used in selected MCU. + */ +typedef enum +{ + /** Keep RAM section S0 ON in System ON mode */ + NRF_POWER_RAMPOWER_S0POWER = POWER_RAM_POWER_S0POWER_Pos, + NRF_POWER_RAMPOWER_S1POWER, /**< Keep RAM section S1 ON in System ON mode */ + NRF_POWER_RAMPOWER_S2POWER, /**< Keep RAM section S2 ON in System ON mode */ + NRF_POWER_RAMPOWER_S3POWER, /**< Keep RAM section S3 ON in System ON mode */ + NRF_POWER_RAMPOWER_S4POWER, /**< Keep RAM section S4 ON in System ON mode */ + NRF_POWER_RAMPOWER_S5POWER, /**< Keep RAM section S5 ON in System ON mode */ + NRF_POWER_RAMPOWER_S6POWER, /**< Keep RAM section S6 ON in System ON mode */ + NRF_POWER_RAMPOWER_S7POWER, /**< Keep RAM section S7 ON in System ON mode */ + NRF_POWER_RAMPOWER_S8POWER, /**< Keep RAM section S8 ON in System ON mode */ + NRF_POWER_RAMPOWER_S9POWER, /**< Keep RAM section S9 ON in System ON mode */ + NRF_POWER_RAMPOWER_S10POWER, /**< Keep RAM section S10 ON in System ON mode */ + NRF_POWER_RAMPOWER_S11POWER, /**< Keep RAM section S11 ON in System ON mode */ + NRF_POWER_RAMPOWER_S12POWER, /**< Keep RAM section S12 ON in System ON mode */ + NRF_POWER_RAMPOWER_S13POWER, /**< Keep RAM section S13 ON in System ON mode */ + NRF_POWER_RAMPOWER_S14POWER, /**< Keep RAM section S14 ON in System ON mode */ + NRF_POWER_RAMPOWER_S15POWER, /**< Keep RAM section S15 ON in System ON mode */ + + /** Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S0RETENTION = POWER_RAM_POWER_S0RETENTION_Pos, + NRF_POWER_RAMPOWER_S1RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S2RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S3RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S4RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S5RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S6RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S7RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S8RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S9RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S10RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S11RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S12RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S13RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S14RETENTION, /**< Keep section retention in OFF mode when section is OFF */ + NRF_POWER_RAMPOWER_S15RETENTION, /**< Keep section retention in OFF mode when section is OFF */ +}nrf_power_rampower_t; + +#if defined ( __CC_ARM ) +#pragma push +#pragma diag_suppress 66 +#endif +/** + * @brief Bit masks for RAMPOWER register + * + * All possible bits described, even if they are not used in selected MCU. + */ +typedef enum +{ + NRF_POWER_RAMPOWER_S0POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S0POWER , + NRF_POWER_RAMPOWER_S1POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S1POWER , + NRF_POWER_RAMPOWER_S2POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S2POWER , + NRF_POWER_RAMPOWER_S3POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S3POWER , + NRF_POWER_RAMPOWER_S4POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S4POWER , + NRF_POWER_RAMPOWER_S5POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S5POWER , + NRF_POWER_RAMPOWER_S7POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S7POWER , + NRF_POWER_RAMPOWER_S8POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S8POWER , + NRF_POWER_RAMPOWER_S9POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S9POWER , + NRF_POWER_RAMPOWER_S10POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S10POWER, + NRF_POWER_RAMPOWER_S11POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S11POWER, + NRF_POWER_RAMPOWER_S12POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S12POWER, + NRF_POWER_RAMPOWER_S13POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S13POWER, + NRF_POWER_RAMPOWER_S14POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S14POWER, + NRF_POWER_RAMPOWER_S15POWER_MASK = 1UL << NRF_POWER_RAMPOWER_S15POWER, + + NRF_POWER_RAMPOWER_S0RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S0RETENTION , + NRF_POWER_RAMPOWER_S1RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S1RETENTION , + NRF_POWER_RAMPOWER_S2RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S2RETENTION , + NRF_POWER_RAMPOWER_S3RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S3RETENTION , + NRF_POWER_RAMPOWER_S4RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S4RETENTION , + NRF_POWER_RAMPOWER_S5RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S5RETENTION , + NRF_POWER_RAMPOWER_S7RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S7RETENTION , + NRF_POWER_RAMPOWER_S8RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S8RETENTION , + NRF_POWER_RAMPOWER_S9RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S9RETENTION , + NRF_POWER_RAMPOWER_S10RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S10RETENTION, + NRF_POWER_RAMPOWER_S11RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S11RETENTION, + NRF_POWER_RAMPOWER_S12RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S12RETENTION, + NRF_POWER_RAMPOWER_S13RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S13RETENTION, + NRF_POWER_RAMPOWER_S14RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S14RETENTION, + NRF_POWER_RAMPOWER_S15RETENTION_MASK = 1UL << NRF_POWER_RAMPOWER_S15RETENTION, +}nrf_power_rampower_mask_t; +#if defined ( __CC_ARM ) +#pragma pop +#endif +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + + +/** + * @brief Get reset reason mask + * + * Function returns the reset reason. + * Unless cleared, the RESETREAS register is cumulative. + * A field is cleared by writing '1' to it (see @ref nrf_power_resetreas_clear). + * If none of the reset sources are flagged, + * this indicates that the chip was reset from the on-chip reset generator, + * which indicates a power-on-reset or a brown out reset. + * + * @return The mask of reset reasons constructed with @ref nrf_power_resetreas_mask_t. + */ +__STATIC_INLINE uint32_t nrf_power_resetreas_get(void); + +/** + * @brief Clear selected reset reason field + * + * Function clears selected reset reason fields. + * + * @param[in] mask The mask constructed from @ref nrf_power_resetreas_mask_t enumerator values. + * @sa nrf_power_resetreas_get + */ +__STATIC_INLINE void nrf_power_resetreas_clear(uint32_t mask); + +#if NRF_POWER_HAS_RAMSTATUS +/** + * @brief Get RAMSTATUS register + * + * Returns the masks of RAM blocks that are powered ON. + * + * @return Value with bits sets according to masks in @ref nrf_power_ramblock_mask_t. + */ +__STATIC_INLINE uint32_t nrf_power_ramstatus_get(void); +#endif // NRF_POWER_HAS_RAMSTATUS + +/** + * @brief Go to system OFF + * + * This function puts the CPU into system off mode. + * The only way to wake up the CPU is by reset. + * + * @note This function never returns. + */ +__STATIC_INLINE void nrf_power_system_off(void); + +/** + * @brief Set power failure comparator configuration + * + * Sets power failure comparator threshold and enable/disable flag. + * + * @param enabled Set to true if power failure comparator should be enabled. + * @param thr Set the voltage threshold value. + * + * @note + * If VDDH settings is present in the device, this function would + * clear it settings (set to the lowest voltage). + * Use @ref nrf_power_pofcon_vddh_set function to set new value. + */ +__STATIC_INLINE void nrf_power_pofcon_set(bool enabled, nrf_power_pof_thr_t thr); + +/** + * @brief Get power failure comparator configuration + * + * Get power failure comparator threshold and enable bit. + * + * @param[out] p_enabled Function would set this boolean variable to true + * if power failure comparator is enabled. + * The pointer can be NULL if we do not need this information. + * @return Threshold setting for power failure comparator + */ +__STATIC_INLINE nrf_power_pof_thr_t nrf_power_pofcon_get(bool * p_enabled); + +#if NRF_POWER_HAS_VDDH +/** + * @brief Set VDDH power failure comparator threshold + * + * @param thr Threshold to be set + */ +__STATIC_INLINE void nrf_power_pofcon_vddh_set(nrf_power_pof_thrvddh_t thr); + +/** + * @brief Get VDDH power failure comparator threshold + * + * @return VDDH threshold currently configured + */ +__STATIC_INLINE nrf_power_pof_thrvddh_t nrf_power_pofcon_vddh_get(void); +#endif + +/** + * @brief Set general purpose retention register + * + * @param val Value to be set in the register + */ +__STATIC_INLINE void nrf_power_gpregret_set(uint8_t val); + +/** + * @brief Get general purpose retention register + * + * @return The value from the register + */ +__STATIC_INLINE uint8_t nrf_power_gpregret_get(void); + +#if defined(POWER_GPREGRET2_GPREGRET_Msk) || defined(__SDK_DOXYGEN__) +/** + * @brief Set general purpose retention register 2 + * + * @param val Value to be set in the register + * @note This register is not available in nrf51 MCU family + */ +__STATIC_INLINE void nrf_power_gpregret2_set(uint8_t val); + +/** + * @brief Get general purpose retention register 2 + * + * @return The value from the register + * @note This register is not available in all MCUs. + */ +__STATIC_INLINE uint8_t nrf_power_gpregret2_get(void); +#endif + +/** + * @brief Enable or disable DCDC converter + * + * @param enable Set true to enable or false to disable DCDC converter. + * + * @note + * If the device consist of high voltage power input (VDDH) this setting + * would relate to the converter on low voltage side (1.3 V output). + */ +__STATIC_INLINE void nrf_power_dcdcen_set(bool enable); + +/** + * @brief Get the state of DCDC converter + * + * @retval true Converter is enabled + * @retval false Converter is disabled + * + * @note + * If the device consist of high voltage power input (VDDH) this setting + * would relate to the converter on low voltage side (1.3 V output). + */ +__STATIC_INLINE bool nrf_power_dcdcen_get(void); + +#if NRF_POWER_HAS_RAMPOWER_REGS +/** + * @brief Turn ON sections in selected RAM block. + * + * This function turns ON sections in block and also block retention. + * + * @sa nrf_power_rampower_mask_t + * @sa nrf_power_rampower_mask_off + * + * @param block RAM block index. + * @param section_mask Mask of the sections created by merging + * @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE void nrf_power_rampower_mask_on(uint8_t block, uint32_t section_mask); + +/** + * @brief Turn ON sections in selected RAM block. + * + * This function turns OFF sections in block and also block retention. + * + * @sa nrf_power_rampower_mask_t + * @sa nrf_power_rampower_mask_off + * + * @param block RAM block index. + * @param section_mask Mask of the sections created by merging + * @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE void nrf_power_rampower_mask_off(uint8_t block, uint32_t section_mask); + +/** + * @brief Get the mask of ON and retention sections in selected RAM block. + * + * @param block RAM block index. + * @return Mask of sections state composed from @ref nrf_power_rampower_mask_t flags. + */ +__STATIC_INLINE uint32_t nrf_power_rampower_mask_get(uint8_t block); +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + +#if NRF_POWER_HAS_VDDH +/** + * @brief Enable of disable DCDC converter on VDDH + * + * @param enable Set true to enable or false to disable DCDC converter. + */ +__STATIC_INLINE void nrf_power_dcdcen_vddh_set(bool enable); + +/** + * @brief Get the state of DCDC converter on VDDH + * + * @retval true Converter is enabled + * @retval false Converter is disabled + */ +__STATIC_INLINE bool nrf_power_dcdcen_vddh_get(void); + +/** + * @brief Get main supply status + * + * @return Current main supply status + */ +__STATIC_INLINE nrf_power_mainregstatus_t nrf_power_mainregstatus_get(void); +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_USBREG +/** + * + * @return Get the whole USBREGSTATUS register + * + * @return The USBREGSTATUS register value. + * Use @ref nrf_power_usbregstatus_mask_t values for bit masking. + * + * @sa nrf_power_usbregstatus_vbusdet_get + * @sa nrf_power_usbregstatus_outrdy_get + */ +__STATIC_INLINE uint32_t nrf_power_usbregstatus_get(void); + +/** + * @brief VBUS input detection status + * + * USBDETECTED and USBREMOVED events are derived from this information + * + * @retval false VBUS voltage below valid threshold + * @retval true VBUS voltage above valid threshold + * + * @sa nrf_power_usbregstatus_get + */ +__STATIC_INLINE bool nrf_power_usbregstatus_vbusdet_get(void); + +/** + * @brief USB supply output settling time elapsed + * + * @retval false USBREG output settling time not elapsed + * @retval true USBREG output settling time elapsed + * (same information as USBPWRRDY event) + * + * @sa nrf_power_usbregstatus_get + */ +__STATIC_INLINE bool nrf_power_usbregstatus_outrdy_get(void); +#endif /* NRF_POWER_HAS_USBREG */ + +/** @} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t nrf_power_resetreas_get(void) +{ + return NRF_POWER->RESETREAS; +} + +__STATIC_INLINE void nrf_power_resetreas_clear(uint32_t mask) +{ + NRF_POWER->RESETREAS = mask; +} + +#if NRF_POWER_HAS_RAMSTATUS +__STATIC_INLINE uint32_t nrf_power_ramstatus_get(void) +{ + return NRF_POWER->RAMSTATUS; +} +#endif // NRF_POWER_HAS_RAMSTATUS + +__STATIC_INLINE void nrf_power_system_off(void) +{ + NRF_POWER->SYSTEMOFF = POWER_SYSTEMOFF_SYSTEMOFF_Enter; + __DSB(); + + /* Solution for simulated System OFF in debug mode */ + while (true) + { + __WFE(); + } +} + +__STATIC_INLINE void nrf_power_pofcon_set(bool enabled, nrf_power_pof_thr_t thr) +{ + ASSERT(thr == (thr & (POWER_POFCON_THRESHOLD_Msk >> POWER_POFCON_THRESHOLD_Pos))); +#if NRF_POWER_HAS_VDDH + uint32_t pofcon = NRF_POWER->POFCON; + pofcon &= ~(POWER_POFCON_THRESHOLD_Msk | POWER_POFCON_POF_Msk); + pofcon |= +#else /* NRF_POWER_HAS_VDDH */ + NRF_POWER->POFCON = +#endif + (((uint32_t)thr) << POWER_POFCON_THRESHOLD_Pos) | + (enabled ? + (POWER_POFCON_POF_Enabled << POWER_POFCON_POF_Pos) + : + (POWER_POFCON_POF_Disabled << POWER_POFCON_POF_Pos)); +#if NRF_POWER_HAS_VDDH + NRF_POWER->POFCON = pofcon; +#endif +} + +__STATIC_INLINE nrf_power_pof_thr_t nrf_power_pofcon_get(bool * p_enabled) +{ + uint32_t pofcon = NRF_POWER->POFCON; + if (NULL != p_enabled) + { + (*p_enabled) = ((pofcon & POWER_POFCON_POF_Msk) >> POWER_POFCON_POF_Pos) + == POWER_POFCON_POF_Enabled; + } + return (nrf_power_pof_thr_t)((pofcon & POWER_POFCON_THRESHOLD_Msk) >> + POWER_POFCON_THRESHOLD_Pos); +} + +#if NRF_POWER_HAS_VDDH +__STATIC_INLINE void nrf_power_pofcon_vddh_set(nrf_power_pof_thrvddh_t thr) +{ + ASSERT(thr == (thr & (POWER_POFCON_THRESHOLDVDDH_Msk >> POWER_POFCON_THRESHOLDVDDH_Pos))); + uint32_t pofcon = NRF_POWER->POFCON; + pofcon &= ~POWER_POFCON_THRESHOLDVDDH_Msk; + pofcon |= (((uint32_t)thr) << POWER_POFCON_THRESHOLDVDDH_Pos); + NRF_POWER->POFCON = pofcon; +} + +__STATIC_INLINE nrf_power_pof_thrvddh_t nrf_power_pofcon_vddh_get(void) +{ + return (nrf_power_pof_thrvddh_t)((NRF_POWER->POFCON & + POWER_POFCON_THRESHOLDVDDH_Msk) >> POWER_POFCON_THRESHOLDVDDH_Pos); +} +#endif /* NRF_POWER_HAS_VDDH */ + +__STATIC_INLINE void nrf_power_gpregret_set(uint8_t val) +{ + NRF_POWER->GPREGRET = val; +} + +__STATIC_INLINE uint8_t nrf_power_gpregret_get(void) +{ + return NRF_POWER->GPREGRET; +} + +#if defined(POWER_GPREGRET2_GPREGRET_Msk) || defined(__SDK_DOXYGEN__) +void nrf_power_gpregret2_set(uint8_t val) +{ + NRF_POWER->GPREGRET2 = val; +} + +__STATIC_INLINE uint8_t nrf_power_gpregret2_get(void) +{ + return NRF_POWER->GPREGRET2; +} +#endif + +__STATIC_INLINE void nrf_power_dcdcen_set(bool enable) +{ +#if NRF_POWER_HAS_VDDH + NRF_POWER->DCDCEN = (enable ? + POWER_DCDCEN_DCDCEN_Enabled : POWER_DCDCEN_DCDCEN_Disabled) << + POWER_DCDCEN_DCDCEN_Pos; +#else + NRF_POWER->DCDCEN = (enable ? + POWER_DCDCEN_DCDCEN_Enabled : POWER_DCDCEN_DCDCEN_Disabled) << + POWER_DCDCEN_DCDCEN_Pos; +#endif +} + +__STATIC_INLINE bool nrf_power_dcdcen_get(void) +{ +#if NRF_POWER_HAS_VDDH + return (NRF_POWER->DCDCEN & POWER_DCDCEN_DCDCEN_Msk) + == + (POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos); +#else + return (NRF_POWER->DCDCEN & POWER_DCDCEN_DCDCEN_Msk) + == + (POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos); +#endif +} + +#if NRF_POWER_HAS_RAMPOWER_REGS +__STATIC_INLINE void nrf_power_rampower_mask_on(uint8_t block, uint32_t section_mask) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + NRF_POWER->RAM[block].POWERSET = section_mask; +} + +__STATIC_INLINE void nrf_power_rampower_mask_off(uint8_t block, uint32_t section_mask) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + NRF_POWER->RAM[block].POWERCLR = section_mask; +} + +__STATIC_INLINE uint32_t nrf_power_rampower_mask_get(uint8_t block) +{ + ASSERT(block < ARRAY_SIZE(NRF_POWER->RAM)); + return NRF_POWER->RAM[block].POWER; +} +#endif /* NRF_POWER_HAS_RAMPOWER_REGS */ + +#if NRF_POWER_HAS_VDDH +__STATIC_INLINE void nrf_power_dcdcen_vddh_set(bool enable) +{ + NRF_POWER->DCDCEN0 = (enable ? + POWER_DCDCEN0_DCDCEN_Enabled : POWER_DCDCEN0_DCDCEN_Disabled) << + POWER_DCDCEN0_DCDCEN_Pos; +} + +bool nrf_power_dcdcen_vddh_get(void) +{ + return (NRF_POWER->DCDCEN0 & POWER_DCDCEN0_DCDCEN_Msk) + == + (POWER_DCDCEN0_DCDCEN_Enabled << POWER_DCDCEN0_DCDCEN_Pos); +} + +nrf_power_mainregstatus_t nrf_power_mainregstatus_get(void) +{ + return (nrf_power_mainregstatus_t)(((NRF_POWER->MAINREGSTATUS) & + POWER_MAINREGSTATUS_MAINREGSTATUS_Msk) >> + POWER_MAINREGSTATUS_MAINREGSTATUS_Pos); +} +#endif /* NRF_POWER_HAS_VDDH */ + +#if NRF_POWER_HAS_USBREG +__STATIC_INLINE uint32_t nrf_power_usbregstatus_get(void) +{ + return NRF_POWER->USBREGSTATUS; +} + +__STATIC_INLINE bool nrf_power_usbregstatus_vbusdet_get(void) +{ + return (nrf_power_usbregstatus_get() & + NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK) != 0; +} + +__STATIC_INLINE bool nrf_power_usbregstatus_outrdy_get(void) +{ + return (nrf_power_usbregstatus_get() & + NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK) != 0; +} +#endif /* NRF_POWER_HAS_USBREG */ + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_POWER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ppi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ppi.h new file mode 100644 index 0000000000..945fedc2d8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_ppi.h @@ -0,0 +1,439 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_PPI_H__ +#define NRF_PPI_H__ + +#include +#include "nrf.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_ppi_hal PPI HAL + * @{ + * @ingroup nrf_ppi + * @brief Hardware access layer for setting up Programmable Peripheral Interconnect (PPI) channels. + */ + +#define NRF_PPI_TASK_SET (1UL) + +/** + * @enum nrf_ppi_channel_t + * @brief PPI channels. + */ +typedef enum +{ + NRF_PPI_CHANNEL0 = PPI_CHEN_CH0_Pos, /**< Channel 0. */ + NRF_PPI_CHANNEL1 = PPI_CHEN_CH1_Pos, /**< Channel 1. */ + NRF_PPI_CHANNEL2 = PPI_CHEN_CH2_Pos, /**< Channel 2. */ + NRF_PPI_CHANNEL3 = PPI_CHEN_CH3_Pos, /**< Channel 3. */ + NRF_PPI_CHANNEL4 = PPI_CHEN_CH4_Pos, /**< Channel 4. */ + NRF_PPI_CHANNEL5 = PPI_CHEN_CH5_Pos, /**< Channel 5. */ + NRF_PPI_CHANNEL6 = PPI_CHEN_CH6_Pos, /**< Channel 6. */ + NRF_PPI_CHANNEL7 = PPI_CHEN_CH7_Pos, /**< Channel 7. */ + NRF_PPI_CHANNEL8 = PPI_CHEN_CH8_Pos, /**< Channel 8. */ + NRF_PPI_CHANNEL9 = PPI_CHEN_CH9_Pos, /**< Channel 9. */ + NRF_PPI_CHANNEL10 = PPI_CHEN_CH10_Pos, /**< Channel 10. */ + NRF_PPI_CHANNEL11 = PPI_CHEN_CH11_Pos, /**< Channel 11. */ + NRF_PPI_CHANNEL12 = PPI_CHEN_CH12_Pos, /**< Channel 12. */ + NRF_PPI_CHANNEL13 = PPI_CHEN_CH13_Pos, /**< Channel 13. */ + NRF_PPI_CHANNEL14 = PPI_CHEN_CH14_Pos, /**< Channel 14. */ + NRF_PPI_CHANNEL15 = PPI_CHEN_CH15_Pos, /**< Channel 15. */ +#if (PPI_CH_NUM > 16) || defined(__SDK_DOXYGEN__) + NRF_PPI_CHANNEL16 = PPI_CHEN_CH16_Pos, /**< Channel 16. */ + NRF_PPI_CHANNEL17 = PPI_CHEN_CH17_Pos, /**< Channel 17. */ + NRF_PPI_CHANNEL18 = PPI_CHEN_CH18_Pos, /**< Channel 18. */ + NRF_PPI_CHANNEL19 = PPI_CHEN_CH19_Pos, /**< Channel 19. */ +#endif + NRF_PPI_CHANNEL20 = PPI_CHEN_CH20_Pos, /**< Channel 20. */ + NRF_PPI_CHANNEL21 = PPI_CHEN_CH21_Pos, /**< Channel 21. */ + NRF_PPI_CHANNEL22 = PPI_CHEN_CH22_Pos, /**< Channel 22. */ + NRF_PPI_CHANNEL23 = PPI_CHEN_CH23_Pos, /**< Channel 23. */ + NRF_PPI_CHANNEL24 = PPI_CHEN_CH24_Pos, /**< Channel 24. */ + NRF_PPI_CHANNEL25 = PPI_CHEN_CH25_Pos, /**< Channel 25. */ + NRF_PPI_CHANNEL26 = PPI_CHEN_CH26_Pos, /**< Channel 26. */ + NRF_PPI_CHANNEL27 = PPI_CHEN_CH27_Pos, /**< Channel 27. */ + NRF_PPI_CHANNEL28 = PPI_CHEN_CH28_Pos, /**< Channel 28. */ + NRF_PPI_CHANNEL29 = PPI_CHEN_CH29_Pos, /**< Channel 29. */ + NRF_PPI_CHANNEL30 = PPI_CHEN_CH30_Pos, /**< Channel 30. */ + NRF_PPI_CHANNEL31 = PPI_CHEN_CH31_Pos /**< Channel 31. */ +} nrf_ppi_channel_t; + +/** + * @enum nrf_ppi_channel_group_t + * @brief PPI channel groups. + */ +typedef enum +{ + NRF_PPI_CHANNEL_GROUP0 = 0, /**< Channel group 0. */ + NRF_PPI_CHANNEL_GROUP1 = 1, /**< Channel group 1. */ + NRF_PPI_CHANNEL_GROUP2 = 2, /**< Channel group 2. */ + NRF_PPI_CHANNEL_GROUP3 = 3, /**< Channel group 3. */ +#if (PPI_GROUP_NUM > 4) || defined(__SDK_DOXYGEN__) + NRF_PPI_CHANNEL_GROUP4 = 4, /**< Channel group 4. */ + NRF_PPI_CHANNEL_GROUP5 = 5 /**< Channel group 5. */ +#endif +} nrf_ppi_channel_group_t; + +/** + * @enum nrf_ppi_channel_include_t + * @brief Definition of which PPI channels belong to a group. + */ +typedef enum +{ + NRF_PPI_CHANNEL_EXCLUDE = PPI_CHG_CH0_Excluded, /**< Channel excluded from a group. */ + NRF_PPI_CHANNEL_INCLUDE = PPI_CHG_CH0_Included /**< Channel included in a group. */ +} nrf_ppi_channel_include_t; + +/** + * @enum nrf_ppi_channel_enable_t + * @brief Definition if a PPI channel is enabled. + */ +typedef enum +{ + NRF_PPI_CHANNEL_DISABLED = PPI_CHEN_CH0_Disabled, /**< Channel disabled. */ + NRF_PPI_CHANNEL_ENABLED = PPI_CHEN_CH0_Enabled /**< Channel enabled. */ +} nrf_ppi_channel_enable_t; + +/** + * @enum nrf_ppi_task_t + * @brief PPI tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_PPI_TASK_CHG0_EN = offsetof(NRF_PPI_Type, TASKS_CHG[0].EN), /**< Task for enabling channel group 0 */ + NRF_PPI_TASK_CHG0_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[0].DIS), /**< Task for disabling channel group 0 */ + NRF_PPI_TASK_CHG1_EN = offsetof(NRF_PPI_Type, TASKS_CHG[1].EN), /**< Task for enabling channel group 1 */ + NRF_PPI_TASK_CHG1_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[1].DIS), /**< Task for disabling channel group 1 */ + NRF_PPI_TASK_CHG2_EN = offsetof(NRF_PPI_Type, TASKS_CHG[2].EN), /**< Task for enabling channel group 2 */ + NRF_PPI_TASK_CHG2_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[2].DIS), /**< Task for disabling channel group 2 */ + NRF_PPI_TASK_CHG3_EN = offsetof(NRF_PPI_Type, TASKS_CHG[3].EN), /**< Task for enabling channel group 3 */ + NRF_PPI_TASK_CHG3_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[3].DIS), /**< Task for disabling channel group 3 */ +#if (PPI_GROUP_NUM > 4) || defined(__SDK_DOXYGEN__) + NRF_PPI_TASK_CHG4_EN = offsetof(NRF_PPI_Type, TASKS_CHG[4].EN), /**< Task for enabling channel group 4 */ + NRF_PPI_TASK_CHG4_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[4].DIS), /**< Task for disabling channel group 4 */ + NRF_PPI_TASK_CHG5_EN = offsetof(NRF_PPI_Type, TASKS_CHG[5].EN), /**< Task for enabling channel group 5 */ + NRF_PPI_TASK_CHG5_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[5].DIS) /**< Task for disabling channel group 5 */ +#endif + /*lint -restore*/ +} nrf_ppi_task_t; + +/** + * @brief Function for enabling a given PPI channel. + * + * @details This function enables only one channel. + * + * @param[in] channel Channel to enable. + * + * */ +__STATIC_INLINE void nrf_ppi_channel_enable(nrf_ppi_channel_t channel) +{ + NRF_PPI->CHENSET = PPI_CHENSET_CH0_Set << ((uint32_t) channel); +} + + +/** + * @brief Function for disabling a given PPI channel. + * + * @details This function disables only one channel. + * + * @param[in] channel Channel to disable. + */ +__STATIC_INLINE void nrf_ppi_channel_disable(nrf_ppi_channel_t channel) +{ + NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Clear << ((uint32_t) channel); +} + + +/** + * @brief Function for checking if a given PPI channel is enabled. + * + * @details This function checks only one channel. + * + * @param[in] channel Channel to check. + * + * @retval NRF_PPI_CHANNEL_ENABLED If the channel is enabled. + * @retval NRF_PPI_CHANNEL_DISABLED If the channel is not enabled. + * + */ +__STATIC_INLINE nrf_ppi_channel_enable_t nrf_ppi_channel_enable_get(nrf_ppi_channel_t channel) +{ + if (NRF_PPI->CHEN & (PPI_CHEN_CH0_Msk << ((uint32_t) channel))) + { + return NRF_PPI_CHANNEL_ENABLED; + } + else + { + return NRF_PPI_CHANNEL_DISABLED; + } +} + + +/** + * @brief Function for disabling all PPI channels. + */ +__STATIC_INLINE void nrf_ppi_channel_disable_all(void) +{ + NRF_PPI->CHENCLR = ((uint32_t)0xFFFFFFFFuL); +} + +/** + * @brief Function for disabling multiple PPI channels. + * + * @param[in] mask Channel mask. + */ +__STATIC_INLINE void nrf_ppi_channels_disable(uint32_t mask) +{ + NRF_PPI->CHENCLR = mask; +} + +/** + * @brief Function for setting up event and task endpoints for a given PPI channel. + * + * @param[in] eep Event register address. + * + * @param[in] tep Task register address. + * + * @param[in] channel Channel to which the given endpoints are assigned. + */ +__STATIC_INLINE void nrf_ppi_channel_endpoint_setup(nrf_ppi_channel_t channel, + uint32_t eep, + uint32_t tep) +{ + NRF_PPI->CH[(uint32_t) channel].EEP = eep; + NRF_PPI->CH[(uint32_t) channel].TEP = tep; +} + +#if defined(PPI_FEATURE_FORKS_PRESENT) || defined(__SDK_DOXYGEN__) +/** + * @brief Function for setting up task endpoint for a given PPI fork. + * + * @param[in] fork_tep Task register address. + * + * @param[in] channel Channel to which the given fork endpoint is assigned. + */ +__STATIC_INLINE void nrf_ppi_fork_endpoint_setup(nrf_ppi_channel_t channel, + uint32_t fork_tep) +{ + NRF_PPI->FORK[(uint32_t) channel].TEP = fork_tep; +} + +/** + * @brief Function for setting up event and task endpoints for a given PPI channel and fork. + * + * @param[in] eep Event register address. + * + * @param[in] tep Task register address. + * + * @param[in] fork_tep Fork task register address (register value). + * + * @param[in] channel Channel to which the given endpoints are assigned. + */ +__STATIC_INLINE void nrf_ppi_channel_and_fork_endpoint_setup(nrf_ppi_channel_t channel, + uint32_t eep, + uint32_t tep, + uint32_t fork_tep) +{ + nrf_ppi_channel_endpoint_setup(channel, eep, tep); + nrf_ppi_fork_endpoint_setup(channel, fork_tep); +} +#endif + +/** + * @brief Function for including a PPI channel in a channel group. + * + * @details This function adds only one channel to the group. + * + * @param[in] channel Channel to be included in the group. + * + * @param[in] channel_group Channel group. + * + */ +__STATIC_INLINE void nrf_ppi_channel_include_in_group(nrf_ppi_channel_t channel, + nrf_ppi_channel_group_t channel_group) +{ + NRF_PPI->CHG[(uint32_t) channel_group] = + NRF_PPI->CHG[(uint32_t) channel_group] | (PPI_CHG_CH0_Included << ((uint32_t) channel)); +} + +/** + * @brief Function for including multiple PPI channels in a channel group. + * + * @details This function adds all specified channels to the group. + * + * @param[in] channel_mask Channels to be included in the group. + * + * @param[in] channel_group Channel group. + * + */ +__STATIC_INLINE void nrf_ppi_channels_include_in_group(uint32_t channel_mask, + nrf_ppi_channel_group_t channel_group) +{ + NRF_PPI->CHG[(uint32_t) channel_group] = + NRF_PPI->CHG[(uint32_t) channel_group] | (channel_mask); +} + + +/** + * @brief Function for removing a PPI channel from a channel group. + * + * @details This function removes only one channel from the group. + * + * @param[in] channel Channel to be removed from the group. + * + * @param[in] channel_group Channel group. + */ +__STATIC_INLINE void nrf_ppi_channel_remove_from_group(nrf_ppi_channel_t channel, + nrf_ppi_channel_group_t channel_group) +{ + NRF_PPI->CHG[(uint32_t) channel_group] = + NRF_PPI->CHG[(uint32_t) channel_group] & ~(PPI_CHG_CH0_Included << ((uint32_t) channel)); +} + +/** + * @brief Function for removing multiple PPI channels from a channel group. + * + * @details This function removes all specified channels from the group. + * + * @param[in] channel_mask Channels to be removed from the group. + * + * @param[in] channel_group Channel group. + */ +__STATIC_INLINE void nrf_ppi_channels_remove_from_group(uint32_t channel_mask, + nrf_ppi_channel_group_t channel_group) +{ + NRF_PPI->CHG[(uint32_t) channel_group] = + NRF_PPI->CHG[(uint32_t) channel_group] & ~(channel_mask); +} + + +/** + * @brief Function for removing all PPI channels from a channel group. + * + * @param[in] group Channel group. + * + */ +__STATIC_INLINE void nrf_ppi_channel_group_clear(nrf_ppi_channel_group_t group) +{ + NRF_PPI->CHG[(uint32_t) group] = 0; +} + + +/** + * @brief Function for enabling a channel group. + * + * @param[in] group Channel group. + * + */ +__STATIC_INLINE void nrf_ppi_group_enable(nrf_ppi_channel_group_t group) +{ + NRF_PPI->TASKS_CHG[(uint32_t) group].EN = NRF_PPI_TASK_SET; +} + + +/** + * @brief Function for disabling a channel group. + * + * @param[in] group Channel group. + * + */ +__STATIC_INLINE void nrf_ppi_group_disable(nrf_ppi_channel_group_t group) +{ + NRF_PPI->TASKS_CHG[(uint32_t) group].DIS = NRF_PPI_TASK_SET; +} + + +/** + * @brief Function for setting a PPI task. + * + * @param[in] ppi_task PPI task to set. + */ +__STATIC_INLINE void nrf_ppi_task_trigger(nrf_ppi_task_t ppi_task) +{ + *((volatile uint32_t *) ((uint8_t *) NRF_PPI_BASE + (uint32_t) ppi_task)) = NRF_PPI_TASK_SET; +} + + +/** + * @brief Function for returning the address of a specific PPI task register. + * + * @param[in] ppi_task PPI task. + */ +__STATIC_INLINE uint32_t * nrf_ppi_task_address_get(nrf_ppi_task_t ppi_task) +{ + return (uint32_t *) ((uint8_t *) NRF_PPI_BASE + (uint32_t) ppi_task); +} + +/** + * @brief Function for returning the PPI enable task address of a specific group. + * + * @param[in] group PPI group. + */ +__STATIC_INLINE uint32_t * nrf_ppi_task_group_enable_address_get(nrf_ppi_channel_group_t group) +{ + return (uint32_t *) &NRF_PPI->TASKS_CHG[(uint32_t) group].EN; +} + +/** + * @brief Function for returning the PPI disable task address of a specific group. + * + * @param[in] group PPI group. + */ +__STATIC_INLINE uint32_t * nrf_ppi_task_group_disable_address_get(nrf_ppi_channel_group_t group) +{ + return (uint32_t *) &NRF_PPI->TASKS_CHG[(uint32_t) group].DIS; +} + + +/** + *@} + **/ + +/*lint --flb "Leave library region" */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_PPI_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pwm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pwm.h new file mode 100644 index 0000000000..710f307e27 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_pwm.h @@ -0,0 +1,701 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_pwm_hal PWM HAL + * @{ + * @ingroup nrf_pwm + * + * @brief @tagAPI52 Hardware access layer for managing the Pulse Width Modulation (PWM) + * peripheral. + */ + +#ifndef NRF_PWM_H__ +#define NRF_PWM_H__ + +#include +#include +#include + +#include "nrf.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be provided as a parameter for the @ref nrf_pwm_pins_set + * function call to specify that a given output channel shall not be + * connected to a physical pin. + */ +#define NRF_PWM_PIN_NOT_CONNECTED 0xFFFFFFFF + +/** + * @brief Number of channels in each Pointer to the peripheral registers structure. + */ +#define NRF_PWM_CHANNEL_COUNT 4 + + +/** + * @brief PWM tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_PWM_TASK_STOP = offsetof(NRF_PWM_Type, TASKS_STOP), ///< Stops PWM pulse generation on all channels at the end of the current PWM period, and stops the sequence playback. + NRF_PWM_TASK_SEQSTART0 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[0]), ///< Starts playback of sequence 0. + NRF_PWM_TASK_SEQSTART1 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[1]), ///< Starts playback of sequence 1. + NRF_PWM_TASK_NEXTSTEP = offsetof(NRF_PWM_Type, TASKS_NEXTSTEP) ///< Steps by one value in the current sequence if the decoder is set to @ref NRF_PWM_STEP_TRIGGERED mode. + /*lint -restore*/ +} nrf_pwm_task_t; + +/** + * @brief PWM events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_PWM_EVENT_STOPPED = offsetof(NRF_PWM_Type, EVENTS_STOPPED), ///< Response to STOP task, emitted when PWM pulses are no longer generated. + NRF_PWM_EVENT_SEQSTARTED0 = offsetof(NRF_PWM_Type, EVENTS_SEQSTARTED[0]), ///< First PWM period started on sequence 0. + NRF_PWM_EVENT_SEQSTARTED1 = offsetof(NRF_PWM_Type, EVENTS_SEQSTARTED[1]), ///< First PWM period started on sequence 1. + NRF_PWM_EVENT_SEQEND0 = offsetof(NRF_PWM_Type, EVENTS_SEQEND[0]), ///< Emitted at the end of every sequence 0 when its last value has been read from RAM. + NRF_PWM_EVENT_SEQEND1 = offsetof(NRF_PWM_Type, EVENTS_SEQEND[1]), ///< Emitted at the end of every sequence 1 when its last value has been read from RAM. + NRF_PWM_EVENT_PWMPERIODEND = offsetof(NRF_PWM_Type, EVENTS_PWMPERIODEND), ///< Emitted at the end of each PWM period. + NRF_PWM_EVENT_LOOPSDONE = offsetof(NRF_PWM_Type, EVENTS_LOOPSDONE) ///< Concatenated sequences have been played the requested number of times. + /*lint -restore*/ +} nrf_pwm_event_t; + +/** + * @brief PWM interrupts. + */ +typedef enum +{ + NRF_PWM_INT_STOPPED_MASK = PWM_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event. + NRF_PWM_INT_SEQSTARTED0_MASK = PWM_INTENSET_SEQSTARTED0_Msk, ///< Interrupt on SEQSTARTED[0] event. + NRF_PWM_INT_SEQSTARTED1_MASK = PWM_INTENSET_SEQSTARTED1_Msk, ///< Interrupt on SEQSTARTED[1] event. + NRF_PWM_INT_SEQEND0_MASK = PWM_INTENSET_SEQEND0_Msk, ///< Interrupt on SEQEND[0] event. + NRF_PWM_INT_SEQEND1_MASK = PWM_INTENSET_SEQEND1_Msk, ///< Interrupt on SEQEND[1] event. + NRF_PWM_INT_PWMPERIODEND_MASK = PWM_INTENSET_PWMPERIODEND_Msk, ///< Interrupt on PWMPERIODEND event. + NRF_PWM_INT_LOOPSDONE_MASK = PWM_INTENSET_LOOPSDONE_Msk ///< Interrupt on LOOPSDONE event. +} nrf_pwm_int_mask_t; + +/** + * @brief PWM shortcuts. + */ +typedef enum +{ + NRF_PWM_SHORT_SEQEND0_STOP_MASK = PWM_SHORTS_SEQEND0_STOP_Msk, ///< Shortcut between SEQEND[0] event and STOP task. + NRF_PWM_SHORT_SEQEND1_STOP_MASK = PWM_SHORTS_SEQEND1_STOP_Msk, ///< Shortcut between SEQEND[1] event and STOP task. + NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK = PWM_SHORTS_LOOPSDONE_SEQSTART0_Msk, ///< Shortcut between LOOPSDONE event and SEQSTART[0] task. + NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK = PWM_SHORTS_LOOPSDONE_SEQSTART1_Msk, ///< Shortcut between LOOPSDONE event and SEQSTART[1] task. + NRF_PWM_SHORT_LOOPSDONE_STOP_MASK = PWM_SHORTS_LOOPSDONE_STOP_Msk ///< Shortcut between LOOPSDONE event and STOP task. +} nrf_pwm_short_mask_t; + +/** + * @brief PWM modes of operation. + */ +typedef enum +{ + NRF_PWM_MODE_UP = PWM_MODE_UPDOWN_Up, ///< Up counter (edge-aligned PWM duty cycle). + NRF_PWM_MODE_UP_AND_DOWN = PWM_MODE_UPDOWN_UpAndDown, ///< Up and down counter (center-aligned PWM duty cycle). +} nrf_pwm_mode_t; + +/** + * @brief PWM base clock frequencies. + */ +typedef enum +{ + NRF_PWM_CLK_16MHz = PWM_PRESCALER_PRESCALER_DIV_1, ///< 16 MHz / 1 = 16 MHz. + NRF_PWM_CLK_8MHz = PWM_PRESCALER_PRESCALER_DIV_2, ///< 16 MHz / 2 = 8 MHz. + NRF_PWM_CLK_4MHz = PWM_PRESCALER_PRESCALER_DIV_4, ///< 16 MHz / 4 = 4 MHz. + NRF_PWM_CLK_2MHz = PWM_PRESCALER_PRESCALER_DIV_8, ///< 16 MHz / 8 = 2 MHz. + NRF_PWM_CLK_1MHz = PWM_PRESCALER_PRESCALER_DIV_16, ///< 16 MHz / 16 = 1 MHz. + NRF_PWM_CLK_500kHz = PWM_PRESCALER_PRESCALER_DIV_32, ///< 16 MHz / 32 = 500 kHz. + NRF_PWM_CLK_250kHz = PWM_PRESCALER_PRESCALER_DIV_64, ///< 16 MHz / 64 = 250 kHz. + NRF_PWM_CLK_125kHz = PWM_PRESCALER_PRESCALER_DIV_128 ///< 16 MHz / 128 = 125 kHz. +} nrf_pwm_clk_t; + +/** + * @brief PWM decoder load modes. + * + * The selected mode determines how the sequence data is read from RAM and + * spread to the compare registers. + */ +typedef enum +{ + NRF_PWM_LOAD_COMMON = PWM_DECODER_LOAD_Common, ///< 1st half word (16-bit) used in all PWM channels (0-3). + NRF_PWM_LOAD_GROUPED = PWM_DECODER_LOAD_Grouped, ///< 1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3. + NRF_PWM_LOAD_INDIVIDUAL = PWM_DECODER_LOAD_Individual, ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; 3rd in channel 2; 4th in channel 3. + NRF_PWM_LOAD_WAVE_FORM = PWM_DECODER_LOAD_WaveForm ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; ... ; 4th as the top value for the pulse generator counter. +} nrf_pwm_dec_load_t; + +/** + * @brief PWM decoder next step modes. + * + * The selected mode determines when the next value from the active sequence + * is loaded. + */ +typedef enum +{ + NRF_PWM_STEP_AUTO = PWM_DECODER_MODE_RefreshCount, ///< Automatically after the current value is played and repeated the requested number of times. + NRF_PWM_STEP_TRIGGERED = PWM_DECODER_MODE_NextStep ///< When the @ref NRF_PWM_TASK_NEXTSTEP task is triggered. +} nrf_pwm_dec_step_t; + + +/** + * @brief Type used for defining duty cycle values for a sequence + * loaded in @ref NRF_PWM_LOAD_COMMON mode. + */ +typedef uint16_t nrf_pwm_values_common_t; + +/** + * @brief Structure for defining duty cycle values for a sequence + * loaded in @ref NRF_PWM_LOAD_GROUPED mode. + */ +typedef struct { + uint16_t group_0; ///< Duty cycle value for group 0 (channels 0 and 1). + uint16_t group_1; ///< Duty cycle value for group 1 (channels 2 and 3). +} nrf_pwm_values_grouped_t; + +/** + * @brief Structure for defining duty cycle values for a sequence + * loaded in @ref NRF_PWM_LOAD_INDIVIDUAL mode. + */ +typedef struct +{ + uint16_t channel_0; ///< Duty cycle value for channel 0. + uint16_t channel_1; ///< Duty cycle value for channel 1. + uint16_t channel_2; ///< Duty cycle value for channel 2. + uint16_t channel_3; ///< Duty cycle value for channel 3. +} nrf_pwm_values_individual_t; + +/** + * @brief Structure for defining duty cycle values for a sequence + * loaded in @ref NRF_PWM_LOAD_WAVE_FORM mode. + */ +typedef struct { + uint16_t channel_0; ///< Duty cycle value for channel 0. + uint16_t channel_1; ///< Duty cycle value for channel 1. + uint16_t channel_2; ///< Duty cycle value for channel 2. + uint16_t counter_top; ///< Top value for the pulse generator counter. +} nrf_pwm_values_wave_form_t; + +/** + * @brief Union grouping pointers to arrays of duty cycle values applicable to + * various loading modes. + */ +typedef union { + nrf_pwm_values_common_t const * p_common; ///< Pointer to be used in @ref NRF_PWM_LOAD_COMMON mode. + nrf_pwm_values_grouped_t const * p_grouped; ///< Pointer to be used in @ref NRF_PWM_LOAD_GROUPED mode. + nrf_pwm_values_individual_t const * p_individual; ///< Pointer to be used in @ref NRF_PWM_LOAD_INDIVIDUAL mode. + nrf_pwm_values_wave_form_t const * p_wave_form; ///< Pointer to be used in @ref NRF_PWM_LOAD_WAVE_FORM mode. + uint16_t const * p_raw; ///< Pointer providing raw access to the values. +} nrf_pwm_values_t; + +/** + * @brief Structure for defining a sequence of PWM duty cycles. + * + * When the sequence is set (by a call to @ref nrf_pwm_sequence_set), the + * provided duty cycle values are not copied. The @p values pointer is stored + * in the peripheral's internal register, and the values are loaded from RAM + * during the sequence playback. Therefore, you must ensure that the values + * do not change before and during the sequence playback (for example, + * the values cannot be placed in a local variable that is allocated on stack). + * If the sequence is played in a loop and the values should be updated + * before the next iteration, it is safe to modify them when the corresponding + * event signaling the end of sequence occurs (@ref NRF_PWM_EVENT_SEQEND0 + * or @ref NRF_PWM_EVENT_SEQEND1, respectively). + * + * @note The @p repeats and @p end_delay values (which are written to the + * SEQ[n].REFRESH and SEQ[n].ENDDELAY registers in the peripheral, + * respectively) are ignored at the end of a complex sequence + * playback, indicated by the LOOPSDONE event. + * See the @linkProductSpecification52 for more information. + */ +typedef struct +{ + nrf_pwm_values_t values; ///< Pointer to an array with duty cycle values. This array must be in Data RAM. + /**< This field is defined as an union of pointers + * to provide a convenient way to define duty + * cycle values in various loading modes + * (see @ref nrf_pwm_dec_load_t). + * In each value, the most significant bit (15) + * determines the polarity of the output and the + * others (14-0) compose the 15-bit value to be + * compared with the pulse generator counter. */ + uint16_t length; ///< Number of 16-bit values in the array pointed by @p values. + uint32_t repeats; ///< Number of times that each duty cycle should be repeated (after being played once). Ignored in @ref NRF_PWM_STEP_TRIGGERED mode. + uint32_t end_delay; ///< Additional time (in PWM periods) that the last duty cycle is to be kept after the sequence is played. Ignored in @ref NRF_PWM_STEP_TRIGGERED mode. +} nrf_pwm_sequence_t; + +/** + * @brief Helper macro for calculating the number of 16-bit values in specified + * array of duty cycle values. + */ +#define NRF_PWM_VALUES_LENGTH(array) (sizeof(array) / sizeof(uint16_t)) + + +/** + * @brief Function for activating a specific PWM task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_pwm_task_trigger(NRF_PWM_Type * p_reg, + nrf_pwm_task_t task); + +/** + * @brief Function for getting the address of a specific PWM task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t nrf_pwm_task_address_get(NRF_PWM_Type const * p_reg, + nrf_pwm_task_t task); + +/** + * @brief Function for clearing a specific PWM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_pwm_event_clear(NRF_PWM_Type * p_reg, + nrf_pwm_event_t event); + +/** + * @brief Function for checking the state of a specific PWM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_pwm_event_check(NRF_PWM_Type const * p_reg, + nrf_pwm_event_t event); + +/** + * @brief Function for getting the address of a specific PWM event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t nrf_pwm_event_address_get(NRF_PWM_Type const * p_reg, + nrf_pwm_event_t event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_pwm_shorts_enable(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_pwm_shorts_disable(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask); + +/** + * @brief Function for setting the configuration of PWM shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_shorts_mask Shortcuts configuration to set. + */ +__STATIC_INLINE void nrf_pwm_shorts_set(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_pwm_int_enable(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_pwm_int_disable(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask); + +/** + * @brief Function for setting the configuration of PWM interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_int_mask Interrupts configuration to set. + */ +__STATIC_INLINE void nrf_pwm_int_set(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] pwm_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_pwm_int_enable_check(NRF_PWM_Type const * p_reg, + nrf_pwm_int_mask_t pwm_int); + +/** + * @brief Function for enabling the PWM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_pwm_enable(NRF_PWM_Type * p_reg); + +/** + * @brief Function for disabling the PWM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_pwm_disable(NRF_PWM_Type * p_reg); + +/** + * @brief Function for assigning pins to PWM output channels. + * + * Usage of all PWM output channels is optional. If a given channel is not + * needed, pass the @ref NRF_PWM_PIN_NOT_CONNECTED value instead of its pin + * number. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] out_pins Array with pin numbers for individual PWM output channels. + */ +__STATIC_INLINE void nrf_pwm_pins_set(NRF_PWM_Type * p_reg, + uint32_t out_pins[NRF_PWM_CHANNEL_COUNT]); + +/** + * @brief Function for configuring the PWM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] base_clock Base clock frequency. + * @param[in] mode Operating mode of the pulse generator counter. + * @param[in] top_value Value up to which the pulse generator counter counts. + */ +__STATIC_INLINE void nrf_pwm_configure(NRF_PWM_Type * p_reg, + nrf_pwm_clk_t base_clock, + nrf_pwm_mode_t mode, + uint16_t top_value); + +/** + * @brief Function for defining a sequence of PWM duty cycles. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] p_seq Pointer to the sequence definition. + */ +__STATIC_INLINE void nrf_pwm_sequence_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + nrf_pwm_sequence_t const * p_seq); + +/** + * @brief Function for modifying the pointer to the duty cycle values + * in the specified sequence. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] p_values Pointer to an array with duty cycle values. + */ +__STATIC_INLINE void nrf_pwm_seq_ptr_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint16_t const * p_values); + +/** + * @brief Function for modifying the total number of duty cycle values + * in the specified sequence. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] length Number of duty cycle values. + */ +__STATIC_INLINE void nrf_pwm_seq_cnt_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint16_t length); + +/** + * @brief Function for modifying the additional number of PWM periods spent + * on each duty cycle value in the specified sequence. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] refresh Number of additional PWM periods for each duty cycle value. + */ +__STATIC_INLINE void nrf_pwm_seq_refresh_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint32_t refresh); + +/** + * @brief Function for modifying the additional time added after the sequence + * is played. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] end_delay Number of PWM periods added at the end of the sequence. + */ +__STATIC_INLINE void nrf_pwm_seq_end_delay_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint32_t end_delay); + +/** + * @brief Function for setting the mode of loading sequence data from RAM + * and advancing the sequence. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] dec_load Mode of loading sequence data from RAM. + * @param[in] dec_step Mode of advancing the active sequence. + */ +__STATIC_INLINE void nrf_pwm_decoder_set(NRF_PWM_Type * p_reg, + nrf_pwm_dec_load_t dec_load, + nrf_pwm_dec_step_t dec_step); + +/** + * @brief Function for setting the number of times the sequence playback + * should be performed. + * + * This function applies to two-sequence playback (concatenated sequence 0 and 1). + * A single sequence can be played back only once. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] loop_count Number of times to perform the sequence playback. + */ +__STATIC_INLINE void nrf_pwm_loop_set(NRF_PWM_Type * p_reg, + uint16_t loop_count); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_pwm_task_trigger(NRF_PWM_Type * p_reg, + nrf_pwm_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_pwm_task_address_get(NRF_PWM_Type const * p_reg, + nrf_pwm_task_t task) +{ + return ((uint32_t)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_pwm_event_clear(NRF_PWM_Type * p_reg, + nrf_pwm_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_pwm_event_check(NRF_PWM_Type const * p_reg, + nrf_pwm_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t nrf_pwm_event_address_get(NRF_PWM_Type const * p_reg, + nrf_pwm_event_t event) +{ + return ((uint32_t)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_pwm_shorts_enable(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask) +{ + p_reg->SHORTS |= pwm_shorts_mask; +} + +__STATIC_INLINE void nrf_pwm_shorts_disable(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask) +{ + p_reg->SHORTS &= ~(pwm_shorts_mask); +} + +__STATIC_INLINE void nrf_pwm_shorts_set(NRF_PWM_Type * p_reg, + uint32_t pwm_shorts_mask) +{ + p_reg->SHORTS = pwm_shorts_mask; +} + +__STATIC_INLINE void nrf_pwm_int_enable(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask) +{ + p_reg->INTENSET = pwm_int_mask; +} + +__STATIC_INLINE void nrf_pwm_int_disable(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask) +{ + p_reg->INTENCLR = pwm_int_mask; +} + +__STATIC_INLINE void nrf_pwm_int_set(NRF_PWM_Type * p_reg, + uint32_t pwm_int_mask) +{ + p_reg->INTEN = pwm_int_mask; +} + +__STATIC_INLINE bool nrf_pwm_int_enable_check(NRF_PWM_Type const * p_reg, + nrf_pwm_int_mask_t pwm_int) +{ + return (bool)(p_reg->INTENSET & pwm_int); +} + +__STATIC_INLINE void nrf_pwm_enable(NRF_PWM_Type * p_reg) +{ + p_reg->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_pwm_disable(NRF_PWM_Type * p_reg) +{ + p_reg->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_pwm_pins_set(NRF_PWM_Type * p_reg, + uint32_t out_pins[NRF_PWM_CHANNEL_COUNT]) +{ + uint8_t i; + for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i) + { + p_reg->PSEL.OUT[i] = out_pins[i]; + } +} + +__STATIC_INLINE void nrf_pwm_configure(NRF_PWM_Type * p_reg, + nrf_pwm_clk_t base_clock, + nrf_pwm_mode_t mode, + uint16_t top_value) +{ + ASSERT(top_value <= PWM_COUNTERTOP_COUNTERTOP_Msk); + + p_reg->PRESCALER = base_clock; + p_reg->MODE = mode; + p_reg->COUNTERTOP = top_value; +} + +__STATIC_INLINE void nrf_pwm_sequence_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + nrf_pwm_sequence_t const * p_seq) +{ + ASSERT(p_seq != NULL); + + nrf_pwm_seq_ptr_set( p_reg, seq_id, p_seq->values.p_raw); + nrf_pwm_seq_cnt_set( p_reg, seq_id, p_seq->length); + nrf_pwm_seq_refresh_set( p_reg, seq_id, p_seq->repeats); + nrf_pwm_seq_end_delay_set(p_reg, seq_id, p_seq->end_delay); +} + +__STATIC_INLINE void nrf_pwm_seq_ptr_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint16_t const * p_values) +{ + ASSERT(seq_id <= 1); + ASSERT(p_values != NULL); + p_reg->SEQ[seq_id].PTR = (uint32_t)p_values; +} + +__STATIC_INLINE void nrf_pwm_seq_cnt_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint16_t length) +{ + ASSERT(seq_id <= 1); + ASSERT(length != 0); + ASSERT(length <= PWM_SEQ_CNT_CNT_Msk); + p_reg->SEQ[seq_id].CNT = length; +} + +__STATIC_INLINE void nrf_pwm_seq_refresh_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint32_t refresh) +{ + ASSERT(seq_id <= 1); + ASSERT(refresh <= PWM_SEQ_REFRESH_CNT_Msk); + p_reg->SEQ[seq_id].REFRESH = refresh; +} + +__STATIC_INLINE void nrf_pwm_seq_end_delay_set(NRF_PWM_Type * p_reg, + uint8_t seq_id, + uint32_t end_delay) +{ + ASSERT(seq_id <= 1); + ASSERT(end_delay <= PWM_SEQ_ENDDELAY_CNT_Msk); + p_reg->SEQ[seq_id].ENDDELAY = end_delay; +} + +__STATIC_INLINE void nrf_pwm_decoder_set(NRF_PWM_Type * p_reg, + nrf_pwm_dec_load_t dec_load, + nrf_pwm_dec_step_t dec_step) +{ + p_reg->DECODER = ((uint32_t)dec_load << PWM_DECODER_LOAD_Pos) | + ((uint32_t)dec_step << PWM_DECODER_MODE_Pos); +} + +__STATIC_INLINE void nrf_pwm_loop_set(NRF_PWM_Type * p_reg, + uint16_t loop_count) +{ + p_reg->LOOP = loop_count; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_PWM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qdec.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qdec.h new file mode 100644 index 0000000000..e6a0fccbfe --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qdec.h @@ -0,0 +1,504 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_QDEC_H__ +#define NRF_QDEC_H__ + +#include +#include "nrf_error.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*lint ++flb "Enter library region" */ + +/** + * @defgroup nrf_qdec_hal QDEC HAL + * @{ + * @ingroup nrf_qdec + * @brief Hardware access layer for accessing the quadrature decoder (QDEC) peripheral. + */ + +/** + * @enum nrf_qdec_task_t + * @brief QDEC tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_QDEC_TASK_START = offsetof(NRF_QDEC_Type, TASKS_START), /**< Starting the quadrature decoder. */ + NRF_QDEC_TASK_STOP = offsetof(NRF_QDEC_Type, TASKS_STOP), /**< Stopping the quadrature decoder. */ + NRF_QDEC_TASK_READCLRACC = offsetof(NRF_QDEC_Type, TASKS_READCLRACC) /**< Reading and clearing ACC and ACCDBL registers. */ +} nrf_qdec_task_t; + +/** + * @enum nrf_qdec_event_t + * @brief QDEC events. + */ +typedef enum +{ + NRF_QDEC_EVENT_SAMPLERDY = offsetof(NRF_QDEC_Type, EVENTS_SAMPLERDY), /**< Event generated for every new sample. */ + NRF_QDEC_EVENT_REPORTRDY = offsetof(NRF_QDEC_Type, EVENTS_REPORTRDY), /**< Event generated for every new report. */ + NRF_QDEC_EVENT_ACCOF = offsetof(NRF_QDEC_Type, EVENTS_ACCOF) /**< Event generated for every accumulator overflow. */ +} nrf_qdec_event_t; /*lint -restore */ + +/** + * @enum nrf_qdec_short_mask_t + * @brief QDEC shortcuts. + */ +typedef enum +{ + NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK = QDEC_SHORTS_REPORTRDY_READCLRACC_Msk, /**< Shortcut between REPORTRDY event and READCLRACC task. */ + NRF_QDEC_SHORT_SAMPLERDY_STOP_MASK = QDEC_SHORTS_SAMPLERDY_STOP_Msk /**< Shortcut between SAMPLERDY event and STOP task. */ +} nrf_qdec_short_mask_t; + +/** + * @enum nrf_qdec_int_mask_t + * @brief QDEC interrupts. + */ +typedef enum +{ + NRF_QDEC_INT_SAMPLERDY_MASK = QDEC_INTENSET_SAMPLERDY_Msk, /**< Mask for enabling or disabling an interrupt on SAMPLERDY event. */ + NRF_QDEC_INT_REPORTRDY_MASK = QDEC_INTENSET_REPORTRDY_Msk, /**< Mask for enabling or disabling an interrupt on REPORTRDY event. */ + NRF_QDEC_INT_ACCOF_MASK = QDEC_INTENSET_ACCOF_Msk /**< Mask for enabling or disabling an interrupt on ACCOF event. */ +} nrf_qdec_int_mask_t; + +/** + * @enum nrf_qdec_enable_t + * @brief States of the enable bit. + */ +typedef enum +{ + NRF_QDEC_DISABLE = QDEC_ENABLE_ENABLE_Disabled, /**< Mask for disabling the QDEC periperal. When disabled, the QDEC decoder pins are not active. */ + NRF_QDEC_ENABLE = QDEC_ENABLE_ENABLE_Enabled /**< Mask for enabling the QDEC periperal. When enabled, the QDEC pins are active. */ +} nrf_qdec_enable_t; + + +/** + * @enum nrf_qdec_dbfen_t + * @brief States of the debounce filter enable bit. + */ +typedef enum +{ + NRF_QDEC_DBFEN_DISABLE = QDEC_DBFEN_DBFEN_Disabled, /**< Mask for disabling the debounce filter. */ + NRF_QDEC_DBFEN_ENABLE = QDEC_DBFEN_DBFEN_Enabled /**< Mask for enabling the debounce filter. */ +} nrf_qdec_dbfen_t; + +/** + * @enum nrf_qdec_ledpol_t + * @brief Active LED polarity. + */ +typedef enum +{ + NRF_QDEC_LEPOL_ACTIVE_LOW = QDEC_LEDPOL_LEDPOL_ActiveLow, /**< QDEC LED active on output pin low. */ + NRF_QDEC_LEPOL_ACTIVE_HIGH = QDEC_LEDPOL_LEDPOL_ActiveHigh /**< QDEC LED active on output pin high. */ +} nrf_qdec_ledpol_t; + + +/** + * @enum nrf_qdec_sampleper_t + * @brief Available sampling periods. + */ +typedef enum +{ + NRF_QDEC_SAMPLEPER_128us = QDEC_SAMPLEPER_SAMPLEPER_128us, /**< QDEC sampling period 128 microseconds. */ + NRF_QDEC_SAMPLEPER_256us = QDEC_SAMPLEPER_SAMPLEPER_256us, /**< QDEC sampling period 256 microseconds. */ + NRF_QDEC_SAMPLEPER_512us = QDEC_SAMPLEPER_SAMPLEPER_512us, /**< QDEC sampling period 512 microseconds. */ + NRF_QDEC_SAMPLEPER_1024us = QDEC_SAMPLEPER_SAMPLEPER_1024us, /**< QDEC sampling period 1024 microseconds. */ + NRF_QDEC_SAMPLEPER_2048us = QDEC_SAMPLEPER_SAMPLEPER_2048us, /**< QDEC sampling period 2048 microseconds. */ + NRF_QDEC_SAMPLEPER_4096us = QDEC_SAMPLEPER_SAMPLEPER_4096us, /**< QDEC sampling period 4096 microseconds. */ + NRF_QDEC_SAMPLEPER_8192us = QDEC_SAMPLEPER_SAMPLEPER_8192us, /**< QDEC sampling period 8192 microseconds. */ + NRF_QDEC_SAMPLEPER_16384us = QDEC_SAMPLEPER_SAMPLEPER_16384us /**< QDEC sampling period 16384 microseconds. */ +} nrf_qdec_sampleper_t; + +/** + * @enum nrf_qdec_reportper_t + * @brief Available report periods. + */ +typedef enum +{ + NRF_QDEC_REPORTPER_10 = QDEC_REPORTPER_REPORTPER_10Smpl, /**< QDEC report period 10 samples. */ + NRF_QDEC_REPORTPER_40 = QDEC_REPORTPER_REPORTPER_40Smpl, /**< QDEC report period 40 samples. */ + NRF_QDEC_REPORTPER_80 = QDEC_REPORTPER_REPORTPER_80Smpl, /**< QDEC report period 80 samples. */ + NRF_QDEC_REPORTPER_120 = QDEC_REPORTPER_REPORTPER_120Smpl, /**< QDEC report period 120 samples. */ + NRF_QDEC_REPORTPER_160 = QDEC_REPORTPER_REPORTPER_160Smpl, /**< QDEC report period 160 samples. */ + NRF_QDEC_REPORTPER_200 = QDEC_REPORTPER_REPORTPER_200Smpl, /**< QDEC report period 200 samples. */ + NRF_QDEC_REPORTPER_240 = QDEC_REPORTPER_REPORTPER_240Smpl, /**< QDEC report period 240 samples. */ + NRF_QDEC_REPORTPER_280 = QDEC_REPORTPER_REPORTPER_280Smpl, /**< QDEC report period 280 samples. */ + NRF_QDEC_REPORTPER_DISABLED /**< QDEC reporting disabled. */ +} nrf_qdec_reportper_t; + +/** + * @brief Function for enabling QDEC. + */ +__STATIC_INLINE void nrf_qdec_enable(void) +{ + NRF_QDEC->ENABLE = NRF_QDEC_ENABLE; +} + + +/** + * @brief Function for disabling QDEC. + */ +__STATIC_INLINE void nrf_qdec_disable(void) +{ + NRF_QDEC->ENABLE = NRF_QDEC_DISABLE; +} + + +/** + * @brief Function for returning the enable state of QDEC. + * @return State of the register. + */ +__STATIC_INLINE uint32_t nrf_qdec_enable_get(void) +{ + return NRF_QDEC->ENABLE; +} + + +/** + * @brief Function for enabling QDEC interrupts by mask. + * @param[in] qdec_int_mask Sources of the interrupts to enable. + */ +__STATIC_INLINE void nrf_qdec_int_enable(uint32_t qdec_int_mask) +{ + NRF_QDEC->INTENSET = qdec_int_mask; // writing 0 has no effect +} + + +/** + * @brief Function for disabling QDEC interrupts by mask. + * @param[in] qdec_int_mask Sources of the interrupts to disable. + * + */ +__STATIC_INLINE void nrf_qdec_int_disable(uint32_t qdec_int_mask) +{ + NRF_QDEC->INTENCLR = qdec_int_mask; // writing 0 has no effect +} + + +/** + * @brief Function for getting the enabled interrupts of the QDEC. + */ +__STATIC_INLINE uint32_t nrf_qdec_int_enable_check(nrf_qdec_int_mask_t qdec_int_mask) +{ + return NRF_QDEC->INTENSET & qdec_int_mask; // when read this register will return the value of INTEN. +} + + +/** + * @brief Function for enabling the debouncing filter of the QED. + */ +__STATIC_INLINE void nrf_qdec_dbfen_enable(void) +{ + NRF_QDEC->DBFEN = NRF_QDEC_DBFEN_ENABLE; +} + + +/** + * @brief Function for disabling the debouncing filter of the QED. + */ +__STATIC_INLINE void nrf_qdec_dbfen_disable(void) +{ + NRF_QDEC->DBFEN = NRF_QDEC_DBFEN_DISABLE; +} + + +/** + * @brief Function for getting the state of the QDEC's debouncing filter. + * @retval NRF_QDEC_DBFEN_DISABLE If the debouncing filter is disabled. + * @retval NRF_QDEC_DBFEN_ENABLE If the debouncing filter is enabled. + */ +__STATIC_INLINE uint32_t nrf_qdec_dbfen_get(void) +{ + return NRF_QDEC->DBFEN; +} + + +/** + * @brief Function for assigning QDEC pins. + * @param[in] psela Pin number. + * @param[in] pselb Pin number. + * @param[in] pselled Pin number. + */ +__STATIC_INLINE void nrf_qdec_pio_assign( uint32_t psela, uint32_t pselb, uint32_t pselled) +{ + NRF_QDEC->PSELA = psela; + NRF_QDEC->PSELB = pselb; + NRF_QDEC->PSELLED = pselled; + +} + +/** + * @brief Function for setting a specific QDEC task. + * @param[in] qdec_task QDEC task to be set. + */ +__STATIC_INLINE void nrf_qdec_task_trigger(nrf_qdec_task_t qdec_task) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_QDEC + qdec_task) ) = 1; +} + + +/** + * @brief Function for retrieving the address of a QDEC task register. + * @param[in] qdec_task QDEC task. + */ +__STATIC_INLINE uint32_t * nrf_qdec_task_address_get(nrf_qdec_task_t qdec_task) +{ + return (uint32_t *)( (uint8_t *)NRF_QDEC + qdec_task); +} + + +/** + * @brief Function for clearing a specific QDEC event. + * @param[in] qdec_event QDEC event to clear. + */ +__STATIC_INLINE void nrf_qdec_event_clear(nrf_qdec_event_t qdec_event) +{ + *( (volatile uint32_t *)( (uint8_t *)NRF_QDEC + qdec_event) ) = 0; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_QDEC + qdec_event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for retrieving the state of a specific QDEC event. + * @return State of the QDEC event. + */ +__STATIC_INLINE uint32_t nrf_qdec_event_check(nrf_qdec_event_t qdec_event) +{ + return *(volatile uint32_t *)( (uint8_t *)NRF_QDEC + qdec_event); +} + + +/** + * @brief Function for retrieving the address of a specific QDEC event register. + * @param[in] qdec_event QDEC event. + * @return Address of the specified QDEC event. + */ +__STATIC_INLINE uint32_t * nrf_qdec_event_address_get(nrf_qdec_event_t qdec_event) +{ + return (uint32_t *)( (uint8_t *)NRF_QDEC + qdec_event); +} + + +/** + * @brief Function for setting QDEC shortcuts. + * @param[in] qdec_short_mask QDEC shortcut by mask. + */ +__STATIC_INLINE void nrf_qdec_shorts_enable(uint32_t qdec_short_mask) +{ + NRF_QDEC->SHORTS |= qdec_short_mask; +} + + +/** + * @brief Function for clearing shortcuts of the QDEC by mask. + * @param[in] qdec_short_mask QDEC shortcute to be cleared. + */ +__STATIC_INLINE void nrf_qdec_shorts_disable(uint32_t qdec_short_mask) +{ + NRF_QDEC->SHORTS &= ~qdec_short_mask; +} + + +/** + * @brief Function for retrieving the value of QDEC's SAMPLEPER register. + * @return Value of the SAMPLEPER register. + */ +__STATIC_INLINE int32_t nrf_qdec_sampleper_reg_get(void) +{ + return NRF_QDEC->SAMPLEPER; +} + + +/** + * @brief Function for converting the value of QDEC's SAMPLE PERIOD to microseconds. + * @retval sampling period in microseconds. + */ +__STATIC_INLINE uint32_t nrf_qdec_sampleper_to_value(uint32_t sampleper) +{ + return (1 << (7 + sampleper)); +} + +/** + * @brief Function for setting the value of QDEC's SAMPLEPER register. + * @param[in] sample_per Sampling period. + */ +__STATIC_INLINE void nrf_qdec_sampleper_set(nrf_qdec_sampleper_t sample_per) +{ + NRF_QDEC->SAMPLEPER = sample_per; +} + + +/** + * @brief Function for retrieving the value of QDEC's SAMPLE register. + * @return Value of the SAMPLE register. + */ +__STATIC_INLINE int32_t nrf_qdec_sample_get(void) +{ + return NRF_QDEC->SAMPLE; +} + + +/** + * @brief Function for retrieving the value of QDEC's ACC register. + * @return Value of the ACC register. + */ +__STATIC_INLINE int32_t nrf_qdec_acc_get(void) +{ + return NRF_QDEC->ACC; +} + + +/** + * @brief Function for retrieving the value of QDEC's ACCREAD register. + * @return Value of the ACCREAD register. + */ +__STATIC_INLINE int32_t nrf_qdec_accread_get(void) +{ + return NRF_QDEC->ACCREAD; +} + + +/** + * @brief Function for retrieving the value of QDEC's ACCDBL register. + * @return Value of the ACCDBL register. + */ +__STATIC_INLINE uint32_t nrf_qdec_accdbl_get(void) +{ + return NRF_QDEC->ACCDBL; +} + + +/** + * @brief Function for retrieving the value of QDEC's ACCDBLREAD register. + * @return Value of the ACCDBLREAD register. + */ +__STATIC_INLINE uint32_t nrf_qdec_accdblread_get(void) +{ + return NRF_QDEC->ACCDBLREAD; +} + + +/** + * @brief Function for setting how long the LED is switched on before sampling. + * @param[in] time_us Time (in microseconds) how long the LED is switched on before sampling. + */ +__STATIC_INLINE void nrf_qdec_ledpre_set(uint32_t time_us) +{ + NRF_QDEC->LEDPRE = time_us; +} + + +/** + * @brief Function for retrieving how long the LED is switched on before sampling. + * @retval time_us Time (in microseconds) how long the LED is switched on before sampling. + */ +__STATIC_INLINE uint32_t nrf_qdec_ledpre_get(void) +{ + return NRF_QDEC->LEDPRE; +} + + +/** + * @brief Function for setting the report period (in samples). + * @param[in] reportper Number of samples. + */ +__STATIC_INLINE void nrf_qdec_reportper_set(nrf_qdec_reportper_t reportper) +{ + NRF_QDEC->REPORTPER = reportper; +} + + +/** + * @brief Function for retrieving the report period. + * @retval reportper Number of samples as encoded in the register. + */ +__STATIC_INLINE uint32_t nrf_qdec_reportper_reg_get(void) +{ + return NRF_QDEC->REPORTPER; +} + + +/** + * @brief Function for retrieving the value of QDEC's SAMPLEPER register. + * @param [in] reportper Reportper to be converted to amount of samples per report. + + */ +__STATIC_INLINE uint32_t nrf_qdec_reportper_to_value(uint32_t reportper) +{ + return (reportper == NRF_QDEC_REPORTPER_10) ? 10 : reportper * 40; +} + + +/** + * @brief Function for setting the active level for the LED. + * @param[in] pol Active level for the LED. + */ +__STATIC_INLINE void nrf_qdec_ledpol_set(nrf_qdec_ledpol_t pol) +{ + NRF_QDEC->LEDPOL = pol; +} + + +/** + * @brief Function for retrieving the active level for the LED. + * @return Active level for the LED. + */ +__STATIC_INLINE uint32_t nrf_qdec_ledpol_get(void) +{ + return NRF_QDEC->LEDPOL; +} + + +/** + *@} + **/ + +/*lint --flb "Leave library region" */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qspi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qspi.h new file mode 100644 index 0000000000..72b2d7237a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_qspi.h @@ -0,0 +1,765 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_qspi_hal QSPI HAL + * @{ + * @ingroup nrf_qspi + * + * @brief Hardware access layer for accessing the QSPI peripheral. + */ + +#ifndef NRF_QSPI_H__ +#define NRF_QSPI_H__ + +#include +#include +#include "boards.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This value can be used as a parameter for the @ref nrf_qspi_pins_set + * function to specify that a given QSPI signal (SCK, CSN, IO0, IO1, IO2, or IO3) + * will not be connected to a physical pin. + */ +#define NRF_QSPI_PIN_NOT_CONNECTED 0xFF + +/** + * @brief Macro for setting proper values to pin registers. + */ + +#define NRF_QSPI_PIN_VAL(pin) (pin) == NRF_QSPI_PIN_NOT_CONNECTED ? 0xFFFFFFFF : (pin) + +/** + * @brief QSPI tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_QSPI_TASK_ACTIVATE = offsetof(NRF_QSPI_Type, TASKS_ACTIVATE), /**< Activate the QSPI interface. */ + NRF_QSPI_TASK_READSTART = offsetof(NRF_QSPI_Type, TASKS_READSTART), /**< Start transfer from external flash memory to internal RAM. */ + NRF_QSPI_TASK_WRITESTART = offsetof(NRF_QSPI_Type, TASKS_WRITESTART), /**< Start transfer from internal RAM to external flash memory. */ + NRF_QSPI_TASK_ERASESTART = offsetof(NRF_QSPI_Type, TASKS_ERASESTART), /**< Start external flash memory erase operation. */ + /*lint -restore*/ +} nrf_qspi_task_t; + +/** + * @brief QSPI events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_QSPI_EVENT_READY = offsetof(NRF_QSPI_Type, EVENTS_READY) /**< QSPI peripheral is ready after it executes any task. */ + /*lint -restore*/ +} nrf_qspi_event_t; + +/** + * @brief QSPI interrupts. + */ +typedef enum +{ + NRF_QSPI_INT_READY_MASK = QSPI_INTENSET_READY_Msk /**< Interrupt on READY event. */ +} nrf_qspi_int_mask_t; + +/** + * @brief QSPI frequency divider values. + */ +typedef enum +{ + NRF_QSPI_FREQ_32MDIV1, /**< 32.0 MHz. */ + NRF_QSPI_FREQ_32MDIV2, /**< 16.0 MHz. */ + NRF_QSPI_FREQ_32MDIV3, /**< 10.6 MHz. */ + NRF_QSPI_FREQ_32MDIV4, /**< 8.00 MHz. */ + NRF_QSPI_FREQ_32MDIV5, /**< 6.40 MHz. */ + NRF_QSPI_FREQ_32MDIV6, /**< 5.33 MHz. */ + NRF_QSPI_FREQ_32MDIV7, /**< 4.57 MHz. */ + NRF_QSPI_FREQ_32MDIV8, /**< 4.00 MHz. */ + NRF_QSPI_FREQ_32MDIV9, /**< 3.55 MHz. */ + NRF_QSPI_FREQ_32MDIV10, /**< 3.20 MHz. */ + NRF_QSPI_FREQ_32MDIV11, /**< 2.90 MHz. */ + NRF_QSPI_FREQ_32MDIV12, /**< 2.66 MHz. */ + NRF_QSPI_FREQ_32MDIV13, /**< 2.46 MHz. */ + NRF_QSPI_FREQ_32MDIV14, /**< 2.29 MHz. */ + NRF_QSPI_FREQ_32MDIV15, /**< 2.13 MHz. */ + NRF_QSPI_FREQ_32MDIV16, /**< 2.00 MHz. */ +} nrf_qspi_frequency_t; + +/** + * @brief Interface configuration for a read operation. + */ +typedef enum +{ + NRF_QSPI_READOC_FASTREAD = QSPI_IFCONFIG0_READOC_FASTREAD, /**< Single data line SPI. FAST_READ (opcode 0x0B). */ + NRF_QSPI_READOC_READ2O = QSPI_IFCONFIG0_READOC_READ2O, /**< Dual data line SPI. READ2O (opcode 0x3B). */ + NRF_QSPI_READOC_READ2IO = QSPI_IFCONFIG0_READOC_READ2IO, /**< Dual data line SPI. READ2IO (opcode 0xBB). */ + NRF_QSPI_READOC_READ4O = QSPI_IFCONFIG0_READOC_READ4O, /**< Quad data line SPI. READ4O (opcode 0x6B). */ + NRF_QSPI_READOC_READ4IO = QSPI_IFCONFIG0_READOC_READ4IO /**< Quad data line SPI. READ4IO (opcode 0xEB). */ +} nrf_qspi_readoc_t; + +/** + * @brief Interface configuration for a write operation. + */ +typedef enum +{ + NRF_QSPI_WRITEOC_PP = QSPI_IFCONFIG0_WRITEOC_PP, /**< Single data line SPI. PP (opcode 0x02). */ + NRF_QSPI_WRITEOC_PP2O = QSPI_IFCONFIG0_WRITEOC_PP2O, /**< Dual data line SPI. PP2O (opcode 0xA2). */ + NRF_QSPI_WRITEOC_PP4O = QSPI_IFCONFIG0_WRITEOC_PP4O, /**< Quad data line SPI. PP4O (opcode 0x32). */ + NRF_QSPI_WRITEOC_PP4IO = QSPI_IFCONFIG0_WRITEOC_PP4IO, /**< Quad data line SPI. READ4O (opcode 0x38). */ +} nrf_qspi_writeoc_t; + +/** + * @brief Interface configuration for addressing mode. + */ +typedef enum +{ + NRF_QSPI_ADDRMODE_24BIT = QSPI_IFCONFIG0_ADDRMODE_24BIT, /**< 24-bit addressing. */ + NRF_QSPI_ADDRMODE_32BIT = QSPI_IFCONFIG0_ADDRMODE_32BIT /**< 32-bit addressing. */ +} nrf_qspi_addrmode_t; + +/** + * @brief QSPI SPI mode. Polarization and phase configuration. + */ +typedef enum +{ + NRF_QSPI_MODE_0 = QSPI_IFCONFIG1_SPIMODE_MODE0, /**< Mode 0 (CPOL=0, CPHA=0). */ + NRF_QSPI_MODE_1 = QSPI_IFCONFIG1_SPIMODE_MODE3 /**< Mode 1 (CPOL=1, CPHA=1). */ +} nrf_qspi_spi_mode_t; + +/** + * @brief Addressing configuration mode. + */ +typedef enum +{ + NRF_QSPI_ADDRCONF_MODE_NOINSTR = QSPI_ADDRCONF_MODE_NoInstr, /**< Do not send any instruction. */ + NRF_QSPI_ADDRCONF_MODE_OPCODE = QSPI_ADDRCONF_MODE_Opcode, /**< Send opcode. */ + NRF_QSPI_ADDRCONF_MODE_OPBYTE0 = QSPI_ADDRCONF_MODE_OpByte0, /**< Send opcode, byte0. */ + NRF_QSPI_ADDRCONF_MODE_ALL = QSPI_ADDRCONF_MODE_All /**< Send opcode, byte0, byte1. */ +} nrf_qspi_addrconfig_mode_t; + +/** + * @brief Erasing data length. + */ +typedef enum +{ + NRF_QSPI_ERASE_LEN_4KB = QSPI_ERASE_LEN_LEN_4KB, /**< Erase 4 kB block (flash command 0x20). */ + NRF_QSPI_ERASE_LEN_64KB = QSPI_ERASE_LEN_LEN_64KB, /**< Erase 64 kB block (flash command 0xD8). */ + NRF_QSPI_ERASE_LEN_ALL = QSPI_ERASE_LEN_LEN_All /**< Erase all (flash command 0xC7). */ +} nrf_qspi_erase_len_t; + +/** + * @brief Custom instruction length. + */ +typedef enum +{ + NRF_QSPI_CINSTR_LEN_1B = QSPI_CINSTRCONF_LENGTH_1B, /**< Send opcode only. */ + NRF_QSPI_CINSTR_LEN_2B = QSPI_CINSTRCONF_LENGTH_2B, /**< Send opcode, CINSTRDAT0.BYTE0. */ + NRF_QSPI_CINSTR_LEN_3B = QSPI_CINSTRCONF_LENGTH_3B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT0.BYTE1. */ + NRF_QSPI_CINSTR_LEN_4B = QSPI_CINSTRCONF_LENGTH_4B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT0.BYTE2. */ + NRF_QSPI_CINSTR_LEN_5B = QSPI_CINSTRCONF_LENGTH_5B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT0.BYTE3. */ + NRF_QSPI_CINSTR_LEN_6B = QSPI_CINSTRCONF_LENGTH_6B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT1.BYTE4. */ + NRF_QSPI_CINSTR_LEN_7B = QSPI_CINSTRCONF_LENGTH_7B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT1.BYTE5. */ + NRF_QSPI_CINSTR_LEN_8B = QSPI_CINSTRCONF_LENGTH_8B, /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT1.BYTE6. */ + NRF_QSPI_CINSTR_LEN_9B = QSPI_CINSTRCONF_LENGTH_9B /**< Send opcode, CINSTRDAT0.BYTE0 -> CINSTRDAT1.BYTE7. */ +} nrf_qspi_cinstr_len_t; + +/** + * @brief Pins configuration. + */ +typedef struct +{ + uint8_t sck_pin; /**< SCK pin number. */ + uint8_t csn_pin; /**< Chip select pin number. */ + uint8_t io0_pin; /**< IO0/MOSI pin number. */ + uint8_t io1_pin; /**< IO1/MISO pin number. */ + uint8_t io2_pin; /**< IO2 pin number (optional). + * Set to @ref NRF_QSPI_PIN_NOT_CONNECTED if this signal is not needed. + */ + uint8_t io3_pin; /**< IO3 pin number (optional). + * Set to @ref NRF_QSPI_PIN_NOT_CONNECTED if this signal is not needed. + */ +} nrf_qspi_pins_t; + +/** + * @brief Custom instruction configuration. + */ +typedef struct +{ + uint8_t opcode; /**< Opcode used in custom instruction transmission. */ + nrf_qspi_cinstr_len_t length; /**< Length of the custom instruction data. */ + bool io2_level; /**< I/O line level during transmission. */ + bool io3_level; /**< I/O line level during transmission. */ + bool wipwait; /**< Wait if a Wait in Progress bit is set in the memory status byte. */ + bool wren; /**< Send write enable before instruction. */ +} nrf_qspi_cinstr_conf_t; + +/** + * @brief Addressing mode register configuration. See @ref nrf_qspi_addrconfig_set + */ +typedef struct +{ + uint8_t opcode; /**< Opcode used to enter proper addressing mode. */ + uint8_t byte0; /**< Byte following the opcode. */ + uint8_t byte1; /**< Byte following byte0. */ + nrf_qspi_addrconfig_mode_t mode; /**< Extended addresing mode. */ + bool wipwait; /**< Enable/disable waiting for complete operation execution. */ + bool wren; /**< Send write enable before instruction. */ +} nrf_qspi_addrconfig_conf_t; + +/** + * @brief Structure with QSPI protocol interface configuration. + */ +typedef struct +{ + nrf_qspi_readoc_t readoc; /**< Read operation code. */ + nrf_qspi_writeoc_t writeoc; /**< Write operation code. */ + nrf_qspi_addrmode_t addrmode; /**< Addresing mode (24-bit or 32-bit). */ + bool dpmconfig; /**< Enable the Deep Power-down Mode (DPM) feature. */ +} nrf_qspi_prot_conf_t; + +/** + * @brief QSPI physical interface configuration. + */ +typedef struct +{ + uint8_t sck_delay; /**< tSHSL, tWHSL, and tSHWL in number of 16 MHz periods (62.5ns). */ + bool dpmen; /**< Enable the DPM feature. */ + nrf_qspi_spi_mode_t spi_mode; /**< SPI phase and polarization. */ + nrf_qspi_frequency_t sck_freq; /**< SCK frequency given as enum @ref nrf_qspi_frequency_t. */ +} nrf_qspi_phy_conf_t; + +/** + * @brief Function for activating a specific QSPI task. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_qspi_task_trigger(NRF_QSPI_Type * p_reg, nrf_qspi_task_t task); + +/** + * @brief Function for getting the address of a specific QSPI task register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t nrf_qspi_task_address_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_task_t task); + +/** + * @brief Function for clearing a specific QSPI event. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_event Event to clear. + */ +__STATIC_INLINE void nrf_qspi_event_clear(NRF_QSPI_Type * p_reg, nrf_qspi_event_t qspi_event); + +/** + * @brief Function for checking the state of a specific SPI event. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_qspi_event_check(NRF_QSPI_Type const * p_reg, nrf_qspi_event_t qspi_event); + +/** + * @brief Function for getting the address of a specific QSPI event register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_qspi_event_address_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_event_t qspi_event); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_qspi_int_enable(NRF_QSPI_Type * p_reg, uint32_t qspi_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_qspi_int_disable(NRF_QSPI_Type * p_reg, uint32_t qspi_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] qspi_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_qspi_int_enable_check(NRF_QSPI_Type const * p_reg, + nrf_qspi_int_mask_t qspi_int); + +/** + * @brief Function for enabling the QSPI peripheral. + * + * @param[in] p_reg Pointer to the peripheral register structure. + */ +__STATIC_INLINE void nrf_qspi_enable(NRF_QSPI_Type * p_reg); + +/** + * @brief Function for disabling the QSPI peripheral. + * + * @param[in] p_reg Pointer to the peripheral register structure. + */ +__STATIC_INLINE void nrf_qspi_disable(NRF_QSPI_Type * p_reg); + +/** + * @brief Function for configuring QSPI pins. + * + * If a given signal is not needed, pass the @ref NRF_QSPI_PIN_NOT_CONNECTED + * value instead of its pin number. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_pins Pointer to the pins configuration structure. See @ref nrf_qspi_pins_t. + */ +__STATIC_INLINE void nrf_qspi_pins_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_pins_t * p_pins); + +/** + * @brief Function for setting the QSPI IFCONFIG0 register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_config Pointer to the QSPI protocol interface configuration structure. See @ref nrf_qspi_prot_conf_t. + */ +__STATIC_INLINE void nrf_qspi_ifconfig0_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_prot_conf_t * p_config); + +/** + * @brief Function for setting the QSPI IFCONFIG1 register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_config Pointer to the QSPI physical interface configuration structure. See @ref nrf_qspi_phy_conf_t. + */ +__STATIC_INLINE void nrf_qspi_ifconfig1_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_phy_conf_t * p_config); + +/** + * @brief Function for setting the QSPI ADDRCONF register. + * + * Function must be executed before sending task NRF_QSPI_TASK_ACTIVATE. Data stored in the structure + * is sent during the start of the peripheral. Remember that the reset instruction can set + * addressing mode to default in the memory device. If memory reset is necessary before configuring + * the addressing mode, use custom instruction feature instead of this function. + * Case with reset: Enable the peripheral without setting ADDRCONF register, send reset instructions + * using a custom instruction feature (reset enable and then reset), set proper addressing mode + * using the custom instruction feature. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_config Pointer to the addressing mode configuration structure. See @ref nrf_qspi_addrconfig_conf_t. +*/ +__STATIC_INLINE void nrf_qspi_addrconfig_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_addrconfig_conf_t * p_config); + +/** + * @brief Function for setting write data into the peripheral register (without starting the process). + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_buffer Pointer to the writing buffer. + * @param[in] length Lenght of the writing data. + * @param[in] dest_addr Address in memory to write to. + */ +__STATIC_INLINE void nrf_qspi_write_buffer_set(NRF_QSPI_Type * p_reg, + void const * p_buffer, + uint32_t length, + uint32_t dest_addr); + +/** + * @brief Function for setting read data into the peripheral register (without starting the process). + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[out] p_buffer Pointer to the reading buffer. + * @param[in] length Length of the read data. + * @param[in] src_addr Address in memory to read from. + */ +__STATIC_INLINE void nrf_qspi_read_buffer_set(NRF_QSPI_Type * p_reg, + void * p_buffer, + uint32_t length, + uint32_t src_addr); + +/** + * @brief Function for setting erase data into the peripheral register (without starting the process). + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] erase_addr Start address to erase. Address must have padding set to 4 bytes. + * @param[in] len Size of erasing area. + */ +__STATIC_INLINE void nrf_qspi_erase_ptr_set(NRF_QSPI_Type * p_reg, + uint32_t erase_addr, + nrf_qspi_erase_len_t len); + +/** + * @brief Function for getting the peripheral status register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * + * @return Peripheral status register. + */ +__STATIC_INLINE uint32_t nrf_qspi_status_reg_get(NRF_QSPI_Type const * p_reg); + +/** + * @brief Function for getting the device status register stored in the peripheral status register. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * + * @return Device status register (lower byte). + */ +__STATIC_INLINE uint8_t nrf_qspi_sreg_get(NRF_QSPI_Type const * p_reg); + +/** + * @brief Function for checking if the peripheral is busy or not. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * + * @retval true If QSPI is busy. + * @retval false If QSPI is ready. + */ +__STATIC_INLINE bool nrf_qspi_busy_check(NRF_QSPI_Type const * p_reg); + +/** + * @brief Function for setting registers sending with custom instruction transmission. + * + * This function can be ommited when using NRF_QSPI_CINSTR_LEN_1B as the length argument + * (sending only opcode without data). + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] length Length of the custom instruction data. + * @param[in] p_tx_data Pointer to the data to send with the custom instruction. + */ +__STATIC_INLINE void nrf_qspi_cinstrdata_set(NRF_QSPI_Type * p_reg, + nrf_qspi_cinstr_len_t length, + void const * p_tx_data); + +/** + * @brief Function for getting data from register after custom instruction transmission. + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] length Length of the custom instruction data. + * @param[in] p_rx_data Pointer to the reading buffer. + */ +__STATIC_INLINE void nrf_qspi_cinstrdata_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_cinstr_len_t length, + void * p_rx_data); + +/** + * @brief Function for sending custom instruction to external memory. + * + * @param[in] p_reg Pointer to the peripheral register structure. + * @param[in] p_config Pointer to the custom instruction configuration structure. See @ref nrf_qspi_cinstr_conf_t. + */ + +__STATIC_INLINE void nrf_qspi_cinstr_transfer_start(NRF_QSPI_Type * p_reg, + const nrf_qspi_cinstr_conf_t * p_config); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_qspi_task_trigger(NRF_QSPI_Type * p_reg, nrf_qspi_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_qspi_task_address_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_task_t task) +{ + return ((uint32_t)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_qspi_event_clear(NRF_QSPI_Type * p_reg, nrf_qspi_event_t qspi_event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)qspi_event)) = 0x0UL; +} + +__STATIC_INLINE bool nrf_qspi_event_check(NRF_QSPI_Type const * p_reg, nrf_qspi_event_t qspi_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)qspi_event); +} + +__STATIC_INLINE uint32_t * nrf_qspi_event_address_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_event_t qspi_event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)qspi_event); +} + +__STATIC_INLINE void nrf_qspi_int_enable(NRF_QSPI_Type * p_reg, uint32_t qspi_int_mask) +{ + p_reg->INTENSET = qspi_int_mask; +} + +__STATIC_INLINE void nrf_qspi_int_disable(NRF_QSPI_Type * p_reg, uint32_t qspi_int_mask) +{ + p_reg->INTENCLR = qspi_int_mask; +} + +__STATIC_INLINE bool nrf_qspi_int_enable_check(NRF_QSPI_Type const * p_reg, + nrf_qspi_int_mask_t qspi_int) +{ + return (bool)(p_reg->INTENSET & qspi_int); +} + +__STATIC_INLINE void nrf_qspi_enable(NRF_QSPI_Type * p_reg) +{ + p_reg->ENABLE = (QSPI_ENABLE_ENABLE_Enabled << QSPI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_qspi_disable(NRF_QSPI_Type * p_reg) +{ + p_reg->ENABLE = (QSPI_ENABLE_ENABLE_Disabled << QSPI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_qspi_pins_set(NRF_QSPI_Type * p_reg, const nrf_qspi_pins_t * p_pins) +{ + p_reg->PSEL.SCK = NRF_QSPI_PIN_VAL(p_pins->sck_pin); + p_reg->PSEL.CSN = NRF_QSPI_PIN_VAL(p_pins->csn_pin); + p_reg->PSEL.IO0 = NRF_QSPI_PIN_VAL(p_pins->io0_pin); + p_reg->PSEL.IO1 = NRF_QSPI_PIN_VAL(p_pins->io1_pin); + p_reg->PSEL.IO2 = NRF_QSPI_PIN_VAL(p_pins->io2_pin); + p_reg->PSEL.IO3 = NRF_QSPI_PIN_VAL(p_pins->io3_pin); +} + +__STATIC_INLINE void nrf_qspi_ifconfig0_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_prot_conf_t * p_config) +{ + uint32_t config = p_config->readoc; + config |= ((uint32_t)p_config->writeoc) << QSPI_IFCONFIG0_WRITEOC_Pos; + config |= ((uint32_t)p_config->addrmode) << QSPI_IFCONFIG0_ADDRMODE_Pos; + config |= (p_config->dpmconfig ? 1U : 0U ) << QSPI_IFCONFIG0_DPMENABLE_Pos; + + p_reg->IFCONFIG0 = config; +} + +__STATIC_INLINE void nrf_qspi_ifconfig1_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_phy_conf_t * p_config) +{ + // IFCONFIG1 mask for reserved fields in the register. + uint32_t config = p_reg->IFCONFIG1 & 0x00FFFF00; + config |= p_config->sck_delay; + config |= (p_config->dpmen ? 1U : 0U) << QSPI_IFCONFIG1_DPMEN_Pos; + config |= ((uint32_t)(p_config->spi_mode)) << QSPI_IFCONFIG1_SPIMODE_Pos; + config |= ((uint32_t)(p_config->sck_freq)) << QSPI_IFCONFIG1_SCKFREQ_Pos; + + p_reg->IFCONFIG1 = config; +} + +__STATIC_INLINE void nrf_qspi_addrconfig_set(NRF_QSPI_Type * p_reg, + const nrf_qspi_addrconfig_conf_t * p_config) +{ + uint32_t config = p_config->opcode; + config |= ((uint32_t)p_config->byte0) << QSPI_ADDRCONF_BYTE0_Pos; + config |= ((uint32_t)p_config->byte1) << QSPI_ADDRCONF_BYTE1_Pos; + config |= ((uint32_t)(p_config->mode)) << QSPI_ADDRCONF_MODE_Pos; + config |= (p_config->wipwait ? 1U : 0U) << QSPI_ADDRCONF_WIPWAIT_Pos; + config |= (p_config->wren ? 1U : 0U) << QSPI_ADDRCONF_WREN_Pos; + + p_reg->ADDRCONF = config; +} + +__STATIC_INLINE void nrf_qspi_write_buffer_set(NRF_QSPI_Type * p_reg, + void const * p_buffer, + uint32_t length, + uint32_t dest_addr) +{ + p_reg->WRITE.DST = dest_addr; + p_reg->WRITE.SRC = (uint32_t) p_buffer; + p_reg->WRITE.CNT = length; +} + +__STATIC_INLINE void nrf_qspi_read_buffer_set(NRF_QSPI_Type * p_reg, + void * p_buffer, + uint32_t length, + uint32_t src_addr) +{ + p_reg->READ.SRC = src_addr; + p_reg->READ.DST = (uint32_t) p_buffer; + p_reg->READ.CNT = length; +} + +__STATIC_INLINE void nrf_qspi_erase_ptr_set(NRF_QSPI_Type * p_reg, + uint32_t erase_addr, + nrf_qspi_erase_len_t len) +{ + p_reg->ERASE.PTR = erase_addr; + p_reg->ERASE.LEN = len; +} + +__STATIC_INLINE uint32_t nrf_qspi_status_reg_get(NRF_QSPI_Type const * p_reg) +{ + return p_reg->STATUS; +} + +__STATIC_INLINE uint8_t nrf_qspi_sreg_get(NRF_QSPI_Type const * p_reg) +{ + return (uint8_t)(p_reg->STATUS & QSPI_STATUS_SREG_Msk) >> QSPI_STATUS_SREG_Pos; +} + +__STATIC_INLINE bool nrf_qspi_busy_check(NRF_QSPI_Type const * p_reg) +{ + return ((p_reg->STATUS & QSPI_STATUS_READY_Msk) >> + QSPI_STATUS_READY_Pos) == QSPI_STATUS_READY_BUSY; +} + +__STATIC_INLINE void nrf_qspi_cinstrdata_set(NRF_QSPI_Type * p_reg, + nrf_qspi_cinstr_len_t length, + void const * p_tx_data) +{ + uint32_t reg = 0; + uint8_t const *p_tx_data_8 = (uint8_t const *) p_tx_data; + + // Load custom instruction. + switch (length) + { + case NRF_QSPI_CINSTR_LEN_9B: + reg |= ((uint32_t)p_tx_data_8[7]) << QSPI_CINSTRDAT1_BYTE7_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_8B: + reg |= ((uint32_t)p_tx_data_8[6]) << QSPI_CINSTRDAT1_BYTE6_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_7B: + reg |= ((uint32_t)p_tx_data_8[5]) << QSPI_CINSTRDAT1_BYTE5_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_6B: + reg |= ((uint32_t)p_tx_data_8[4]); + p_reg->CINSTRDAT1 = reg; + reg = 0; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_5B: + reg |= ((uint32_t)p_tx_data_8[3]) << QSPI_CINSTRDAT0_BYTE3_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_4B: + reg |= ((uint32_t)p_tx_data_8[2]) << QSPI_CINSTRDAT0_BYTE2_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_3B: + reg |= ((uint32_t)p_tx_data_8[1]) << QSPI_CINSTRDAT0_BYTE1_Pos; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_2B: + reg |= ((uint32_t)p_tx_data_8[0]); + p_reg->CINSTRDAT0 = reg; + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_1B: + /* Send only opcode. Case to avoid compiler warnings. */ + break; + default: + break; + } +} + +__STATIC_INLINE void nrf_qspi_cinstrdata_get(NRF_QSPI_Type const * p_reg, + nrf_qspi_cinstr_len_t length, + void * p_rx_data) +{ + uint8_t *p_rx_data_8 = (uint8_t *) p_rx_data; + + uint32_t reg = p_reg->CINSTRDAT1; + switch (length) + { + case NRF_QSPI_CINSTR_LEN_9B: + p_rx_data_8[7] = (uint8_t)(reg >> QSPI_CINSTRDAT1_BYTE7_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_8B: + p_rx_data_8[6] = (uint8_t)(reg >> QSPI_CINSTRDAT1_BYTE6_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_7B: + p_rx_data_8[5] = (uint8_t)(reg >> QSPI_CINSTRDAT1_BYTE5_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_6B: + p_rx_data_8[4] = (uint8_t)(reg); + /* fall-through */ + default: + break; + } + + reg = p_reg->CINSTRDAT0; + switch (length) + { + case NRF_QSPI_CINSTR_LEN_5B: + p_rx_data_8[3] = (uint8_t)(reg >> QSPI_CINSTRDAT0_BYTE3_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_4B: + p_rx_data_8[2] = (uint8_t)(reg >> QSPI_CINSTRDAT0_BYTE2_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_3B: + p_rx_data_8[1] = (uint8_t)(reg >> QSPI_CINSTRDAT0_BYTE1_Pos); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_2B: + p_rx_data_8[0] = (uint8_t)(reg); + /* fall-through */ + case NRF_QSPI_CINSTR_LEN_1B: + /* Send only opcode. Case to avoid compiler warnings. */ + break; + default: + break; + } +} + +__STATIC_INLINE void nrf_qspi_cinstr_transfer_start(NRF_QSPI_Type * p_reg, + const nrf_qspi_cinstr_conf_t * p_config) +{ + p_reg->CINSTRCONF = (((uint32_t)p_config->opcode << QSPI_CINSTRCONF_OPCODE_Pos) | + ((uint32_t)p_config->length << QSPI_CINSTRCONF_LENGTH_Pos) | + ((uint32_t)p_config->io2_level << QSPI_CINSTRCONF_LIO2_Pos) | + ((uint32_t)p_config->io3_level << QSPI_CINSTRCONF_LIO3_Pos) | + ((uint32_t)p_config->wipwait << QSPI_CINSTRCONF_WIPWAIT_Pos) | + ((uint32_t)p_config->wren << QSPI_CINSTRCONF_WREN_Pos)); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_QSPI_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rng.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rng.h new file mode 100644 index 0000000000..9ebf81748a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rng.h @@ -0,0 +1,282 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief RNG HAL API. + */ + +#ifndef NRF_RNG_H__ +#define NRF_RNG_H__ +/** + * @defgroup nrf_rng_hal RNG HAL + * @{ + * @ingroup nrf_rng + * @brief Hardware access layer for managing the random number generator (RNG). + */ + +#include +#include +#include +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_RNG_TASK_SET (1UL) +#define NRF_RNG_EVENT_CLEAR (0UL) +/** + * @enum nrf_rng_task_t + * @brief RNG tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_RNG_TASK_START = offsetof(NRF_RNG_Type, TASKS_START), /**< Start the random number generator. */ + NRF_RNG_TASK_STOP = offsetof(NRF_RNG_Type, TASKS_STOP) /**< Stop the random number generator. */ +} nrf_rng_task_t; /*lint -restore */ + +/** + * @enum nrf_rng_event_t + * @brief RNG events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_RNG_EVENT_VALRDY = offsetof(NRF_RNG_Type, EVENTS_VALRDY) /**< New random number generated event. */ +} nrf_rng_event_t; /*lint -restore */ + +/** + * @enum nrf_rng_int_mask_t + * @brief RNG interrupts. + */ +typedef enum +{ + NRF_RNG_INT_VALRDY_MASK = RNG_INTENSET_VALRDY_Msk /**< Mask for enabling or disabling an interrupt on VALRDY event. */ +} nrf_rng_int_mask_t; + +/** + * @enum nrf_rng_short_mask_t + * @brief Types of RNG shortcuts. + */ +typedef enum +{ + NRF_RNG_SHORT_VALRDY_STOP_MASK = RNG_SHORTS_VALRDY_STOP_Msk /**< Mask for setting shortcut between EVENT_VALRDY and TASK_STOP. */ +} nrf_rng_short_mask_t; + +/** + * @brief Function for enabling interrupts. + * + * @param[in] rng_int_mask Mask of interrupts. + */ +__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask); + +/** + * @brief Function for disabling interrupts. + * + * @param[in] rng_int_mask Mask of interrupts. + */ +__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask); + +/** + * @brief Function for getting the state of a specific interrupt. + * + * @param[in] rng_int_mask Interrupt. + * + * @retval true If the interrupt is not enabled. + * @retval false If the interrupt is enabled. + */ +__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask); + +/** + * @brief Function for getting the address of a specific task. + * + * This function can be used by the PPI module. + * + * @param[in] rng_task Task. + */ +__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task); + +/** + * @brief Function for setting a specific task. + * + * @param[in] rng_task Task. + */ +__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task); + +/** + * @brief Function for getting address of a specific event. + * + * This function can be used by the PPI module. + * + * @param[in] rng_event Event. + */ +__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event); + +/** + * @brief Function for clearing a specific event. + * + * @param[in] rng_event Event. + */ +__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event); + +/** + * @brief Function for getting the state of a specific event. + * + * @param[in] rng_event Event. + * + * @retval true If the event is not set. + * @retval false If the event is set. + */ +__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event); + +/** + * @brief Function for setting shortcuts. + * + * @param[in] rng_short_mask Mask of shortcuts. + * + */ +__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask); + +/** + * @brief Function for clearing shortcuts. + * + * @param[in] rng_short_mask Mask of shortcuts. + * + */ +__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask); + +/** + * @brief Function for getting the previously generated random value. + * + * @return Previously generated random value. + */ +__STATIC_INLINE uint8_t nrf_rng_random_value_get(void); + +/** + * @brief Function for enabling digital error correction. + */ +__STATIC_INLINE void nrf_rng_error_correction_enable(void); + +/** + * @brief Function for disabling digital error correction. + */ +__STATIC_INLINE void nrf_rng_error_correction_disable(void); + +/** + *@} + **/ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask) +{ + NRF_RNG->INTENSET = rng_int_mask; +} + +__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask) +{ + NRF_RNG->INTENCLR = rng_int_mask; +} + +__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask) +{ + return (bool)(NRF_RNG->INTENCLR & rng_int_mask); +} + +__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task) +{ + return (uint32_t *)((uint8_t *)NRF_RNG + rng_task); +} + +__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_task)) = NRF_RNG_TASK_SET; +} + +__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event) +{ + return (uint32_t *)((uint8_t *)NRF_RNG + rng_event); +} + +__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)) = NRF_RNG_EVENT_CLEAR; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event) +{ + return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)); +} + +__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask) +{ + NRF_RNG->SHORTS |= rng_short_mask; +} + +__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask) +{ + NRF_RNG->SHORTS &= ~rng_short_mask; +} + +__STATIC_INLINE uint8_t nrf_rng_random_value_get(void) +{ + return (uint8_t)(NRF_RNG->VALUE & RNG_VALUE_VALUE_Msk); +} + +__STATIC_INLINE void nrf_rng_error_correction_enable(void) +{ + NRF_RNG->CONFIG |= RNG_CONFIG_DERCEN_Msk; +} + +__STATIC_INLINE void nrf_rng_error_correction_disable(void) +{ + NRF_RNG->CONFIG &= ~RNG_CONFIG_DERCEN_Msk; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_RNG_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rtc.h new file mode 100644 index 0000000000..1b1f83988e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_rtc.h @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief RTC HAL API. + */ + +#ifndef NRF_RTC_H +#define NRF_RTC_H + +/** + * @defgroup nrf_rtc_hal RTC HAL + * @{ + * @ingroup nrf_rtc + * @brief Hardware access layer for managing the real time counter (RTC). + */ + +#include +#include +#include +#include "nrf.h" +#include "nrf_assert.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Macro for getting the number of compare channels available + * in a given RTC instance. + */ + +#define NRF_RTC_CC_CHANNEL_COUNT(id) CONCAT_3(RTC, id, _CC_NUM) + +#define RTC_INPUT_FREQ 32768 /**< Input frequency of the RTC instance. */ + +/** + * @brief Macro for converting expected frequency to prescaler setting. + */ +#define RTC_FREQ_TO_PRESCALER(FREQ) (uint16_t)(((RTC_INPUT_FREQ) / (FREQ)) - 1) + +/**< Macro for wrapping values to RTC capacity. */ +#define RTC_WRAP(val) ((val) & RTC_COUNTER_COUNTER_Msk) + +#define RTC_CHANNEL_INT_MASK(ch) ((uint32_t)(NRF_RTC_INT_COMPARE0_MASK) << (ch)) +#define RTC_CHANNEL_EVENT_ADDR(ch) (nrf_rtc_event_t)((NRF_RTC_EVENT_COMPARE_0) + (ch) * sizeof(uint32_t)) +/** + * @enum nrf_rtc_task_t + * @brief RTC tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_RTC_TASK_START = offsetof(NRF_RTC_Type,TASKS_START), /**< Start. */ + NRF_RTC_TASK_STOP = offsetof(NRF_RTC_Type,TASKS_STOP), /**< Stop. */ + NRF_RTC_TASK_CLEAR = offsetof(NRF_RTC_Type,TASKS_CLEAR), /**< Clear. */ + NRF_RTC_TASK_TRIGGER_OVERFLOW = offsetof(NRF_RTC_Type,TASKS_TRIGOVRFLW),/**< Trigger overflow. */ + /*lint -restore*/ +} nrf_rtc_task_t; + +/** + * @enum nrf_rtc_event_t + * @brief RTC events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_RTC_EVENT_TICK = offsetof(NRF_RTC_Type,EVENTS_TICK), /**< Tick event. */ + NRF_RTC_EVENT_OVERFLOW = offsetof(NRF_RTC_Type,EVENTS_OVRFLW), /**< Overflow event. */ + NRF_RTC_EVENT_COMPARE_0 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[0]), /**< Compare 0 event. */ + NRF_RTC_EVENT_COMPARE_1 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[1]), /**< Compare 1 event. */ + NRF_RTC_EVENT_COMPARE_2 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[2]), /**< Compare 2 event. */ + NRF_RTC_EVENT_COMPARE_3 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[3]) /**< Compare 3 event. */ + /*lint -restore*/ +} nrf_rtc_event_t; + +/** + * @enum nrf_rtc_int_t + * @brief RTC interrupts. + */ +typedef enum +{ + NRF_RTC_INT_TICK_MASK = RTC_INTENSET_TICK_Msk, /**< RTC interrupt from tick event. */ + NRF_RTC_INT_OVERFLOW_MASK = RTC_INTENSET_OVRFLW_Msk, /**< RTC interrupt from overflow event. */ + NRF_RTC_INT_COMPARE0_MASK = RTC_INTENSET_COMPARE0_Msk, /**< RTC interrupt from compare event on channel 0. */ + NRF_RTC_INT_COMPARE1_MASK = RTC_INTENSET_COMPARE1_Msk, /**< RTC interrupt from compare event on channel 1. */ + NRF_RTC_INT_COMPARE2_MASK = RTC_INTENSET_COMPARE2_Msk, /**< RTC interrupt from compare event on channel 2. */ + NRF_RTC_INT_COMPARE3_MASK = RTC_INTENSET_COMPARE3_Msk /**< RTC interrupt from compare event on channel 3. */ +} nrf_rtc_int_t; + +/**@brief Function for setting a compare value for a channel. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] ch Channel. + * @param[in] cc_val Compare value to set. + */ +__STATIC_INLINE void nrf_rtc_cc_set(NRF_RTC_Type * p_rtc, uint32_t ch, uint32_t cc_val); + +/**@brief Function for returning the compare value for a channel. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] ch Channel. + * + * @return COMPARE[ch] value. + */ +__STATIC_INLINE uint32_t nrf_rtc_cc_get(NRF_RTC_Type * p_rtc, uint32_t ch); + +/**@brief Function for enabling interrupts. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] mask Interrupt mask to be enabled. + */ +__STATIC_INLINE void nrf_rtc_int_enable(NRF_RTC_Type * p_rtc, uint32_t mask); + +/**@brief Function for disabling interrupts. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] mask Interrupt mask to be disabled. + */ +__STATIC_INLINE void nrf_rtc_int_disable(NRF_RTC_Type * p_rtc, uint32_t mask); + +/**@brief Function for checking if interrupts are enabled. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] mask Mask of interrupt flags to check. + * + * @return Mask with enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_rtc_int_is_enabled(NRF_RTC_Type * p_rtc, uint32_t mask); + +/**@brief Function for returning the status of currently enabled interrupts. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * + * @return Value in INTEN register. + */ +__STATIC_INLINE uint32_t nrf_rtc_int_get(NRF_RTC_Type * p_rtc); + +/**@brief Function for checking if an event is pending. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] event Address of the event. + * + * @return Mask of pending events. + */ +__STATIC_INLINE uint32_t nrf_rtc_event_pending(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event); + +/**@brief Function for clearing an event. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_rtc_event_clear(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event); + +/**@brief Function for returning a counter value. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * + * @return Counter value. + */ +__STATIC_INLINE uint32_t nrf_rtc_counter_get(NRF_RTC_Type * p_rtc); + +/**@brief Function for setting a prescaler value. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] val Value to set the prescaler to. + */ +__STATIC_INLINE void nrf_rtc_prescaler_set(NRF_RTC_Type * p_rtc, uint32_t val); + +/**@brief Function for returning the address of an event. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the requested event register. + */ +__STATIC_INLINE uint32_t nrf_rtc_event_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event); + +/**@brief Function for returning the address of a task. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the requested task register. + */ +__STATIC_INLINE uint32_t nrf_rtc_task_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task); + +/**@brief Function for starting a task. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] task Requested task. + */ +__STATIC_INLINE void nrf_rtc_task_trigger(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task); + +/**@brief Function for enabling events. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] mask Mask of event flags to enable. + */ +__STATIC_INLINE void nrf_rtc_event_enable(NRF_RTC_Type * p_rtc, uint32_t mask); + +/**@brief Function for disabling an event. + * + * @param[in] p_rtc Pointer to the peripheral registers structure. + * @param[in] event Requested event. + */ +__STATIC_INLINE void nrf_rtc_event_disable(NRF_RTC_Type * p_rtc, uint32_t event); + +/** + *@} + **/ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_rtc_cc_set(NRF_RTC_Type * p_rtc, uint32_t ch, uint32_t cc_val) +{ + p_rtc->CC[ch] = cc_val; +} + +__STATIC_INLINE uint32_t nrf_rtc_cc_get(NRF_RTC_Type * p_rtc, uint32_t ch) +{ + return p_rtc->CC[ch]; +} + +__STATIC_INLINE void nrf_rtc_int_enable(NRF_RTC_Type * p_rtc, uint32_t mask) +{ + p_rtc->INTENSET = mask; +} + +__STATIC_INLINE void nrf_rtc_int_disable(NRF_RTC_Type * p_rtc, uint32_t mask) +{ + p_rtc->INTENCLR = mask; +} + +__STATIC_INLINE uint32_t nrf_rtc_int_is_enabled(NRF_RTC_Type * p_rtc, uint32_t mask) +{ + return (p_rtc->INTENSET & mask); +} + +__STATIC_INLINE uint32_t nrf_rtc_int_get(NRF_RTC_Type * p_rtc) +{ + return p_rtc->INTENSET; +} + +__STATIC_INLINE uint32_t nrf_rtc_event_pending(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event) +{ + return *(volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event); +} + +__STATIC_INLINE void nrf_rtc_event_clear(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event)) = 0; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE uint32_t nrf_rtc_counter_get(NRF_RTC_Type * p_rtc) +{ + return p_rtc->COUNTER; +} + +__STATIC_INLINE void nrf_rtc_prescaler_set(NRF_RTC_Type * p_rtc, uint32_t val) +{ + ASSERT(val <= (RTC_PRESCALER_PRESCALER_Msk >> RTC_PRESCALER_PRESCALER_Pos)); + p_rtc->PRESCALER = val; +} +__STATIC_INLINE uint32_t rtc_prescaler_get(NRF_RTC_Type * p_rtc) +{ + return p_rtc->PRESCALER; +} + +__STATIC_INLINE uint32_t nrf_rtc_event_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event) +{ + return (uint32_t)p_rtc + event; +} + +__STATIC_INLINE uint32_t nrf_rtc_task_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task) +{ + return (uint32_t)p_rtc + task; +} + +__STATIC_INLINE void nrf_rtc_task_trigger(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task) +{ + *(__IO uint32_t *)((uint32_t)p_rtc + task) = 1; +} + +__STATIC_INLINE void nrf_rtc_event_enable(NRF_RTC_Type * p_rtc, uint32_t mask) +{ + p_rtc->EVTENSET = mask; +} +__STATIC_INLINE void nrf_rtc_event_disable(NRF_RTC_Type * p_rtc, uint32_t mask) +{ + p_rtc->EVTENCLR = mask; +} +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_RTC_H */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.c new file mode 100644 index 0000000000..c028eaa49e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.c @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief SAADC HAL implementation + */ +#include "sdk_config.h" +#if SAADC_ENABLED +#include "nrf_saadc.h" + +void nrf_saadc_channel_init(uint8_t channel, nrf_saadc_channel_config_t const * const config) +{ + NRF_SAADC->CH[channel].CONFIG = + ((config->resistor_p << SAADC_CH_CONFIG_RESP_Pos) & SAADC_CH_CONFIG_RESP_Msk) + | ((config->resistor_n << SAADC_CH_CONFIG_RESN_Pos) & SAADC_CH_CONFIG_RESN_Msk) + | ((config->gain << SAADC_CH_CONFIG_GAIN_Pos) & SAADC_CH_CONFIG_GAIN_Msk) + | ((config->reference << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk) + | ((config->acq_time << SAADC_CH_CONFIG_TACQ_Pos) & SAADC_CH_CONFIG_TACQ_Msk) + | ((config->mode << SAADC_CH_CONFIG_MODE_Pos) & SAADC_CH_CONFIG_MODE_Msk) + | ((config->burst << SAADC_CH_CONFIG_BURST_Pos) & SAADC_CH_CONFIG_BURST_Msk); + nrf_saadc_channel_input_set(channel, config->pin_p, config->pin_n); + return; +} +#endif //SAADC_ENABLED + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.h new file mode 100644 index 0000000000..73eb8128b1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_saadc.h @@ -0,0 +1,609 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SAADC_H_ +#define NRF_SAADC_H_ + +/** + * @defgroup nrf_saadc_hal SAADC HAL + * @{ + * @ingroup nrf_saadc + * + * @brief @tagAPI52 Hardware access layer for accessing the SAADC peripheral. + */ + +#include +#include +#include "nrf.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_SAADC_CHANNEL_COUNT 8 + +/** + * @brief Resolution of the analog-to-digital converter. + */ +typedef enum +{ + NRF_SAADC_RESOLUTION_8BIT = SAADC_RESOLUTION_VAL_8bit, ///< 8 bit resolution. + NRF_SAADC_RESOLUTION_10BIT = SAADC_RESOLUTION_VAL_10bit, ///< 10 bit resolution. + NRF_SAADC_RESOLUTION_12BIT = SAADC_RESOLUTION_VAL_12bit, ///< 12 bit resolution. + NRF_SAADC_RESOLUTION_14BIT = SAADC_RESOLUTION_VAL_14bit ///< 14 bit resolution. +} nrf_saadc_resolution_t; + + +/** + * @brief Input selection for the analog-to-digital converter. + */ +typedef enum +{ + NRF_SAADC_INPUT_DISABLED = SAADC_CH_PSELP_PSELP_NC, ///< Not connected. + NRF_SAADC_INPUT_AIN0 = SAADC_CH_PSELP_PSELP_AnalogInput0, ///< Analog input 0 (AIN0). + NRF_SAADC_INPUT_AIN1 = SAADC_CH_PSELP_PSELP_AnalogInput1, ///< Analog input 1 (AIN1). + NRF_SAADC_INPUT_AIN2 = SAADC_CH_PSELP_PSELP_AnalogInput2, ///< Analog input 2 (AIN2). + NRF_SAADC_INPUT_AIN3 = SAADC_CH_PSELP_PSELP_AnalogInput3, ///< Analog input 3 (AIN3). + NRF_SAADC_INPUT_AIN4 = SAADC_CH_PSELP_PSELP_AnalogInput4, ///< Analog input 4 (AIN4). + NRF_SAADC_INPUT_AIN5 = SAADC_CH_PSELP_PSELP_AnalogInput5, ///< Analog input 5 (AIN5). + NRF_SAADC_INPUT_AIN6 = SAADC_CH_PSELP_PSELP_AnalogInput6, ///< Analog input 6 (AIN6). + NRF_SAADC_INPUT_AIN7 = SAADC_CH_PSELP_PSELP_AnalogInput7, ///< Analog input 7 (AIN7). + NRF_SAADC_INPUT_VDD = SAADC_CH_PSELP_PSELP_VDD ///< VDD as input. +} nrf_saadc_input_t; + + +/** + * @brief Analog-to-digital converter oversampling mode. + */ +typedef enum +{ + NRF_SAADC_OVERSAMPLE_DISABLED = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass, ///< No oversampling. + NRF_SAADC_OVERSAMPLE_2X = SAADC_OVERSAMPLE_OVERSAMPLE_Over2x, ///< Oversample 2x. + NRF_SAADC_OVERSAMPLE_4X = SAADC_OVERSAMPLE_OVERSAMPLE_Over4x, ///< Oversample 4x. + NRF_SAADC_OVERSAMPLE_8X = SAADC_OVERSAMPLE_OVERSAMPLE_Over8x, ///< Oversample 8x. + NRF_SAADC_OVERSAMPLE_16X = SAADC_OVERSAMPLE_OVERSAMPLE_Over16x, ///< Oversample 16x. + NRF_SAADC_OVERSAMPLE_32X = SAADC_OVERSAMPLE_OVERSAMPLE_Over32x, ///< Oversample 32x. + NRF_SAADC_OVERSAMPLE_64X = SAADC_OVERSAMPLE_OVERSAMPLE_Over64x, ///< Oversample 64x. + NRF_SAADC_OVERSAMPLE_128X = SAADC_OVERSAMPLE_OVERSAMPLE_Over128x, ///< Oversample 128x. + NRF_SAADC_OVERSAMPLE_256X = SAADC_OVERSAMPLE_OVERSAMPLE_Over256x ///< Oversample 256x. +} nrf_saadc_oversample_t; + + +/** + * @brief Analog-to-digital converter channel resistor control. + */ +typedef enum +{ + NRF_SAADC_RESISTOR_DISABLED = SAADC_CH_CONFIG_RESP_Bypass, ///< Bypass resistor ladder. + NRF_SAADC_RESISTOR_PULLDOWN = SAADC_CH_CONFIG_RESP_Pulldown, ///< Pull-down to GND. + NRF_SAADC_RESISTOR_PULLUP = SAADC_CH_CONFIG_RESP_Pullup, ///< Pull-up to VDD. + NRF_SAADC_RESISTOR_VDD1_2 = SAADC_CH_CONFIG_RESP_VDD1_2 ///< Set input at VDD/2. +} nrf_saadc_resistor_t; + + +/** + * @brief Gain factor of the analog-to-digital converter input. + */ +typedef enum +{ + NRF_SAADC_GAIN1_6 = SAADC_CH_CONFIG_GAIN_Gain1_6, ///< Gain factor 1/6. + NRF_SAADC_GAIN1_5 = SAADC_CH_CONFIG_GAIN_Gain1_5, ///< Gain factor 1/5. + NRF_SAADC_GAIN1_4 = SAADC_CH_CONFIG_GAIN_Gain1_4, ///< Gain factor 1/4. + NRF_SAADC_GAIN1_3 = SAADC_CH_CONFIG_GAIN_Gain1_3, ///< Gain factor 1/3. + NRF_SAADC_GAIN1_2 = SAADC_CH_CONFIG_GAIN_Gain1_2, ///< Gain factor 1/2. + NRF_SAADC_GAIN1 = SAADC_CH_CONFIG_GAIN_Gain1, ///< Gain factor 1. + NRF_SAADC_GAIN2 = SAADC_CH_CONFIG_GAIN_Gain2, ///< Gain factor 2. + NRF_SAADC_GAIN4 = SAADC_CH_CONFIG_GAIN_Gain4, ///< Gain factor 4. +} nrf_saadc_gain_t; + + +/** + * @brief Reference selection for the analog-to-digital converter. + */ +typedef enum +{ + NRF_SAADC_REFERENCE_INTERNAL = SAADC_CH_CONFIG_REFSEL_Internal, ///< Internal reference (0.6 V). + NRF_SAADC_REFERENCE_VDD4 = SAADC_CH_CONFIG_REFSEL_VDD1_4 ///< VDD/4 as reference. +} nrf_saadc_reference_t; + + +/** + * @brief Analog-to-digital converter acquisition time. + */ +typedef enum +{ + NRF_SAADC_ACQTIME_3US = SAADC_CH_CONFIG_TACQ_3us, ///< 3 us. + NRF_SAADC_ACQTIME_5US = SAADC_CH_CONFIG_TACQ_5us, ///< 5 us. + NRF_SAADC_ACQTIME_10US = SAADC_CH_CONFIG_TACQ_10us, ///< 10 us. + NRF_SAADC_ACQTIME_15US = SAADC_CH_CONFIG_TACQ_15us, ///< 15 us. + NRF_SAADC_ACQTIME_20US = SAADC_CH_CONFIG_TACQ_20us, ///< 20 us. + NRF_SAADC_ACQTIME_40US = SAADC_CH_CONFIG_TACQ_40us ///< 40 us. +} nrf_saadc_acqtime_t; + + +/** + * @brief Analog-to-digital converter channel mode. + */ +typedef enum +{ + NRF_SAADC_MODE_SINGLE_ENDED = SAADC_CH_CONFIG_MODE_SE, ///< Single ended, PSELN will be ignored, negative input to ADC shorted to GND. + NRF_SAADC_MODE_DIFFERENTIAL = SAADC_CH_CONFIG_MODE_Diff ///< Differential mode. +} nrf_saadc_mode_t; + + +/** + * @brief Analog-to-digital converter channel burst mode. + */ +typedef enum +{ + NRF_SAADC_BURST_DISABLED = SAADC_CH_CONFIG_BURST_Disabled, ///< Burst mode is disabled (normal operation). + NRF_SAADC_BURST_ENABLED = SAADC_CH_CONFIG_BURST_Enabled ///< Burst mode is enabled. SAADC takes 2^OVERSAMPLE number of samples as fast as it can, and sends the average to Data RAM. +} nrf_saadc_burst_t; + + +/** + * @brief Analog-to-digital converter tasks. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_SAADC_TASK_START = offsetof(NRF_SAADC_Type, TASKS_START), ///< Start the ADC and prepare the result buffer in RAM. + NRF_SAADC_TASK_SAMPLE = offsetof(NRF_SAADC_Type, TASKS_SAMPLE), ///< Take one ADC sample. If scan is enabled, all channels are sampled. + NRF_SAADC_TASK_STOP = offsetof(NRF_SAADC_Type, TASKS_STOP), ///< Stop the ADC and terminate any on-going conversion. + NRF_SAADC_TASK_CALIBRATEOFFSET = offsetof(NRF_SAADC_Type, TASKS_CALIBRATEOFFSET), ///< Starts offset auto-calibration. +} nrf_saadc_task_t; + + +/** + * @brief Analog-to-digital converter events. + */ +typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */ +{ + NRF_SAADC_EVENT_STARTED = offsetof(NRF_SAADC_Type, EVENTS_STARTED), ///< The ADC has started. + NRF_SAADC_EVENT_END = offsetof(NRF_SAADC_Type, EVENTS_END), ///< The ADC has filled up the result buffer. + NRF_SAADC_EVENT_DONE = offsetof(NRF_SAADC_Type, EVENTS_DONE), ///< A conversion task has been completed. + NRF_SAADC_EVENT_RESULTDONE = offsetof(NRF_SAADC_Type, EVENTS_RESULTDONE), ///< A result is ready to get transferred to RAM. + NRF_SAADC_EVENT_CALIBRATEDONE = offsetof(NRF_SAADC_Type, EVENTS_CALIBRATEDONE), ///< Calibration is complete. + NRF_SAADC_EVENT_STOPPED = offsetof(NRF_SAADC_Type, EVENTS_STOPPED), ///< The ADC has stopped. + NRF_SAADC_EVENT_CH0_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[0].LIMITH), ///< Last result is equal or above CH[0].LIMIT.HIGH. + NRF_SAADC_EVENT_CH0_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[0].LIMITL), ///< Last result is equal or below CH[0].LIMIT.LOW. + NRF_SAADC_EVENT_CH1_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[1].LIMITH), ///< Last result is equal or above CH[1].LIMIT.HIGH. + NRF_SAADC_EVENT_CH1_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[1].LIMITL), ///< Last result is equal or below CH[1].LIMIT.LOW. + NRF_SAADC_EVENT_CH2_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[2].LIMITH), ///< Last result is equal or above CH[2].LIMIT.HIGH. + NRF_SAADC_EVENT_CH2_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[2].LIMITL), ///< Last result is equal or below CH[2].LIMIT.LOW. + NRF_SAADC_EVENT_CH3_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[3].LIMITH), ///< Last result is equal or above CH[3].LIMIT.HIGH. + NRF_SAADC_EVENT_CH3_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[3].LIMITL), ///< Last result is equal or below CH[3].LIMIT.LOW. + NRF_SAADC_EVENT_CH4_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[4].LIMITH), ///< Last result is equal or above CH[4].LIMIT.HIGH. + NRF_SAADC_EVENT_CH4_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[4].LIMITL), ///< Last result is equal or below CH[4].LIMIT.LOW. + NRF_SAADC_EVENT_CH5_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[5].LIMITH), ///< Last result is equal or above CH[5].LIMIT.HIGH. + NRF_SAADC_EVENT_CH5_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[5].LIMITL), ///< Last result is equal or below CH[5].LIMIT.LOW. + NRF_SAADC_EVENT_CH6_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[6].LIMITH), ///< Last result is equal or above CH[6].LIMIT.HIGH. + NRF_SAADC_EVENT_CH6_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[6].LIMITL), ///< Last result is equal or below CH[6].LIMIT.LOW. + NRF_SAADC_EVENT_CH7_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[7].LIMITH), ///< Last result is equal or above CH[7].LIMIT.HIGH. + NRF_SAADC_EVENT_CH7_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[7].LIMITL) ///< Last result is equal or below CH[7].LIMIT.LOW. +} nrf_saadc_event_t; + + +/** + * @brief Analog-to-digital converter interrupt masks. + */ +typedef enum +{ + NRF_SAADC_INT_STARTED = SAADC_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event. + NRF_SAADC_INT_END = SAADC_INTENSET_END_Msk, ///< Interrupt on EVENTS_END event. + NRF_SAADC_INT_DONE = SAADC_INTENSET_DONE_Msk, ///< Interrupt on EVENTS_DONE event. + NRF_SAADC_INT_RESULTDONE = SAADC_INTENSET_RESULTDONE_Msk, ///< Interrupt on EVENTS_RESULTDONE event. + NRF_SAADC_INT_CALIBRATEDONE = SAADC_INTENSET_CALIBRATEDONE_Msk, ///< Interrupt on EVENTS_CALIBRATEDONE event. + NRF_SAADC_INT_STOPPED = SAADC_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event. + NRF_SAADC_INT_CH0LIMITH = SAADC_INTENSET_CH0LIMITH_Msk, ///< Interrupt on EVENTS_CH[0].LIMITH event. + NRF_SAADC_INT_CH0LIMITL = SAADC_INTENSET_CH0LIMITL_Msk, ///< Interrupt on EVENTS_CH[0].LIMITL event. + NRF_SAADC_INT_CH1LIMITH = SAADC_INTENSET_CH1LIMITH_Msk, ///< Interrupt on EVENTS_CH[1].LIMITH event. + NRF_SAADC_INT_CH1LIMITL = SAADC_INTENSET_CH1LIMITL_Msk, ///< Interrupt on EVENTS_CH[1].LIMITL event. + NRF_SAADC_INT_CH2LIMITH = SAADC_INTENSET_CH2LIMITH_Msk, ///< Interrupt on EVENTS_CH[2].LIMITH event. + NRF_SAADC_INT_CH2LIMITL = SAADC_INTENSET_CH2LIMITL_Msk, ///< Interrupt on EVENTS_CH[2].LIMITL event. + NRF_SAADC_INT_CH3LIMITH = SAADC_INTENSET_CH3LIMITH_Msk, ///< Interrupt on EVENTS_CH[3].LIMITH event. + NRF_SAADC_INT_CH3LIMITL = SAADC_INTENSET_CH3LIMITL_Msk, ///< Interrupt on EVENTS_CH[3].LIMITL event. + NRF_SAADC_INT_CH4LIMITH = SAADC_INTENSET_CH4LIMITH_Msk, ///< Interrupt on EVENTS_CH[4].LIMITH event. + NRF_SAADC_INT_CH4LIMITL = SAADC_INTENSET_CH4LIMITL_Msk, ///< Interrupt on EVENTS_CH[4].LIMITL event. + NRF_SAADC_INT_CH5LIMITH = SAADC_INTENSET_CH5LIMITH_Msk, ///< Interrupt on EVENTS_CH[5].LIMITH event. + NRF_SAADC_INT_CH5LIMITL = SAADC_INTENSET_CH5LIMITL_Msk, ///< Interrupt on EVENTS_CH[5].LIMITL event. + NRF_SAADC_INT_CH6LIMITH = SAADC_INTENSET_CH6LIMITH_Msk, ///< Interrupt on EVENTS_CH[6].LIMITH event. + NRF_SAADC_INT_CH6LIMITL = SAADC_INTENSET_CH6LIMITL_Msk, ///< Interrupt on EVENTS_CH[6].LIMITL event. + NRF_SAADC_INT_CH7LIMITH = SAADC_INTENSET_CH7LIMITH_Msk, ///< Interrupt on EVENTS_CH[7].LIMITH event. + NRF_SAADC_INT_CH7LIMITL = SAADC_INTENSET_CH7LIMITL_Msk, ///< Interrupt on EVENTS_CH[7].LIMITL event. + NRF_SAADC_INT_ALL = 0x7FFFFFFFUL ///< Mask of all interrupts. +} nrf_saadc_int_mask_t; + + +/** + * @brief Analog-to-digital converter value limit type. + */ +typedef enum +{ + NRF_SAADC_LIMIT_LOW = 0, + NRF_SAADC_LIMIT_HIGH = 1 +} nrf_saadc_limit_t; + + +typedef int16_t nrf_saadc_value_t; ///< Type of a single ADC conversion result. + + +/** + * @brief Analog-to-digital converter configuration structure. + */ +typedef struct +{ + nrf_saadc_resolution_t resolution; + nrf_saadc_oversample_t oversample; + nrf_saadc_value_t * buffer; + uint32_t buffer_size; +} nrf_saadc_config_t; + + +/** + * @brief Analog-to-digital converter channel configuration structure. + */ +typedef struct +{ + nrf_saadc_resistor_t resistor_p; + nrf_saadc_resistor_t resistor_n; + nrf_saadc_gain_t gain; + nrf_saadc_reference_t reference; + nrf_saadc_acqtime_t acq_time; + nrf_saadc_mode_t mode; + nrf_saadc_burst_t burst; + nrf_saadc_input_t pin_p; + nrf_saadc_input_t pin_n; +} nrf_saadc_channel_config_t; + + +/** + * @brief Function for triggering a specific SAADC task. + * + * @param[in] saadc_task SAADC task. + */ +__STATIC_INLINE void nrf_saadc_task_trigger(nrf_saadc_task_t saadc_task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_task)) = 0x1UL; +} + + +/** + * @brief Function for getting the address of a specific SAADC task register. + * + * @param[in] saadc_task SAADC task. + * + * @return Address of the specified SAADC task. + */ +__STATIC_INLINE uint32_t nrf_saadc_task_address_get(nrf_saadc_task_t saadc_task) +{ + return (uint32_t)((uint8_t *)NRF_SAADC + (uint32_t)saadc_task); +} + + +/** + * @brief Function for getting the state of a specific SAADC event. + * + * @param[in] saadc_event SAADC event. + * + * @return State of the specified SAADC event. + */ +__STATIC_INLINE bool nrf_saadc_event_check(nrf_saadc_event_t saadc_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event); +} + + +/** + * @brief Function for clearing the specific SAADC event. + * + * @param[in] saadc_event SAADC event. + */ +__STATIC_INLINE void nrf_saadc_event_clear(nrf_saadc_event_t saadc_event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for getting the address of a specific SAADC event register. + * + * @param[in] saadc_event SAADC event. + * + * @return Address of the specified SAADC event. + */ +__STATIC_INLINE uint32_t nrf_saadc_event_address_get(nrf_saadc_event_t saadc_event) +{ + return (uint32_t )((uint8_t *)NRF_SAADC + (uint32_t)saadc_event); +} + + +/** + * @brief Function for getting the address of a specific SAADC limit event register. + * + * @param[in] channel Channel number. + * @param[in] limit_type Low limit or high limit. + * + * @return Address of the specified SAADC limit event. + */ +__STATIC_INLINE volatile uint32_t * nrf_saadc_event_limit_address_get(uint8_t channel, nrf_saadc_limit_t limit_type) +{ + ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); + if (limit_type == NRF_SAADC_LIMIT_HIGH) + { + return &NRF_SAADC->EVENTS_CH[channel].LIMITH; + } + else + { + return &NRF_SAADC->EVENTS_CH[channel].LIMITL; + } +} + + +/** + * @brief Function for getting the SAADC channel monitoring limit events. + * + * @param[in] channel Channel number. + * @param[in] limit_type Low limit or high limit. + */ +__STATIC_INLINE nrf_saadc_event_t nrf_saadc_event_limit_get(uint8_t channel, nrf_saadc_limit_t limit_type) +{ + if (limit_type == NRF_SAADC_LIMIT_HIGH) + { + return (nrf_saadc_event_t)( (uint32_t) NRF_SAADC_EVENT_CH0_LIMITH + + (uint32_t) (NRF_SAADC_EVENT_CH1_LIMITH - NRF_SAADC_EVENT_CH0_LIMITH) + * (uint32_t) channel ); + } + else + { + return (nrf_saadc_event_t)( (uint32_t) NRF_SAADC_EVENT_CH0_LIMITL + + (uint32_t) (NRF_SAADC_EVENT_CH1_LIMITL - NRF_SAADC_EVENT_CH0_LIMITL) + * (uint32_t) channel ); + } +} + + +/** + * @brief Function for configuring the input pins for a specific SAADC channel. + * + * @param[in] channel Channel number. + * @param[in] pselp Positive input. + * @param[in] pseln Negative input. Set to NRF_SAADC_INPUT_DISABLED in single ended mode. + */ +__STATIC_INLINE void nrf_saadc_channel_input_set(uint8_t channel, + nrf_saadc_input_t pselp, + nrf_saadc_input_t pseln) +{ + NRF_SAADC->CH[channel].PSELN = pseln; + NRF_SAADC->CH[channel].PSELP = pselp; +} + + +/** + * @brief Function for setting the SAADC channel monitoring limits. + * + * @param[in] channel Channel number. + * @param[in] low Low limit. + * @param[in] high High limit. + */ +__STATIC_INLINE void nrf_saadc_channel_limits_set(uint8_t channel, int16_t low, int16_t high) +{ + NRF_SAADC->CH[channel].LIMIT = ( + (((uint32_t) low << SAADC_CH_LIMIT_LOW_Pos) & SAADC_CH_LIMIT_LOW_Msk) + | (((uint32_t) high << SAADC_CH_LIMIT_HIGH_Pos) & SAADC_CH_LIMIT_HIGH_Msk)); +} + + +/** + * @brief Function for enabling specified SAADC interrupts. + * + * @param[in] saadc_int_mask Interrupt(s) to enable. + */ +__STATIC_INLINE void nrf_saadc_int_enable(uint32_t saadc_int_mask) +{ + NRF_SAADC->INTENSET = saadc_int_mask; +} + + +/** + * @brief Function for retrieving the state of specified SAADC interrupts. + * + * @param[in] saadc_int_mask Interrupt(s) to check. + * + * @retval true If all specified interrupts are enabled. + * @retval false If at least one of the given interrupts is not enabled. + */ +__STATIC_INLINE bool nrf_saadc_int_enable_check(uint32_t saadc_int_mask) +{ + return (bool)(NRF_SAADC->INTENSET & saadc_int_mask); +} + + +/** + * @brief Function for disabling specified interrupts. + * + * @param saadc_int_mask Interrupt(s) to disable. + */ +__STATIC_INLINE void nrf_saadc_int_disable(uint32_t saadc_int_mask) +{ + NRF_SAADC->INTENCLR = saadc_int_mask; +} + + +/** + * @brief Function for generating masks for SAADC channel limit interrupts. + * + * @param[in] channel SAADC channel number. + * @param[in] limit_type Limit type. + * + * @returns Interrupt mask. + */ +__STATIC_INLINE uint32_t nrf_saadc_limit_int_get(uint8_t channel, nrf_saadc_limit_t limit_type) +{ + ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); + uint32_t mask = (limit_type == NRF_SAADC_LIMIT_LOW) ? NRF_SAADC_INT_CH0LIMITL : NRF_SAADC_INT_CH0LIMITH; + return mask << (channel * 2); +} + + +/** + * @brief Function for checking whether the SAADC is busy. + * + * This function checks whether the analog-to-digital converter is busy with a conversion. + * + * @retval true If the SAADC is busy. + * @retval false If the SAADC is not busy. + */ +__STATIC_INLINE bool nrf_saadc_busy_check(void) +{ + //return ((NRF_SAADC->STATUS & SAADC_STATUS_STATUS_Msk) == SAADC_STATUS_STATUS_Msk); + //simplified for performance + return NRF_SAADC->STATUS; +} + + +/** + * @brief Function for enabling the SAADC. + * + * The analog-to-digital converter must be enabled before use. + */ +__STATIC_INLINE void nrf_saadc_enable(void) +{ + NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos); +} + + +/** + * @brief Function for disabling the SAADC. + */ +__STATIC_INLINE void nrf_saadc_disable(void) +{ + NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos); +} + + +/** + * @brief Function for checking if the SAADC is enabled. + * + * @retval true If the SAADC is enabled. + * @retval false If the SAADC is not enabled. + */ +__STATIC_INLINE bool nrf_saadc_enable_check(void) +{ + //simplified for performance + return NRF_SAADC->ENABLE; +} + + +/** + * @brief Function for initializing the SAADC result buffer. + * + * @param[in] buffer Pointer to the result buffer. + * @param[in] num Size of buffer in words. + */ +__STATIC_INLINE void nrf_saadc_buffer_init(nrf_saadc_value_t * buffer, uint32_t num) +{ + NRF_SAADC->RESULT.PTR = (uint32_t)buffer; + NRF_SAADC->RESULT.MAXCNT = num; +} + +/** + * @brief Function for getting the number of buffer words transferred since last START operation. + * + * @returns Number of words transferred. + */ +__STATIC_INLINE uint16_t nrf_saadc_amount_get(void) +{ + return NRF_SAADC->RESULT.AMOUNT; +} + + +/** + * @brief Function for setting the SAADC sample resolution. + * + * @param[in] resolution Bit resolution. + */ +__STATIC_INLINE void nrf_saadc_resolution_set(nrf_saadc_resolution_t resolution) +{ + NRF_SAADC->RESOLUTION = resolution; +} + + +/** + * @brief Function for configuring the oversampling feature. + * + * @param[in] oversample Oversampling mode. + */ +__STATIC_INLINE void nrf_saadc_oversample_set(nrf_saadc_oversample_t oversample) +{ + NRF_SAADC->OVERSAMPLE = oversample; +} + +/** + * @brief Function for getting the oversampling feature configuration. + * + * @return Oversampling configuration. + */ +__STATIC_INLINE nrf_saadc_oversample_t nrf_saadc_oversample_get(void) +{ + return (nrf_saadc_oversample_t)NRF_SAADC->OVERSAMPLE; +} + +/** + * @brief Function for initializing the SAADC channel. + * + * @param[in] channel Channel number. + * @param[in] config Pointer to the channel configuration structure. + */ +void nrf_saadc_channel_init(uint8_t channel, nrf_saadc_channel_config_t const * const config); + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_SAADC_H_ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spi.h new file mode 100644 index 0000000000..3f7215e73f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spi.h @@ -0,0 +1,375 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_spi_hal SPI HAL + * @{ + * @ingroup nrf_spi + * + * @brief Hardware access layer for accessing the SPI peripheral. + */ + +#ifndef NRF_SPI_H__ +#define NRF_SPI_H__ + +#include +#include +#include + +#include "nrf.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be used as a parameter for the @ref nrf_spi_pins_set + * function to specify that a given SPI signal (SCK, MOSI, or MISO) + * shall not be connected to a physical pin. + */ +#define NRF_SPI_PIN_NOT_CONNECTED 0xFFFFFFFF + + +/** + * @brief SPI events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_SPI_EVENT_READY = offsetof(NRF_SPI_Type, EVENTS_READY) ///< TXD byte sent and RXD byte received. + /*lint -restore*/ +} nrf_spi_event_t; + +/** + * @brief SPI interrupts. + */ +typedef enum +{ + NRF_SPI_INT_READY_MASK = SPI_INTENSET_READY_Msk ///< Interrupt on READY event. +} nrf_spi_int_mask_t; + +/** + * @brief SPI data rates. + */ +typedef enum +{ + NRF_SPI_FREQ_125K = SPI_FREQUENCY_FREQUENCY_K125, ///< 125 kbps. + NRF_SPI_FREQ_250K = SPI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps. + NRF_SPI_FREQ_500K = SPI_FREQUENCY_FREQUENCY_K500, ///< 500 kbps. + NRF_SPI_FREQ_1M = SPI_FREQUENCY_FREQUENCY_M1, ///< 1 Mbps. + NRF_SPI_FREQ_2M = SPI_FREQUENCY_FREQUENCY_M2, ///< 2 Mbps. + NRF_SPI_FREQ_4M = SPI_FREQUENCY_FREQUENCY_M4, ///< 4 Mbps. + // [conversion to 'int' needed to prevent compilers from complaining + // that the provided value (0x80000000UL) is out of range of "int"] + NRF_SPI_FREQ_8M = (int)SPI_FREQUENCY_FREQUENCY_M8 ///< 8 Mbps. +} nrf_spi_frequency_t; + +/** + * @brief SPI modes. + */ +typedef enum +{ + NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock. + NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock. + NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock. + NRF_SPI_MODE_3 ///< SCK active low, sample on trailing edge of clock. +} nrf_spi_mode_t; + +/** + * @brief SPI bit orders. + */ +typedef enum +{ + NRF_SPI_BIT_ORDER_MSB_FIRST = SPI_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first. + NRF_SPI_BIT_ORDER_LSB_FIRST = SPI_CONFIG_ORDER_LsbFirst ///< Least significant bit shifted out first. +} nrf_spi_bit_order_t; + + +/** + * @brief Function for clearing a specific SPI event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_event Event to clear. + */ +__STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event); + +/** + * @brief Function for checking the state of a specific SPI event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event); + +/** + * @brief Function for getting the address of a specific SPI event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg, + uint32_t spi_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg, + uint32_t spi_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_reg, + nrf_spi_int_mask_t spi_int); + +/** + * @brief Function for enabling the SPI peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg); + +/** + * @brief Function for disabling the SPI peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg); + +/** + * @brief Function for configuring SPI pins. + * + * If a given signal is not needed, pass the @ref NRF_SPI_PIN_NOT_CONNECTED + * value instead of its pin number. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] sck_pin SCK pin number. + * @param[in] mosi_pin MOSI pin number. + * @param[in] miso_pin MISO pin number. + */ +__STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin); + +/** + * @brief Function for writing data to the SPI transmitter register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] data TX data to send. + */ +__STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data); + +/** + * @brief Function for reading data from the SPI receiver register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return RX data received. + */ +__STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_reg); + +/** + * @brief Function for setting the SPI master data rate. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency SPI frequency. + */ +__STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg, + nrf_spi_frequency_t frequency); + +/** + * @brief Function for setting the SPI configuration. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_mode SPI mode. + * @param[in] spi_bit_order SPI bit order. + */ +__STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg, + nrf_spi_mode_t spi_mode, + nrf_spi_bit_order_t spi_bit_order); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event); +} + +__STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type * p_reg, + nrf_spi_event_t spi_event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event); +} + +__STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg, + uint32_t spi_int_mask) +{ + p_reg->INTENSET = spi_int_mask; +} + +__STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg, + uint32_t spi_int_mask) +{ + p_reg->INTENCLR = spi_int_mask; +} + +__STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_reg, + nrf_spi_int_mask_t spi_int) +{ + return (bool)(p_reg->INTENSET & spi_int); +} + +__STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg) +{ + p_reg->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg) +{ + p_reg->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin) +{ + p_reg->PSELSCK = sck_pin; + p_reg->PSELMOSI = mosi_pin; + p_reg->PSELMISO = miso_pin; +} + +__STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data) +{ + p_reg->TXD = data; +} + +__STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_reg) +{ + return p_reg->RXD; +} + +__STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg, + nrf_spi_frequency_t frequency) +{ + p_reg->FREQUENCY = frequency; +} + +__STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg, + nrf_spi_mode_t spi_mode, + nrf_spi_bit_order_t spi_bit_order) +{ + uint32_t config = (spi_bit_order == NRF_SPI_BIT_ORDER_MSB_FIRST ? + SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst); + switch (spi_mode) + { + default: + case NRF_SPI_MODE_0: + config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) | + (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos); + break; + + case NRF_SPI_MODE_1: + config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) | + (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos); + break; + + case NRF_SPI_MODE_2: + config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) | + (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos); + break; + + case NRF_SPI_MODE_3: + config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) | + (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos); + break; + } + p_reg->CONFIG = config; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SPI_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spim.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spim.h new file mode 100644 index 0000000000..d20eaa44ab --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spim.h @@ -0,0 +1,571 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_spim_hal SPIM HAL + * @{ + * @ingroup nrf_spi + * + * @brief Hardware access layer for accessing the SPIM peripheral. + */ + +#ifndef NRF_SPIM_H__ +#define NRF_SPIM_H__ + +#include +#include +#include + +#include "nrf.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be used as a parameter for the @ref nrf_spim_pins_set + * function to specify that a given SPI signal (SCK, MOSI, or MISO) + * shall not be connected to a physical pin. + */ +#define NRF_SPIM_PIN_NOT_CONNECTED 0xFFFFFFFF + + +/** + * @brief SPIM tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_SPIM_TASK_START = offsetof(NRF_SPIM_Type, TASKS_START), ///< Start SPI transaction. + NRF_SPIM_TASK_STOP = offsetof(NRF_SPIM_Type, TASKS_STOP), ///< Stop SPI transaction. + NRF_SPIM_TASK_SUSPEND = offsetof(NRF_SPIM_Type, TASKS_SUSPEND), ///< Suspend SPI transaction. + NRF_SPIM_TASK_RESUME = offsetof(NRF_SPIM_Type, TASKS_RESUME) ///< Resume SPI transaction. + /*lint -restore*/ +} nrf_spim_task_t; + +/** + * @brief SPIM events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_SPIM_EVENT_STOPPED = offsetof(NRF_SPIM_Type, EVENTS_STOPPED), ///< SPI transaction has stopped. + NRF_SPIM_EVENT_ENDRX = offsetof(NRF_SPIM_Type, EVENTS_ENDRX), ///< End of RXD buffer reached. + NRF_SPIM_EVENT_END = offsetof(NRF_SPIM_Type, EVENTS_END), ///< End of RXD buffer and TXD buffer reached. + NRF_SPIM_EVENT_ENDTX = offsetof(NRF_SPIM_Type, EVENTS_ENDTX), ///< End of TXD buffer reached. + NRF_SPIM_EVENT_STARTED = offsetof(NRF_SPIM_Type, EVENTS_STARTED) ///< Transaction started. + /*lint -restore*/ +} nrf_spim_event_t; + +/** + * @brief SPIM shortcuts. + */ +typedef enum +{ + NRF_SPIM_SHORT_END_START_MASK = SPIM_SHORTS_END_START_Msk ///< Shortcut between END event and START task. +} nrf_spim_short_mask_t; + +/** + * @brief SPIM interrupts. + */ +typedef enum +{ + NRF_SPIM_INT_STOPPED_MASK = SPIM_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event. + NRF_SPIM_INT_ENDRX_MASK = SPIM_INTENSET_ENDRX_Msk, ///< Interrupt on ENDRX event. + NRF_SPIM_INT_END_MASK = SPIM_INTENSET_END_Msk, ///< Interrupt on END event. + NRF_SPIM_INT_ENDTX_MASK = SPIM_INTENSET_ENDTX_Msk, ///< Interrupt on ENDTX event. + NRF_SPIM_INT_STARTED_MASK = SPIM_INTENSET_STARTED_Msk ///< Interrupt on STARTED event. +} nrf_spim_int_mask_t; + +/** + * @brief SPI master data rates. + */ +typedef enum +{ + NRF_SPIM_FREQ_125K = SPIM_FREQUENCY_FREQUENCY_K125, ///< 125 kbps. + NRF_SPIM_FREQ_250K = SPIM_FREQUENCY_FREQUENCY_K250, ///< 250 kbps. + NRF_SPIM_FREQ_500K = SPIM_FREQUENCY_FREQUENCY_K500, ///< 500 kbps. + NRF_SPIM_FREQ_1M = SPIM_FREQUENCY_FREQUENCY_M1, ///< 1 Mbps. + NRF_SPIM_FREQ_2M = SPIM_FREQUENCY_FREQUENCY_M2, ///< 2 Mbps. + NRF_SPIM_FREQ_4M = SPIM_FREQUENCY_FREQUENCY_M4, ///< 4 Mbps. + // [conversion to 'int' needed to prevent compilers from complaining + // that the provided value (0x80000000UL) is out of range of "int"] + NRF_SPIM_FREQ_8M = (int)SPIM_FREQUENCY_FREQUENCY_M8,///< 8 Mbps. +#ifndef SPI_PRESENT + NRF_SPI_FREQ_125K = NRF_SPIM_FREQ_125K, + NRF_SPI_FREQ_250K = NRF_SPIM_FREQ_250K, + NRF_SPI_FREQ_500K = NRF_SPIM_FREQ_500K, + NRF_SPI_FREQ_1M = NRF_SPIM_FREQ_1M, + NRF_SPI_FREQ_2M = NRF_SPIM_FREQ_2M, + NRF_SPI_FREQ_4M = NRF_SPIM_FREQ_4M, + NRF_SPI_FREQ_8M = NRF_SPIM_FREQ_8M, +#endif +} nrf_spim_frequency_t; + +/** + * @brief SPI modes. + */ +typedef enum +{ + NRF_SPIM_MODE_0, ///< SCK active high, sample on leading edge of clock. + NRF_SPIM_MODE_1, ///< SCK active high, sample on trailing edge of clock. + NRF_SPIM_MODE_2, ///< SCK active low, sample on leading edge of clock. + NRF_SPIM_MODE_3, ///< SCK active low, sample on trailing edge of clock. +#ifndef SPI_PRESENT + NRF_SPI_MODE_0 = NRF_SPIM_MODE_0, + NRF_SPI_MODE_1 = NRF_SPIM_MODE_1, + NRF_SPI_MODE_2 = NRF_SPIM_MODE_2, + NRF_SPI_MODE_3 = NRF_SPIM_MODE_3, +#endif +} nrf_spim_mode_t; + +/** + * @brief SPI bit orders. + */ +typedef enum +{ + NRF_SPIM_BIT_ORDER_MSB_FIRST = SPIM_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first. + NRF_SPIM_BIT_ORDER_LSB_FIRST = SPIM_CONFIG_ORDER_LsbFirst, ///< Least significant bit shifted out first. +#ifndef SPI_PRESENT + NRF_SPI_BIT_ORDER_MSB_FIRST = NRF_SPIM_BIT_ORDER_MSB_FIRST, + NRF_SPI_BIT_ORDER_LSB_FIRST = NRF_SPIM_BIT_ORDER_LSB_FIRST, +#endif +} nrf_spim_bit_order_t; + + +/** + * @brief Function for activating a specific SPIM task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_task Task to activate. + */ +__STATIC_INLINE void nrf_spim_task_trigger(NRF_SPIM_Type * p_reg, + nrf_spim_task_t spim_task); + +/** + * @brief Function for getting the address of a specific SPIM task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t nrf_spim_task_address_get(NRF_SPIM_Type * p_reg, + nrf_spim_task_t spim_task); + +/** + * @brief Function for clearing a specific SPIM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_event Event to clear. + */ +__STATIC_INLINE void nrf_spim_event_clear(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event); + +/** + * @brief Function for checking the state of a specific SPIM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_spim_event_check(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event); + +/** + * @brief Function for getting the address of a specific SPIM event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t nrf_spim_event_address_get(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event); +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_spim_shorts_enable(NRF_SPIM_Type * p_reg, + uint32_t spim_shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_spim_shorts_disable(NRF_SPIM_Type * p_reg, + uint32_t spim_shorts_mask); + +/** + * @brief Function for getting shorts setting. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_spim_shorts_get(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_spim_int_enable(NRF_SPIM_Type * p_reg, + uint32_t spim_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_spim_int_disable(NRF_SPIM_Type * p_reg, + uint32_t spim_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spim_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_spim_int_enable_check(NRF_SPIM_Type * p_reg, + nrf_spim_int_mask_t spim_int); + +/** + * @brief Function for enabling the SPIM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_enable(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for disabling the SPIM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_disable(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for configuring SPIM pins. + * + * If a given signal is not needed, pass the @ref NRF_SPIM_PIN_NOT_CONNECTED + * value instead of its pin number. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] sck_pin SCK pin number. + * @param[in] mosi_pin MOSI pin number. + * @param[in] miso_pin MISO pin number. + */ +__STATIC_INLINE void nrf_spim_pins_set(NRF_SPIM_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin); + +/** + * @brief Function for setting the SPI master data rate. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency SPI frequency. + */ +__STATIC_INLINE void nrf_spim_frequency_set(NRF_SPIM_Type * p_reg, + nrf_spim_frequency_t frequency); + +/** + * @brief Function for setting the transmit buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer with data to send. + * @param[in] length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_spim_tx_buffer_set(NRF_SPIM_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length); + +/** + * @brief Function for setting the receive buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer for received data. + * @param[in] length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_spim_rx_buffer_set(NRF_SPIM_Type * p_reg, + uint8_t * p_buffer, + uint8_t length); + +/** + * @brief Function for setting the SPI configuration. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_mode SPI mode. + * @param[in] spi_bit_order SPI bit order. + */ +__STATIC_INLINE void nrf_spim_configure(NRF_SPIM_Type * p_reg, + nrf_spim_mode_t spi_mode, + nrf_spim_bit_order_t spi_bit_order); + +/** + * @brief Function for setting the over-read character. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] orc Over-read character that is clocked out in case of + * an over-read of the TXD buffer. + */ +__STATIC_INLINE void nrf_spim_orc_set(NRF_SPIM_Type * p_reg, + uint8_t orc); + +/** + * @brief Function for enabling the TX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_tx_list_enable(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for disabling the TX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_tx_list_disable(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for enabling the RX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_rx_list_enable(NRF_SPIM_Type * p_reg); + +/** + * @brief Function for disabling the RX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spim_rx_list_disable(NRF_SPIM_Type * p_reg); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_spim_task_trigger(NRF_SPIM_Type * p_reg, + nrf_spim_task_t spim_task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spim_task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_spim_task_address_get(NRF_SPIM_Type * p_reg, + nrf_spim_task_t spim_task) +{ + return (uint32_t)((uint8_t *)p_reg + (uint32_t)spim_task); +} + +__STATIC_INLINE void nrf_spim_event_clear(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spim_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spim_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_spim_event_check(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spim_event); +} + +__STATIC_INLINE uint32_t nrf_spim_event_address_get(NRF_SPIM_Type * p_reg, + nrf_spim_event_t spim_event) +{ + return (uint32_t)((uint8_t *)p_reg + (uint32_t)spim_event); +} + +__STATIC_INLINE void nrf_spim_shorts_enable(NRF_SPIM_Type * p_reg, + uint32_t spim_shorts_mask) +{ + p_reg->SHORTS |= spim_shorts_mask; +} + +__STATIC_INLINE void nrf_spim_shorts_disable(NRF_SPIM_Type * p_reg, + uint32_t spim_shorts_mask) +{ + p_reg->SHORTS &= ~(spim_shorts_mask); +} + +__STATIC_INLINE uint32_t nrf_spim_shorts_get(NRF_SPIM_Type * p_reg) +{ + return p_reg->SHORTS; +} + +__STATIC_INLINE void nrf_spim_int_enable(NRF_SPIM_Type * p_reg, + uint32_t spim_int_mask) +{ + p_reg->INTENSET = spim_int_mask; +} + +__STATIC_INLINE void nrf_spim_int_disable(NRF_SPIM_Type * p_reg, + uint32_t spim_int_mask) +{ + p_reg->INTENCLR = spim_int_mask; +} + +__STATIC_INLINE bool nrf_spim_int_enable_check(NRF_SPIM_Type * p_reg, + nrf_spim_int_mask_t spim_int) +{ + return (bool)(p_reg->INTENSET & spim_int); +} + +__STATIC_INLINE void nrf_spim_enable(NRF_SPIM_Type * p_reg) +{ + p_reg->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_spim_disable(NRF_SPIM_Type * p_reg) +{ + p_reg->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_spim_pins_set(NRF_SPIM_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin) +{ + p_reg->PSEL.SCK = sck_pin; + p_reg->PSEL.MOSI = mosi_pin; + p_reg->PSEL.MISO = miso_pin; +} + +__STATIC_INLINE void nrf_spim_frequency_set(NRF_SPIM_Type * p_reg, + nrf_spim_frequency_t frequency) +{ + p_reg->FREQUENCY = frequency; +} + +__STATIC_INLINE void nrf_spim_tx_buffer_set(NRF_SPIM_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length) +{ + p_reg->TXD.PTR = (uint32_t)p_buffer; + p_reg->TXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_spim_rx_buffer_set(NRF_SPIM_Type * p_reg, + uint8_t * p_buffer, + uint8_t length) +{ + p_reg->RXD.PTR = (uint32_t)p_buffer; + p_reg->RXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_spim_configure(NRF_SPIM_Type * p_reg, + nrf_spim_mode_t spi_mode, + nrf_spim_bit_order_t spi_bit_order) +{ + uint32_t config = (spi_bit_order == NRF_SPIM_BIT_ORDER_MSB_FIRST ? + SPIM_CONFIG_ORDER_MsbFirst : SPIM_CONFIG_ORDER_LsbFirst); + switch (spi_mode) + { + default: + case NRF_SPIM_MODE_0: + config |= (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) | + (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos); + break; + + case NRF_SPIM_MODE_1: + config |= (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) | + (SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos); + break; + + case NRF_SPIM_MODE_2: + config |= (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) | + (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos); + break; + + case NRF_SPIM_MODE_3: + config |= (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) | + (SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos); + break; + } + p_reg->CONFIG = config; +} + +__STATIC_INLINE void nrf_spim_orc_set(NRF_SPIM_Type * p_reg, + uint8_t orc) +{ + p_reg->ORC = orc; +} + + +__STATIC_INLINE void nrf_spim_tx_list_enable(NRF_SPIM_Type * p_reg) +{ + p_reg->TXD.LIST = 1; +} + +__STATIC_INLINE void nrf_spim_tx_list_disable(NRF_SPIM_Type * p_reg) +{ + p_reg->TXD.LIST = 0; +} + +__STATIC_INLINE void nrf_spim_rx_list_enable(NRF_SPIM_Type * p_reg) +{ + p_reg->RXD.LIST = 1; +} + +__STATIC_INLINE void nrf_spim_rx_list_disable(NRF_SPIM_Type * p_reg) +{ + p_reg->RXD.LIST = 0; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SPIM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spis.h new file mode 100644 index 0000000000..68746ad382 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_spis.h @@ -0,0 +1,553 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_spis_hal SPIS HAL + * @{ + * @ingroup nrf_spis + * + * @brief Hardware access layer for accessing the SPIS peripheral. + */ + +#ifndef NRF_SPIS_H__ +#define NRF_SPIS_H__ + +#include +#include +#include + +#include "nrf.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be used as a parameter for the @ref nrf_spis_pins_set + * function to specify that a given SPI signal (SCK, MOSI, or MISO) + * shall not be connected to a physical pin. + */ +#define NRF_SPIS_PIN_NOT_CONNECTED 0xFFFFFFFF + + +/** + * @brief SPIS tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_SPIS_TASK_ACQUIRE = offsetof(NRF_SPIS_Type, TASKS_ACQUIRE), ///< Acquire SPI semaphore. + NRF_SPIS_TASK_RELEASE = offsetof(NRF_SPIS_Type, TASKS_RELEASE), ///< Release SPI semaphore, enabling the SPI slave to acquire it. + /*lint -restore*/ +} nrf_spis_task_t; + +/** + * @brief SPIS events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_SPIS_EVENT_END = offsetof(NRF_SPIS_Type, EVENTS_END), ///< Granted transaction completed. + NRF_SPIS_EVENT_ACQUIRED = offsetof(NRF_SPIS_Type, EVENTS_ACQUIRED) ///< Semaphore acquired. + /*lint -restore*/ +} nrf_spis_event_t; + +/** + * @brief SPIS shortcuts. + */ +typedef enum +{ + NRF_SPIS_SHORT_END_ACQUIRE = SPIS_SHORTS_END_ACQUIRE_Msk ///< Shortcut between END event and ACQUIRE task. +} nrf_spis_short_mask_t; + +/** + * @brief SPIS interrupts. + */ +typedef enum +{ + NRF_SPIS_INT_END_MASK = SPIS_INTENSET_END_Msk, ///< Interrupt on END event. + NRF_SPIS_INT_ACQUIRED_MASK = SPIS_INTENSET_ACQUIRED_Msk ///< Interrupt on ACQUIRED event. +} nrf_spis_int_mask_t; + +/** + * @brief SPI modes. + */ +typedef enum +{ + NRF_SPIS_MODE_0, ///< SCK active high, sample on leading edge of clock. + NRF_SPIS_MODE_1, ///< SCK active high, sample on trailing edge of clock. + NRF_SPIS_MODE_2, ///< SCK active low, sample on leading edge of clock. + NRF_SPIS_MODE_3 ///< SCK active low, sample on trailing edge of clock. +} nrf_spis_mode_t; + +/** + * @brief SPI bit orders. + */ +typedef enum +{ + NRF_SPIS_BIT_ORDER_MSB_FIRST = SPIS_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first. + NRF_SPIS_BIT_ORDER_LSB_FIRST = SPIS_CONFIG_ORDER_LsbFirst ///< Least significant bit shifted out first. +} nrf_spis_bit_order_t; + +/** + * @brief SPI semaphore status. + */ +typedef enum +{ + NRF_SPIS_SEMSTAT_FREE = 0, ///< Semaphore is free. + NRF_SPIS_SEMSTAT_CPU = 1, ///< Semaphore is assigned to the CPU. + NRF_SPIS_SEMSTAT_SPIS = 2, ///< Semaphore is assigned to the SPI slave. + NRF_SPIS_SEMSTAT_CPUPENDING = 3 ///< Semaphore is assigned to the SPI, but a handover to the CPU is pending. +} nrf_spis_semstat_t; + +/** + * @brief SPIS status. + */ +typedef enum +{ + NRF_SPIS_STATUS_OVERREAD = SPIS_STATUS_OVERREAD_Msk, ///< TX buffer over-read detected and prevented. + NRF_SPIS_STATUS_OVERFLOW = SPIS_STATUS_OVERFLOW_Msk ///< RX buffer overflow detected and prevented. +} nrf_spis_status_mask_t; + +/** + * @brief Function for activating a specific SPIS task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_task Task to activate. + */ +__STATIC_INLINE void nrf_spis_task_trigger(NRF_SPIS_Type * p_reg, + nrf_spis_task_t spis_task); + +/** + * @brief Function for getting the address of a specific SPIS task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t nrf_spis_task_address_get(NRF_SPIS_Type const * p_reg, + nrf_spis_task_t spis_task); + +/** + * @brief Function for clearing a specific SPIS event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_event Event to clear. + */ +__STATIC_INLINE void nrf_spis_event_clear(NRF_SPIS_Type * p_reg, + nrf_spis_event_t spis_event); + +/** + * @brief Function for checking the state of a specific SPIS event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_spis_event_check(NRF_SPIS_Type const * p_reg, + nrf_spis_event_t spis_event); + +/** + * @brief Function for getting the address of a specific SPIS event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t nrf_spis_event_address_get(NRF_SPIS_Type const * p_reg, + nrf_spis_event_t spis_event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_spis_shorts_enable(NRF_SPIS_Type * p_reg, + uint32_t spis_shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_spis_shorts_disable(NRF_SPIS_Type * p_reg, + uint32_t spis_shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_spis_int_enable(NRF_SPIS_Type * p_reg, + uint32_t spis_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_spis_int_disable(NRF_SPIS_Type * p_reg, + uint32_t spis_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spis_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_spis_int_enable_check(NRF_SPIS_Type const * p_reg, + nrf_spis_int_mask_t spis_int); + +/** + * @brief Function for enabling the SPIS peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spis_enable(NRF_SPIS_Type * p_reg); + +/** + * @brief Function for disabling the SPIS peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_spis_disable(NRF_SPIS_Type * p_reg); + +/** + * @brief Function for retrieving the SPIS semaphore status. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @returns Current semaphore status. + */ +__STATIC_INLINE nrf_spis_semstat_t nrf_spis_semaphore_status_get(NRF_SPIS_Type * p_reg); + +/** + * @brief Function for retrieving the SPIS status. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @returns Current SPIS status. + */ +__STATIC_INLINE nrf_spis_status_mask_t nrf_spis_status_get(NRF_SPIS_Type * p_reg); + +/** + * @brief Function for configuring SPIS pins. + * + * If a given signal is not needed, pass the @ref NRF_SPIS_PIN_NOT_CONNECTED + * value instead of its pin number. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] sck_pin SCK pin number. + * @param[in] mosi_pin MOSI pin number. + * @param[in] miso_pin MISO pin number. + * @param[in] csn_pin CSN pin number. + */ +__STATIC_INLINE void nrf_spis_pins_set(NRF_SPIS_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin, + uint32_t csn_pin); + +/** + * @brief Function for setting the transmit buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer that contains the data to send. + * @param[in] length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_spis_tx_buffer_set(NRF_SPIS_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length); + +/** + * @brief Function for setting the receive buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer for received data. + * @param[in] length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_spis_rx_buffer_set(NRF_SPIS_Type * p_reg, + uint8_t * p_buffer, + uint8_t length); + +/** + * @brief Function for getting the number of bytes transmitted + * in the last granted transaction. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @returns Number of bytes transmitted. + */ +__STATIC_INLINE uint8_t nrf_spis_tx_amount_get(NRF_SPIS_Type const * p_reg); + +/** + * @brief Function for getting the number of bytes received + * in the last granted transaction. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @returns Number of bytes received. + */ +__STATIC_INLINE uint8_t nrf_spis_rx_amount_get(NRF_SPIS_Type const * p_reg); + +/** + * @brief Function for setting the SPI configuration. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] spi_mode SPI mode. + * @param[in] spi_bit_order SPI bit order. + */ +__STATIC_INLINE void nrf_spis_configure(NRF_SPIS_Type * p_reg, + nrf_spis_mode_t spi_mode, + nrf_spis_bit_order_t spi_bit_order); + +/** + * @brief Function for setting the default character. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] def Default character that is clocked out in case of + * an overflow of the RXD buffer. + */ +__STATIC_INLINE void nrf_spis_def_set(NRF_SPIS_Type * p_reg, + uint8_t def); + +/** + * @brief Function for setting the over-read character. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] orc Over-read character that is clocked out in case of + * an over-read of the TXD buffer. + */ +__STATIC_INLINE void nrf_spis_orc_set(NRF_SPIS_Type * p_reg, + uint8_t orc); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_spis_task_trigger(NRF_SPIS_Type * p_reg, + nrf_spis_task_t spis_task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spis_task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_spis_task_address_get(NRF_SPIS_Type const * p_reg, + nrf_spis_task_t spis_task) +{ + return (uint32_t)p_reg + (uint32_t)spis_task; +} + +__STATIC_INLINE void nrf_spis_event_clear(NRF_SPIS_Type * p_reg, + nrf_spis_event_t spis_event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spis_event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spis_event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_spis_event_check(NRF_SPIS_Type const * p_reg, + nrf_spis_event_t spis_event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spis_event); +} + +__STATIC_INLINE uint32_t nrf_spis_event_address_get(NRF_SPIS_Type const * p_reg, + nrf_spis_event_t spis_event) +{ + return (uint32_t)p_reg + (uint32_t)spis_event; +} + +__STATIC_INLINE void nrf_spis_shorts_enable(NRF_SPIS_Type * p_reg, + uint32_t spis_shorts_mask) +{ + p_reg->SHORTS |= spis_shorts_mask; +} + +__STATIC_INLINE void nrf_spis_shorts_disable(NRF_SPIS_Type * p_reg, + uint32_t spis_shorts_mask) +{ + p_reg->SHORTS &= ~(spis_shorts_mask); +} + +__STATIC_INLINE void nrf_spis_int_enable(NRF_SPIS_Type * p_reg, + uint32_t spis_int_mask) +{ + p_reg->INTENSET = spis_int_mask; +} + +__STATIC_INLINE void nrf_spis_int_disable(NRF_SPIS_Type * p_reg, + uint32_t spis_int_mask) +{ + p_reg->INTENCLR = spis_int_mask; +} + +__STATIC_INLINE bool nrf_spis_int_enable_check(NRF_SPIS_Type const * p_reg, + nrf_spis_int_mask_t spis_int) +{ + return (bool)(p_reg->INTENSET & spis_int); +} + +__STATIC_INLINE void nrf_spis_enable(NRF_SPIS_Type * p_reg) +{ + p_reg->ENABLE = (SPIS_ENABLE_ENABLE_Enabled << SPIS_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_spis_disable(NRF_SPIS_Type * p_reg) +{ + p_reg->ENABLE = (SPIS_ENABLE_ENABLE_Disabled << SPIS_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE nrf_spis_semstat_t nrf_spis_semaphore_status_get(NRF_SPIS_Type * p_reg) +{ + return (nrf_spis_semstat_t) ((p_reg->SEMSTAT & SPIS_SEMSTAT_SEMSTAT_Msk) + >> SPIS_SEMSTAT_SEMSTAT_Pos); +} + +__STATIC_INLINE nrf_spis_status_mask_t nrf_spis_status_get(NRF_SPIS_Type * p_reg) +{ + return (nrf_spis_status_mask_t) p_reg->STATUS; +} + +__STATIC_INLINE void nrf_spis_pins_set(NRF_SPIS_Type * p_reg, + uint32_t sck_pin, + uint32_t mosi_pin, + uint32_t miso_pin, + uint32_t csn_pin) +{ + p_reg->PSELSCK = sck_pin; + p_reg->PSELMOSI = mosi_pin; + p_reg->PSELMISO = miso_pin; + p_reg->PSELCSN = csn_pin; +} + +__STATIC_INLINE void nrf_spis_tx_buffer_set(NRF_SPIS_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length) +{ + p_reg->TXDPTR = (uint32_t)p_buffer; + p_reg->MAXTX = length; +} + +__STATIC_INLINE void nrf_spis_rx_buffer_set(NRF_SPIS_Type * p_reg, + uint8_t * p_buffer, + uint8_t length) +{ + p_reg->RXDPTR = (uint32_t)p_buffer; + p_reg->MAXRX = length; +} + +__STATIC_INLINE uint8_t nrf_spis_tx_amount_get(NRF_SPIS_Type const * p_reg) +{ + return (uint8_t) p_reg->AMOUNTTX; +} + +__STATIC_INLINE uint8_t nrf_spis_rx_amount_get(NRF_SPIS_Type const * p_reg) +{ + return (uint8_t) p_reg->AMOUNTRX; +} + +__STATIC_INLINE void nrf_spis_configure(NRF_SPIS_Type * p_reg, + nrf_spis_mode_t spi_mode, + nrf_spis_bit_order_t spi_bit_order) +{ + uint32_t config = (spi_bit_order == NRF_SPIS_BIT_ORDER_MSB_FIRST ? + SPIS_CONFIG_ORDER_MsbFirst : SPIS_CONFIG_ORDER_LsbFirst); + + switch (spi_mode) + { + default: + case NRF_SPIS_MODE_0: + config |= (SPIS_CONFIG_CPOL_ActiveHigh << SPIS_CONFIG_CPOL_Pos) | + (SPIS_CONFIG_CPHA_Leading << SPIS_CONFIG_CPHA_Pos); + break; + + case NRF_SPIS_MODE_1: + config |= (SPIS_CONFIG_CPOL_ActiveHigh << SPIS_CONFIG_CPOL_Pos) | + (SPIS_CONFIG_CPHA_Trailing << SPIS_CONFIG_CPHA_Pos); + break; + + case NRF_SPIS_MODE_2: + config |= (SPIS_CONFIG_CPOL_ActiveLow << SPIS_CONFIG_CPOL_Pos) | + (SPIS_CONFIG_CPHA_Leading << SPIS_CONFIG_CPHA_Pos); + break; + + case NRF_SPIS_MODE_3: + config |= (SPIS_CONFIG_CPOL_ActiveLow << SPIS_CONFIG_CPOL_Pos) | + (SPIS_CONFIG_CPHA_Trailing << SPIS_CONFIG_CPHA_Pos); + break; + } + p_reg->CONFIG = config; +} + +__STATIC_INLINE void nrf_spis_orc_set(NRF_SPIS_Type * p_reg, + uint8_t orc) +{ + p_reg->ORC = orc; +} + +__STATIC_INLINE void nrf_spis_def_set(NRF_SPIS_Type * p_reg, + uint8_t def) +{ + p_reg->DEF = def; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SPIS_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_systick.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_systick.h new file mode 100644 index 0000000000..26fbf37e33 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_systick.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SYSTICK_H__ +#define NRF_SYSTICK_H__ + +#include "nrf.h" +#include +#include +#include + +/** + * @defgroup nrf_systick_hal SYSTICK HAL + * @{ + * @ingroup nrf_systick + * + * @brief Hardware access layer for accessing the SYSTICK peripheral. + * + * SYSTICK is ARM peripheral, not Nordic design. + * It means that it has no Nordic-typical interface with Tasks and Events. + * + * Its usage is limited here to implement simple delays. + * Also keep in mind that this timer would be stopped when CPU is sleeping + * (WFE/WFI instruction is successfully executed). + */ + +/** + * @brief Mask of usable bits in the SysTick value + */ +#define NRF_SYSTICK_VAL_MASK SysTick_VAL_CURRENT_Msk + +/** + * @brief Flags used by SysTick configuration. + * + * @sa nrf_systick_csr_set + * @sa nrf_systick_csr_get + */ +typedef enum { + NRF_SYSTICK_CSR_COUNTFLAG_MASK = SysTick_CTRL_COUNTFLAG_Msk, /**< Status flag: Returns 1 if timer counted to 0 since the last read of this register. */ + + NRF_SYSTICK_CSR_CLKSOURCE_MASK = SysTick_CTRL_CLKSOURCE_Msk, /**< Configuration bit: Select the SysTick clock source. */ + NRF_SYSTICK_CSR_CLKSOURCE_REF = 0U << SysTick_CTRL_CLKSOURCE_Pos, /**< Configuration value: Select reference clock. */ + NRF_SYSTICK_CSR_CLKSOURCE_CPU = 1U << SysTick_CTRL_CLKSOURCE_Pos, /**< Configuration value: Select CPU clock. */ + + NRF_SYSTICK_CSR_TICKINT_MASK = SysTick_CTRL_TICKINT_Msk, /**< Configuration bit: Enables SysTick exception request. */ + NRF_SYSTICK_CSR_TICKINT_ENABLE = 1U << SysTick_CTRL_TICKINT_Pos, /**< Configuration value: Counting down to zero does not assert the SysTick exception request. */ + NRF_SYSTICK_CSR_TICKINT_DISABLE = 0U << SysTick_CTRL_TICKINT_Pos, /**< Configuration value: Counting down to zero to asserts the SysTick exception request. */ + + NRF_SYSTICK_CSR_ENABLE_MASK = SysTick_CTRL_ENABLE_Msk, /**< Configuration bit: Enable the SysTick timer. */ + NRF_SYSTICK_CSR_ENABLE = 1U << SysTick_CTRL_ENABLE_Pos, /**< Configuration value: Counter enabled. */ + NRF_SYSTICK_CSR_DISABLE = 0U << SysTick_CTRL_ENABLE_Pos /**< Configuration value: Counter disabled. */ +} nrf_systick_csr_flags_t; + +/** + * @brief Get Configuration and Status Register + * + * @return Values composed by @ref nrf_systick_csr_flags_t. + * @note The @ref NRF_SYSTICK_CSR_COUNTFLAG_MASK value is cleared when CSR register is read. + */ +__STATIC_INLINE uint32_t nrf_systick_csr_get(void); + +/** + * @brief Set Configuration and Status Register + * + * @param[in] val The value composed from @ref nrf_systick_csr_flags_t. + */ +__STATIC_INLINE void nrf_systick_csr_set(uint32_t val); + +/** + * @brief Get the current reload value. + * + * @return The reload register value. + */ +__STATIC_INLINE uint32_t nrf_systick_load_get(void); + +/** + * @brief Configure the reload value. + * + * @param[in] val The value to set in the reload register. + */ +__STATIC_INLINE void nrf_systick_load_set(uint32_t val); + +/** + * @brief Read the SysTick current value + * + * @return The current SysTick value + * @sa NRF_SYSTICK_VAL_MASK + */ +__STATIC_INLINE uint32_t nrf_systick_val_get(void); + +/** + * @brief Clear the SysTick current value + * + * @note The SysTick does not allow setting current value. + * Any write to VAL register would clear the timer. + */ +__STATIC_INLINE void nrf_systick_val_clear(void); + +/** + * @brief Read the calibration register + * + * @return The calibration register value + */ +__STATIC_INLINE uint32_t nrf_systick_calib_get(void); + + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t nrf_systick_csr_get(void) +{ + return SysTick->CTRL; +} + +__STATIC_INLINE void nrf_systick_csr_set(uint32_t val) +{ + SysTick->CTRL = val; +} + +__STATIC_INLINE uint32_t nrf_systick_load_get(void) +{ + return SysTick->LOAD; +} + +__STATIC_INLINE void nrf_systick_load_set(uint32_t val) +{ + SysTick->LOAD = val; +} + +__STATIC_INLINE uint32_t nrf_systick_val_get(void) +{ + return SysTick->VAL; +} + +__STATIC_INLINE void nrf_systick_val_clear(void) +{ + SysTick->VAL = 0; +} + +__STATIC_INLINE uint32_t nrf_systick_calib_get(void) +{ + return SysTick->CALIB; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/** @} */ +#endif /* NRF_SYSTICK_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_temp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_temp.h new file mode 100644 index 0000000000..415a3e74e2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_temp.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_TEMP_H__ +#define NRF_TEMP_H__ + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @defgroup nrf_temperature TEMP (temperature) abstraction +* @{ +* @ingroup nrf_drivers temperature_example +* @brief Temperature module init and read functions. +* +*/ + +/**@cond NO_DOXYGEN */ +#define MASK_SIGN (0x00000200UL) +#define MASK_SIGN_EXTENSION (0xFFFFFC00UL) + +/** + * @brief Function for preparing the temp module for temperature measurement. + * + * This function initializes the TEMP module and writes to the hidden configuration register. + */ +static __INLINE void nrf_temp_init(void) +{ + /**@note Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module */ + *(uint32_t *) 0x4000C504 = 0; +} + +/** + * @brief Function for reading temperature measurement. + * + * The function reads the 10 bit 2's complement value and transforms it to a 32 bit 2's complement value. + */ +static __INLINE int32_t nrf_temp_read(void) +{ + /**@note Workaround for PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly */ + return ((NRF_TEMP->TEMP & MASK_SIGN) != 0) ? (NRF_TEMP->TEMP | MASK_SIGN_EXTENSION) : (NRF_TEMP->TEMP); +} +/**@endcond */ + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_timer.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_timer.h new file mode 100644 index 0000000000..d089d01b35 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_timer.h @@ -0,0 +1,630 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_timer_hal Timer HAL + * @{ + * @ingroup nrf_timer + * + * @brief Hardware access layer for accessing the timer peripheral. + */ + +#ifndef NRF_TIMER_H__ +#define NRF_TIMER_H__ + +#include +#include +#include + +#include "nrf_peripherals.h" +#include "nrf.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Macro for validating the correctness of the BIT_WIDTH setting. + */ + +#define TIMER_MAX_SIZE(id) CONCAT_3(TIMER, id, _MAX_SIZE) + +#define TIMER_BIT_WIDTH_MAX(id, bit_width) \ + (TIMER_MAX_SIZE(id) == 8 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) : \ + (TIMER_MAX_SIZE(id) == 16 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) : \ + (TIMER_MAX_SIZE(id) == 24 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_24) : \ + (TIMER_MAX_SIZE(id) == 32 ? (bit_width == NRF_TIMER_BIT_WIDTH_8) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_16) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_24) || \ + (bit_width == NRF_TIMER_BIT_WIDTH_32) : \ + false)))) + +#if TIMER_COUNT > 3 +#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_reg, bit_width) ( \ + ((p_reg == NRF_TIMER0) && (TIMER_BIT_WIDTH_MAX(0, bit_width))) \ + || ((p_reg == NRF_TIMER1) && (TIMER_BIT_WIDTH_MAX(1, bit_width))) \ + || ((p_reg == NRF_TIMER2) && (TIMER_BIT_WIDTH_MAX(2, bit_width))) \ + || ((p_reg == NRF_TIMER3) && (TIMER_BIT_WIDTH_MAX(3, bit_width))) \ + || ((p_reg == NRF_TIMER4) && (TIMER_BIT_WIDTH_MAX(4, bit_width))) ) + +#else +#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_reg, bit_width) ( \ + ((p_reg == NRF_TIMER0) && TIMER_BIT_WIDTH_MAX(0, bit_width)) \ + || ((p_reg == NRF_TIMER1) && TIMER_BIT_WIDTH_MAX(1, bit_width)) \ + || ((p_reg == NRF_TIMER2) && TIMER_BIT_WIDTH_MAX(2, bit_width)) ) + +#endif + +/** + * @brief Macro for getting the number of capture/compare channels available + * in a given timer instance. + */ +#define NRF_TIMER_CC_CHANNEL_COUNT(id) CONCAT_3(TIMER, id, _CC_NUM) + +/** + * @brief Timer tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_TIMER_TASK_START = offsetof(NRF_TIMER_Type, TASKS_START), ///< Task for starting the timer. + NRF_TIMER_TASK_STOP = offsetof(NRF_TIMER_Type, TASKS_STOP), ///< Task for stopping the timer. + NRF_TIMER_TASK_COUNT = offsetof(NRF_TIMER_Type, TASKS_COUNT), ///< Task for incrementing the timer (in counter mode). + NRF_TIMER_TASK_CLEAR = offsetof(NRF_TIMER_Type, TASKS_CLEAR), ///< Task for resetting the timer value. + NRF_TIMER_TASK_SHUTDOWN = offsetof(NRF_TIMER_Type, TASKS_SHUTDOWN), ///< Task for powering off the timer. + NRF_TIMER_TASK_CAPTURE0 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[0]), ///< Task for capturing the timer value on channel 0. + NRF_TIMER_TASK_CAPTURE1 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[1]), ///< Task for capturing the timer value on channel 1. + NRF_TIMER_TASK_CAPTURE2 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[2]), ///< Task for capturing the timer value on channel 2. + NRF_TIMER_TASK_CAPTURE3 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[3]), ///< Task for capturing the timer value on channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_TASK_CAPTURE4 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[4]), ///< Task for capturing the timer value on channel 4. + NRF_TIMER_TASK_CAPTURE5 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[5]), ///< Task for capturing the timer value on channel 5. +#endif + /*lint -restore*/ +} nrf_timer_task_t; + +/** + * @brief Timer events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TIMER_EVENT_COMPARE0 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[0]), ///< Event from compare channel 0. + NRF_TIMER_EVENT_COMPARE1 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[1]), ///< Event from compare channel 1. + NRF_TIMER_EVENT_COMPARE2 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[2]), ///< Event from compare channel 2. + NRF_TIMER_EVENT_COMPARE3 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[3]), ///< Event from compare channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_EVENT_COMPARE4 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[4]), ///< Event from compare channel 4. + NRF_TIMER_EVENT_COMPARE5 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[5]), ///< Event from compare channel 5. +#endif + /*lint -restore*/ +} nrf_timer_event_t; + +/** + * @brief Types of timer shortcuts. + */ +typedef enum +{ + NRF_TIMER_SHORT_COMPARE0_STOP_MASK = TIMER_SHORTS_COMPARE0_STOP_Msk, ///< Shortcut for stopping the timer based on compare 0. + NRF_TIMER_SHORT_COMPARE1_STOP_MASK = TIMER_SHORTS_COMPARE1_STOP_Msk, ///< Shortcut for stopping the timer based on compare 1. + NRF_TIMER_SHORT_COMPARE2_STOP_MASK = TIMER_SHORTS_COMPARE2_STOP_Msk, ///< Shortcut for stopping the timer based on compare 2. + NRF_TIMER_SHORT_COMPARE3_STOP_MASK = TIMER_SHORTS_COMPARE3_STOP_Msk, ///< Shortcut for stopping the timer based on compare 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_SHORT_COMPARE4_STOP_MASK = TIMER_SHORTS_COMPARE4_STOP_Msk, ///< Shortcut for stopping the timer based on compare 4. + NRF_TIMER_SHORT_COMPARE5_STOP_MASK = TIMER_SHORTS_COMPARE5_STOP_Msk, ///< Shortcut for stopping the timer based on compare 5. +#endif + NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK = TIMER_SHORTS_COMPARE0_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 0. + NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK = TIMER_SHORTS_COMPARE1_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 1. + NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK = TIMER_SHORTS_COMPARE2_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 2. + NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK = TIMER_SHORTS_COMPARE3_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK = TIMER_SHORTS_COMPARE4_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 4. + NRF_TIMER_SHORT_COMPARE5_CLEAR_MASK = TIMER_SHORTS_COMPARE5_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 5. +#endif +} nrf_timer_short_mask_t; + +/** + * @brief Timer modes. + */ +typedef enum +{ + NRF_TIMER_MODE_TIMER = TIMER_MODE_MODE_Timer, ///< Timer mode: timer. + NRF_TIMER_MODE_COUNTER = TIMER_MODE_MODE_Counter, ///< Timer mode: counter. +#if defined(TIMER_MODE_MODE_LowPowerCounter) || defined(__SDK_DOXYGEN__) + NRF_TIMER_MODE_LOW_POWER_COUNTER = TIMER_MODE_MODE_LowPowerCounter, ///< Timer mode: low-power counter. +#endif +} nrf_timer_mode_t; + +/** + * @brief Timer bit width. + */ +typedef enum +{ + NRF_TIMER_BIT_WIDTH_8 = TIMER_BITMODE_BITMODE_08Bit, ///< Timer bit width 8 bit. + NRF_TIMER_BIT_WIDTH_16 = TIMER_BITMODE_BITMODE_16Bit, ///< Timer bit width 16 bit. + NRF_TIMER_BIT_WIDTH_24 = TIMER_BITMODE_BITMODE_24Bit, ///< Timer bit width 24 bit. + NRF_TIMER_BIT_WIDTH_32 = TIMER_BITMODE_BITMODE_32Bit ///< Timer bit width 32 bit. +} nrf_timer_bit_width_t; + +/** + * @brief Timer prescalers. + */ +typedef enum +{ + NRF_TIMER_FREQ_16MHz = 0, ///< Timer frequency 16 MHz. + NRF_TIMER_FREQ_8MHz, ///< Timer frequency 8 MHz. + NRF_TIMER_FREQ_4MHz, ///< Timer frequency 4 MHz. + NRF_TIMER_FREQ_2MHz, ///< Timer frequency 2 MHz. + NRF_TIMER_FREQ_1MHz, ///< Timer frequency 1 MHz. + NRF_TIMER_FREQ_500kHz, ///< Timer frequency 500 kHz. + NRF_TIMER_FREQ_250kHz, ///< Timer frequency 250 kHz. + NRF_TIMER_FREQ_125kHz, ///< Timer frequency 125 kHz. + NRF_TIMER_FREQ_62500Hz, ///< Timer frequency 62500 Hz. + NRF_TIMER_FREQ_31250Hz ///< Timer frequency 31250 Hz. +} nrf_timer_frequency_t; + +/** + * @brief Timer capture/compare channels. + */ +typedef enum +{ + NRF_TIMER_CC_CHANNEL0 = 0, ///< Timer capture/compare channel 0. + NRF_TIMER_CC_CHANNEL1, ///< Timer capture/compare channel 1. + NRF_TIMER_CC_CHANNEL2, ///< Timer capture/compare channel 2. + NRF_TIMER_CC_CHANNEL3, ///< Timer capture/compare channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_CC_CHANNEL4, ///< Timer capture/compare channel 4. + NRF_TIMER_CC_CHANNEL5, ///< Timer capture/compare channel 5. +#endif +} nrf_timer_cc_channel_t; + +/** + * @brief Timer interrupts. + */ +typedef enum +{ + NRF_TIMER_INT_COMPARE0_MASK = TIMER_INTENSET_COMPARE0_Msk, ///< Timer interrupt from compare event on channel 0. + NRF_TIMER_INT_COMPARE1_MASK = TIMER_INTENSET_COMPARE1_Msk, ///< Timer interrupt from compare event on channel 1. + NRF_TIMER_INT_COMPARE2_MASK = TIMER_INTENSET_COMPARE2_Msk, ///< Timer interrupt from compare event on channel 2. + NRF_TIMER_INT_COMPARE3_MASK = TIMER_INTENSET_COMPARE3_Msk, ///< Timer interrupt from compare event on channel 3. +#if (TIMER_COUNT > 3) || defined(__SDK_DOXYGEN__) + NRF_TIMER_INT_COMPARE4_MASK = TIMER_INTENSET_COMPARE4_Msk, ///< Timer interrupt from compare event on channel 4. + NRF_TIMER_INT_COMPARE5_MASK = TIMER_INTENSET_COMPARE5_Msk, ///< Timer interrupt from compare event on channel 5. +#endif +} nrf_timer_int_mask_t; + + +/** + * @brief Function for activating a specific timer task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task); + +/** + * @brief Function for getting the address of a specific timer task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task); + +/** + * @brief Function for clearing a specific timer event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for checking the state of a specific timer event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for getting the address of a specific timer event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] timer_int Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_reg, + uint32_t timer_int); + +/** + * @brief Function for setting the timer mode. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] mode Timer mode. + */ +__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_reg, + nrf_timer_mode_t mode); + +/** + * @brief Function for retrieving the timer mode. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer mode. + */ +__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for setting the timer bit width. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] bit_width Timer bit width. + */ +__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_reg, + nrf_timer_bit_width_t bit_width); + +/** + * @brief Function for retrieving the timer bit width. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer bit width. + */ +__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for setting the timer frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency Timer frequency. + */ +__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_reg, + nrf_timer_frequency_t frequency); + +/** + * @brief Function for retrieving the timer frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Timer frequency. + */ +__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_reg); + +/** + * @brief Function for writing the capture/compare register for a specified channel. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] cc_channel Requested capture/compare channel. + * @param[in] cc_value Value to write to the capture/compare register. + */ +__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value); + +/** + * @brief Function for retrieving the capture/compare value for a specified channel. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] cc_channel Requested capture/compare channel. + * + * @return Value from the requested capture/compare register. + */ +__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel); + +/** + * @brief Function for getting a specific timer capture task. + * + * @param[in] channel Capture channel. + * + * @return Capture task. + */ +__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel); + +/** + * @brief Function for getting a specific timer compare event. + * + * @param[in] channel Compare channel. + * + * @return Compare event. + */ +__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel); + +/** + * @brief Function for getting a specific timer compare interrupt. + * + * @param[in] channel Compare channel. + * + * @return Compare interrupt. + */ +__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel); + +/** + * @brief Function for calculating the number of timer ticks for a given time + * (in microseconds) and timer frequency. + * + * @param[in] time_us Time in microseconds. + * @param[in] frequency Timer frequency. + * + * @return Number of timer ticks. + */ +__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us, + nrf_timer_frequency_t frequency); + +/** + * @brief Function for calculating the number of timer ticks for a given time + * (in milliseconds) and timer frequency. + * + * @param[in] time_ms Time in milliseconds. + * @param[in] frequency Timer frequency. + * + * @return Number of timer ticks. + */ +__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms, + nrf_timer_frequency_t frequency); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_task_t task) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_reg, + nrf_timer_event_t event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask) +{ + p_reg->SHORTS |= timer_shorts_mask; +} + +__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_shorts_mask) +{ + p_reg->SHORTS &= ~(timer_shorts_mask); +} + +__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask) +{ + p_reg->INTENSET = timer_int_mask; +} + +__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_reg, + uint32_t timer_int_mask) +{ + p_reg->INTENCLR = timer_int_mask; +} + +__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_reg, + uint32_t timer_int) +{ + return (bool)(p_reg->INTENSET & timer_int); +} + +__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_reg, + nrf_timer_mode_t mode) +{ + p_reg->MODE = (p_reg->MODE & ~TIMER_MODE_MODE_Msk) | + ((mode << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk); +} + +__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_mode_t)(p_reg->MODE); +} + +__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_reg, + nrf_timer_bit_width_t bit_width) +{ + p_reg->BITMODE = (p_reg->BITMODE & ~TIMER_BITMODE_BITMODE_Msk) | + ((bit_width << TIMER_BITMODE_BITMODE_Pos) & + TIMER_BITMODE_BITMODE_Msk); +} + +__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_bit_width_t)(p_reg->BITMODE); +} + +__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_reg, + nrf_timer_frequency_t frequency) +{ + p_reg->PRESCALER = (p_reg->PRESCALER & ~TIMER_PRESCALER_PRESCALER_Msk) | + ((frequency << TIMER_PRESCALER_PRESCALER_Pos) & + TIMER_PRESCALER_PRESCALER_Msk); +} + +__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_reg) +{ + return (nrf_timer_frequency_t)(p_reg->PRESCALER); +} + +__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value) +{ + p_reg->CC[cc_channel] = cc_value; +} + +__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_reg, + nrf_timer_cc_channel_t cc_channel) +{ + return (uint32_t)p_reg->CC[cc_channel]; +} + +__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel) +{ + return (nrf_timer_task_t) + ((uint32_t)NRF_TIMER_TASK_CAPTURE0 + (channel * sizeof(uint32_t))); +} + +__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel) +{ + return (nrf_timer_event_t) + ((uint32_t)NRF_TIMER_EVENT_COMPARE0 + (channel * sizeof(uint32_t))); +} + +__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel) +{ + return (nrf_timer_int_mask_t) + ((uint32_t)NRF_TIMER_INT_COMPARE0_MASK << channel); +} + +__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us, + nrf_timer_frequency_t frequency) +{ + // The "frequency" parameter here is actually the prescaler value, and the + // timer runs at the following frequency: f = 16 MHz / 2^prescaler. + uint32_t prescaler = (uint32_t)frequency; + ASSERT(time_us <= (UINT32_MAX / 16UL)); + return ((time_us * 16UL) >> prescaler); +} + +__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms, + nrf_timer_frequency_t frequency) +{ + // The "frequency" parameter here is actually the prescaler value, and the + // timer runs at the following frequency: f = 16000 kHz / 2^prescaler. + uint32_t prescaler = (uint32_t)frequency; + ASSERT(time_ms <= (UINT32_MAX / 16000UL)); + return ((time_ms * 16000UL) >> prescaler); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_TIMER_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twi.h new file mode 100644 index 0000000000..5e80272bec --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twi.h @@ -0,0 +1,452 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_TWI_H__ +#define NRF_TWI_H__ + +/** + * @defgroup nrf_twi_hal TWI HAL + * @{ + * @ingroup nrf_twi + * + * @brief Hardware access layer for managing the TWI peripheral. + */ + +#include +#include +#include + +#include "nrf_peripherals.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief TWI tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWI_TASK_STARTRX = offsetof(NRF_TWI_Type, TASKS_STARTRX), ///< Start TWI receive sequence. + NRF_TWI_TASK_STARTTX = offsetof(NRF_TWI_Type, TASKS_STARTTX), ///< Start TWI transmit sequence. + NRF_TWI_TASK_STOP = offsetof(NRF_TWI_Type, TASKS_STOP), ///< Stop TWI transaction. + NRF_TWI_TASK_SUSPEND = offsetof(NRF_TWI_Type, TASKS_SUSPEND), ///< Suspend TWI transaction. + NRF_TWI_TASK_RESUME = offsetof(NRF_TWI_Type, TASKS_RESUME) ///< Resume TWI transaction. + /*lint -restore*/ +} nrf_twi_task_t; + +/** + * @brief TWI events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWI_EVENT_STOPPED = offsetof(NRF_TWI_Type, EVENTS_STOPPED), ///< TWI stopped. + NRF_TWI_EVENT_RXDREADY = offsetof(NRF_TWI_Type, EVENTS_RXDREADY), ///< TWI RXD byte received. + NRF_TWI_EVENT_TXDSENT = offsetof(NRF_TWI_Type, EVENTS_TXDSENT), ///< TWI TXD byte sent. + NRF_TWI_EVENT_ERROR = offsetof(NRF_TWI_Type, EVENTS_ERROR), ///< TWI error. + NRF_TWI_EVENT_BB = offsetof(NRF_TWI_Type, EVENTS_BB), ///< TWI byte boundary, generated before each byte that is sent or received. + NRF_TWI_EVENT_SUSPENDED = offsetof(NRF_TWI_Type, EVENTS_SUSPENDED) ///< TWI entered the suspended state. + /*lint -restore*/ +} nrf_twi_event_t; + +/** + * @brief TWI shortcuts. + */ +typedef enum +{ + NRF_TWI_SHORT_BB_SUSPEND_MASK = TWI_SHORTS_BB_SUSPEND_Msk, ///< Shortcut between BB event and SUSPEND task. + NRF_TWI_SHORT_BB_STOP_MASK = TWI_SHORTS_BB_STOP_Msk, ///< Shortcut between BB event and STOP task. +} nrf_twi_short_mask_t; + +/** + * @brief TWI interrupts. + */ +typedef enum +{ + NRF_TWI_INT_STOPPED_MASK = TWI_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event. + NRF_TWI_INT_RXDREADY_MASK = TWI_INTENSET_RXDREADY_Msk, ///< Interrupt on RXDREADY event. + NRF_TWI_INT_TXDSENT_MASK = TWI_INTENSET_TXDSENT_Msk, ///< Interrupt on TXDSENT event. + NRF_TWI_INT_ERROR_MASK = TWI_INTENSET_ERROR_Msk, ///< Interrupt on ERROR event. + NRF_TWI_INT_BB_MASK = TWI_INTENSET_BB_Msk, ///< Interrupt on BB event. + NRF_TWI_INT_SUSPENDED_MASK = TWI_INTENSET_SUSPENDED_Msk ///< Interrupt on SUSPENDED event. +} nrf_twi_int_mask_t; + +/** + * @brief TWI error source. + */ +typedef enum +{ + NRF_TWI_ERROR_ADDRESS_NACK = TWI_ERRORSRC_ANACK_Msk, ///< NACK received after sending the address. + NRF_TWI_ERROR_DATA_NACK = TWI_ERRORSRC_DNACK_Msk, ///< NACK received after sending a data byte. + NRF_TWI_ERROR_OVERRUN = TWI_ERRORSRC_OVERRUN_Msk ///< Overrun error. + /**< A new byte was received before the previous byte was read + * from the RXD register (previous data is lost). */ +} nrf_twi_error_t; + +/** + * @brief TWI master clock frequency. + */ +typedef enum +{ + NRF_TWI_FREQ_100K = TWI_FREQUENCY_FREQUENCY_K100, ///< 100 kbps. + NRF_TWI_FREQ_250K = TWI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps. + NRF_TWI_FREQ_400K = TWI_FREQUENCY_FREQUENCY_K400 ///< 400 kbps. +} nrf_twi_frequency_t; + + +/** + * @brief Function for activating a specific TWI task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg, + nrf_twi_task_t task); + +/** + * @brief Function for getting the address of a specific TWI task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_reg, + nrf_twi_task_t task); + +/** + * @brief Function for clearing a specific TWI event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_reg, + nrf_twi_event_t event); + +/** + * @brief Function for checking the state of a specific event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_reg, + nrf_twi_event_t event); + +/** + * @brief Function for getting the address of a specific TWI event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_reg, + nrf_twi_event_t event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg, + uint32_t shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg, + uint32_t shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg, + uint32_t int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg, + uint32_t int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_reg, + nrf_twi_int_mask_t int_mask); + +/** + * @brief Function for enabling the TWI peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg); + +/** + * @brief Function for disabling the TWI peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg); + +/** + * @brief Function for configuring TWI pins. + * + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] scl_pin SCL pin number. + * @param[in] sda_pin SDA pin number. + */ +__STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg, + uint32_t scl_pin, + uint32_t sda_pin); + +/** + * @brief Function for setting the TWI master clock frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency TWI frequency. + */ +__STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_reg, + nrf_twi_frequency_t frequency); + +/** + * @brief Function for checking the TWI error source. + * + * The error flags are cleared after reading. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Mask with error source flags. + */ +__STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg); + +/** + * @brief Function for setting the address to be used in TWI transfers. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] address Address to be used in transfers. + */ +__STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address); + +/** + * @brief Function for reading data received by TWI. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Received data. + */ +__STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_reg); + +/** + * @brief Function for writing data to be transmitted by TWI. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] data Data to be transmitted. + */ +__STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data); + +__STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg, + uint32_t shorts_mask); + +/** + * @} + */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg, + nrf_twi_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_reg, + nrf_twi_task_t task) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_reg, + nrf_twi_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_reg, + nrf_twi_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_reg, + nrf_twi_event_t event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS |= shorts_mask; +} + +__STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS &= ~(shorts_mask); +} + +__STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg, + uint32_t int_mask) +{ + p_reg->INTENSET = int_mask; +} + +__STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg, + uint32_t int_mask) +{ + p_reg->INTENCLR = int_mask; +} + +__STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_reg, + nrf_twi_int_mask_t int_mask) +{ + return (bool)(p_reg->INTENSET & int_mask); +} + +__STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg) +{ + p_reg->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg) +{ + p_reg->ENABLE = (TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg, + uint32_t scl_pin, + uint32_t sda_pin) +{ +#if defined(TWI_PSEL_SCL_CONNECT_Pos) + p_reg->PSEL.SCL = scl_pin; +#else + p_reg->PSELSCL = scl_pin; +#endif + +#if defined(TWI_PSEL_SDA_CONNECT_Pos) + p_reg->PSEL.SDA = sda_pin; +#else + p_reg->PSELSDA = sda_pin; +#endif +} + +__STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_reg, + nrf_twi_frequency_t frequency) +{ + p_reg->FREQUENCY = frequency; +} + +__STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg) +{ + uint32_t error_source = p_reg->ERRORSRC; + + // [error flags are cleared by writing '1' on their position] + p_reg->ERRORSRC = error_source; + + return error_source; +} + +__STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address) +{ + p_reg->ADDRESS = address; +} + +__STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_reg) +{ + return (uint8_t)p_reg->RXD; +} + +__STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data) +{ + p_reg->TXD = data; +} + +__STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS = shorts_mask; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_TWI_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twim.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twim.h new file mode 100644 index 0000000000..73d790efbf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twim.h @@ -0,0 +1,527 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_TWIM_H__ +#define NRF_TWIM_H__ + +/** + * @defgroup nrf_twim_hal TWIM HAL + * @{ + * @ingroup nrf_twi + * + * @brief Hardware access layer for managing the TWIM peripheral. + */ + +#include +#include +#include + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief TWIM tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWIM_TASK_STARTRX = offsetof(NRF_TWIM_Type, TASKS_STARTRX), ///< Start TWI receive sequence. + NRF_TWIM_TASK_STARTTX = offsetof(NRF_TWIM_Type, TASKS_STARTTX), ///< Start TWI transmit sequence. + NRF_TWIM_TASK_STOP = offsetof(NRF_TWIM_Type, TASKS_STOP), ///< Stop TWI transaction. + NRF_TWIM_TASK_SUSPEND = offsetof(NRF_TWIM_Type, TASKS_SUSPEND), ///< Suspend TWI transaction. + NRF_TWIM_TASK_RESUME = offsetof(NRF_TWIM_Type, TASKS_RESUME) ///< Resume TWI transaction. + /*lint -restore*/ +} nrf_twim_task_t; + +/** + * @brief TWIM events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWIM_EVENT_STOPPED = offsetof(NRF_TWIM_Type, EVENTS_STOPPED), ///< TWI stopped. + NRF_TWIM_EVENT_ERROR = offsetof(NRF_TWIM_Type, EVENTS_ERROR), ///< TWI error. + NRF_TWIM_EVENT_SUSPENDED = 0x148, ///< TWI suspended. + NRF_TWIM_EVENT_RXSTARTED = offsetof(NRF_TWIM_Type, EVENTS_RXSTARTED), ///< Receive sequence started. + NRF_TWIM_EVENT_TXSTARTED = offsetof(NRF_TWIM_Type, EVENTS_TXSTARTED), ///< Transmit sequence started. + NRF_TWIM_EVENT_LASTRX = offsetof(NRF_TWIM_Type, EVENTS_LASTRX), ///< Byte boundary, starting to receive the last byte. + NRF_TWIM_EVENT_LASTTX = offsetof(NRF_TWIM_Type, EVENTS_LASTTX) ///< Byte boundary, starting to transmit the last byte. + /*lint -restore*/ +} nrf_twim_event_t; + +/** + * @brief TWIM shortcuts. + */ +typedef enum +{ + NRF_TWIM_SHORT_LASTTX_STARTRX_MASK = TWIM_SHORTS_LASTTX_STARTRX_Msk, ///< Shortcut between LASTTX event and STARTRX task. + NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK = TWIM_SHORTS_LASTTX_SUSPEND_Msk, ///< Shortcut between LASTTX event and SUSPEND task. + NRF_TWIM_SHORT_LASTTX_STOP_MASK = TWIM_SHORTS_LASTTX_STOP_Msk, ///< Shortcut between LASTTX event and STOP task. + NRF_TWIM_SHORT_LASTRX_STARTTX_MASK = TWIM_SHORTS_LASTRX_STARTTX_Msk, ///< Shortcut between LASTRX event and STARTTX task. + NRF_TWIM_SHORT_LASTRX_STOP_MASK = TWIM_SHORTS_LASTRX_STOP_Msk ///< Shortcut between LASTRX event and STOP task. +} nrf_twim_short_mask_t; + +/** + * @brief TWIM interrupts. + */ +typedef enum +{ + NRF_TWIM_INT_STOPPED_MASK = TWIM_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event. + NRF_TWIM_INT_ERROR_MASK = TWIM_INTENSET_ERROR_Msk, ///< Interrupt on ERROR event. + NRF_TWIM_INT_SUSPENDED_MASK = (1 << 18), ///< Interrupt on SUSPENDED event. + NRF_TWIM_INT_RXSTARTED_MASK = TWIM_INTENSET_RXSTARTED_Msk, ///< Interrupt on RXSTARTED event. + NRF_TWIM_INT_TXSTARTED_MASK = TWIM_INTENSET_TXSTARTED_Msk, ///< Interrupt on TXSTARTED event. + NRF_TWIM_INT_LASTRX_MASK = TWIM_INTENSET_LASTRX_Msk, ///< Interrupt on LASTRX event. + NRF_TWIM_INT_LASTTX_MASK = TWIM_INTENSET_LASTTX_Msk ///< Interrupt on LASTTX event. +} nrf_twim_int_mask_t; + +/** + * @brief TWIM master clock frequency. + */ +typedef enum +{ + NRF_TWIM_FREQ_100K = TWIM_FREQUENCY_FREQUENCY_K100, ///< 100 kbps. + NRF_TWIM_FREQ_250K = TWIM_FREQUENCY_FREQUENCY_K250, ///< 250 kbps. + NRF_TWIM_FREQ_400K = TWIM_FREQUENCY_FREQUENCY_K400, ///< 400 kbps. +#ifndef TWI_PRESENT + NRF_TWI_FREQ_100K = NRF_TWIM_FREQ_100K, + NRF_TWI_FREQ_250K = NRF_TWIM_FREQ_250K, + NRF_TWI_FREQ_400K = NRF_TWIM_FREQ_400K, +#endif +} nrf_twim_frequency_t; + +/** + * @brief TWIM error source. + */ +typedef enum +{ + NRF_TWIM_ERROR_ADDRESS_NACK = TWIM_ERRORSRC_ANACK_Msk, ///< NACK received after sending the address. + NRF_TWIM_ERROR_DATA_NACK = TWIM_ERRORSRC_DNACK_Msk, ///< NACK received after sending a data byte. +#ifndef TWI_PRESENT + NRF_TWI_ERROR_ADDRESS_NACK = NRF_TWIM_ERROR_ADDRESS_NACK, + NRF_TWI_ERROR_DATA_NACK = NRF_TWIM_ERROR_DATA_NACK, +#endif +} nrf_twim_error_t; + + +/** + * @brief Function for activating a specific TWIM task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Task to activate. + */ +__STATIC_INLINE void nrf_twim_task_trigger(NRF_TWIM_Type * p_reg, + nrf_twim_task_t task); + +/** + * @brief Function for getting the address of a specific TWIM task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] task Requested task. + * + * @return Address of the specified task register. + */ +__STATIC_INLINE uint32_t * nrf_twim_task_address_get(NRF_TWIM_Type * p_reg, + nrf_twim_task_t task); + +/** + * @brief Function for clearing a specific TWIM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_twim_event_clear(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event); + +/** + * @brief Function for checking the state of a specific TWIM event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_twim_event_check(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event); + +/** + * @brief Function for getting the address of a specific TWIM event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Requested event. + * + * @return Address of the specified event register. + */ +__STATIC_INLINE uint32_t * nrf_twim_event_address_get(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event); + +/** + * @brief Function for enabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_twim_shorts_enable(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask); + +/** + * @brief Function for disabling specified shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_twim_shorts_disable(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask); + +/** + * @brief Function for enabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_twim_int_enable(NRF_TWIM_Type * p_reg, + uint32_t int_mask); + +/** + * @brief Function for disabling specified interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_twim_int_disable(NRF_TWIM_Type * p_reg, + uint32_t int_mask); + +/** + * @brief Function for checking the state of a given interrupt. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] int_mask Interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_twim_int_enable_check(NRF_TWIM_Type * p_reg, + nrf_twim_int_mask_t int_mask); + +/** + * @brief Function for enabling the TWIM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_enable(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for disabling the TWIM peripheral. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_disable(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for configuring TWI pins. + * + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] scl_pin SCL pin number. + * @param[in] sda_pin SDA pin number. + */ +__STATIC_INLINE void nrf_twim_pins_set(NRF_TWIM_Type * p_reg, + uint32_t scl_pin, + uint32_t sda_pin); + +/** + * @brief Function for setting the TWI master clock frequency. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] frequency TWI frequency. + */ +__STATIC_INLINE void nrf_twim_frequency_set(NRF_TWIM_Type * p_reg, + nrf_twim_frequency_t frequency); + +/** + * @brief Function for checking the TWI error source. + * + * The error flags are cleared after reading. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Mask with error source flags. + */ +__STATIC_INLINE uint32_t nrf_twim_errorsrc_get_and_clear(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for setting the address to be used in TWI transfers. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] address Address to be used in transfers. + */ +__STATIC_INLINE void nrf_twim_address_set(NRF_TWIM_Type * p_reg, + uint8_t address); + +/** + * @brief Function for setting the transmit buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer with data to send. + * @param[in] length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_twim_tx_buffer_set(NRF_TWIM_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length); + +/** + * @brief Function for setting the receive buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer for received data. + * @param[in] length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_twim_rx_buffer_set(NRF_TWIM_Type * p_reg, + uint8_t * p_buffer, + uint8_t length); + +__STATIC_INLINE void nrf_twim_shorts_set(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask); + +__STATIC_INLINE uint32_t nrf_twim_txd_amount_get(NRF_TWIM_Type * p_reg); + +__STATIC_INLINE uint32_t nrf_twim_rxd_amount_get(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for enabling the TX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_tx_list_enable(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for disabling the TX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_tx_list_disable(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for enabling the RX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_rx_list_enable(NRF_TWIM_Type * p_reg); + +/** + * @brief Function for disabling the RX list feature. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twim_rx_list_disable(NRF_TWIM_Type * p_reg); + +/** + * @} + */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_twim_task_trigger(NRF_TWIM_Type * p_reg, + nrf_twim_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t * nrf_twim_task_address_get(NRF_TWIM_Type * p_reg, + nrf_twim_task_t task) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)task); +} + +__STATIC_INLINE void nrf_twim_event_clear(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +__STATIC_INLINE bool nrf_twim_event_check(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t * nrf_twim_event_address_get(NRF_TWIM_Type * p_reg, + nrf_twim_event_t event) +{ + return (uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_twim_shorts_enable(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS |= shorts_mask; +} + +__STATIC_INLINE void nrf_twim_shorts_disable(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS &= ~(shorts_mask); +} + +__STATIC_INLINE void nrf_twim_int_enable(NRF_TWIM_Type * p_reg, + uint32_t int_mask) +{ + p_reg->INTENSET = int_mask; +} + +__STATIC_INLINE void nrf_twim_int_disable(NRF_TWIM_Type * p_reg, + uint32_t int_mask) +{ + p_reg->INTENCLR = int_mask; +} + +__STATIC_INLINE bool nrf_twim_int_enable_check(NRF_TWIM_Type * p_reg, + nrf_twim_int_mask_t int_mask) +{ + return (bool)(p_reg->INTENSET & int_mask); +} + +__STATIC_INLINE void nrf_twim_enable(NRF_TWIM_Type * p_reg) +{ + p_reg->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_twim_disable(NRF_TWIM_Type * p_reg) +{ + p_reg->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); +} + +__STATIC_INLINE void nrf_twim_pins_set(NRF_TWIM_Type * p_reg, + uint32_t scl_pin, + uint32_t sda_pin) +{ + p_reg->PSEL.SCL = scl_pin; + p_reg->PSEL.SDA = sda_pin; +} + +__STATIC_INLINE void nrf_twim_frequency_set(NRF_TWIM_Type * p_reg, + nrf_twim_frequency_t frequency) +{ + p_reg->FREQUENCY = frequency; +} + +__STATIC_INLINE uint32_t nrf_twim_errorsrc_get_and_clear(NRF_TWIM_Type * p_reg) +{ + uint32_t error_source = p_reg->ERRORSRC; + + // [error flags are cleared by writing '1' on their position] + p_reg->ERRORSRC = error_source; + + return error_source; +} + +__STATIC_INLINE void nrf_twim_address_set(NRF_TWIM_Type * p_reg, + uint8_t address) +{ + p_reg->ADDRESS = address; +} + +__STATIC_INLINE void nrf_twim_tx_buffer_set(NRF_TWIM_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length) +{ + p_reg->TXD.PTR = (uint32_t)p_buffer; + p_reg->TXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_twim_rx_buffer_set(NRF_TWIM_Type * p_reg, + uint8_t * p_buffer, + uint8_t length) +{ + p_reg->RXD.PTR = (uint32_t)p_buffer; + p_reg->RXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_twim_shorts_set(NRF_TWIM_Type * p_reg, + uint32_t shorts_mask) +{ + p_reg->SHORTS = shorts_mask; +} + +__STATIC_INLINE uint32_t nrf_twim_txd_amount_get(NRF_TWIM_Type * p_reg) +{ + return p_reg->TXD.AMOUNT; +} + +__STATIC_INLINE uint32_t nrf_twim_rxd_amount_get(NRF_TWIM_Type * p_reg) +{ + return p_reg->RXD.AMOUNT; +} + +__STATIC_INLINE void nrf_twim_tx_list_enable(NRF_TWIM_Type * p_reg) +{ + p_reg->TXD.LIST = 1; +} + +__STATIC_INLINE void nrf_twim_tx_list_disable(NRF_TWIM_Type * p_reg) +{ + p_reg->TXD.LIST = 0; +} + +__STATIC_INLINE void nrf_twim_rx_list_enable(NRF_TWIM_Type * p_reg) +{ + p_reg->RXD.LIST = 1; +} + +__STATIC_INLINE void nrf_twim_rx_list_disable(NRF_TWIM_Type * p_reg) +{ + p_reg->RXD.LIST = 0; +} +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_TWIM_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twis.h new file mode 100644 index 0000000000..3cd56d6ce6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_twis.h @@ -0,0 +1,706 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** + * @ingroup nrf_twis + * @defgroup nrf_twis_hal TWIS HAL + * @{ + * + * @brief @tagAPI52 Hardware access layer for Two Wire Interface Slave with EasyDMA + * (TWIS) peripheral. + */ +#ifndef NRF_TWIS_H__ +#define NRF_TWIS_H__ + +#include "nrf.h" +#include "sdk_config.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief TWIS tasks + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWIS_TASK_STOP = offsetof(NRF_TWIS_Type, TASKS_STOP), /**< Stop TWIS transaction */ + NRF_TWIS_TASK_SUSPEND = offsetof(NRF_TWIS_Type, TASKS_SUSPEND), /**< Suspend TWIS transaction */ + NRF_TWIS_TASK_RESUME = offsetof(NRF_TWIS_Type, TASKS_RESUME), /**< Resume TWIS transaction */ + NRF_TWIS_TASK_PREPARERX = offsetof(NRF_TWIS_Type, TASKS_PREPARERX), /**< Prepare the TWIS slave to respond to a write command */ + NRF_TWIS_TASK_PREPARETX = offsetof(NRF_TWIS_Type, TASKS_PREPARETX) /**< Prepare the TWIS slave to respond to a read command */ + /*lint -restore*/ +} nrf_twis_task_t; + +/** + * @brief TWIS events + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_TWIS_EVENT_STOPPED = offsetof(NRF_TWIS_Type, EVENTS_STOPPED), /**< TWIS stopped */ + NRF_TWIS_EVENT_ERROR = offsetof(NRF_TWIS_Type, EVENTS_ERROR), /**< TWIS error */ + NRF_TWIS_EVENT_RXSTARTED = offsetof(NRF_TWIS_Type, EVENTS_RXSTARTED), /**< Receive sequence started */ + NRF_TWIS_EVENT_TXSTARTED = offsetof(NRF_TWIS_Type, EVENTS_TXSTARTED), /**< Transmit sequence started */ + NRF_TWIS_EVENT_WRITE = offsetof(NRF_TWIS_Type, EVENTS_WRITE), /**< Write command received */ + NRF_TWIS_EVENT_READ = offsetof(NRF_TWIS_Type, EVENTS_READ) /**< Read command received */ + /*lint -restore*/ +} nrf_twis_event_t; + +/** + * @brief TWIS shortcuts + */ +typedef enum +{ + NRF_TWIS_SHORT_WRITE_SUSPEND_MASK = TWIS_SHORTS_WRITE_SUSPEND_Msk, /**< Shortcut between WRITE event and SUSPEND task */ + NRF_TWIS_SHORT_READ_SUSPEND_MASK = TWIS_SHORTS_READ_SUSPEND_Msk, /**< Shortcut between READ event and SUSPEND task */ +} nrf_twis_short_mask_t; + +/** + * @brief TWIS interrupts + */ +typedef enum +{ + NRF_TWIS_INT_STOPPED_MASK = TWIS_INTEN_STOPPED_Msk, /**< Interrupt on STOPPED event */ + NRF_TWIS_INT_ERROR_MASK = TWIS_INTEN_ERROR_Msk, /**< Interrupt on ERROR event */ + NRF_TWIS_INT_RXSTARTED_MASK = TWIS_INTEN_RXSTARTED_Msk, /**< Interrupt on RXSTARTED event */ + NRF_TWIS_INT_TXSTARTED_MASK = TWIS_INTEN_TXSTARTED_Msk, /**< Interrupt on TXSTARTED event */ + NRF_TWIS_INT_WRITE_MASK = TWIS_INTEN_WRITE_Msk, /**< Interrupt on WRITE event */ + NRF_TWIS_INT_READ_MASK = TWIS_INTEN_READ_Msk, /**< Interrupt on READ event */ +} nrf_twis_int_mask_t; + +/** + * @brief TWIS error source + */ +typedef enum +{ + NRF_TWIS_ERROR_OVERFLOW = TWIS_ERRORSRC_OVERFLOW_Msk, /**< RX buffer overflow detected, and prevented */ + NRF_TWIS_ERROR_DATA_NACK = TWIS_ERRORSRC_DNACK_Msk, /**< NACK sent after receiving a data byte */ + NRF_TWIS_ERROR_OVERREAD = TWIS_ERRORSRC_OVERREAD_Msk /**< TX buffer over-read detected, and prevented */ +} nrf_twis_error_t; + +/** + * @brief TWIS address matching configuration + */ +typedef enum +{ + NRF_TWIS_CONFIG_ADDRESS0_MASK = TWIS_CONFIG_ADDRESS0_Msk, /**< Enable or disable address matching on ADDRESS[0] */ + NRF_TWIS_CONFIG_ADDRESS1_MASK = TWIS_CONFIG_ADDRESS1_Msk, /**< Enable or disable address matching on ADDRESS[1] */ + NRF_TWIS_CONFIG_ADDRESS01_MASK = TWIS_CONFIG_ADDRESS0_Msk | TWIS_CONFIG_ADDRESS1_Msk /**< Enable both address matching */ +} nrf_twis_config_addr_mask_t; + +/** + * @brief Variable type to hold amount of data for EasyDMA + * + * Variable of the minimum size that can hold the amount of data to transfer. + * + * @note + * Defined to make it simple to change if EasyDMA would be updated to support more data in + * the future devices to. + */ +typedef uint8_t nrf_twis_amount_t; + +/** + * @brief Smallest variable type to hold TWI address + * + * Variable of the minimum size that can hold single TWI address. + * + * @note + * Defined to make it simple to change if new TWI would support for example + * 10 bit addressing mode. + */ +typedef uint8_t nrf_twis_address_t; + + +/** + * @brief Function for activating a specific TWIS task. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param task Task. + */ +__STATIC_INLINE void nrf_twis_task_trigger(NRF_TWIS_Type * const p_reg, nrf_twis_task_t task); + +/** + * @brief Function for returning the address of a specific TWIS task register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_twis_task_address_get( + NRF_TWIS_Type const * const p_reg, + nrf_twis_task_t task); + +/** + * @brief Function for clearing a specific event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param event Event. + */ +__STATIC_INLINE void nrf_twis_event_clear( + NRF_TWIS_Type * const p_reg, + nrf_twis_event_t event); +/** + * @brief Function for returning the state of a specific event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_twis_event_check( + NRF_TWIS_Type const * const p_reg, + nrf_twis_event_t event); + + +/** + * @brief Function for getting and clearing the state of specific event + * + * This function checks the state of the event and clears it. + * @param[in,out] p_reg Pointer to the peripheral registers structure. + * @param event Event. + * + * @retval true If the event was set. + * @retval false If the event was not set. + */ +__STATIC_INLINE bool nrf_twis_event_get_and_clear( + NRF_TWIS_Type * const p_reg, + nrf_twis_event_t event); + + +/** + * @brief Function for returning the address of a specific TWIS event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param event Event. + * + * @return Address. + */ +__STATIC_INLINE uint32_t nrf_twis_event_address_get( + NRF_TWIS_Type const * const p_reg, + nrf_twis_event_t event); + +/** + * @brief Function for setting a shortcut. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_twis_shorts_enable(NRF_TWIS_Type * const p_reg, uint32_t short_mask); + +/** + * @brief Function for clearing shortcuts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_twis_shorts_disable(NRF_TWIS_Type * const p_reg, uint32_t short_mask); + +/** + * @brief Get the shorts mask + * + * Function returns shorts register. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @return Flags of currently enabled shortcuts + */ +__STATIC_INLINE uint32_t nrf_twis_shorts_get(NRF_TWIS_Type * const p_reg); + +/** + * @brief Function for enabling selected interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_twis_int_enable(NRF_TWIS_Type * const p_reg, uint32_t int_mask); + +/** + * @brief Function for retrieving the state of selected interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts mask. + * + * @retval true If any of selected interrupts is enabled. + * @retval false If none of selected interrupts is enabled. + */ +__STATIC_INLINE bool nrf_twis_int_enable_check(NRF_TWIS_Type const * const p_reg, uint32_t int_mask); + +/** + * @brief Function for disabling selected interrupts. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_twis_int_disable(NRF_TWIS_Type * const p_reg, uint32_t int_mask); + +/** + * @brief Function for retrieving and clearing the TWIS error source. + * + * @attention Error sources are cleared after read. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @return Error source mask with values from @ref nrf_twis_error_t. + */ +__STATIC_INLINE uint32_t nrf_twis_error_source_get_and_clear(NRF_TWIS_Type * const p_reg); + +/** + * @brief Get information which of addresses matched + * + * Function returns index in the address table + * that points to the address that already matched. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @return Index of matched address + */ +__STATIC_INLINE uint_fast8_t nrf_twis_match_get(NRF_TWIS_Type const * p_reg); + +/** + * @brief Function for enabling TWIS. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twis_enable(NRF_TWIS_Type * const p_reg); + +/** + * @brief Function for disabling TWIS. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_twis_disable(NRF_TWIS_Type * const p_reg); + +/** + * @brief Function for configuring TWIS pins. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param scl SCL pin number. + * @param sda SDA pin number. + */ +__STATIC_INLINE void nrf_twis_pins_set(NRF_TWIS_Type * const p_reg, uint32_t scl, uint32_t sda); + +/** + * @brief Function for setting the receive buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param p_buf Pointer to the buffer for received data. + * @param length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_twis_rx_buffer_set( + NRF_TWIS_Type * const p_reg, + uint8_t * p_buf, + nrf_twis_amount_t length); + +/** + * @brief Function that prepares TWIS for receiving + * + * This function sets receive buffer and then sets NRF_TWIS_TASK_PREPARERX task. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param p_buf Pointer to the buffer for received data. + * @param length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_twis_rx_prepare( + NRF_TWIS_Type * const p_reg, + uint8_t * p_buf, + nrf_twis_amount_t length); + +/** + * @brief Function for getting number of bytes received in the last transaction. + * + * @param[in] p_reg TWIS instance. + * @return Amount of bytes received. + * */ +__STATIC_INLINE nrf_twis_amount_t nrf_twis_rx_amount_get(NRF_TWIS_Type const * const p_reg); + +/** + * @brief Function for setting the transmit buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param p_buf Pointer to the buffer with data to send. + * @param length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_twis_tx_buffer_set( + NRF_TWIS_Type * const p_reg, + uint8_t const * p_buf, + nrf_twis_amount_t length); + +/** + * @brief Function that prepares TWIS for transmitting + * + * This function sets transmit buffer and then sets NRF_TWIS_TASK_PREPARETX task. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param p_buf Pointer to the buffer with data to send. + * @param length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_twis_tx_prepare( + NRF_TWIS_Type * const p_reg, + uint8_t const * p_buf, + nrf_twis_amount_t length); + +/** + * @brief Function for getting number of bytes transmitted in the last transaction. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @return Amount of bytes transmitted. + */ +__STATIC_INLINE nrf_twis_amount_t nrf_twis_tx_amount_get(NRF_TWIS_Type const * const p_reg); + +/** + * @brief Function for setting slave address + * + * Function sets the selected address for this TWI interface. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param n Index of address to set + * @param addr Addres to set + * @sa nrf_twis_config_address_set + * @sa nrf_twis_config_address_get + */ +__STATIC_INLINE void nrf_twis_address_set( + NRF_TWIS_Type * const p_reg, + uint_fast8_t n, + nrf_twis_address_t addr); + +/** + * @brief Function for retrieving configured slave address + * + * Function gets the selected address for this TWI interface. + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param n Index of address to get + */ +__STATIC_INLINE nrf_twis_address_t nrf_twis_address_get( + NRF_TWIS_Type const * const p_reg, + uint_fast8_t n); + +/** + * @brief Function for setting the device address configuration. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param addr_mask Mask of address indexes of what device should answer to. + * + * @sa nrf_twis_address_set + */ +__STATIC_INLINE void nrf_twis_config_address_set( + NRF_TWIS_Type * const p_reg, + nrf_twis_config_addr_mask_t addr_mask); + +/** + * @brief Function for retrieving the device address configuration. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Mask of address indexes of what device should answer to. + */ +__STATIC_INLINE nrf_twis_config_addr_mask_t nrf_twis_config_address_get( + NRF_TWIS_Type const * const p_reg); + +/** + * @brief Function for setting the over-read character. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] orc Over-read character. Character clocked out in case of + * over-read of the TXD buffer. + */ +__STATIC_INLINE void nrf_twis_orc_set( + NRF_TWIS_Type * const p_reg, + uint8_t orc); + +/** + * @brief Function for setting the over-read character. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @return Over-read character configured for selected instance. + */ +__STATIC_INLINE uint8_t nrf_twis_orc_get(NRF_TWIS_Type const * const p_reg); + + +/** @} */ /* End of nrf_twis_hal */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/* ------------------------------------------------------------------------------------------------ + * Internal functions + */ + +/** + * @internal + * @brief Internal function for getting task/event register address + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile uint32_t* nrf_twis_getRegPtr(NRF_TWIS_Type * const p_reg, uint32_t offset) +{ + return (volatile uint32_t*)((uint8_t *)p_reg + (uint32_t)offset); +} + +/** + * @internal + * @brief Internal function for getting task/event register address - constant version + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile const uint32_t* nrf_twis_getRegPtr_c(NRF_TWIS_Type const * const p_reg, uint32_t offset) +{ + return (volatile const uint32_t*)((uint8_t *)p_reg + (uint32_t)offset); +} + + +/* ------------------------------------------------------------------------------------------------ + * Interface functions definitions + */ + + +void nrf_twis_task_trigger(NRF_TWIS_Type * const p_reg, nrf_twis_task_t task) +{ + *(nrf_twis_getRegPtr(p_reg, (uint32_t)task)) = 1UL; +} + +uint32_t nrf_twis_task_address_get( + NRF_TWIS_Type const * const p_reg, + nrf_twis_task_t task) +{ + return (uint32_t)nrf_twis_getRegPtr_c(p_reg, (uint32_t)task); +} + +void nrf_twis_event_clear( + NRF_TWIS_Type * const p_reg, + nrf_twis_event_t event) +{ + *(nrf_twis_getRegPtr(p_reg, (uint32_t)event)) = 0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif +} + +bool nrf_twis_event_check( + NRF_TWIS_Type const * const p_reg, + nrf_twis_event_t event) +{ + return (bool)*nrf_twis_getRegPtr_c(p_reg, (uint32_t)event); +} + +bool nrf_twis_event_get_and_clear( + NRF_TWIS_Type * const p_reg, + nrf_twis_event_t event) +{ + bool ret = nrf_twis_event_check(p_reg, event); + if (ret) + { + nrf_twis_event_clear(p_reg, event); + } + return ret; +} + +uint32_t nrf_twis_event_address_get( + NRF_TWIS_Type const * const p_reg, + nrf_twis_event_t event) +{ + return (uint32_t)nrf_twis_getRegPtr_c(p_reg, (uint32_t)event); +} + +void nrf_twis_shorts_enable(NRF_TWIS_Type * const p_reg, uint32_t short_mask) +{ + p_reg->SHORTS |= short_mask; +} + +void nrf_twis_shorts_disable(NRF_TWIS_Type * const p_reg, uint32_t short_mask) +{ + if (~0U == short_mask) + { + /* Optimized version for "disable all" */ + p_reg->SHORTS = 0; + } + else + { + p_reg->SHORTS &= ~short_mask; + } +} + +uint32_t nrf_twis_shorts_get(NRF_TWIS_Type * const p_reg) +{ + return p_reg->SHORTS; +} + +void nrf_twis_int_enable(NRF_TWIS_Type * const p_reg, uint32_t int_mask) +{ + p_reg->INTENSET = int_mask; +} + +bool nrf_twis_int_enable_check(NRF_TWIS_Type const * const p_reg, uint32_t int_mask) +{ + return (bool)(p_reg->INTENSET & int_mask); +} + +void nrf_twis_int_disable(NRF_TWIS_Type * const p_reg, uint32_t int_mask) +{ + p_reg->INTENCLR = int_mask; +} + +uint32_t nrf_twis_error_source_get_and_clear(NRF_TWIS_Type * const p_reg) +{ + uint32_t ret = p_reg->ERRORSRC; + p_reg->ERRORSRC = ret; + return ret; +} + +uint_fast8_t nrf_twis_match_get(NRF_TWIS_Type const * p_reg) +{ + return (uint_fast8_t)p_reg->MATCH; +} + +void nrf_twis_enable(NRF_TWIS_Type * const p_reg) +{ + p_reg->ENABLE = (TWIS_ENABLE_ENABLE_Enabled << TWIS_ENABLE_ENABLE_Pos); +} + +void nrf_twis_disable(NRF_TWIS_Type * const p_reg) +{ + p_reg->ENABLE = (TWIS_ENABLE_ENABLE_Disabled << TWIS_ENABLE_ENABLE_Pos); +} + +void nrf_twis_pins_set(NRF_TWIS_Type * const p_reg, uint32_t scl, uint32_t sda) +{ + p_reg->PSEL.SCL = scl; + p_reg->PSEL.SDA = sda; +} + +void nrf_twis_rx_buffer_set( + NRF_TWIS_Type * const p_reg, + uint8_t * p_buf, + nrf_twis_amount_t length) +{ + p_reg->RXD.PTR = (uint32_t)p_buf; + p_reg->RXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_twis_rx_prepare( + NRF_TWIS_Type * const p_reg, + uint8_t * p_buf, + nrf_twis_amount_t length) +{ + nrf_twis_rx_buffer_set(p_reg, p_buf, length); + nrf_twis_task_trigger(p_reg, NRF_TWIS_TASK_PREPARERX); +} + +nrf_twis_amount_t nrf_twis_rx_amount_get(NRF_TWIS_Type const * const p_reg) +{ + return (nrf_twis_amount_t)p_reg->RXD.AMOUNT; +} + +void nrf_twis_tx_buffer_set( + NRF_TWIS_Type * const p_reg, + uint8_t const * p_buf, + nrf_twis_amount_t length) +{ + p_reg->TXD.PTR = (uint32_t)p_buf; + p_reg->TXD.MAXCNT = length; +} + +__STATIC_INLINE void nrf_twis_tx_prepare( + NRF_TWIS_Type * const p_reg, + uint8_t const * p_buf, + nrf_twis_amount_t length) +{ + nrf_twis_tx_buffer_set(p_reg, p_buf, length); + nrf_twis_task_trigger(p_reg, NRF_TWIS_TASK_PREPARETX); +} + +nrf_twis_amount_t nrf_twis_tx_amount_get(NRF_TWIS_Type const * const p_reg) +{ + return (nrf_twis_amount_t)p_reg->TXD.AMOUNT; +} + +void nrf_twis_address_set( + NRF_TWIS_Type * const p_reg, + uint_fast8_t n, + nrf_twis_address_t addr) +{ + p_reg->ADDRESS[n] = addr; +} + +nrf_twis_address_t nrf_twis_address_get( + NRF_TWIS_Type const * const p_reg, + uint_fast8_t n) +{ + return (nrf_twis_address_t)p_reg->ADDRESS[n]; +} +void nrf_twis_config_address_set( + NRF_TWIS_Type * const p_reg, + nrf_twis_config_addr_mask_t addr_mask) +{ + /* This is the only configuration in TWIS - just write it without masking */ + p_reg->CONFIG = addr_mask; +} + +nrf_twis_config_addr_mask_t nrf_twis_config_address_get(NRF_TWIS_Type const * const p_reg) +{ + return (nrf_twis_config_addr_mask_t)(p_reg->CONFIG & TWIS_ADDRESS_ADDRESS_Msk); +} + +void nrf_twis_orc_set( + NRF_TWIS_Type * const p_reg, + uint8_t orc) +{ + p_reg->ORC = orc; +} + +uint8_t nrf_twis_orc_get(NRF_TWIS_Type const * const p_reg) +{ + return (uint8_t)p_reg->ORC; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_TWIS_H__ */ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uart.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uart.h new file mode 100644 index 0000000000..5bb1dcd17c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uart.h @@ -0,0 +1,549 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_UART_H__ +#define NRF_UART_H__ + +#include "nrf.h" +#include "nrf_peripherals.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//Temporary defining legacy UART for instance 1 +#define NRF_UART1 (NRF_UART_Type *)NRF_UARTE1 + +/** + * @defgroup nrf_uart_hal UART HAL + * @{ + * @ingroup nrf_uart + * + * @brief Hardware access layer for accessing the UART peripheral. + */ + +#define NRF_UART_PSEL_DISCONNECTED 0xFFFFFFFF + +/** + * @enum nrf_uart_task_t + * @brief UART tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_UART_TASK_STARTRX = offsetof(NRF_UART_Type, TASKS_STARTRX), /**< Task for starting reception. */ + NRF_UART_TASK_STOPRX = offsetof(NRF_UART_Type, TASKS_STOPRX), /**< Task for stopping reception. */ + NRF_UART_TASK_STARTTX = offsetof(NRF_UART_Type, TASKS_STARTTX), /**< Task for starting transmission. */ + NRF_UART_TASK_STOPTX = offsetof(NRF_UART_Type, TASKS_STOPTX), /**< Task for stopping transmission. */ + NRF_UART_TASK_SUSPEND = offsetof(NRF_UART_Type, TASKS_SUSPEND), /**< Task for suspending UART. */ + /*lint -restore*/ +} nrf_uart_task_t; + +/** + * @enum nrf_uart_event_t + * @brief UART events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_UART_EVENT_CTS = offsetof(NRF_UART_Type, EVENTS_CTS), /**< Event from CTS line activation. */ + NRF_UART_EVENT_NCTS = offsetof(NRF_UART_Type, EVENTS_NCTS), /**< Event from CTS line deactivation. */ + NRF_UART_EVENT_RXDRDY = offsetof(NRF_UART_Type, EVENTS_RXDRDY),/**< Event from data ready in RXD. */ + NRF_UART_EVENT_TXDRDY = offsetof(NRF_UART_Type, EVENTS_TXDRDY),/**< Event from data sent from TXD. */ + NRF_UART_EVENT_ERROR = offsetof(NRF_UART_Type, EVENTS_ERROR), /**< Event from error detection. */ + NRF_UART_EVENT_RXTO = offsetof(NRF_UART_Type, EVENTS_RXTO) /**< Event from receiver timeout. */ + /*lint -restore*/ +} nrf_uart_event_t; + +/** + * @enum nrf_uart_int_mask_t + * @brief UART interrupts. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_UART_INT_MASK_CTS = UART_INTENCLR_CTS_Msk, /**< CTS line activation interrupt. */ + NRF_UART_INT_MASK_NCTS = UART_INTENCLR_NCTS_Msk, /**< CTS line deactivation interrupt. */ + NRF_UART_INT_MASK_RXDRDY = UART_INTENCLR_RXDRDY_Msk, /**< Data ready in RXD interrupt. */ + NRF_UART_INT_MASK_TXDRDY = UART_INTENCLR_TXDRDY_Msk, /**< Data sent from TXD interrupt. */ + NRF_UART_INT_MASK_ERROR = UART_INTENCLR_ERROR_Msk, /**< Error detection interrupt. */ + NRF_UART_INT_MASK_RXTO = UART_INTENCLR_RXTO_Msk /**< Receiver timeout interrupt. */ + /*lint -restore*/ +} nrf_uart_int_mask_t; + +/** + * @enum nrf_uart_baudrate_t + * @brief Baudrates supported by UART. + */ +typedef enum +{ +#ifdef UARTE_PRESENT + NRF_UART_BAUDRATE_1200 = UARTE_BAUDRATE_BAUDRATE_Baud1200, /**< 1200 baud. */ + NRF_UART_BAUDRATE_2400 = UARTE_BAUDRATE_BAUDRATE_Baud2400, /**< 2400 baud. */ + NRF_UART_BAUDRATE_4800 = UARTE_BAUDRATE_BAUDRATE_Baud4800, /**< 4800 baud. */ + NRF_UART_BAUDRATE_9600 = UARTE_BAUDRATE_BAUDRATE_Baud9600, /**< 9600 baud. */ + NRF_UART_BAUDRATE_14400 = UARTE_BAUDRATE_BAUDRATE_Baud14400, /**< 14400 baud. */ + NRF_UART_BAUDRATE_19200 = UARTE_BAUDRATE_BAUDRATE_Baud19200, /**< 19200 baud. */ + NRF_UART_BAUDRATE_28800 = UARTE_BAUDRATE_BAUDRATE_Baud28800, /**< 28800 baud. */ + NRF_UART_BAUDRATE_38400 = UARTE_BAUDRATE_BAUDRATE_Baud38400, /**< 38400 baud. */ + NRF_UART_BAUDRATE_57600 = UARTE_BAUDRATE_BAUDRATE_Baud57600, /**< 57600 baud. */ + NRF_UART_BAUDRATE_76800 = UARTE_BAUDRATE_BAUDRATE_Baud76800, /**< 76800 baud. */ + NRF_UART_BAUDRATE_115200 = UARTE_BAUDRATE_BAUDRATE_Baud115200, /**< 115200 baud. */ + NRF_UART_BAUDRATE_230400 = UARTE_BAUDRATE_BAUDRATE_Baud230400, /**< 230400 baud. */ + NRF_UART_BAUDRATE_250000 = UARTE_BAUDRATE_BAUDRATE_Baud250000, /**< 250000 baud. */ + NRF_UART_BAUDRATE_460800 = UARTE_BAUDRATE_BAUDRATE_Baud460800, /**< 460800 baud. */ + NRF_UART_BAUDRATE_921600 = UARTE_BAUDRATE_BAUDRATE_Baud921600, /**< 921600 baud. */ + NRF_UART_BAUDRATE_1000000 = UARTE_BAUDRATE_BAUDRATE_Baud1M, /**< 1000000 baud. */ +#else + NRF_UART_BAUDRATE_1200 = UART_BAUDRATE_BAUDRATE_Baud1200, /**< 1200 baud. */ + NRF_UART_BAUDRATE_2400 = UART_BAUDRATE_BAUDRATE_Baud2400, /**< 2400 baud. */ + NRF_UART_BAUDRATE_4800 = UART_BAUDRATE_BAUDRATE_Baud4800, /**< 4800 baud. */ + NRF_UART_BAUDRATE_9600 = UART_BAUDRATE_BAUDRATE_Baud9600, /**< 9600 baud. */ + NRF_UART_BAUDRATE_14400 = UART_BAUDRATE_BAUDRATE_Baud14400, /**< 14400 baud. */ + NRF_UART_BAUDRATE_19200 = UART_BAUDRATE_BAUDRATE_Baud19200, /**< 19200 baud. */ + NRF_UART_BAUDRATE_28800 = UART_BAUDRATE_BAUDRATE_Baud28800, /**< 28800 baud. */ + NRF_UART_BAUDRATE_38400 = UART_BAUDRATE_BAUDRATE_Baud38400, /**< 38400 baud. */ + NRF_UART_BAUDRATE_57600 = UART_BAUDRATE_BAUDRATE_Baud57600, /**< 57600 baud. */ + NRF_UART_BAUDRATE_76800 = UART_BAUDRATE_BAUDRATE_Baud76800, /**< 76800 baud. */ + NRF_UART_BAUDRATE_115200 = UART_BAUDRATE_BAUDRATE_Baud115200, /**< 115200 baud. */ + NRF_UART_BAUDRATE_230400 = UART_BAUDRATE_BAUDRATE_Baud230400, /**< 230400 baud. */ + NRF_UART_BAUDRATE_250000 = UART_BAUDRATE_BAUDRATE_Baud250000, /**< 250000 baud. */ + NRF_UART_BAUDRATE_460800 = UART_BAUDRATE_BAUDRATE_Baud460800, /**< 460800 baud. */ + NRF_UART_BAUDRATE_921600 = UART_BAUDRATE_BAUDRATE_Baud921600, /**< 921600 baud. */ + NRF_UART_BAUDRATE_1000000 = UART_BAUDRATE_BAUDRATE_Baud1M, /**< 1000000 baud. */ +#endif +} nrf_uart_baudrate_t; + +/** + * @enum nrf_uart_error_mask_t + * @brief Types of UART error masks. + */ +typedef enum +{ + NRF_UART_ERROR_OVERRUN_MASK = UART_ERRORSRC_OVERRUN_Msk, /**< Overrun error. */ + NRF_UART_ERROR_PARITY_MASK = UART_ERRORSRC_PARITY_Msk, /**< Parity error. */ + NRF_UART_ERROR_FRAMING_MASK = UART_ERRORSRC_FRAMING_Msk, /**< Framing error. */ + NRF_UART_ERROR_BREAK_MASK = UART_ERRORSRC_BREAK_Msk, /**< Break error. */ +} nrf_uart_error_mask_t; + +/** + * @enum nrf_uart_parity_t + * @brief Types of UART parity modes. + */ +typedef enum +{ + NRF_UART_PARITY_EXCLUDED = UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos, /**< Parity excluded. */ + NRF_UART_PARITY_INCLUDED = UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos, /**< Parity included. */ +} nrf_uart_parity_t; + +/** + * @enum nrf_uart_hwfc_t + * @brief Types of UART flow control modes. + */ +typedef enum +{ + NRF_UART_HWFC_DISABLED = UART_CONFIG_HWFC_Disabled, /**< HW flow control disabled. */ + NRF_UART_HWFC_ENABLED = UART_CONFIG_HWFC_Enabled, /**< HW flow control enabled. */ +} nrf_uart_hwfc_t; + +/** + * @brief Function for clearing a specific UART event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_uart_event_clear(NRF_UART_Type * p_reg, nrf_uart_event_t event); + +/** + * @brief Function for checking the state of a specific UART event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval True if event is set, False otherwise. + */ +__STATIC_INLINE bool nrf_uart_event_check(NRF_UART_Type * p_reg, nrf_uart_event_t event); + +/** + * @brief Function for returning the address of a specific UART event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Desired event. + * + * @retval Address of specified event register. + */ +__STATIC_INLINE uint32_t nrf_uart_event_address_get(NRF_UART_Type * p_reg, + nrf_uart_event_t event); + +/** + * @brief Function for enabling a specific interrupt. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_uart_int_enable(NRF_UART_Type * p_reg, uint32_t int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param int_mask Mask of interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_uart_int_enable_check(NRF_UART_Type * p_reg, uint32_t int_mask); + +/** + * @brief Function for disabling specific interrupts. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_uart_int_disable(NRF_UART_Type * p_reg, uint32_t int_mask); + +/** + * @brief Function for getting error source mask. Function is clearing error source flags after reading. + * + * @param p_reg Pointer to the peripheral registers structure. + * @return Mask with error source flags. + */ +__STATIC_INLINE uint32_t nrf_uart_errorsrc_get_and_clear(NRF_UART_Type * p_reg); + +/** + * @brief Function for enabling UART. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uart_enable(NRF_UART_Type * p_reg); + +/** + * @brief Function for disabling UART. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uart_disable(NRF_UART_Type * p_reg); + +/** + * @brief Function for configuring TX/RX pins. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param pseltxd TXD pin number. + * @param pselrxd RXD pin number. + */ +__STATIC_INLINE void nrf_uart_txrx_pins_set(NRF_UART_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd); + +/** + * @brief Function for disconnecting TX/RX pins. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uart_txrx_pins_disconnect(NRF_UART_Type * p_reg); + +/** + * @brief Function for getting TX pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uart_tx_pin_get(NRF_UART_Type * p_reg); + +/** + * @brief Function for getting RX pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uart_rx_pin_get(NRF_UART_Type * p_reg); + +/** + * @brief Function for getting RTS pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uart_rts_pin_get(NRF_UART_Type * p_reg); + +/** + * @brief Function for getting CTS pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uart_cts_pin_get(NRF_UART_Type * p_reg); + + +/** + * @brief Function for configuring flow control pins. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param pselrts RTS pin number. + * @param pselcts CTS pin number. + */ +__STATIC_INLINE void nrf_uart_hwfc_pins_set(NRF_UART_Type * p_reg, + uint32_t pselrts, + uint32_t pselcts); + +/** + * @brief Function for disconnecting flow control pins. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uart_hwfc_pins_disconnect(NRF_UART_Type * p_reg); + +/** + * @brief Function for reading RX data. + * + * @param p_reg Pointer to the peripheral registers structure. + * @return Received byte. + */ +__STATIC_INLINE uint8_t nrf_uart_rxd_get(NRF_UART_Type * p_reg); + +/** + * @brief Function for setting Tx data. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param txd Byte. + */ +__STATIC_INLINE void nrf_uart_txd_set(NRF_UART_Type * p_reg, uint8_t txd); + +/** + * @brief Function for starting an UART task. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param task Task. + */ +__STATIC_INLINE void nrf_uart_task_trigger(NRF_UART_Type * p_reg, nrf_uart_task_t task); + +/** + * @brief Function for returning the address of a specific task register. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_uart_task_address_get(NRF_UART_Type * p_reg, nrf_uart_task_t task); + +/** + * @brief Function for configuring UART. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param hwfc Hardware flow control. Enabled if true. + * @param parity Parity. Included if true. + */ +__STATIC_INLINE void nrf_uart_configure(NRF_UART_Type * p_reg, + nrf_uart_parity_t parity, + nrf_uart_hwfc_t hwfc); + +/** + * @brief Function for setting UART baudrate. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param baudrate Baudrate. + */ +__STATIC_INLINE void nrf_uart_baudrate_set(NRF_UART_Type * p_reg, nrf_uart_baudrate_t baudrate); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_uart_event_clear(NRF_UART_Type * p_reg, nrf_uart_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif + +} + +__STATIC_INLINE bool nrf_uart_event_check(NRF_UART_Type * p_reg, nrf_uart_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t nrf_uart_event_address_get(NRF_UART_Type * p_reg, + nrf_uart_event_t event) +{ + return (uint32_t)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_uart_int_enable(NRF_UART_Type * p_reg, uint32_t int_mask) +{ + p_reg->INTENSET = int_mask; +} + +__STATIC_INLINE bool nrf_uart_int_enable_check(NRF_UART_Type * p_reg, uint32_t int_mask) +{ + return (bool)(p_reg->INTENSET & int_mask); +} + +__STATIC_INLINE void nrf_uart_int_disable(NRF_UART_Type * p_reg, uint32_t int_mask) +{ + p_reg->INTENCLR = int_mask; +} + +__STATIC_INLINE uint32_t nrf_uart_errorsrc_get_and_clear(NRF_UART_Type * p_reg) +{ + uint32_t errsrc_mask = p_reg->ERRORSRC; + p_reg->ERRORSRC = errsrc_mask; + return errsrc_mask; +} + +__STATIC_INLINE void nrf_uart_enable(NRF_UART_Type * p_reg) +{ + p_reg->ENABLE = UART_ENABLE_ENABLE_Enabled; +} + +__STATIC_INLINE void nrf_uart_disable(NRF_UART_Type * p_reg) +{ + p_reg->ENABLE = UART_ENABLE_ENABLE_Disabled; +} + +__STATIC_INLINE void nrf_uart_txrx_pins_set(NRF_UART_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd) +{ +#if defined(UART_PSEL_RXD_CONNECT_Pos) + p_reg->PSEL.RXD = pselrxd; +#else + p_reg->PSELRXD = pselrxd; +#endif +#if defined(UART_PSEL_TXD_CONNECT_Pos) + p_reg->PSEL.TXD = pseltxd; +#else + p_reg->PSELTXD = pseltxd; +#endif +} + +__STATIC_INLINE void nrf_uart_txrx_pins_disconnect(NRF_UART_Type * p_reg) +{ + nrf_uart_txrx_pins_set(p_reg, NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED); +} + +__STATIC_INLINE uint32_t nrf_uart_tx_pin_get(NRF_UART_Type * p_reg) +{ +#if defined(UART_PSEL_TXD_CONNECT_Pos) + return p_reg->PSEL.TXD; +#else + return p_reg->PSELTXD; +#endif +} + +__STATIC_INLINE uint32_t nrf_uart_rx_pin_get(NRF_UART_Type * p_reg) +{ +#if defined(UART_PSEL_RXD_CONNECT_Pos) + return p_reg->PSEL.RXD; +#else + return p_reg->PSELRXD; +#endif +} + +__STATIC_INLINE uint32_t nrf_uart_rts_pin_get(NRF_UART_Type * p_reg) +{ +#if defined(UART_PSEL_RTS_CONNECT_Pos) + return p_reg->PSEL.RTS; +#else + return p_reg->PSELRTS; +#endif +} + +__STATIC_INLINE uint32_t nrf_uart_cts_pin_get(NRF_UART_Type * p_reg) +{ +#if defined(UART_PSEL_RTS_CONNECT_Pos) + return p_reg->PSEL.CTS; +#else + return p_reg->PSELCTS; +#endif +} + +__STATIC_INLINE void nrf_uart_hwfc_pins_set(NRF_UART_Type * p_reg, uint32_t pselrts, uint32_t pselcts) +{ +#if defined(UART_PSEL_RTS_CONNECT_Pos) + p_reg->PSEL.RTS = pselrts; +#else + p_reg->PSELRTS = pselrts; +#endif + +#if defined(UART_PSEL_RTS_CONNECT_Pos) + p_reg->PSEL.CTS = pselcts; +#else + p_reg->PSELCTS = pselcts; +#endif +} + +__STATIC_INLINE void nrf_uart_hwfc_pins_disconnect(NRF_UART_Type * p_reg) +{ + nrf_uart_hwfc_pins_set(p_reg, NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED); +} + +__STATIC_INLINE uint8_t nrf_uart_rxd_get(NRF_UART_Type * p_reg) +{ + return p_reg->RXD; +} + +__STATIC_INLINE void nrf_uart_txd_set(NRF_UART_Type * p_reg, uint8_t txd) +{ + p_reg->TXD = txd; +} + +__STATIC_INLINE void nrf_uart_task_trigger(NRF_UART_Type * p_reg, nrf_uart_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_uart_task_address_get(NRF_UART_Type * p_reg, nrf_uart_task_t task) +{ + return (uint32_t)p_reg + (uint32_t)task; +} + +__STATIC_INLINE void nrf_uart_configure(NRF_UART_Type * p_reg, + nrf_uart_parity_t parity, + nrf_uart_hwfc_t hwfc) +{ + p_reg->CONFIG = (uint32_t)parity | (uint32_t)hwfc; +} + +__STATIC_INLINE void nrf_uart_baudrate_set(NRF_UART_Type * p_reg, nrf_uart_baudrate_t baudrate) +{ + p_reg->BAUDRATE = baudrate; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif //NRF_UART_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uarte.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uarte.h new file mode 100644 index 0000000000..49a5c4e5d4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_uarte.h @@ -0,0 +1,609 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_UARTE_H__ +#define NRF_UARTE_H__ + +#include "nrf.h" +#include "nrf_peripherals.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_UARTE_PSEL_DISCONNECTED 0xFFFFFFFF + +/** + * @defgroup nrf_uarte_hal UARTE HAL + * @{ + * @ingroup nrf_uart + * + * @brief Hardware access layer for accessing the UARTE peripheral. + */ + +/** + * @enum nrf_uarte_task_t + * @brief UARTE tasks. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_UARTE_TASK_STARTRX = offsetof(NRF_UARTE_Type, TASKS_STARTRX),///< Start UART receiver. + NRF_UARTE_TASK_STOPRX = offsetof(NRF_UARTE_Type, TASKS_STOPRX), ///< Stop UART receiver. + NRF_UARTE_TASK_STARTTX = offsetof(NRF_UARTE_Type, TASKS_STARTTX),///< Start UART transmitter. + NRF_UARTE_TASK_STOPTX = offsetof(NRF_UARTE_Type, TASKS_STOPTX), ///< Stop UART transmitter. + NRF_UARTE_TASK_FLUSHRX = offsetof(NRF_UARTE_Type, TASKS_FLUSHRX) ///< Flush RX FIFO in RX buffer. + /*lint -restore*/ +} nrf_uarte_task_t; + +/** + * @enum nrf_uarte_event_t + * @brief UARTE events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_UARTE_EVENT_CTS = offsetof(NRF_UARTE_Type, EVENTS_CTS), ///< CTS is activated. + NRF_UARTE_EVENT_NCTS = offsetof(NRF_UARTE_Type, EVENTS_NCTS), ///< CTS is deactivated. + NRF_UARTE_EVENT_ENDRX = offsetof(NRF_UARTE_Type, EVENTS_ENDRX), ///< Receive buffer is filled up. + NRF_UARTE_EVENT_ENDTX = offsetof(NRF_UARTE_Type, EVENTS_ENDTX), ///< Last TX byte transmitted. + NRF_UARTE_EVENT_ERROR = offsetof(NRF_UARTE_Type, EVENTS_ERROR), ///< Error detected. + NRF_UARTE_EVENT_RXTO = offsetof(NRF_UARTE_Type, EVENTS_RXTO), ///< Receiver timeout. + NRF_UARTE_EVENT_RXSTARTED = offsetof(NRF_UARTE_Type, EVENTS_RXSTARTED),///< Receiver has started. + NRF_UARTE_EVENT_TXSTARTED = offsetof(NRF_UARTE_Type, EVENTS_TXSTARTED),///< Transmitter has started. + NRF_UARTE_EVENT_TXSTOPPED = offsetof(NRF_UARTE_Type, EVENTS_TXSTOPPED) ///< Transmitted stopped. + /*lint -restore*/ +} nrf_uarte_event_t; + +/** + * @brief Types of UARTE shortcuts. + */ +typedef enum +{ + NRF_UARTE_SHORT_ENDRX_STARTRX = UARTE_SHORTS_ENDRX_STARTRX_Msk,///< Shortcut between ENDRX event and STARTRX task. + NRF_UARTE_SHORT_ENDRX_STOPRX = UARTE_SHORTS_ENDRX_STOPRX_Msk, ///< Shortcut between ENDRX event and STOPRX task. +} nrf_uarte_short_t; + + +/** + * @enum nrf_uarte_int_mask_t + * @brief UARTE interrupts. + */ +typedef enum +{ + NRF_UARTE_INT_CTS_MASK = UARTE_INTENSET_CTS_Msk, ///< Interrupt on CTS event. + NRF_UARTE_INT_NCTSRX_MASK = UARTE_INTENSET_NCTS_Msk, ///< Interrupt on NCTS event. + NRF_UARTE_INT_ENDRX_MASK = UARTE_INTENSET_ENDRX_Msk, ///< Interrupt on ENDRX event. + NRF_UARTE_INT_ENDTX_MASK = UARTE_INTENSET_ENDTX_Msk, ///< Interrupt on ENDTX event. + NRF_UARTE_INT_ERROR_MASK = UARTE_INTENSET_ERROR_Msk, ///< Interrupt on ERROR event. + NRF_UARTE_INT_RXTO_MASK = UARTE_INTENSET_RXTO_Msk, ///< Interrupt on RXTO event. + NRF_UARTE_INT_RXSTARTED_MASK = UARTE_INTENSET_RXSTARTED_Msk,///< Interrupt on RXSTARTED event. + NRF_UARTE_INT_TXSTARTED_MASK = UARTE_INTENSET_TXSTARTED_Msk,///< Interrupt on TXSTARTED event. + NRF_UARTE_INT_TXSTOPPED_MASK = UARTE_INTENSET_TXSTOPPED_Msk ///< Interrupt on TXSTOPPED event. +} nrf_uarte_int_mask_t; + +/** + * @enum nrf_uarte_baudrate_t + * @brief Baudrates supported by UARTE. + */ +typedef enum +{ + NRF_UARTE_BAUDRATE_1200 = UARTE_BAUDRATE_BAUDRATE_Baud1200, ///< 1200 baud. + NRF_UARTE_BAUDRATE_2400 = UARTE_BAUDRATE_BAUDRATE_Baud2400, ///< 2400 baud. + NRF_UARTE_BAUDRATE_4800 = UARTE_BAUDRATE_BAUDRATE_Baud4800, ///< 4800 baud. + NRF_UARTE_BAUDRATE_9600 = UARTE_BAUDRATE_BAUDRATE_Baud9600, ///< 9600 baud. + NRF_UARTE_BAUDRATE_14400 = UARTE_BAUDRATE_BAUDRATE_Baud14400, ///< 14400 baud. + NRF_UARTE_BAUDRATE_19200 = UARTE_BAUDRATE_BAUDRATE_Baud19200, ///< 19200 baud. + NRF_UARTE_BAUDRATE_28800 = UARTE_BAUDRATE_BAUDRATE_Baud28800, ///< 28800 baud. + NRF_UARTE_BAUDRATE_38400 = UARTE_BAUDRATE_BAUDRATE_Baud38400, ///< 38400 baud. + NRF_UARTE_BAUDRATE_57600 = UARTE_BAUDRATE_BAUDRATE_Baud57600, ///< 57600 baud. + NRF_UARTE_BAUDRATE_76800 = UARTE_BAUDRATE_BAUDRATE_Baud76800, ///< 76800 baud. + NRF_UARTE_BAUDRATE_115200 = UARTE_BAUDRATE_BAUDRATE_Baud115200, ///< 115200 baud. + NRF_UARTE_BAUDRATE_230400 = UARTE_BAUDRATE_BAUDRATE_Baud230400, ///< 230400 baud. + NRF_UARTE_BAUDRATE_250000 = UARTE_BAUDRATE_BAUDRATE_Baud250000, ///< 250000 baud. + NRF_UARTE_BAUDRATE_460800 = UARTE_BAUDRATE_BAUDRATE_Baud460800, ///< 460800 baud. + NRF_UARTE_BAUDRATE_921600 = UARTE_BAUDRATE_BAUDRATE_Baud921600, ///< 921600 baud. + NRF_UARTE_BAUDRATE_1000000 = UARTE_BAUDRATE_BAUDRATE_Baud1M, ///< 1000000 baud. +#ifndef UART_PRESENT + NRF_UART_BAUDRATE_1200 = NRF_UARTE_BAUDRATE_1200, + NRF_UART_BAUDRATE_2400 = NRF_UARTE_BAUDRATE_2400, + NRF_UART_BAUDRATE_4800 = NRF_UARTE_BAUDRATE_4800, + NRF_UART_BAUDRATE_9600 = NRF_UARTE_BAUDRATE_9600, + NRF_UART_BAUDRATE_14400 = NRF_UARTE_BAUDRATE_14400, + NRF_UART_BAUDRATE_19200 = NRF_UARTE_BAUDRATE_19200, + NRF_UART_BAUDRATE_28800 = NRF_UARTE_BAUDRATE_28800, + NRF_UART_BAUDRATE_38400 = NRF_UARTE_BAUDRATE_38400, + NRF_UART_BAUDRATE_57600 = NRF_UARTE_BAUDRATE_57600, + NRF_UART_BAUDRATE_76800 = NRF_UARTE_BAUDRATE_76800, + NRF_UART_BAUDRATE_115200 = NRF_UARTE_BAUDRATE_115200, + NRF_UART_BAUDRATE_230400 = NRF_UARTE_BAUDRATE_230400, + NRF_UART_BAUDRATE_250000 = NRF_UARTE_BAUDRATE_250000, + NRF_UART_BAUDRATE_460800 = NRF_UARTE_BAUDRATE_460800, + NRF_UART_BAUDRATE_921600 = NRF_UARTE_BAUDRATE_921600, + NRF_UART_BAUDRATE_1000000 = NRF_UARTE_BAUDRATE_1000000, +#endif +} nrf_uarte_baudrate_t; + +/** + * @enum nrf_uarte_error_mask_t + * @brief Types of UARTE error masks. + */ +typedef enum +{ + NRF_UARTE_ERROR_OVERRUN_MASK = UARTE_ERRORSRC_OVERRUN_Msk, ///< Overrun error. + NRF_UARTE_ERROR_PARITY_MASK = UARTE_ERRORSRC_PARITY_Msk, ///< Parity error. + NRF_UARTE_ERROR_FRAMING_MASK = UARTE_ERRORSRC_FRAMING_Msk, ///< Framing error. + NRF_UARTE_ERROR_BREAK_MASK = UARTE_ERRORSRC_BREAK_Msk, ///< Break error. +#ifndef UART_PRESENT + NRF_UART_ERROR_OVERRUN_MASK = NRF_UARTE_ERROR_OVERRUN_MASK, + NRF_UART_ERROR_PARITY_MASK = NRF_UARTE_ERROR_PARITY_MASK, + NRF_UART_ERROR_FRAMING_MASK = NRF_UARTE_ERROR_FRAMING_MASK, + NRF_UART_ERROR_BREAK_MASK = NRF_UARTE_ERROR_BREAK_MASK, +#endif +} nrf_uarte_error_mask_t; + +/** + * @enum nrf_uarte_parity_t + * @brief Types of UARTE parity modes. + */ +typedef enum +{ + NRF_UARTE_PARITY_EXCLUDED = UARTE_CONFIG_PARITY_Excluded << UARTE_CONFIG_PARITY_Pos, ///< Parity excluded. + NRF_UARTE_PARITY_INCLUDED = UARTE_CONFIG_PARITY_Included << UARTE_CONFIG_PARITY_Pos, ///< Parity included. +#ifndef UART_PRESENT + NRF_UART_PARITY_EXCLUDED = NRF_UARTE_PARITY_EXCLUDED, + NRF_UART_PARITY_INCLUDED = NRF_UARTE_PARITY_INCLUDED, +#endif +} nrf_uarte_parity_t; + +/** + * @enum nrf_uarte_hwfc_t + * @brief Types of UARTE flow control modes. + */ +typedef enum +{ + NRF_UARTE_HWFC_DISABLED = UARTE_CONFIG_HWFC_Disabled << UARTE_CONFIG_HWFC_Pos, ///< HW flow control disabled. + NRF_UARTE_HWFC_ENABLED = UARTE_CONFIG_HWFC_Enabled << UARTE_CONFIG_HWFC_Pos, ///< HW flow control enabled. +#ifndef UART_PRESENT + NRF_UART_HWFC_DISABLED = NRF_UARTE_HWFC_DISABLED, + NRF_UART_HWFC_ENABLED = NRF_UARTE_HWFC_ENABLED, +#endif +} nrf_uarte_hwfc_t; + + +/** + * @brief Function for clearing a specific UARTE event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to clear. + */ +__STATIC_INLINE void nrf_uarte_event_clear(NRF_UARTE_Type * p_reg, nrf_uarte_event_t event); + +/** + * @brief Function for checking the state of a specific UARTE event. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Event to check. + * + * @retval True if event is set, False otherwise. + */ +__STATIC_INLINE bool nrf_uarte_event_check(NRF_UARTE_Type * p_reg, nrf_uarte_event_t event); + +/** + * @brief Function for returning the address of a specific UARTE event register. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] event Desired event. + * + * @retval Address of specified event register. + */ +__STATIC_INLINE uint32_t nrf_uarte_event_address_get(NRF_UARTE_Type * p_reg, + nrf_uarte_event_t event); + +/** + * @brief Function for enabling UARTE shortcuts. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param shorts_mask Shortcuts to enable. + */ +__STATIC_INLINE void nrf_uarte_shorts_enable(NRF_UARTE_Type * p_reg, uint32_t shorts_mask); + +/** + * @brief Function for disabling UARTE shortcuts. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param shorts_mask Shortcuts to disable. + */ +__STATIC_INLINE void nrf_uarte_shorts_disable(NRF_UARTE_Type * p_reg, uint32_t shorts_mask); + +/** + * @brief Function for enabling UARTE interrupts. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param int_mask Interrupts to enable. + */ +__STATIC_INLINE void nrf_uarte_int_enable(NRF_UARTE_Type * p_reg, uint32_t int_mask); + +/** + * @brief Function for retrieving the state of a given interrupt. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param int_mask Mask of interrupt to check. + * + * @retval true If the interrupt is enabled. + * @retval false If the interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_uarte_int_enable_check(NRF_UARTE_Type * p_reg, nrf_uarte_int_mask_t int_mask); + +/** + * @brief Function for disabling specific interrupts. + * + * @param p_reg Instance. + * @param int_mask Interrupts to disable. + */ +__STATIC_INLINE void nrf_uarte_int_disable(NRF_UARTE_Type * p_reg, uint32_t int_mask); + +/** + * @brief Function for getting error source mask. Function is clearing error source flags after reading. + * + * @param p_reg Pointer to the peripheral registers structure. + * @return Mask with error source flags. + */ +__STATIC_INLINE uint32_t nrf_uarte_errorsrc_get_and_clear(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for enabling UARTE. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uarte_enable(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for disabling UARTE. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uarte_disable(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for configuring TX/RX pins. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param pseltxd TXD pin number. + * @param pselrxd RXD pin number. + */ +__STATIC_INLINE void nrf_uarte_txrx_pins_set(NRF_UARTE_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd); + +/** + * @brief Function for disconnecting TX/RX pins. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uarte_txrx_pins_disconnect(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for getting TX pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uarte_tx_pin_get(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for getting RX pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uarte_rx_pin_get(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for getting RTS pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uarte_rts_pin_get(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for getting CTS pin. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE uint32_t nrf_uarte_cts_pin_get(NRF_UARTE_Type * p_reg); + + +/** + * @brief Function for configuring flow control pins. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param pselrts RTS pin number. + * @param pselcts CTS pin number. + */ +__STATIC_INLINE void nrf_uarte_hwfc_pins_set(NRF_UARTE_Type * p_reg, + uint32_t pselrts, + uint32_t pselcts); + +/** + * @brief Function for disconnecting flow control pins. + * + * @param p_reg Pointer to the peripheral registers structure. + */ +__STATIC_INLINE void nrf_uarte_hwfc_pins_disconnect(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for starting an UARTE task. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param task Task. + */ +__STATIC_INLINE void nrf_uarte_task_trigger(NRF_UARTE_Type * p_reg, nrf_uarte_task_t task); + +/** + * @brief Function for returning the address of a specific task register. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_uarte_task_address_get(NRF_UARTE_Type * p_reg, nrf_uarte_task_t task); + +/** + * @brief Function for configuring UARTE. + * + * @param p_reg Pointer to the peripheral registers structure. + * @param hwfc Hardware flow control. Enabled if true. + * @param parity Parity. Included if true. + */ +__STATIC_INLINE void nrf_uarte_configure(NRF_UARTE_Type * p_reg, + nrf_uarte_parity_t parity, + nrf_uarte_hwfc_t hwfc); + + +/** + * @brief Function for setting UARTE baudrate. + * + * @param p_reg Instance. + * @param baudrate Baudrate. + */ +__STATIC_INLINE void nrf_uarte_baudrate_set(NRF_UARTE_Type * p_reg, nrf_uarte_baudrate_t baudrate); + +/** + * @brief Function for setting the transmit buffer. + * + * @param[in] p_reg Instance. + * @param[in] p_buffer Pointer to the buffer with data to send. + * @param[in] length Maximum number of data bytes to transmit. + */ +__STATIC_INLINE void nrf_uarte_tx_buffer_set(NRF_UARTE_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length); + +/** + * @brief Function for getting number of bytes transmitted in the last transaction. + * + * @param[in] p_reg Instance. + * + * @retval Amount of bytes transmitted. + */ +__STATIC_INLINE uint32_t nrf_uarte_tx_amount_get(NRF_UARTE_Type * p_reg); + +/** + * @brief Function for setting the receive buffer. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * @param[in] p_buffer Pointer to the buffer for received data. + * @param[in] length Maximum number of data bytes to receive. + */ +__STATIC_INLINE void nrf_uarte_rx_buffer_set(NRF_UARTE_Type * p_reg, + uint8_t * p_buffer, + uint8_t length); + +/** + * @brief Function for getting number of bytes received in the last transaction. + * + * @param[in] p_reg Pointer to the peripheral registers structure. + * + * @retval Amount of bytes received. + */ +__STATIC_INLINE uint32_t nrf_uarte_rx_amount_get(NRF_UARTE_Type * p_reg); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_uarte_event_clear(NRF_UARTE_Type * p_reg, nrf_uarte_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)); + (void)dummy; +#endif + +} + +__STATIC_INLINE bool nrf_uarte_event_check(NRF_UARTE_Type * p_reg, nrf_uarte_event_t event) +{ + return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE uint32_t nrf_uarte_event_address_get(NRF_UARTE_Type * p_reg, + nrf_uarte_event_t event) +{ + return (uint32_t)((uint8_t *)p_reg + (uint32_t)event); +} + +__STATIC_INLINE void nrf_uarte_shorts_enable(NRF_UARTE_Type * p_reg, uint32_t shorts_mask) +{ + p_reg->SHORTS |= shorts_mask; +} + +__STATIC_INLINE void nrf_uarte_shorts_disable(NRF_UARTE_Type * p_reg, uint32_t shorts_mask) +{ + p_reg->SHORTS &= ~(shorts_mask); +} + +__STATIC_INLINE void nrf_uarte_int_enable(NRF_UARTE_Type * p_reg, uint32_t int_mask) +{ + p_reg->INTENSET = int_mask; +} + +__STATIC_INLINE bool nrf_uarte_int_enable_check(NRF_UARTE_Type * p_reg, nrf_uarte_int_mask_t int_mask) +{ + return (bool)(p_reg->INTENSET & int_mask); +} + +__STATIC_INLINE void nrf_uarte_int_disable(NRF_UARTE_Type * p_reg, uint32_t int_mask) +{ + p_reg->INTENCLR = int_mask; +} + +__STATIC_INLINE uint32_t nrf_uarte_errorsrc_get_and_clear(NRF_UARTE_Type * p_reg) +{ + uint32_t errsrc_mask = p_reg->ERRORSRC; + p_reg->ERRORSRC = errsrc_mask; + return errsrc_mask; +} + +__STATIC_INLINE void nrf_uarte_enable(NRF_UARTE_Type * p_reg) +{ + p_reg->ENABLE = UARTE_ENABLE_ENABLE_Enabled; +} + +__STATIC_INLINE void nrf_uarte_disable(NRF_UARTE_Type * p_reg) +{ + p_reg->ENABLE = UARTE_ENABLE_ENABLE_Disabled; +} + +__STATIC_INLINE void nrf_uarte_txrx_pins_set(NRF_UARTE_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd) +{ + p_reg->PSEL.TXD = pseltxd; + p_reg->PSEL.RXD = pselrxd; +} + +__STATIC_INLINE void nrf_uarte_txrx_pins_disconnect(NRF_UARTE_Type * p_reg) +{ + nrf_uarte_txrx_pins_set(p_reg, NRF_UARTE_PSEL_DISCONNECTED, NRF_UARTE_PSEL_DISCONNECTED); +} + +__STATIC_INLINE uint32_t nrf_uarte_tx_pin_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->PSEL.TXD; +} + +__STATIC_INLINE uint32_t nrf_uarte_rx_pin_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->PSEL.RXD; +} + +__STATIC_INLINE uint32_t nrf_uarte_rts_pin_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->PSEL.RTS; +} + +__STATIC_INLINE uint32_t nrf_uarte_cts_pin_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->PSEL.CTS; +} + +__STATIC_INLINE void nrf_uarte_hwfc_pins_set(NRF_UARTE_Type * p_reg, uint32_t pselrts, uint32_t pselcts) +{ + p_reg->PSEL.RTS = pselrts; + p_reg->PSEL.CTS = pselcts; +} + +__STATIC_INLINE void nrf_uarte_hwfc_pins_disconnect(NRF_UARTE_Type * p_reg) +{ + nrf_uarte_hwfc_pins_set(p_reg, NRF_UARTE_PSEL_DISCONNECTED, NRF_UARTE_PSEL_DISCONNECTED); +} + +__STATIC_INLINE void nrf_uarte_task_trigger(NRF_UARTE_Type * p_reg, nrf_uarte_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL; +} + +__STATIC_INLINE uint32_t nrf_uarte_task_address_get(NRF_UARTE_Type * p_reg, nrf_uarte_task_t task) +{ + return (uint32_t)p_reg + (uint32_t)task; +} + +__STATIC_INLINE void nrf_uarte_configure(NRF_UARTE_Type * p_reg, + nrf_uarte_parity_t parity, + nrf_uarte_hwfc_t hwfc) +{ + p_reg->CONFIG = (uint32_t)parity | (uint32_t)hwfc; +} + +__STATIC_INLINE void nrf_uarte_baudrate_set(NRF_UARTE_Type * p_reg, nrf_uarte_baudrate_t baudrate) +{ + p_reg->BAUDRATE = baudrate; +} + +__STATIC_INLINE void nrf_uarte_tx_buffer_set(NRF_UARTE_Type * p_reg, + uint8_t const * p_buffer, + uint8_t length) +{ + p_reg->TXD.PTR = (uint32_t)p_buffer; + p_reg->TXD.MAXCNT = length; +} + +__STATIC_INLINE uint32_t nrf_uarte_tx_amount_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->TXD.AMOUNT; +} + +__STATIC_INLINE void nrf_uarte_rx_buffer_set(NRF_UARTE_Type * p_reg, + uint8_t * p_buffer, + uint8_t length) +{ + p_reg->RXD.PTR = (uint32_t)p_buffer; + p_reg->RXD.MAXCNT = length; +} + +__STATIC_INLINE uint32_t nrf_uarte_rx_amount_get(NRF_UARTE_Type * p_reg) +{ + return p_reg->RXD.AMOUNT; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif //NRF_UARTE_H__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_usbd.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_usbd.h new file mode 100644 index 0000000000..8905788db0 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_usbd.h @@ -0,0 +1,1435 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_USBD_H__ +#define NRF_USBD_H__ + +/** + * @ingroup nrf_drivers + * @defgroup nrf_usbd_hal USBD HAL + * @{ + * + * @brief @tagAPI52840 Hardware access layer for Universal Serial Bus Device (USBD) peripheral. + */ + +#include "nrf_peripherals.h" +#include "nrf.h" +#include "nrf_assert.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief USBD tasks + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_USBD_TASK_STARTEPIN0 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[0] ), /**< Captures the EPIN[0].PTR, EPIN[0].MAXCNT and EPIN[0].CONFIG registers values, and enables control endpoint IN 0 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN1 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[1] ), /**< Captures the EPIN[1].PTR, EPIN[1].MAXCNT and EPIN[1].CONFIG registers values, and enables data endpoint IN 1 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN2 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[2] ), /**< Captures the EPIN[2].PTR, EPIN[2].MAXCNT and EPIN[2].CONFIG registers values, and enables data endpoint IN 2 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN3 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[3] ), /**< Captures the EPIN[3].PTR, EPIN[3].MAXCNT and EPIN[3].CONFIG registers values, and enables data endpoint IN 3 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN4 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[4] ), /**< Captures the EPIN[4].PTR, EPIN[4].MAXCNT and EPIN[4].CONFIG registers values, and enables data endpoint IN 4 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN5 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[5] ), /**< Captures the EPIN[5].PTR, EPIN[5].MAXCNT and EPIN[5].CONFIG registers values, and enables data endpoint IN 5 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN6 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[6] ), /**< Captures the EPIN[6].PTR, EPIN[6].MAXCNT and EPIN[6].CONFIG registers values, and enables data endpoint IN 6 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPIN7 = offsetof(NRF_USBD_Type, TASKS_STARTEPIN[7] ), /**< Captures the EPIN[7].PTR, EPIN[7].MAXCNT and EPIN[7].CONFIG registers values, and enables data endpoint IN 7 to respond to traffic from host */ + NRF_USBD_TASK_STARTISOIN = offsetof(NRF_USBD_Type, TASKS_STARTISOIN ), /**< Captures the ISOIN.PTR, ISOIN.MAXCNT and ISOIN.CONFIG registers values, and enables sending data on iso endpoint 8 */ + NRF_USBD_TASK_STARTEPOUT0 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[0]), /**< Captures the EPOUT[0].PTR, EPOUT[0].MAXCNT and EPOUT[0].CONFIG registers values, and enables control endpoint 0 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT1 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[1]), /**< Captures the EPOUT[1].PTR, EPOUT[1].MAXCNT and EPOUT[1].CONFIG registers values, and enables data endpoint 1 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT2 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[2]), /**< Captures the EPOUT[2].PTR, EPOUT[2].MAXCNT and EPOUT[2].CONFIG registers values, and enables data endpoint 2 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT3 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[3]), /**< Captures the EPOUT[3].PTR, EPOUT[3].MAXCNT and EPOUT[3].CONFIG registers values, and enables data endpoint 3 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT4 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[4]), /**< Captures the EPOUT[4].PTR, EPOUT[4].MAXCNT and EPOUT[4].CONFIG registers values, and enables data endpoint 4 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT5 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[5]), /**< Captures the EPOUT[5].PTR, EPOUT[5].MAXCNT and EPOUT[5].CONFIG registers values, and enables data endpoint 5 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT6 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[6]), /**< Captures the EPOUT[6].PTR, EPOUT[6].MAXCNT and EPOUT[6].CONFIG registers values, and enables data endpoint 6 to respond to traffic from host */ + NRF_USBD_TASK_STARTEPOUT7 = offsetof(NRF_USBD_Type, TASKS_STARTEPOUT[7]), /**< Captures the EPOUT[7].PTR, EPOUT[7].MAXCNT and EPOUT[7].CONFIG registers values, and enables data endpoint 7 to respond to traffic from host */ + NRF_USBD_TASK_STARTISOOUT = offsetof(NRF_USBD_Type, TASKS_STARTISOOUT ), /**< Captures the ISOOUT.PTR, ISOOUT.MAXCNT and ISOOUT.CONFIG registers values, and enables receiving of data on iso endpoint 8 */ + NRF_USBD_TASK_EP0RCVOUT = offsetof(NRF_USBD_Type, TASKS_EP0RCVOUT ), /**< Allows OUT data stage on control endpoint 0 */ + NRF_USBD_TASK_EP0STATUS = offsetof(NRF_USBD_Type, TASKS_EP0STATUS ), /**< Allows status stage on control endpoint 0 */ + NRF_USBD_TASK_EP0STALL = offsetof(NRF_USBD_Type, TASKS_EP0STALL ), /**< STALLs data and status stage on control endpoint 0 */ + NRF_USBD_TASK_DRIVEDPDM = offsetof(NRF_USBD_Type, TASKS_DPDMDRIVE ), /**< Forces D+ and D-lines to the state defined in the DPDMVALUE register */ + NRF_USBD_TASK_NODRIVEDPDM = offsetof(NRF_USBD_Type, TASKS_DPDMNODRIVE ), /**< Stops forcing D+ and D- lines to any state (USB engine takes control) */ + /*lint -restore*/ +}nrf_usbd_task_t; + +/** + * @brief USBD events + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_USBD_EVENT_USBRESET = offsetof(NRF_USBD_Type, EVENTS_USBRESET ), /**< Signals that a USB reset condition has been detected on the USB lines */ + NRF_USBD_EVENT_STARTED = offsetof(NRF_USBD_Type, EVENTS_STARTED ), /**< Confirms that the EPIN[n].PTR, EPIN[n].MAXCNT, EPIN[n].CONFIG, or EPOUT[n].PTR, EPOUT[n].MAXCNT and EPOUT[n].CONFIG registers have been captured on all endpoints reported in the EPSTATUS register */ + NRF_USBD_EVENT_ENDEPIN0 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[0] ), /**< The whole EPIN[0] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN1 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[1] ), /**< The whole EPIN[1] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN2 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[2] ), /**< The whole EPIN[2] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN3 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[3] ), /**< The whole EPIN[3] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN4 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[4] ), /**< The whole EPIN[4] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN5 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[5] ), /**< The whole EPIN[5] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN6 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[6] ), /**< The whole EPIN[6] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPIN7 = offsetof(NRF_USBD_Type, EVENTS_ENDEPIN[7] ), /**< The whole EPIN[7] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_EP0DATADONE = offsetof(NRF_USBD_Type, EVENTS_EP0DATADONE), /**< An acknowledged data transfer has taken place on the control endpoint */ + NRF_USBD_EVENT_ENDISOIN0 = offsetof(NRF_USBD_Type, EVENTS_ENDISOIN ), /**< The whole ISOIN buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT0 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[0]), /**< The whole EPOUT[0] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT1 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[1]), /**< The whole EPOUT[1] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT2 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[2]), /**< The whole EPOUT[2] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT3 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[3]), /**< The whole EPOUT[3] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT4 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[4]), /**< The whole EPOUT[4] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT5 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[5]), /**< The whole EPOUT[5] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT6 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[6]), /**< The whole EPOUT[6] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDEPOUT7 = offsetof(NRF_USBD_Type, EVENTS_ENDEPOUT[7]), /**< The whole EPOUT[7] buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_ENDISOOUT0 = offsetof(NRF_USBD_Type, EVENTS_ENDISOOUT ), /**< The whole ISOOUT buffer has been consumed. The RAM buffer can be accessed safely by software. */ + NRF_USBD_EVENT_SOF = offsetof(NRF_USBD_Type, EVENTS_SOF ), /**< Signals that a SOF (start of frame) condition has been detected on the USB lines */ + NRF_USBD_EVENT_USBEVENT = offsetof(NRF_USBD_Type, EVENTS_USBEVENT ), /**< An event or an error not covered by specific events has occurred, check EVENTCAUSE register to find the cause */ + NRF_USBD_EVENT_EP0SETUP = offsetof(NRF_USBD_Type, EVENTS_EP0SETUP ), /**< A valid SETUP token has been received (and acknowledged) on the control endpoint */ + NRF_USBD_EVENT_DATAEP = offsetof(NRF_USBD_Type, EVENTS_EPDATA ), /**< A data transfer has occurred on a data endpoint, indicated by the EPDATASTATUS register */ + NRF_USBD_EVENT_ACCESSFAULT = offsetof(NRF_USBD_Type, EVENTS_ACCESSFAULT), /**< >Access to an unavailable USB register has been attempted (software or EasyDMA) */ + /*lint -restore*/ +}nrf_usbd_event_t; + +/** + * @brief USBD shorts + */ +typedef enum +{ + NRF_USBD_SHORT_EP0DATADONE_STARTEPIN0_MASK = USBD_SHORTS_EP0DATADONE_STARTEPIN0_Msk , /**< Shortcut between EP0DATADONE event and STARTEPIN0 task */ + NRF_USBD_SHORT_EP0DATADONE_STARTEPOUT0_MASK = USBD_SHORTS_EP0DATADONE_STARTEPOUT0_Msk, /**< Shortcut between EP0DATADONE event and STARTEPOUT0 task */ + NRF_USBD_SHORT_EP0DATADONE_EP0STATUS_MASK = USBD_SHORTS_EP0DATADONE_EP0STATUS_Msk , /**< Shortcut between EP0DATADONE event and EP0STATUS task */ + NRF_USBD_SHORT_ENDEPOUT0_EP0STATUS_MASK = USBD_SHORTS_ENDEPOUT0_EP0STATUS_Msk , /**< Shortcut between ENDEPOUT[0] event and EP0STATUS task */ + NRF_USBD_SHORT_ENDEPOUT0_EP0RCVOUT_MASK = USBD_SHORTS_ENDEPOUT0_EP0RCVOUT_Msk , /**< Shortcut between ENDEPOUT[0] event and EP0RCVOUT task */ +}nrf_usbd_short_mask_t; + +/** + * @brief USBD interrupts + */ +typedef enum +{ + NRF_USBD_INT_USBRESET_MASK = USBD_INTEN_USBRESET_Msk , /**< Enable or disable interrupt for USBRESET event */ + NRF_USBD_INT_STARTED_MASK = USBD_INTEN_STARTED_Msk , /**< Enable or disable interrupt for STARTED event */ + NRF_USBD_INT_ENDEPIN0_MASK = USBD_INTEN_ENDEPIN0_Msk , /**< Enable or disable interrupt for ENDEPIN[0] event */ + NRF_USBD_INT_ENDEPIN1_MASK = USBD_INTEN_ENDEPIN1_Msk , /**< Enable or disable interrupt for ENDEPIN[1] event */ + NRF_USBD_INT_ENDEPIN2_MASK = USBD_INTEN_ENDEPIN2_Msk , /**< Enable or disable interrupt for ENDEPIN[2] event */ + NRF_USBD_INT_ENDEPIN3_MASK = USBD_INTEN_ENDEPIN3_Msk , /**< Enable or disable interrupt for ENDEPIN[3] event */ + NRF_USBD_INT_ENDEPIN4_MASK = USBD_INTEN_ENDEPIN4_Msk , /**< Enable or disable interrupt for ENDEPIN[4] event */ + NRF_USBD_INT_ENDEPIN5_MASK = USBD_INTEN_ENDEPIN5_Msk , /**< Enable or disable interrupt for ENDEPIN[5] event */ + NRF_USBD_INT_ENDEPIN6_MASK = USBD_INTEN_ENDEPIN6_Msk , /**< Enable or disable interrupt for ENDEPIN[6] event */ + NRF_USBD_INT_ENDEPIN7_MASK = USBD_INTEN_ENDEPIN7_Msk , /**< Enable or disable interrupt for ENDEPIN[7] event */ + NRF_USBD_INT_EP0DATADONE_MASK = USBD_INTEN_EP0DATADONE_Msk, /**< Enable or disable interrupt for EP0DATADONE event */ + NRF_USBD_INT_ENDISOIN0_MASK = USBD_INTEN_ENDISOIN_Msk , /**< Enable or disable interrupt for ENDISOIN[0] event */ + NRF_USBD_INT_ENDEPOUT0_MASK = USBD_INTEN_ENDEPOUT0_Msk , /**< Enable or disable interrupt for ENDEPOUT[0] event */ + NRF_USBD_INT_ENDEPOUT1_MASK = USBD_INTEN_ENDEPOUT1_Msk , /**< Enable or disable interrupt for ENDEPOUT[1] event */ + NRF_USBD_INT_ENDEPOUT2_MASK = USBD_INTEN_ENDEPOUT2_Msk , /**< Enable or disable interrupt for ENDEPOUT[2] event */ + NRF_USBD_INT_ENDEPOUT3_MASK = USBD_INTEN_ENDEPOUT3_Msk , /**< Enable or disable interrupt for ENDEPOUT[3] event */ + NRF_USBD_INT_ENDEPOUT4_MASK = USBD_INTEN_ENDEPOUT4_Msk , /**< Enable or disable interrupt for ENDEPOUT[4] event */ + NRF_USBD_INT_ENDEPOUT5_MASK = USBD_INTEN_ENDEPOUT5_Msk , /**< Enable or disable interrupt for ENDEPOUT[5] event */ + NRF_USBD_INT_ENDEPOUT6_MASK = USBD_INTEN_ENDEPOUT6_Msk , /**< Enable or disable interrupt for ENDEPOUT[6] event */ + NRF_USBD_INT_ENDEPOUT7_MASK = USBD_INTEN_ENDEPOUT7_Msk , /**< Enable or disable interrupt for ENDEPOUT[7] event */ + NRF_USBD_INT_ENDISOOUT0_MASK = USBD_INTEN_ENDISOOUT_Msk , /**< Enable or disable interrupt for ENDISOOUT[0] event */ + NRF_USBD_INT_SOF_MASK = USBD_INTEN_SOF_Msk , /**< Enable or disable interrupt for SOF event */ + NRF_USBD_INT_USBEVENT_MASK = USBD_INTEN_USBEVENT_Msk , /**< Enable or disable interrupt for USBEVENT event */ + NRF_USBD_INT_EP0SETUP_MASK = USBD_INTEN_EP0SETUP_Msk , /**< Enable or disable interrupt for EP0SETUP event */ + NRF_USBD_INT_DATAEP_MASK = USBD_INTEN_EPDATA_Msk , /**< Enable or disable interrupt for EPDATA event */ + NRF_USBD_INT_ACCESSFAULT_MASK = USBD_INTEN_ACCESSFAULT_Msk, /**< Enable or disable interrupt for ACCESSFAULT event */ +}nrf_usbd_int_mask_t; + + +/** + * @brief Function for activating a specific USBD task. + * + * @param task Task. + */ +__STATIC_INLINE void nrf_usbd_task_trigger(nrf_usbd_task_t task); + +/** + * @brief Function for returning the address of a specific USBD task register. + * + * @param task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_usbd_task_address_get(nrf_usbd_task_t task); + +/** + * @brief Function for clearing a specific event. + * + * @param event Event. + */ +__STATIC_INLINE void nrf_usbd_event_clear(nrf_usbd_event_t event); + +/** + * @brief Function for returning the state of a specific event. + * + * @param event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_usbd_event_check(nrf_usbd_event_t event); + +/** + * @brief Function for getting and clearing the state of specific event + * + * This function checks the state of the event and clears it. + * + * @param event Event. + * + * @retval true If the event was set. + * @retval false If the event was not set. + */ +__STATIC_INLINE bool nrf_usbd_event_get_and_clear(nrf_usbd_event_t event); + +/** + * @brief Function for returning the address of a specific USBD event register. + * + * @param event Event. + * + * @return Address. + */ +__STATIC_INLINE uint32_t nrf_usbd_event_address_get(nrf_usbd_event_t event); + +/** + * @brief Function for setting a shortcut. + * + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_usbd_shorts_enable(uint32_t short_mask); + +/** + * @brief Function for clearing shortcuts. + * + * @param short_mask Shortcuts mask. + */ +__STATIC_INLINE void nrf_usbd_shorts_disable(uint32_t short_mask); + +/** + * @brief Get the shorts mask + * + * Function returns shorts register. + * + * @return Flags of currently enabled shortcuts + */ +__STATIC_INLINE uint32_t nrf_usbd_shorts_get(void); + +/** + * @brief Function for enabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_usbd_int_enable(uint32_t int_mask); + +/** + * @brief Function for retrieving the state of selected interrupts. + * + * @param int_mask Interrupts mask. + * + * @retval true If any of selected interrupts is enabled. + * @retval false If none of selected interrupts is enabled. + */ +__STATIC_INLINE bool nrf_usbd_int_enable_check(uint32_t int_mask); + +/** + * @brief Function for retrieving the information about enabled interrupts. + * + * @return The flags of enabled interrupts. + */ +__STATIC_INLINE uint32_t nrf_usbd_int_enable_get(void); + +/** + * @brief Function for disabling selected interrupts. + * + * @param int_mask Interrupts mask. + */ +__STATIC_INLINE void nrf_usbd_int_disable(uint32_t int_mask); + + +/** @} */ /* End of nrf_usbd_hal */ + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +/* ------------------------------------------------------------------------------------------------ + * Internal functions + */ + +/** + * @internal + * @brief Internal function for getting task/event register address + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile uint32_t* nrf_usbd_getRegPtr(uint32_t offset) +{ + return (volatile uint32_t*)(((uint8_t *)NRF_USBD) + (uint32_t)offset); +} + +/** + * @internal + * @brief Internal function for getting task/event register address - constant version + * + * @oaram offset Offset of the register from the instance beginning + * + * @attention offset has to be modulo 4 value. In other case we can get hardware fault. + * @return Pointer to the register + */ +__STATIC_INLINE volatile const uint32_t* nrf_usbd_getRegPtr_c(uint32_t offset) +{ + return (volatile const uint32_t*)(((uint8_t *)NRF_USBD) + (uint32_t)offset); +} + +/* ------------------------------------------------------------------------------------------------ + * Interface functions definitions + */ + +void nrf_usbd_task_trigger(nrf_usbd_task_t task) +{ + *(nrf_usbd_getRegPtr((uint32_t)task)) = 1UL; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_task_address_get(nrf_usbd_task_t task) +{ + return (uint32_t)nrf_usbd_getRegPtr_c((uint32_t)task); +} + +void nrf_usbd_event_clear(nrf_usbd_event_t event) +{ + *(nrf_usbd_getRegPtr((uint32_t)event)) = 0UL; + __ISB(); + __DSB(); +} + +bool nrf_usbd_event_check(nrf_usbd_event_t event) +{ + return (bool)*nrf_usbd_getRegPtr_c((uint32_t)event); +} + +bool nrf_usbd_event_get_and_clear(nrf_usbd_event_t event) +{ + bool ret = nrf_usbd_event_check(event); + if (ret) + { + nrf_usbd_event_clear(event); + } + return ret; +} + +uint32_t nrf_usbd_event_address_get(nrf_usbd_event_t event) +{ + return (uint32_t)nrf_usbd_getRegPtr_c((uint32_t)event); +} + +void nrf_usbd_shorts_enable(uint32_t short_mask) +{ + NRF_USBD->SHORTS |= short_mask; +} + +void nrf_usbd_shorts_disable(uint32_t short_mask) +{ + if (~0U == short_mask) + { + /* Optimized version for "disable all" */ + NRF_USBD->SHORTS = 0; + } + else + { + NRF_USBD->SHORTS &= ~short_mask; + } +} + +uint32_t nrf_usbd_shorts_get(void) +{ + return NRF_USBD->SHORTS; +} + +void nrf_usbd_int_enable(uint32_t int_mask) +{ + NRF_USBD->INTENSET = int_mask; +} + +bool nrf_usbd_int_enable_check(uint32_t int_mask) +{ + return !!(NRF_USBD->INTENSET & int_mask); +} + +uint32_t nrf_usbd_int_enable_get(void) +{ + return NRF_USBD->INTENSET; +} + +void nrf_usbd_int_disable(uint32_t int_mask) +{ + NRF_USBD->INTENCLR = int_mask; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/* ------------------------------------------------------------------------------------------------ + * End of automatically generated part + * ------------------------------------------------------------------------------------------------ + */ +/** + * @addtogroup nrf_usbd_hal + * @{ + */ + +/** + * @brief Frame counter size + * + * The number of counts that can be fitted into frame counter + */ +#define NRF_USBD_FRAMECNTR_SIZE \ + ( (USBD_FRAMECNTR_FRAMECNTR_Msk >> USBD_FRAMECNTR_FRAMECNTR_Pos) + 1UL ) +#ifndef USBD_FRAMECNTR_FRAMECNTR_Msk +#error USBD_FRAMECNTR_FRAMECNTR_Msk should be changed into USBD_FRAMECNTR_FRAMECNTR_Msk +#endif + +/** + * @brief First isochronous endpoint number + * + * The number of the first isochronous endpoint + */ +#define NRF_USBD_EPISO_FIRST 8 + +/** + * @brief Total number of IN endpoints + * + * Total number of IN endpoint (including ISOCHRONOUS). + */ +#define NRF_USBD_EPIN_CNT 9 + +/** + * @brief Total number of OUT endpoints + * + * Total number of OUT endpoint (including ISOCHRONOUS). + */ +#define NRF_USBD_EPOUT_CNT 9 + +/** + * @brief Mask of the direction bit in endpoint number + */ +#define NRF_USBD_EP_DIR_Msk (1U << 7) + +/** + * @brief The value of direction bit for IN endpoint direction + */ +#define NRF_USBD_EP_DIR_IN (1U << 7) + +/** + * @brief The value of direction bit for OUT endpoint direction + */ +#define NRF_USBD_EP_DIR_OUT (0U << 7) + +/** + * @brief Macro for making IN endpoint identifier from endpoint number + * + * Macro that sets direction bit to make IN endpoint + * @param[in] epnr Endpoint number + * @return IN Endpoint identifier + */ +#define NRF_USBD_EPIN(epnr) (((uint8_t)(epnr)) | NRF_USBD_EP_DIR_IN) + +/** + * @brief Macro for making OUT endpoint identifier from endpoint number + * + * Macro that sets direction bit to make OUT endpoint + * @param[in] epnr Endpoint number + * @return OUT Endpoint identifier + */ +#define NRF_USBD_EPOUT(epnr) (((uint8_t)(epnr)) | NRF_USBD_EP_DIR_OUT) + +/** + * @brief Macro for extracting the endpoint number from endpoint identifier + * + * Macro that strips out the information about endpoint direction. + * @param[in] ep Endpoint identifier + * @return Endpoint number + */ +#define NRF_USBD_EP_NR_GET(ep) ((uint8_t)(((uint8_t)(ep)) & 0xFU)) + +/** + * @brief Macro for checking endpoint direction + * + * This macro checks if given endpoint has IN direction + * @param ep Endpoint identifier + * @retval true If the endpoint direction is IN + * @retval false If the endpoint direction is OUT + */ +#define NRF_USBD_EPIN_CHECK(ep) ( (((uint8_t)(ep)) & NRF_USBD_EP_DIR_Msk) == NRF_USBD_EP_DIR_IN ) + +/** + * @brief Macro for checking endpoint direction + * + * This macro checks if given endpoint has OUT direction + * @param ep Endpoint identifier + * @retval true If the endpoint direction is OUT + * @retval false If the endpoint direction is IN + */ +#define NRF_USBD_EPOUT_CHECK(ep) ( (((uint8_t)(ep)) & NRF_USBD_EP_DIR_Msk) == NRF_USBD_EP_DIR_OUT ) + +/** + * @brief Macro for checking if endpoint is isochronous + * + * @param ep It can be endpoint identifier or just endpoint number to check + * @retval true The endpoint is isochronous type + * @retval false The endpoint is bulk of interrupt type + */ +#define NRF_USBD_EPISO_CHECK(ep) (NRF_USBD_EP_NR_GET(ep) >= NRF_USBD_EPISO_FIRST) + +/** + * @brief Macro for checking if given number is valid endpoint number + * + * @param ep Endpoint number to check + * @retval true The endpoint is valid + * @retval false The endpoint is not valid + */ +#define NRF_USBD_EP_VALIDATE(ep) ( \ + (NRF_USBD_EPIN_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPIN_CNT)) \ + || \ + (NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPOUT_CNT)) \ + ) + +/** + * @brief Not isochronous data frame received + * + * Special value returned by @ref nrf_usbd_episoout_size_get function that means that + * data frame was not received at all. + * This allows differentiate between situations when zero size data comes or no data comes at all + * on isochronous endpoint. + */ +#define NRF_USBD_EPISOOUT_NO_DATA ((size_t)(-1)) + +/** + * @brief EVENTCAUSE register bit masks + */ +typedef enum +{ + NRF_USBD_EVENTCAUSE_ISOOUTCRC_MASK = USBD_EVENTCAUSE_ISOOUTCRC_Msk, /**< CRC error was detected on isochronous OUT endpoint 8. */ + NRF_USBD_EVENTCAUSE_SUSPEND_MASK = USBD_EVENTCAUSE_SUSPEND_Msk , /**< Signals that the USB lines have been seen idle long enough for the device to enter suspend. */ + NRF_USBD_EVENTCAUSE_RESUME_MASK = USBD_EVENTCAUSE_RESUME_Msk , /**< Signals that a RESUME condition (K state or activity restart) has been detected on the USB lines. */ + NRF_USBD_EVENTCAUSE_READY_MASK = USBD_EVENTCAUSE_READY_Msk, /**< MAC is ready for normal operation, rised few us after USBD enabling */ + NRF_USBD_EVENTCAUSE_WUREQ_MASK = (1U << 10) /**< The USBD peripheral has exited Low Power mode */ +}nrf_usbd_eventcause_mask_t; + +/** + * @brief BUSSTATE register bit masks + */ +typedef enum +{ + NRF_USBD_BUSSTATE_DM_MASK = USBD_BUSSTATE_DM_Msk, /**< Negative line mask */ + NRF_USBD_BUSSTATE_DP_MASK = USBD_BUSSTATE_DP_Msk, /**< Positive line mask */ + /** Both lines are low */ + NRF_USBD_BUSSTATE_DPDM_LL = (USBD_BUSSTATE_DM_Low << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_Low << USBD_BUSSTATE_DP_Pos), + /** Positive line is high, negative line is low */ + NRF_USBD_BUSSTATE_DPDM_HL = (USBD_BUSSTATE_DM_Low << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_High << USBD_BUSSTATE_DP_Pos), + /** Positive line is low, negative line is high */ + NRF_USBD_BUSSTATE_DPDM_LH = (USBD_BUSSTATE_DM_High << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_Low << USBD_BUSSTATE_DP_Pos), + /** Both lines are high */ + NRF_USBD_BUSSTATE_DPDM_HH = (USBD_BUSSTATE_DM_High << USBD_BUSSTATE_DM_Pos) | (USBD_BUSSTATE_DP_High << USBD_BUSSTATE_DP_Pos), + /** J state */ + NRF_USBD_BUSSTATE_J = NRF_USBD_BUSSTATE_DPDM_HL, + /** K state */ + NRF_USBD_BUSSTATE_K = NRF_USBD_BUSSTATE_DPDM_LH, + /** Single ended 0 */ + NRF_USBD_BUSSTATE_SE0 = NRF_USBD_BUSSTATE_DPDM_LL, + /** Single ended 1 */ + NRF_USBD_BUSSTATE_SE1 = NRF_USBD_BUSSTATE_DPDM_HH +}nrf_usbd_busstate_t; + +/** + * @brief DPDMVALUE register + */ +typedef enum +{ + /**Generate Resume signal. Signal is generated for 50 us or 5 ms, + * depending on bus state */ + NRF_USBD_DPDMVALUE_RESUME = USBD_DPDMVALUE_STATE_Resume, + /** D+ Forced high, D- forced low (J state) */ + NRF_USBD_DPDMVALUE_J = USBD_DPDMVALUE_STATE_J, + /** D+ Forced low, D- forced high (K state) */ + NRF_USBD_DPMVALUE_K = USBD_DPDMVALUE_STATE_K +}nrf_usbd_dpdmvalue_t; + +/** + * @brief Dtoggle value or operation + */ +typedef enum +{ + NRF_USBD_DTOGGLE_NOP = USBD_DTOGGLE_VALUE_Nop, /**< No operation - do not change current data toggle on selected endpoint */ + NRF_USBD_DTOGGLE_DATA0 = USBD_DTOGGLE_VALUE_Data0,/**< Data toggle is DATA0 on selected endpoint */ + NRF_USBD_DTOGGLE_DATA1 = USBD_DTOGGLE_VALUE_Data1 /**< Data toggle is DATA1 on selected endpoint */ +}nrf_usbd_dtoggle_t; + +/** + * @brief EPSTATUS bit masks + */ +typedef enum +{ + NRF_USBD_EPSTATUS_EPIN0_MASK = USBD_EPSTATUS_EPIN0_Msk, + NRF_USBD_EPSTATUS_EPIN1_MASK = USBD_EPSTATUS_EPIN1_Msk, + NRF_USBD_EPSTATUS_EPIN2_MASK = USBD_EPSTATUS_EPIN2_Msk, + NRF_USBD_EPSTATUS_EPIN3_MASK = USBD_EPSTATUS_EPIN3_Msk, + NRF_USBD_EPSTATUS_EPIN4_MASK = USBD_EPSTATUS_EPIN4_Msk, + NRF_USBD_EPSTATUS_EPIN5_MASK = USBD_EPSTATUS_EPIN5_Msk, + NRF_USBD_EPSTATUS_EPIN6_MASK = USBD_EPSTATUS_EPIN6_Msk, + NRF_USBD_EPSTATUS_EPIN7_MASK = USBD_EPSTATUS_EPIN7_Msk, + + NRF_USBD_EPSTATUS_EPOUT0_MASK = USBD_EPSTATUS_EPOUT0_Msk, + NRF_USBD_EPSTATUS_EPOUT1_MASK = USBD_EPSTATUS_EPOUT1_Msk, + NRF_USBD_EPSTATUS_EPOUT2_MASK = USBD_EPSTATUS_EPOUT2_Msk, + NRF_USBD_EPSTATUS_EPOUT3_MASK = USBD_EPSTATUS_EPOUT3_Msk, + NRF_USBD_EPSTATUS_EPOUT4_MASK = USBD_EPSTATUS_EPOUT4_Msk, + NRF_USBD_EPSTATUS_EPOUT5_MASK = USBD_EPSTATUS_EPOUT5_Msk, + NRF_USBD_EPSTATUS_EPOUT6_MASK = USBD_EPSTATUS_EPOUT6_Msk, + NRF_USBD_EPSTATUS_EPOUT7_MASK = USBD_EPSTATUS_EPOUT7_Msk, +}nrf_usbd_epstatus_mask_t; + +/** + * @brief DATAEPSTATUS bit masks + */ +typedef enum +{ + NRF_USBD_EPDATASTATUS_EPIN1_MASK = USBD_EPDATASTATUS_EPIN1_Msk, + NRF_USBD_EPDATASTATUS_EPIN2_MASK = USBD_EPDATASTATUS_EPIN2_Msk, + NRF_USBD_EPDATASTATUS_EPIN3_MASK = USBD_EPDATASTATUS_EPIN3_Msk, + NRF_USBD_EPDATASTATUS_EPIN4_MASK = USBD_EPDATASTATUS_EPIN4_Msk, + NRF_USBD_EPDATASTATUS_EPIN5_MASK = USBD_EPDATASTATUS_EPIN5_Msk, + NRF_USBD_EPDATASTATUS_EPIN6_MASK = USBD_EPDATASTATUS_EPIN6_Msk, + NRF_USBD_EPDATASTATUS_EPIN7_MASK = USBD_EPDATASTATUS_EPIN7_Msk, + + NRF_USBD_EPDATASTATUS_EPOUT1_MASK = USBD_EPDATASTATUS_EPOUT1_Msk, + NRF_USBD_EPDATASTATUS_EPOUT2_MASK = USBD_EPDATASTATUS_EPOUT2_Msk, + NRF_USBD_EPDATASTATUS_EPOUT3_MASK = USBD_EPDATASTATUS_EPOUT3_Msk, + NRF_USBD_EPDATASTATUS_EPOUT4_MASK = USBD_EPDATASTATUS_EPOUT4_Msk, + NRF_USBD_EPDATASTATUS_EPOUT5_MASK = USBD_EPDATASTATUS_EPOUT5_Msk, + NRF_USBD_EPDATASTATUS_EPOUT6_MASK = USBD_EPDATASTATUS_EPOUT6_Msk, + NRF_USBD_EPDATASTATUS_EPOUT7_MASK = USBD_EPDATASTATUS_EPOUT7_Msk, +}nrf_usbd_dataepstatus_mask_t; + +/** + * @brief ISOSPLIT configurations + */ +typedef enum +{ + NRF_USBD_ISOSPLIT_OneDir = USBD_ISOSPLIT_SPLIT_OneDir, /**< Full buffer dedicated to either iso IN or OUT */ + NRF_USBD_ISOSPLIT_Half = USBD_ISOSPLIT_SPLIT_HalfIN, /**< Buffer divided in half */ +}nrf_usbd_isosplit_t; + +/** + * @brief Function for enabling USBD + */ +__STATIC_INLINE void nrf_usbd_enable(void); + +/** + * @brief Function for disabling USBD + */ +__STATIC_INLINE void nrf_usbd_disable(void); + +/** + * @brief Function for getting EVENTCAUSE register + * + * @return Flag values defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_eventcause_get(void); + +/** + * @brief Function for clearing EVENTCAUSE flags + * + * @param flags Flags defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE void nrf_usbd_eventcause_clear(uint32_t flags); + +/** + * @brief Function for getting EVENTCAUSE register and clear flags that are set + * + * The safest way to return current EVENTCAUSE register. + * All the flags that are returned would be cleared inside EVENTCAUSE register. + * + * @return Flag values defined in @ref nrf_usbd_eventcause_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_eventcause_get_and_clear(void); + +/** + * @brief Function for getting BUSSTATE register value + * + * @return The value of BUSSTATE register + */ +__STATIC_INLINE nrf_usbd_busstate_t nrf_usbd_busstate_get(void); + +/** + * @brief Function for getting HALTEDEPIN register value + * + * @param ep Endpoint number with IN/OUT flag + * + * @return The value of HALTEDEPIN or HALTEDOUT register for selected endpoint + * + * @note + * Use this function for the response for GetStatus() request to endpoint. + * To check if endpoint is stalled in the code use @ref nrf_usbd_ep_is_stall. + */ +__STATIC_INLINE uint32_t nrf_usbd_haltedep(uint8_t ep); + +/** + * @brief Function for checking if selected endpoint is stalled + * + * Function to be used as a syntax sweeter for @ref nrf_usbd_haltedep. + * + * Also as the isochronous endpoint cannot be halted - it returns always false + * if isochronous endpoint is checked. + * + * @param ep Endpoint number with IN/OUT flag + * + * @return The information if the enepoint is halted. + */ +__STATIC_INLINE bool nrf_usbd_ep_is_stall(uint8_t ep); + +/** + * @brief Function for getting EPSTATUS register value + * + * @return Flag values defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epstatus_get(void); + +/** + * @brief Function for clearing EPSTATUS register value + * + * @param flags Flags defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE void nrf_usbd_epstatus_clear(uint32_t flags); + +/** + * @brief Function for getting and clearing EPSTATUS register value + * + * Function clears all flags in register set before returning its value. + * @return Flag values defined in @ref nrf_usbd_epstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epstatus_get_and_clear(void); + +/** + * @brief Function for getting DATAEPSTATUS register value + * + * @return Flag values defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epdatastatus_get(void); + +/** + * @brief Function for clearing DATAEPSTATUS register value + * + * @param flags Flags defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE void nrf_usbd_epdatastatus_clear(uint32_t flags); + +/** + * @brief Function for getting and clearing DATAEPSTATUS register value + * + * Function clears all flags in register set before returning its value. + * @return Flag values defined in @ref nrf_usbd_dataepstatus_mask_t + */ +__STATIC_INLINE uint32_t nrf_usbd_epdatastatus_get_and_clear(void); + +/** + * @name Setup command frame functions + * + * Functions for setup command frame parts access + * @{ + */ + /** + * @brief Function for reading BMREQUESTTYPE - part of SETUP packet + * + * @return the value of BREQUESTTYPE on last received SETUP frame + */ + __STATIC_INLINE uint8_t nrf_usbd_setup_bmrequesttype_get(void); + + /** + * @brief Function for reading BMREQUEST - part of SETUP packet + * + * @return the value of BREQUEST on last received SETUP frame + */ + __STATIC_INLINE uint8_t nrf_usbd_setup_brequest_get(void); + + /** + * @brief Function for reading WVALUE - part of SETUP packet + * + * @return the value of WVALUE on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_wvalue_get(void); + + /** + * @brief Function for reading WINDEX - part of SETUP packet + * + * @return the value of WINDEX on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_windex_get(void); + + /** + * @brief Function for reading WLENGTH - part of SETUP packet + * + * @return the value of WLENGTH on last received SETUP frame + */ + __STATIC_INLINE uint16_t nrf_usbd_setup_wlength_get(void); +/** @} */ + +/** + * @brief Function for getting number of received bytes on selected endpoint + * + * @param ep Endpoint identifier. + * + * @return Number of received bytes. + * + * @note This function may be used on Bulk/Interrupt and Isochronous endpoints. + * @note For the function that returns different value for ISOOUT zero transfer or no transfer at all, + * see @ref nrf_usbd_episoout_size_get function. This function would return 0 for both cases. + */ +__STATIC_INLINE size_t nrf_usbd_epout_size_get(uint8_t ep); + +/** + * @brief Function for getting number of received bytes on isochronous endpoint. + * + * @param ep Endpoint identifier, has to be isochronous out endpoint. + * + * @return Number of bytes received or @ref NRF_USBD_EPISOOUT_NO_DATA + */ +__STATIC_INLINE size_t nrf_usbd_episoout_size_get(uint8_t ep); + +/** + * @brief Function for clearing out endpoint to accept any new incoming traffic + * + * @param ep ep Endpoint identifier. Only OUT Interrupt/Bulk endpoints are accepted. + */ +__STATIC_INLINE void nrf_usbd_epout_clear(uint8_t ep); + +/** + * @brief Function for enabling USB pullup + */ +__STATIC_INLINE void nrf_usbd_pullup_enable(void); + +/** + * @brief Function for disabling USB pullup + */ +__STATIC_INLINE void nrf_usbd_pullup_disable(void); + +/** + * @brief Function for returning current USB pullup state + * + * @retval true USB pullup is enabled + * @retval false USB pullup is disabled + */ +__STATIC_INLINE bool nrf_usbd_pullup_check(void); + +/** + * @brief Function for configuring the value to be forced on the bus on DRIVEDPDM task + * + * Selected state would be forced on the bus when @ref NRF_USBD_TASK_DRIVEDPDM is set. + * The state would be removed from the bus on @ref NRF_USBD_TASK_NODRIVEDPDM and + * the control would be returned to the USBD peripheral. + * @param val State to be set + */ +__STATIC_INLINE void nrf_usbd_dpdmvalue_set(nrf_usbd_dpdmvalue_t val); + +/** + * @brief Function for setting data toggle + * + * Configuration of current state of data toggling + * @param ep Endpoint number with the information about its direction + * @param op Operation to execute + */ +__STATIC_INLINE void nrf_usbd_dtoggle_set(uint8_t ep, nrf_usbd_dtoggle_t op); + +/** + * @brief Function for getting data toggle + * + * Get the current state of data toggling + * @param ep Endpoint number to return the information about current data toggling + * @retval NRF_USBD_DTOGGLE_DATA0 Data toggle is DATA0 on selected endpoint + * @retval NRF_USBD_DTOGGLE_DATA1 Data toggle is DATA1 on selected endpoint + */ +__STATIC_INLINE nrf_usbd_dtoggle_t nrf_usbd_dtoggle_get(uint8_t ep); + +/** + * @brief Function for checking if endpoint is enabled + * + * @param ep Endpoint id to check + * + * @retval true Endpoint is enabled + * @retval false Endpoint is disabled + */ +__STATIC_INLINE bool nrf_usbd_ep_enable_check(uint8_t ep); + +/** + * @brief Function for enabling selected endpoint + * + * Enabled endpoint responds for the tokens on the USB bus + * + * @param ep Endpoint id to enable + */ +__STATIC_INLINE void nrf_usbd_ep_enable(uint8_t ep); + +/** + * @brief Function for disabling selected endpoint + * + * Disabled endpoint does not respond for the tokens on the USB bus + * + * @param ep Endpoint id to disable + */ +__STATIC_INLINE void nrf_usbd_ep_disable(uint8_t ep); + +/** + * @brief Function for disabling all endpoints + * + * Auxiliary function to simply disable all aviable endpoints. + * It lefts only EP0 IN and OUT enabled. + */ +__STATIC_INLINE void nrf_usbd_ep_all_disable(void); + +/** + * @brief Function for stalling selected endpoint + * + * @param ep Endpoint identifier + * @note This function cannot be called on isochronous endpoint + */ +__STATIC_INLINE void nrf_usbd_ep_stall(uint8_t ep); + +/** + * @brief Function for unstalling selected endpoint + * + * @param ep Endpoint identifier + * @note This function cannot be called on isochronous endpoint + */ +__STATIC_INLINE void nrf_usbd_ep_unstall(uint8_t ep); + +/** + * @brief Function for configuration of isochronous buffer splitting + * + * Configure isochronous buffer splitting between IN and OUT endpoints. + * + * @param split Required configuration + */ +__STATIC_INLINE void nrf_usbd_isosplit_set(nrf_usbd_isosplit_t split); + +/** + * @brief Function for getting the isochronous buffer splitting configuration + * + * Get the current isochronous buffer splitting configuration. + * + * @return Current configuration + */ +__STATIC_INLINE nrf_usbd_isosplit_t nrf_usbd_isosplit_get(void); + +/** + * @brief Function for getting current frame counter + * + * @return Current frame counter + */ +__STATIC_INLINE uint32_t nrf_usbd_framecntr_get(void); + +/** + * @brief Function for entering into low power mode + * + * After this function is called the clock source from the USBD is disconnected internally. + * After this function is called most of the USBD registers cannot be accessed anymore. + * + * @sa nrf_usbd_lowpower_disable + * @sa nrf_usbd_lowpower_check + */ +__STATIC_INLINE void nrf_usbd_lowpower_enable(void); + +/** + * @brief Function for exiting from low power mode + * + * After this function is called the clock source for the USBD is connected internally. + * The @ref NRF_USBD_EVENTCAUSE_WUREQ_MASK event would be generated and + * then the USBD registers may be accessed. + * + * @sa nrf_usbd_lowpower_enable + * @sa nrf_usbd_lowpower_check + */ +__STATIC_INLINE void nrf_usbd_lowpower_disable(void); + +/** + * @brief Function for checking the state of the low power mode + * + * @retval true USBD is in low power mode + * @retval false USBD is not in low power mode + */ +__STATIC_INLINE bool nrf_usbd_lowpower_check(void); + +/** + * @brief Function for configuring EasyDMA channel + * + * Configures EasyDMA for the transfer. + * + * @param ep Endpoint identifier (with direction) + * @param ptr Pointer to the data + * @param maxcnt Number of bytes to transfer + */ +__STATIC_INLINE void nrf_usbd_ep_easydma_set(uint8_t ep, uint32_t ptr, uint32_t maxcnt); + +/** + * @brief Function for getting number of transferred bytes + * + * Get number of transferred bytes in the last transaction + * + * @param ep Endpoint identifier + * + * @return The content of the AMOUNT register + */ +__STATIC_INLINE uint32_t nrf_usbd_ep_amount_get(uint8_t ep); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +void nrf_usbd_enable(void) +{ +#ifdef NRF_FPGA_IMPLEMENTATION + *(volatile uint32_t *)0x400005F4 = 3; + __ISB(); + __DSB(); + *(volatile uint32_t *)0x400005F0 = 3; + __ISB(); + __DSB(); +#endif + + NRF_USBD->ENABLE = USBD_ENABLE_ENABLE_Enabled << USBD_ENABLE_ENABLE_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_disable(void) +{ + NRF_USBD->ENABLE = USBD_ENABLE_ENABLE_Disabled << USBD_ENABLE_ENABLE_Pos; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_eventcause_get(void) +{ + return NRF_USBD->EVENTCAUSE; +} + +void nrf_usbd_eventcause_clear(uint32_t flags) +{ + NRF_USBD->EVENTCAUSE = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_eventcause_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_eventcause_get(); + nrf_usbd_eventcause_clear(ret); + __ISB(); + __DSB(); + return ret; +} + +nrf_usbd_busstate_t nrf_usbd_busstate_get(void) +{ + return (nrf_usbd_busstate_t)(NRF_USBD->BUSSTATE); +} + +uint32_t nrf_usbd_haltedep(uint8_t ep) +{ + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + if (NRF_USBD_EPIN_CHECK(ep)) + { + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->HALTED.EPIN)); + return NRF_USBD->HALTED.EPIN[epnr]; + } + else + { + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->HALTED.EPOUT)); + return NRF_USBD->HALTED.EPOUT[epnr]; + } +} + +bool nrf_usbd_ep_is_stall(uint8_t ep) +{ + if (NRF_USBD_EPISO_CHECK(ep)) + return false; + return USBD_HALTED_EPOUT_GETSTATUS_Halted == nrf_usbd_haltedep(ep); +} + +uint32_t nrf_usbd_epstatus_get(void) +{ + return NRF_USBD->EPSTATUS; +} + +void nrf_usbd_epstatus_clear(uint32_t flags) +{ + NRF_USBD->EPSTATUS = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_epstatus_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_epstatus_get(); + nrf_usbd_epstatus_clear(ret); + return ret; +} + +uint32_t nrf_usbd_epdatastatus_get(void) +{ + return NRF_USBD->EPDATASTATUS; +} + +void nrf_usbd_epdatastatus_clear(uint32_t flags) +{ + NRF_USBD->EPDATASTATUS = flags; + __ISB(); + __DSB(); +} + +uint32_t nrf_usbd_epdatastatus_get_and_clear(void) +{ + uint32_t ret; + ret = nrf_usbd_epdatastatus_get(); + nrf_usbd_epdatastatus_clear(ret); + __ISB(); + __DSB(); + return ret; +} + +uint8_t nrf_usbd_setup_bmrequesttype_get(void) +{ + return (uint8_t)(NRF_USBD->BMREQUESTTYPE); +} + +uint8_t nrf_usbd_setup_brequest_get(void) +{ + return (uint8_t)(NRF_USBD->BREQUEST); +} + +uint16_t nrf_usbd_setup_wvalue_get(void) +{ + const uint16_t val = NRF_USBD->WVALUEL; + return (uint16_t)(val | ((NRF_USBD->WVALUEH) << 8)); +} + +uint16_t nrf_usbd_setup_windex_get(void) +{ + const uint16_t val = NRF_USBD->WINDEXL; + return (uint16_t)(val | ((NRF_USBD->WINDEXH) << 8)); +} + +uint16_t nrf_usbd_setup_wlength_get(void) +{ + const uint16_t val = NRF_USBD->WLENGTHL; + return (uint16_t)(val | ((NRF_USBD->WLENGTHH) << 8)); +} + +size_t nrf_usbd_epout_size_get(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + if (NRF_USBD_EPISO_CHECK(ep)) + { + size_t size_isoout = NRF_USBD->SIZE.ISOOUT; + if ((size_isoout & USBD_SIZE_ISOOUT_ZERO_Msk) == (USBD_SIZE_ISOOUT_ZERO_ZeroData << USBD_SIZE_ISOOUT_ZERO_Pos)) + { + size_isoout = 0; + } + return size_isoout; + } + + ASSERT(NRF_USBD_EP_NR_GET(ep) < ARRAY_SIZE(NRF_USBD->SIZE.EPOUT)); + return NRF_USBD->SIZE.EPOUT[NRF_USBD_EP_NR_GET(ep)]; +} + +size_t nrf_usbd_episoout_size_get(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + ASSERT(NRF_USBD_EPISO_CHECK(ep)); + + size_t size_isoout = NRF_USBD->SIZE.ISOOUT; + if (size_isoout == 0) + { + size_isoout = NRF_USBD_EPISOOUT_NO_DATA; + } + else if ((size_isoout & USBD_SIZE_ISOOUT_ZERO_Msk) == (USBD_SIZE_ISOOUT_ZERO_ZeroData << USBD_SIZE_ISOOUT_ZERO_Pos)) + { + size_isoout = 0; + } + return size_isoout; +} + +void nrf_usbd_epout_clear(uint8_t ep) +{ + ASSERT(NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < ARRAY_SIZE(NRF_USBD->SIZE.EPOUT))); + NRF_USBD->SIZE.EPOUT[NRF_USBD_EP_NR_GET(ep)] = 0; + __ISB(); + __DSB(); +} + +void nrf_usbd_pullup_enable(void) +{ + NRF_USBD->USBPULLUP = USBD_USBPULLUP_CONNECT_Enabled << USBD_USBPULLUP_CONNECT_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_pullup_disable(void) +{ + NRF_USBD->USBPULLUP = USBD_USBPULLUP_CONNECT_Disabled << USBD_USBPULLUP_CONNECT_Pos; + __ISB(); + __DSB(); +} + +bool nrf_usbd_pullup_check(void) +{ + return NRF_USBD->USBPULLUP == (USBD_USBPULLUP_CONNECT_Enabled << USBD_USBPULLUP_CONNECT_Pos); +} + +void nrf_usbd_dpdmvalue_set(nrf_usbd_dpdmvalue_t val) +{ + NRF_USBD->DPDMVALUE = ((uint32_t)val) << USBD_DPDMVALUE_STATE_Pos; +} + +void nrf_usbd_dtoggle_set(uint8_t ep, nrf_usbd_dtoggle_t op) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + NRF_USBD->DTOGGLE = ep | (NRF_USBD_DTOGGLE_NOP << USBD_DTOGGLE_VALUE_Pos); + __DSB(); + NRF_USBD->DTOGGLE = ep | (op << USBD_DTOGGLE_VALUE_Pos); + __ISB(); + __DSB(); +} + +nrf_usbd_dtoggle_t nrf_usbd_dtoggle_get(uint8_t ep) +{ + uint32_t retval; + /* Select the endpoint to read */ + NRF_USBD->DTOGGLE = ep | (NRF_USBD_DTOGGLE_NOP << USBD_DTOGGLE_VALUE_Pos); + retval = ((NRF_USBD->DTOGGLE) & USBD_DTOGGLE_VALUE_Msk) >> USBD_DTOGGLE_VALUE_Pos; + return (nrf_usbd_dtoggle_t)retval; +} + +bool nrf_usbd_ep_enable_check(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + return 0 != (NRF_USBD->EPINEN & (1UL << epnr)); + } + else + { + return 0 != (NRF_USBD->EPOUTEN & (1UL << epnr)); + } +} + +void nrf_usbd_ep_enable(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + NRF_USBD->EPINEN |= 1UL << epnr; + } + else + { + NRF_USBD->EPOUTEN |= 1UL << epnr; + } + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_disable(uint8_t ep) +{ + ASSERT(NRF_USBD_EP_VALIDATE(ep)); + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + NRF_USBD->EPINEN &= ~(1UL << epnr); + } + else + { + NRF_USBD->EPOUTEN &= ~(1UL << epnr); + } + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_all_disable(void) +{ + NRF_USBD->EPINEN = USBD_EPINEN_IN0_Enable << USBD_EPINEN_IN0_Pos; + NRF_USBD->EPOUTEN = USBD_EPOUTEN_OUT0_Enable << USBD_EPOUTEN_OUT0_Pos; + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_stall(uint8_t ep) +{ + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep; + __ISB(); + __DSB(); +} + +void nrf_usbd_ep_unstall(uint8_t ep) +{ + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep; + __ISB(); + __DSB(); +} + +void nrf_usbd_isosplit_set(nrf_usbd_isosplit_t split) +{ + NRF_USBD->ISOSPLIT = split << USBD_ISOSPLIT_SPLIT_Pos; +} + +nrf_usbd_isosplit_t nrf_usbd_isosplit_get(void) +{ + return (nrf_usbd_isosplit_t) + (((NRF_USBD->ISOSPLIT) & USBD_ISOSPLIT_SPLIT_Msk) >> USBD_ISOSPLIT_SPLIT_Pos); +} + +uint32_t nrf_usbd_framecntr_get(void) +{ + return NRF_USBD->FRAMECNTR; +} + +void nrf_usbd_lowpower_enable(void) +{ + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_LowPower << USBD_LOWPOWER_LOWPOWER_Pos; +} + +void nrf_usbd_lowpower_disable(void) +{ + NRF_USBD->LOWPOWER = USBD_LOWPOWER_LOWPOWER_ForceNormal << USBD_LOWPOWER_LOWPOWER_Pos; +} + +bool nrf_usbd_lowpower_check(void) +{ + return (NRF_USBD->LOWPOWER != (USBD_LOWPOWER_LOWPOWER_ForceNormal << USBD_LOWPOWER_LOWPOWER_Pos)); +} + + +void nrf_usbd_ep_easydma_set(uint8_t ep, uint32_t ptr, uint32_t maxcnt) +{ + if (NRF_USBD_EPIN_CHECK(ep)) + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + NRF_USBD->ISOIN.PTR = ptr; + NRF_USBD->ISOIN.MAXCNT = maxcnt; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPIN)); + NRF_USBD->EPIN[epnr].PTR = ptr; + NRF_USBD->EPIN[epnr].MAXCNT = maxcnt; + } + } + else + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + NRF_USBD->ISOOUT.PTR = ptr; + NRF_USBD->ISOOUT.MAXCNT = maxcnt; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + NRF_USBD->EPOUT[epnr].PTR = ptr; + NRF_USBD->EPOUT[epnr].MAXCNT = maxcnt; + } + } +} + +uint32_t nrf_usbd_ep_amount_get(uint8_t ep) +{ + uint32_t ret; + + if (NRF_USBD_EPIN_CHECK(ep)) + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + ret = NRF_USBD->ISOIN.AMOUNT; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + ret = NRF_USBD->EPIN[epnr].AMOUNT; + } + } + else + { + if (NRF_USBD_EPISO_CHECK(ep)) + { + ret = NRF_USBD->ISOOUT.AMOUNT; + } + else + { + uint8_t epnr = NRF_USBD_EP_NR_GET(ep); + ASSERT(epnr < ARRAY_SIZE(NRF_USBD->EPOUT)); + ret = NRF_USBD->EPOUT[epnr].AMOUNT; + } + } + + return ret; +} + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_USBD_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_wdt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_wdt.h new file mode 100644 index 0000000000..d497fc2464 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/hal/nrf_wdt.h @@ -0,0 +1,339 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_wdt_hal WDT HAL + * @{ + * @ingroup nrf_wdt + * + * @brief Hardware access layer for accessing the watchdog timer (WDT) peripheral. + */ + +#ifndef NRF_WDT_H__ +#define NRF_WDT_H__ + +#include +#include +#include + +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_WDT_CHANNEL_NUMBER 0x8UL +#define NRF_WDT_RR_VALUE 0x6E524635UL /* Fixed value, shouldn't be modified.*/ + +#define NRF_WDT_TASK_SET 1UL +#define NRF_WDT_EVENT_CLEAR 0UL + +/** + * @enum nrf_wdt_task_t + * @brief WDT tasks. + */ +typedef enum +{ + /*lint -save -e30 -esym(628,__INTADDR__)*/ + NRF_WDT_TASK_START = offsetof(NRF_WDT_Type, TASKS_START), /**< Task for starting WDT. */ + /*lint -restore*/ +} nrf_wdt_task_t; + +/** + * @enum nrf_wdt_event_t + * @brief WDT events. + */ +typedef enum +{ + /*lint -save -e30*/ + NRF_WDT_EVENT_TIMEOUT = offsetof(NRF_WDT_Type, EVENTS_TIMEOUT), /**< Event from WDT time-out. */ + /*lint -restore*/ +} nrf_wdt_event_t; + +/** + * @enum nrf_wdt_behaviour_t + * @brief WDT behavior in CPU SLEEP or HALT mode. + */ +typedef enum +{ + NRF_WDT_BEHAVIOUR_RUN_SLEEP = WDT_CONFIG_SLEEP_Msk, /**< WDT will run when CPU is in SLEEP mode. */ + NRF_WDT_BEHAVIOUR_RUN_HALT = WDT_CONFIG_HALT_Msk, /**< WDT will run when CPU is in HALT mode. */ + NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT = WDT_CONFIG_SLEEP_Msk | WDT_CONFIG_HALT_Msk, /**< WDT will run when CPU is in SLEEP or HALT mode. */ + NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT = 0, /**< WDT will be paused when CPU is in SLEEP or HALT mode. */ +} nrf_wdt_behaviour_t; + +/** + * @enum nrf_wdt_rr_register_t + * @brief WDT reload request registers. + */ +typedef enum +{ + NRF_WDT_RR0 = 0, /**< Reload request register 0. */ + NRF_WDT_RR1, /**< Reload request register 1. */ + NRF_WDT_RR2, /**< Reload request register 2. */ + NRF_WDT_RR3, /**< Reload request register 3. */ + NRF_WDT_RR4, /**< Reload request register 4. */ + NRF_WDT_RR5, /**< Reload request register 5. */ + NRF_WDT_RR6, /**< Reload request register 6. */ + NRF_WDT_RR7 /**< Reload request register 7. */ +} nrf_wdt_rr_register_t; + +/** + * @enum nrf_wdt_int_mask_t + * @brief WDT interrupts. + */ +typedef enum +{ + NRF_WDT_INT_TIMEOUT_MASK = WDT_INTENSET_TIMEOUT_Msk, /**< WDT interrupt from time-out event. */ +} nrf_wdt_int_mask_t; + +/** + * @brief Function for configuring the watchdog behavior when the CPU is sleeping or halted. + * + * @param behaviour Watchdog behavior when CPU is in SLEEP or HALT mode. + */ +__STATIC_INLINE void nrf_wdt_behaviour_set(nrf_wdt_behaviour_t behaviour) +{ + NRF_WDT->CONFIG = behaviour; +} + + +/** + * @brief Function for starting the watchdog. + * + * @param[in] task Task. + */ +__STATIC_INLINE void nrf_wdt_task_trigger(nrf_wdt_task_t task) +{ + *((volatile uint32_t *)((uint8_t *)NRF_WDT + task)) = NRF_WDT_TASK_SET; +} + + +/** + * @brief Function for clearing the WDT event. + * + * @param[in] event Event. + */ +__STATIC_INLINE void nrf_wdt_event_clear(nrf_wdt_event_t event) +{ + *((volatile uint32_t *)((uint8_t *)NRF_WDT + (uint32_t)event)) = NRF_WDT_EVENT_CLEAR; +#if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_WDT + (uint32_t)event)); + (void)dummy; +#endif +} + + +/** + * @brief Function for retrieving the state of the WDT event. + * + * @param[in] event Event. + * + * @retval true If the event is set. + * @retval false If the event is not set. + */ +__STATIC_INLINE bool nrf_wdt_event_check(nrf_wdt_event_t event) +{ + return (bool)*((volatile uint32_t *)((uint8_t *)NRF_WDT + event)); +} + + +/** + * @brief Function for enabling a specific interrupt. + * + * @param[in] int_mask Interrupt. + */ +__STATIC_INLINE void nrf_wdt_int_enable(uint32_t int_mask) +{ + NRF_WDT->INTENSET = int_mask; +} + + +/** + * @brief Function for retrieving the state of given interrupt. + * + * @param[in] int_mask Interrupt. + * + * @retval true Interrupt is enabled. + * @retval false Interrupt is not enabled. + */ +__STATIC_INLINE bool nrf_wdt_int_enable_check(uint32_t int_mask) +{ + return (bool)(NRF_WDT->INTENSET & int_mask); +} + + +/** + * @brief Function for disabling a specific interrupt. + * + * @param[in] int_mask Interrupt. + */ +__STATIC_INLINE void nrf_wdt_int_disable(uint32_t int_mask) +{ + NRF_WDT->INTENCLR = int_mask; +} + + +/** + * @brief Function for returning the address of a specific WDT task register. + * + * @param[in] task Task. + */ +__STATIC_INLINE uint32_t nrf_wdt_task_address_get(nrf_wdt_task_t task) +{ + return ((uint32_t)NRF_WDT + task); +} + + +/** + * @brief Function for returning the address of a specific WDT event register. + * + * @param[in] event Event. + * + * @retval address of requested event register + */ +__STATIC_INLINE uint32_t nrf_wdt_event_address_get(nrf_wdt_event_t event) +{ + return ((uint32_t)NRF_WDT + event); +} + + +/** + * @brief Function for retrieving the watchdog status. + * + * @retval true If the watchdog is started. + * @retval false If the watchdog is not started. + */ +__STATIC_INLINE bool nrf_wdt_started(void) +{ + return (bool)(NRF_WDT->RUNSTATUS); +} + + +/** + * @brief Function for retrieving the watchdog reload request status. + * + * @param[in] rr_register Reload request register to check. + * + * @retval true If a reload request is running. + * @retval false If no reload request is running. + */ +__STATIC_INLINE bool nrf_wdt_request_status(nrf_wdt_rr_register_t rr_register) +{ + return (bool)(((NRF_WDT->REQSTATUS) >> rr_register) & 0x1UL); +} + + +/** + * @brief Function for setting the watchdog reload value. + * + * @param[in] reload_value Watchdog counter initial value. + */ +__STATIC_INLINE void nrf_wdt_reload_value_set(uint32_t reload_value) +{ + NRF_WDT->CRV = reload_value; +} + + +/** + * @brief Function for retrieving the watchdog reload value. + * + * @retval Reload value. + */ +__STATIC_INLINE uint32_t nrf_wdt_reload_value_get(void) +{ + return (uint32_t)NRF_WDT->CRV; +} + + +/** + * @brief Function for enabling a specific reload request register. + * + * @param[in] rr_register Reload request register to enable. + */ +__STATIC_INLINE void nrf_wdt_reload_request_enable(nrf_wdt_rr_register_t rr_register) +{ + NRF_WDT->RREN |= 0x1UL << rr_register; +} + + +/** + * @brief Function for disabling a specific reload request register. + * + * @param[in] rr_register Reload request register to disable. + */ +__STATIC_INLINE void nrf_wdt_reload_request_disable(nrf_wdt_rr_register_t rr_register) +{ + NRF_WDT->RREN &= ~(0x1UL << rr_register); +} + + +/** + * @brief Function for retrieving the status of a specific reload request register. + * + * @param[in] rr_register Reload request register to check. + * + * @retval true If the reload request register is enabled. + * @retval false If the reload request register is not enabled. + */ +__STATIC_INLINE bool nrf_wdt_reload_request_is_enabled(nrf_wdt_rr_register_t rr_register) +{ + return (bool)(NRF_WDT->RREN & (0x1UL << rr_register)); +} + + +/** + * @brief Function for setting a specific reload request register. + * + * @param[in] rr_register Reload request register to set. + */ +__STATIC_INLINE void nrf_wdt_reload_request_set(nrf_wdt_rr_register_t rr_register) +{ + NRF_WDT->RR[rr_register] = NRF_WDT_RR_VALUE; +} + + + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.c new file mode 100644 index 0000000000..ba4fe016c5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.c @@ -0,0 +1,446 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(I2S) +#include "nrf_drv_i2s.h" +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "nrf_assert.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME i2s + +#if I2S_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL I2S_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR I2S_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR I2S_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_I2S_EVENT_RXPTRUPD ? "NRF_I2S_EVENT_RXPTRUPD" : \ + (event == NRF_I2S_EVENT_TXPTRUPD ? "NRF_I2S_EVENT_TXPTRUPD" : \ + (event == NRF_I2S_EVENT_STOPPED ? "NRF_I2S_EVENT_STOPPED" : "UNKNOWN EVENT"))) +#else //I2S_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //I2S_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define MODULE_INITIALIZED (m_cb.state == NRF_DRV_STATE_INITIALIZED) /**< Macro designating whether the module has been initialized properly. */ + +// Control block - driver instance local data. +typedef struct +{ + nrf_drv_i2s_data_handler_t handler; + nrf_drv_state_t state; + + bool synchronized_mode : 1; + bool rx_ready : 1; + bool tx_ready : 1; + bool just_started : 1; + uint16_t buffer_half_size; + uint32_t * p_rx_buffer; + uint32_t * p_tx_buffer; +} i2s_control_block_t; +static i2s_control_block_t m_cb; + + +static nrf_drv_i2s_config_t const m_default_config = NRF_DRV_I2S_DEFAULT_CONFIG; + + +static void configure_pins(nrf_drv_i2s_config_t const * p_config) +{ + uint32_t mck_pin, sdout_pin, sdin_pin; + + // Configure pins used by the peripheral: + + // - SCK and LRCK (required) - depending on the mode of operation these + // pins are configured as outputs (in Master mode) or inputs (in Slave + // mode). + if (p_config->mode == NRF_I2S_MODE_MASTER) + { + nrf_gpio_cfg_output(p_config->sck_pin); + nrf_gpio_cfg_output(p_config->lrck_pin); + } + else + { + nrf_gpio_cfg_input(p_config->sck_pin, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(p_config->lrck_pin, NRF_GPIO_PIN_NOPULL); + } + + // - MCK (optional) - always output, + if (p_config->mck_pin != NRF_DRV_I2S_PIN_NOT_USED) + { + mck_pin = p_config->mck_pin; + nrf_gpio_cfg_output(mck_pin); + } + else + { + mck_pin = NRF_I2S_PIN_NOT_CONNECTED; + } + + // - SDOUT (optional) - always output, + if (p_config->sdout_pin != NRF_DRV_I2S_PIN_NOT_USED) + { + sdout_pin = p_config->sdout_pin; + nrf_gpio_cfg_output(sdout_pin); + } + else + { + sdout_pin = NRF_I2S_PIN_NOT_CONNECTED; + } + + // - SDIN (optional) - always input. + if (p_config->sdin_pin != NRF_DRV_I2S_PIN_NOT_USED) + { + sdin_pin = p_config->sdin_pin; + nrf_gpio_cfg_input(sdin_pin, NRF_GPIO_PIN_NOPULL); + } + else + { + sdin_pin = NRF_I2S_PIN_NOT_CONNECTED; + } + + nrf_i2s_pins_set(NRF_I2S, p_config->sck_pin, p_config->lrck_pin, + mck_pin, sdout_pin, sdin_pin); +} + + +ret_code_t nrf_drv_i2s_init(nrf_drv_i2s_config_t const * p_config, + nrf_drv_i2s_data_handler_t handler) +{ + ASSERT(handler); + + ret_code_t err_code; + + if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + + if (!nrf_i2s_configure(NRF_I2S, p_config->mode, + p_config->format, + p_config->alignment, + p_config->sample_width, + p_config->channels, + p_config->mck_setup, + p_config->ratio)) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + configure_pins(p_config); + + m_cb.handler = handler; + + nrf_drv_common_irq_enable(I2S_IRQn, p_config->irq_priority); + + m_cb.state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_i2s_uninit(void) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_drv_i2s_stop(); + + nrf_drv_common_irq_disable(I2S_IRQn); + + m_cb.state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + + +ret_code_t nrf_drv_i2s_start(uint32_t * p_rx_buffer, + uint32_t * p_tx_buffer, + uint16_t buffer_size, + uint8_t flags) +{ + ASSERT((p_rx_buffer != NULL) || (p_tx_buffer != NULL)); + + uint16_t buffer_half_size = buffer_size / 2; + ASSERT(buffer_half_size != 0); + + VERIFY_MODULE_INITIALIZED(); + + ret_code_t err_code; + + if ((p_rx_buffer != NULL) && !nrf_drv_is_in_RAM(p_rx_buffer)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if ((p_tx_buffer != NULL) && !nrf_drv_is_in_RAM(p_tx_buffer)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + // Initially we set up the peripheral to use the first half of each buffer, + // then in 'I2S_IRQHandler' we will switch to the second half. + nrf_i2s_transfer_set(NRF_I2S, buffer_half_size, p_rx_buffer, p_tx_buffer); + + m_cb.p_rx_buffer = p_rx_buffer; + m_cb.p_tx_buffer = p_tx_buffer; + m_cb.buffer_half_size = buffer_half_size; + m_cb.just_started = true; + + if ((flags & NRF_DRV_I2S_FLAG_SYNCHRONIZED_MODE) && + // [synchronized mode makes sense only when both RX and TX are enabled] + (m_cb.p_rx_buffer != NULL) && (m_cb.p_tx_buffer != NULL)) + { + m_cb.synchronized_mode = true; + m_cb.rx_ready = false; + m_cb.tx_ready = false; + } + else + { + m_cb.synchronized_mode = false; + } + + nrf_i2s_enable(NRF_I2S); + + m_cb.state = NRF_DRV_STATE_POWERED_ON; + + if (m_cb.p_tx_buffer != NULL) + { + // Get from the application the first portion of data to be sent - we + // need to have it in the transmit buffer before we start the transfer. + // Unless the synchronized mode is active. In this mode we must wait + // with this until the first portion of data is received, so here we + // just make sure that there will be silence on the SDOUT line prior + // to that moment. + if (m_cb.synchronized_mode) + { + memset(m_cb.p_tx_buffer, 0, + m_cb.buffer_half_size * sizeof(uint32_t)); + } + else + { + m_cb.handler(NULL, m_cb.p_tx_buffer, m_cb.buffer_half_size); + } + } + + nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD); + nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD); + nrf_i2s_int_enable(NRF_I2S, + NRF_I2S_INT_RXPTRUPD_MASK | NRF_I2S_INT_TXPTRUPD_MASK); + nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_START); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_i2s_stop(void) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + // First disable interrupts, then trigger the STOP task, so no spurious + // RXPTRUPD and TXPTRUPD events (see FTPAN-55) will be processed. + nrf_i2s_int_disable(NRF_I2S, + NRF_I2S_INT_RXPTRUPD_MASK | NRF_I2S_INT_TXPTRUPD_MASK); + + nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_STOP); + + nrf_i2s_disable(NRF_I2S); + + m_cb.state = NRF_DRV_STATE_INITIALIZED; + + NRF_LOG_INFO("Disabled."); +} + + +void I2S_IRQHandler(void) +{ + uint32_t const * p_data_received = NULL; + uint32_t * p_data_to_send = NULL; + + if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD)) + { + nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD); + NRF_LOG_DEBUG("Event: %s.", + (uint32_t)EVT_TO_STR(NRF_I2S_EVENT_TXPTRUPD)); + + // If transmission is not enabled, but for some reason the TXPTRUPD + // event has been generated, just ignore it. + if (m_cb.p_tx_buffer != NULL) + { + uint32_t * p_tx_buffer_next; + if (nrf_i2s_tx_buffer_get(NRF_I2S) == m_cb.p_tx_buffer) + { + p_tx_buffer_next = m_cb.p_tx_buffer + m_cb.buffer_half_size; + } + else + { + p_tx_buffer_next = m_cb.p_tx_buffer; + } + nrf_i2s_tx_buffer_set(NRF_I2S, p_tx_buffer_next); + + m_cb.tx_ready = true; + + // Now the part of the buffer that we've configured as "next" should + // be filled by the application with proper data to be sent; + // the peripheral is sending data from the other part of the buffer + // (but it will finish soon...). + p_data_to_send = p_tx_buffer_next; + + } + } + + if (nrf_i2s_event_check(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD)) + { + nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD); + NRF_LOG_DEBUG("Event: %s.", + (uint32_t)EVT_TO_STR(NRF_I2S_EVENT_RXPTRUPD)); + + // If reception is not enabled, but for some reason the RXPTRUPD event + // has been generated, just ignore it. + if (m_cb.p_rx_buffer != NULL) + { + uint32_t * p_rx_buffer_next; + if (nrf_i2s_rx_buffer_get(NRF_I2S) == m_cb.p_rx_buffer) + { + p_rx_buffer_next = m_cb.p_rx_buffer + m_cb.buffer_half_size; + } + else + { + p_rx_buffer_next = m_cb.p_rx_buffer; + } + nrf_i2s_rx_buffer_set(NRF_I2S, p_rx_buffer_next); + + m_cb.rx_ready = true; + + // The RXPTRUPD event is generated for the first time right after + // the transfer is started. Since there is no data received yet at + // this point we only update the buffer pointer (it is done above), + // there is no callback to the application. + // [for synchronized mode this has to be handled differently - + // see below] + if (m_cb.just_started && !m_cb.synchronized_mode) + { + m_cb.just_started = false; + } + else + { + // The RXPTRUPD event indicates that from now on the peripheral + // will be filling the part of the buffer that was pointed at + // the time the event has been generated, hence now we can let + // the application process the data stored in the other part of + // the buffer - the one that we've just set to be filled next. + p_data_received = p_rx_buffer_next; + } + } + } + + // Call the data handler passing received data to the application and/or + // requesting data to be sent. + if (!m_cb.synchronized_mode) + { + if ((p_data_received != NULL) || (p_data_to_send != NULL)) + { + if (p_data_received != NULL) + { + NRF_LOG_DEBUG("Rx data:"); + NRF_LOG_HEXDUMP_DEBUG(p_data_received, + m_cb.buffer_half_size * sizeof(p_data_received[0])); + } + m_cb.handler(p_data_received, p_data_to_send, + m_cb.buffer_half_size); + if (p_data_to_send != NULL) + { + NRF_LOG_DEBUG("Tx data:"); + NRF_LOG_HEXDUMP_DEBUG(p_data_to_send, + m_cb.buffer_half_size * sizeof(p_data_to_send[0])); + } + } + } + // In the synchronized mode wait until the events for both RX and TX occur. + // And ignore the initial occurrences of these events, since they only + // indicate that the transfer has started - no data is received yet at + // that moment, so we have got nothing to pass to the application. + else + { + if (m_cb.rx_ready && m_cb.tx_ready) + { + m_cb.rx_ready = false; + m_cb.tx_ready = false; + + if (m_cb.just_started) + { + m_cb.just_started = false; + } + else + { + NRF_LOG_DEBUG("Rx data:"); + NRF_LOG_HEXDUMP_DEBUG(nrf_i2s_rx_buffer_get(NRF_I2S), + m_cb.buffer_half_size * sizeof(p_data_to_send[0])); + m_cb.handler(nrf_i2s_rx_buffer_get(NRF_I2S), + nrf_i2s_tx_buffer_get(NRF_I2S), + m_cb.buffer_half_size); + NRF_LOG_DEBUG("Tx data:"); + NRF_LOG_HEXDUMP_DEBUG(nrf_i2s_tx_buffer_get(NRF_I2S), + m_cb.buffer_half_size * sizeof(p_data_to_send[0])); + } + } + } +} +#endif //NRF_MODULE_ENABLED(I2S) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.h new file mode 100644 index 0000000000..9ed4bf742e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/i2s/nrf_drv_i2s.h @@ -0,0 +1,255 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_i2s I2S HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52 Inter-IC Sound (I2S) interface APIs. + * + * @defgroup nrf_drv_i2s I2S driver + * @{ + * @ingroup nrf_i2s + * @brief @tagAPI52 Inter-IC Sound (I2S) interface driver. + */ + + +#ifndef NRF_DRV_I2S_H__ +#define NRF_DRV_I2S_H__ + +#include "nordic_common.h" +#include "sdk_config.h" +#include "nrf_i2s.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief This value can be provided instead of a pin number for the signals + * SDOUT, SDIN, and MCK to specify that a given signal is not used + * and therefore does not need to be connected to a pin. + */ +#define NRF_DRV_I2S_PIN_NOT_USED 0xFF + +/** + * @brief Flag indicating that calls to the data handler for RX and TX should + * be synchronized, thus always combined into one call. + * + * Use this flag when calling @ref nrf_drv_i2s_start to force a common call + * to the @ref nrf_drv_i2s_data_handler_t "data handler" for RX and TX data. + * This is useful, for example, when received data should be processed and + * then be sent back. Obviously, this flag is only applicable when both + * directions (RX and TX) are enabled. + */ +#define NRF_DRV_I2S_FLAG_SYNCHRONIZED_MODE 0x01 + +/** + * @brief I2S driver configuration structure. + */ +typedef struct +{ + uint8_t sck_pin; ///< SCK pin number. + uint8_t lrck_pin; ///< LRCK pin number. + uint8_t mck_pin; ///< MCK pin number. + /**< Optional. Use @ref NRF_DRV_I2S_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t sdout_pin; ///< SDOUT pin number. + /**< Optional. Use @ref NRF_DRV_I2S_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t sdin_pin; ///< SDIN pin number. + /**< Optional. Use @ref NRF_DRV_I2S_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t irq_priority; ///< Interrupt priority. + + nrf_i2s_mode_t mode; ///< Mode of operation. + nrf_i2s_format_t format; ///< Frame format. + nrf_i2s_align_t alignment; ///< Alignment of sample within a frame. + nrf_i2s_swidth_t sample_width; ///< Sample width. + nrf_i2s_channels_t channels; ///< Enabled channels. + nrf_i2s_mck_t mck_setup; ///< Master clock setup. + nrf_i2s_ratio_t ratio; ///< MCK/LRCK ratio. +} nrf_drv_i2s_config_t; + +/** + * @brief I2S driver default configuration. + */ +#define NRF_DRV_I2S_DEFAULT_CONFIG \ +{ \ + .sck_pin = I2S_CONFIG_SCK_PIN, \ + .lrck_pin = I2S_CONFIG_LRCK_PIN, \ + .mck_pin = I2S_CONFIG_MCK_PIN, \ + .sdout_pin = I2S_CONFIG_SDOUT_PIN, \ + .sdin_pin = I2S_CONFIG_SDIN_PIN, \ + .irq_priority = I2S_CONFIG_IRQ_PRIORITY, \ + .mode = (nrf_i2s_mode_t)I2S_CONFIG_MASTER, \ + .format = (nrf_i2s_format_t)I2S_CONFIG_FORMAT, \ + .alignment = (nrf_i2s_align_t)I2S_CONFIG_ALIGN, \ + .sample_width = (nrf_i2s_swidth_t)I2S_CONFIG_SWIDTH, \ + .channels = (nrf_i2s_channels_t)I2S_CONFIG_CHANNELS, \ + .mck_setup = (nrf_i2s_mck_t)I2S_CONFIG_MCK_SETUP, \ + .ratio = (nrf_i2s_ratio_t)I2S_CONFIG_RATIO, \ +} + +/** + * @brief I2S driver data handler type. + * + * A data handling function of this type must be specified during initialization + * of the driver. The driver will call this function when a new portion of data + * is received or a new portion of data should be prepared for transmission. + * The first case is indicated by a non-NULL value in the @p p_data_received + * parameter (which points to the memory containing the received data). + * Similarly, the second case is indicated by a non-NULL value in the + * @p p_data_to_send parameter (which points to where the data to be transmitted + * should be placed). + * + * @note The two cases mentioned above may be indicated separately or combined + * into one call (depending on the environment in which the driver is + * used). Therefore, both parameters should be checked and handled + * properly in every call. @ref NRF_DRV_I2S_FLAG_SYNCHRONIZED_MODE + * "Synchronized mode" can be used to always combine these indications. + * + * @param[in] p_data_received Pointer to the buffer with received data, + * or NULL if the handler is called to prepare + * transmission only. + * @param[out] p_data_to_send Pointer to the buffer where data to be sent + * should be written, or NULL if the handler is + * called for received data only. + * @param[in] number_of_words Length of data received and/or to be written + * (in 32-bit words). This value is always equal to + * half the size of the buffers set by the call + * to the @ref nrf_drv_i2s_start function. + */ +typedef void (* nrf_drv_i2s_data_handler_t)(uint32_t const * p_data_received, + uint32_t * p_data_to_send, + uint16_t number_of_words); + + +/** + * @brief Function for initializing the I2S driver. + * + * @param[in] p_config Pointer to the structure with initial configuration. + * If NULL, the default configuration is used. + * @param[in] handler Data handler provided by the user. Must not be NULL. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + * @retval NRF_ERROR_INVALID_PARAM If the requested combination of configuration + * options is not allowed by the I2S peripheral. + */ +ret_code_t nrf_drv_i2s_init(nrf_drv_i2s_config_t const * p_config, + nrf_drv_i2s_data_handler_t handler); + +/** + * @brief Function for uninitializing the I2S driver. + */ +void nrf_drv_i2s_uninit(void); + +/** + * @brief Function for starting the continuous I2S transfer. + * + * The I2S data transfer can be performed in one of three modes: RX (reception) + * only, TX (transmission) only, or in both directions simultaneously. + * The mode is selected by specifying a proper buffer for a given direction + * in the call to this function or by passing NULL instead if this direction + * should be disabled. + * + * The length of the buffer (which is a common value for RX and TX if both + * directions are enabled) is specified in 32-bit words. One 32-bit memory + * word can either contain four 8-bit samples, two 16-bit samples, or one + * right-aligned 24-bit sample sign-extended to a 32-bit value. + * For a detailed memory mapping for different supported configurations, + * see the @linkProductSpecification52. + * + * The provided buffers are logically divided into two parts of equal size. + * One of them is in use by the peripheral (for storing received data or for + * getting data to be transmitted, respectively). The other part is provided + * to the application via a call to the defined @ref nrf_drv_i2s_data_handler_t + * "data handling function", so that the application can process the received + * data or prepare the next portion of data to be sent. The two parts are + * swapped every time @p buffer_size/2 data words are received or transmitted. + * + * Additional options are provided using the @p flags parameter: + * - @ref NRF_DRV_I2S_FLAG_SYNCHRONIZED_MODE - the calls to data handler should + * be done in a synchronized manner (one common call for TX and RX). + * Applicable only when both RX and TX are enabled. + * + * @attention All data exchange is done in the data handler only. In particular, + * no data should be written to the transmit buffer before calling + * this function (a proper call to the data handler to get the first + * portion of data to be sent will be done before the actual transfer + * starts). + * + * @note Peripherals using EasyDMA (like I2S) require the transfer buffers + * to be placed in the Data RAM region. If this condition is not met, + * this function will fail with the error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_rx_buffer Pointer to the receive buffer. + * Pass NULL if reception is not required. + * @param[in] p_tx_buffer Pointer to the transmit buffer. + * Pass NULL if transmission is not required. + * @param[in] buffer_size Size of the buffers (in 32-bit words). + * The size must be an even number greater than 0. + * @param[in] flags Transfer options (0 for default settings). + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If a transfer was already started or + * the driver has not been initialized. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed + * in the Data RAM region. + */ +ret_code_t nrf_drv_i2s_start(uint32_t * p_rx_buffer, + uint32_t * p_tx_buffer, + uint16_t buffer_size, + uint8_t flags); + +/** + * @brief Function for stopping the I2S transfer. + */ +void nrf_drv_i2s_stop(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_I2S_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.c new file mode 100644 index 0000000000..38be84bce2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.c @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(LPCOMP) +#include "nrf_drv_lpcomp.h" +#include "nrf_assert.h" +#include "nrf_error.h" +#include "nrf_soc.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" +#include +#include +#include + +#define NRF_LOG_MODULE_NAME lpcomp + +#if LPCOMP_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL LPCOMP_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR LPCOMP_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR LPCOMP_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_LPCOMP_EVENT_READY ? "NRF_LPCOMP_EVENT_READY" : \ + (event == NRF_LPCOMP_EVENT_DOWN ? "NRF_LPCOMP_EVENT_DOWN" : \ + (event == NRF_LPCOMP_EVENT_UP ? "NRF_LPCOMP_EVENT_UP" : \ + (event == NRF_LPCOMP_EVENT_CROSS ? "NRF_LPCOMP_EVENT_CROSS" : "UNKNOWN EVENT")))) +#else //LPCOMP_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //LPCOMP_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +static lpcomp_events_handler_t m_lpcomp_events_handler = NULL; +static nrf_drv_state_t m_state = NRF_DRV_STATE_UNINITIALIZED; + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME irq_handler_for_lpcomp + #define IRQ_HANDLER static void IRQ_HANDLER_NAME(void) + + IRQ_HANDLER; +#else + #define IRQ_HANDLER void LPCOMP_IRQHandler(void) +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +static void lpcomp_execute_handler(nrf_lpcomp_event_t event, uint32_t event_mask) +{ + if ( nrf_lpcomp_event_check(event) && nrf_lpcomp_int_enable_check(event_mask) ) + { + nrf_lpcomp_event_clear(event); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(event)); + + m_lpcomp_events_handler(event); + } +} + + +IRQ_HANDLER +{ + lpcomp_execute_handler(NRF_LPCOMP_EVENT_READY, LPCOMP_INTENSET_READY_Msk); + lpcomp_execute_handler(NRF_LPCOMP_EVENT_DOWN, LPCOMP_INTENSET_DOWN_Msk); + lpcomp_execute_handler(NRF_LPCOMP_EVENT_UP, LPCOMP_INTENSET_UP_Msk); + lpcomp_execute_handler(NRF_LPCOMP_EVENT_CROSS, LPCOMP_INTENSET_CROSS_Msk); +} + + +ret_code_t nrf_drv_lpcomp_init(const nrf_drv_lpcomp_config_t * p_config, + lpcomp_events_handler_t events_handler) +{ + ASSERT(p_config); + ret_code_t err_code; + + if (m_state != NRF_DRV_STATE_UNINITIALIZED) + { // LPCOMP driver is already initialized + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(NRF_LPCOMP, IRQ_HANDLER_NAME) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif + + nrf_lpcomp_configure(&(p_config->hal) ); + + if (events_handler) + { + m_lpcomp_events_handler = events_handler; + } + else + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_lpcomp_input_select(p_config->input); + + switch (p_config->hal.detection) + { + case NRF_LPCOMP_DETECT_UP: + nrf_lpcomp_int_enable(LPCOMP_INTENSET_UP_Msk); + break; + + case NRF_LPCOMP_DETECT_DOWN: + nrf_lpcomp_int_enable(LPCOMP_INTENSET_DOWN_Msk); + break; + + case NRF_LPCOMP_DETECT_CROSS: + nrf_lpcomp_int_enable(LPCOMP_INTENSET_CROSS_Msk); + break; + + default: + break; + } + nrf_lpcomp_shorts_enable(NRF_LPCOMP_SHORT_READY_SAMPLE_MASK); + + nrf_drv_common_irq_enable(LPCOMP_IRQn, p_config->interrupt_priority); + + m_state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_lpcomp_uninit(void) +{ + ASSERT(m_state != NRF_DRV_STATE_UNINITIALIZED); + nrf_drv_common_irq_disable(LPCOMP_IRQn); + nrf_drv_lpcomp_disable(); +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(NRF_LPCOMP); +#endif + m_state = NRF_DRV_STATE_UNINITIALIZED; + m_lpcomp_events_handler = NULL; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_lpcomp_enable(void) +{ + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + nrf_lpcomp_enable(); + nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_START); + m_state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled."); +} + +void nrf_drv_lpcomp_disable(void) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_lpcomp_disable(); + nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_STOP); + m_state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled."); +} + +void nrf_drv_lpcomp_event_handler_register(lpcomp_events_handler_t lpcomp_events_handler) +{ + m_lpcomp_events_handler = lpcomp_events_handler; +} + +#endif //NRF_MODULE_ENABLED(LPCOMP) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.h new file mode 100644 index 0000000000..7cd1852873 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/lpcomp/nrf_drv_lpcomp.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_LPCOMP_H__ +#define NRF_DRV_LPCOMP_H__ + +#include "nrf_lpcomp.h" +#include "sdk_errors.h" +#include "nrf_drv_common.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup nrf_lpcomp LPCOMP HAL and driver + * @ingroup nrf_drivers + * @brief Low Power Comparator (LPCOMP) APIs. + * @details The LPCOMP HAL provides basic APIs for accessing the registers of Low Power Comparator. + * The LPCOMP driver provides APIs on a higher level. + * + * @defgroup nrf_drv_lpcomp LPCOMP driver + * @{ + * @ingroup nrf_lpcomp + * @brief Low Power Comparator (LPCOMP) driver. + */ + +/**@brief LPCOMP event handler function type. + * @param[in] event LPCOMP event. + */ +typedef void (* lpcomp_events_handler_t)(nrf_lpcomp_event_t event); + +/**@brief LPCOMP configuration. + */ +typedef struct +{ + nrf_lpcomp_config_t hal; /**< LPCOMP HAL configuration. */ + nrf_lpcomp_input_t input; /**< Input to be monitored. */ + uint8_t interrupt_priority; /**< LPCOMP interrupt priority. */ +} nrf_drv_lpcomp_config_t; + +/** @brief LPCOMP driver default configuration including the LPCOMP HAL configuration. */ +#ifdef NRF52_SERIES +#define NRF_DRV_LPCOMP_DEFAULT_CONFIG \ + { \ + .hal = {(nrf_lpcomp_ref_t)LPCOMP_CONFIG_REFERENCE , (nrf_lpcomp_detect_t)LPCOMP_CONFIG_DETECTION, \ + (nrf_lpcomp_hysteresis_t)LPCOMP_CONFIG_HYST}, \ + .input = (nrf_lpcomp_input_t)LPCOMP_CONFIG_INPUT, \ + .interrupt_priority = LPCOMP_CONFIG_IRQ_PRIORITY \ + } +#else +#define NRF_DRV_LPCOMP_DEFAULT_CONFIG \ + { \ + .hal = {(nrf_lpcomp_ref_t)LPCOMP_CONFIG_REFERENCE , (nrf_lpcomp_detect_t)LPCOMP_CONFIG_DETECTION}, \ + .input = (nrf_lpcomp_input_t)LPCOMP_CONFIG_INPUT, \ + .interrupt_priority = LPCOMP_CONFIG_IRQ_PRIORITY \ + } +#endif + +/** + * @brief Function for initializing the LPCOMP driver. + * + * This function initializes the LPCOMP driver, but does not enable the peripheral or any interrupts. + * To start the driver, call the function nrf_drv_lpcomp_enable() after initialization. + * + * If no configuration structure is provided, the driver is initialized with the default settings. + * + * @param[in] p_config Initial configuration. If NULL, the default configuration is used. + * @param[in] events_handler Handler function. + * @retval NRF_ERROR_INVALID_PARAM If the configuration is invalid. + * @retval NRF_ERROR_INVALID_STATE If the driver has already been initialized. + */ +ret_code_t nrf_drv_lpcomp_init(const nrf_drv_lpcomp_config_t * p_config, + lpcomp_events_handler_t events_handler); + + +/** + * @brief Function for uninitializing the LCOMP driver. + * + * This function uninitializes the LPCOMP driver. The LPCOMP peripheral and + * its interrupts are disabled, and local variables are cleaned. After this call, you must + * initialize the driver again by calling nrf_drv_lpcomp_init() if you want to use it. + * + * @sa nrf_drv_lpcomp_disable() + * @sa nrf_drv_lpcomp_init() + */ +void nrf_drv_lpcomp_uninit(void); + +/**@brief Function for enabling the LPCOMP peripheral and interrupts. + * + * Before calling this function, the driver must be initialized. This function + * enables the LPCOMP peripheral and its interrupts. + * + * @sa nrf_drv_lpcomp_disable() + */ +void nrf_drv_lpcomp_enable(void); + +/**@brief Function for disabling the LPCOMP peripheral. + * + * Before calling this function, the driver must be initialized. This function disables the LPCOMP + * peripheral and its interrupts. + * + * @sa nrf_drv_lpcomp_enable() + */ +void nrf_drv_lpcomp_disable(void); + +/** + *@} + **/ + + +#ifdef __cplusplus +} +#endif + + #endif /* NRF_DRV_LPCOMP_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.c new file mode 100644 index 0000000000..5a7aca44d0 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.c @@ -0,0 +1,365 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PDM) +#include "nrf_drv_pdm.h" +#include "nrf_assert.h" +#include "nrf_drv_common.h" +#include "nrf_gpio.h" + +#define NRF_LOG_MODULE_NAME pdm + +#if PDM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL PDM_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR PDM_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR PDM_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_PDM_EVENT_STARTED ? "NRF_PDM_EVENT_STARTED" : \ + (event == NRF_PDM_EVENT_STOPPED ? "NRF_PDM_EVENT_STOPPED" : \ + (event == NRF_PDM_EVENT_END ? "NRF_PDM_EVENT_END" : "UNKNOWN EVENT"))) +#else //PDM_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //PDM_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/** @brief PDM interface status. */ +typedef enum +{ + NRF_PDM_STATE_IDLE, + NRF_PDM_STATE_RUNNING, + NRF_PDM_STATE_STARTING, + NRF_PDM_STATE_STOPPING +} nrf_drv_pdm_state_t; + + +/** @brief PDM interface control block.*/ +typedef struct +{ + nrf_drv_pdm_event_handler_t event_handler; ///< Event handler function pointer. + int16_t * buff_address[2]; ///< Sample buffers. + uint16_t buff_length[2]; ///< Length of the sample buffers. + nrf_drv_state_t drv_state; ///< Driver state. + volatile nrf_drv_pdm_state_t op_state; ///< PDM peripheral operation state. + uint8_t active_buffer; ///< Number of currently active buffer. + uint8_t error; ///< Driver error flag. + uint8_t irq_priority; ///< Interrupt priority. + volatile uint8_t irq_buff_request; ///< Request the next buffer in the ISR. +} nrf_drv_pdm_cb_t; + + +static nrf_drv_pdm_cb_t m_cb; + + +void PDM_IRQHandler(void) +{ + if (nrf_pdm_event_check(NRF_PDM_EVENT_STARTED)) + { + nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_PDM_EVENT_STARTED)); + + nrf_drv_pdm_evt_t evt; + uint8_t finished_buffer = m_cb.active_buffer; + + // Check if the next buffer was set before. + uint8_t next_buffer = (~m_cb.active_buffer) & 0x01; + if (m_cb.buff_address[next_buffer] || m_cb.op_state == NRF_PDM_STATE_STARTING) + { + evt.error = PDM_NO_ERROR; + m_cb.error = 0; + + // Release the full buffer if ready and request the next one. + if (m_cb.op_state == NRF_PDM_STATE_STARTING) + { + evt.buffer_released = 0; + m_cb.op_state = NRF_PDM_STATE_RUNNING; + } + else + { + evt.buffer_released = m_cb.buff_address[finished_buffer]; + m_cb.buff_address[finished_buffer] = 0; + m_cb.active_buffer = next_buffer; + } + evt.buffer_requested = true; + m_cb.event_handler(&evt); + } + else + { + // No next buffer available. Report an error. + // Do not request the new buffer as it was already done. + if (m_cb.error == 0) + { + evt.error = PDM_ERROR_OVERFLOW; + evt.buffer_released = 0; + evt.buffer_requested = false; + m_cb.error = 1; + m_cb.event_handler(&evt); + } + } + + if (m_cb.op_state == NRF_PDM_STATE_STARTING) + { + m_cb.op_state = NRF_PDM_STATE_RUNNING; + } + } + else if (nrf_pdm_event_check(NRF_PDM_EVENT_STOPPED)) + { + nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_PDM_EVENT_STOPPED)); + nrf_pdm_disable(); + m_cb.op_state = NRF_PDM_STATE_IDLE; + + // Release the buffers. + nrf_drv_pdm_evt_t evt; + evt.error = PDM_NO_ERROR; + evt.buffer_requested = false; + if (m_cb.buff_address[m_cb.active_buffer]) + { + evt.buffer_released = m_cb.buff_address[m_cb.active_buffer]; + m_cb.buff_address[m_cb.active_buffer] = 0; + m_cb.event_handler(&evt); + } + + uint8_t second_buffer = (~m_cb.active_buffer) & 0x01; + if (m_cb.buff_address[second_buffer]) + { + evt.buffer_released = m_cb.buff_address[second_buffer]; + m_cb.buff_address[second_buffer] = 0; + m_cb.event_handler(&evt); + } + m_cb.active_buffer = 0; + + + } + + if (m_cb.irq_buff_request) + { + nrf_drv_pdm_evt_t evt; + evt.buffer_released = 0; + evt.error = PDM_NO_ERROR; + evt.buffer_requested = true; + m_cb.irq_buff_request = 0; + m_cb.event_handler(&evt); + } +} + + +ret_code_t nrf_drv_pdm_init(nrf_drv_pdm_config_t const * p_config, + nrf_drv_pdm_event_handler_t event_handler) +{ + ret_code_t err_code; + + if (m_cb.drv_state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if ((p_config == NULL) + || (event_handler == NULL)) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if (p_config->gain_l > NRF_PDM_GAIN_MAXIMUM + || p_config->gain_r > NRF_PDM_GAIN_MAXIMUM) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + + m_cb.buff_address[0] = 0; + m_cb.buff_address[1] = 0; + m_cb.active_buffer = 0; + m_cb.error = 0; + m_cb.event_handler = event_handler; + m_cb.op_state = NRF_PDM_STATE_IDLE; + + nrf_pdm_clock_set(p_config->clock_freq); + nrf_pdm_mode_set(p_config->mode, p_config->edge); + nrf_pdm_gain_set(p_config->gain_l, p_config->gain_r); + + nrf_gpio_cfg_output(p_config->pin_clk); + nrf_gpio_pin_clear(p_config->pin_clk); + nrf_gpio_cfg_input(p_config->pin_din, NRF_GPIO_PIN_NOPULL); + nrf_pdm_psel_connect(p_config->pin_clk, p_config->pin_din); + + nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED); + nrf_pdm_event_clear(NRF_PDM_EVENT_END); + nrf_pdm_event_clear(NRF_PDM_EVENT_STOPPED); + nrf_pdm_int_enable(NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED); + m_cb.irq_priority = p_config->interrupt_priority; + nrf_drv_common_irq_enable(PDM_IRQn, m_cb.irq_priority); + m_cb.drv_state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_pdm_uninit(void) +{ + nrf_pdm_disable(); + nrf_pdm_psel_disconnect(); + m_cb.drv_state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + +static void pdm_start() +{ + m_cb.drv_state = NRF_DRV_STATE_POWERED_ON; + nrf_pdm_enable(); + nrf_pdm_event_clear(NRF_PDM_EVENT_STARTED); + nrf_pdm_task_trigger(NRF_PDM_TASK_START); +} + +static void pdm_buf_request() +{ + m_cb.irq_buff_request = 1; + NVIC_SetPendingIRQ(PDM_IRQn); +} + +ret_code_t nrf_drv_pdm_start(void) +{ + ASSERT(m_cb.drv_state != NRF_DRV_STATE_UNINITIALIZED); + ret_code_t err_code; + + if (m_cb.op_state != NRF_PDM_STATE_IDLE) + { + if (m_cb.op_state == NRF_PDM_STATE_RUNNING) + { + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + m_cb.op_state = NRF_PDM_STATE_STARTING; + pdm_buf_request(); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +ret_code_t nrf_drv_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length) +{ + if (m_cb.drv_state == NRF_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + if (m_cb.op_state == NRF_PDM_STATE_STOPPING) + { + return NRF_ERROR_BUSY; + } + if ((!buffer) || (buffer_length > NRF_PDM_MAX_BUFFER_SIZE)) + { + return NRF_ERROR_INVALID_PARAM; + } + + ret_code_t err_code = NRF_SUCCESS; + + // Enter the PDM critical section. + nrf_drv_common_irq_disable(PDM_IRQn); + + uint8_t next_buffer = (~m_cb.active_buffer) & 0x01; + if (m_cb.op_state == NRF_PDM_STATE_STARTING) + { + next_buffer = 0; + } + + if (m_cb.buff_address[next_buffer]) + { + // Buffer already set. + err_code = NRF_ERROR_BUSY; + } + else + { + m_cb.buff_address[next_buffer] = buffer; + m_cb.buff_length[next_buffer] = buffer_length; + nrf_pdm_buffer_set((uint32_t *)buffer, buffer_length); + + if (m_cb.drv_state != NRF_DRV_STATE_POWERED_ON) + { + pdm_start(); + } + } + + nrf_drv_common_irq_enable(PDM_IRQn, m_cb.irq_priority); + return err_code; +} + +ret_code_t nrf_drv_pdm_stop(void) +{ + ASSERT(m_cb.drv_state != NRF_DRV_STATE_UNINITIALIZED); + ret_code_t err_code; + + if (m_cb.op_state != NRF_PDM_STATE_RUNNING) + { + if (m_cb.op_state == NRF_PDM_STATE_IDLE || m_cb.op_state == NRF_PDM_STATE_STARTING) + { + nrf_pdm_disable(); + m_cb.op_state = NRF_PDM_STATE_IDLE; + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + m_cb.drv_state = NRF_DRV_STATE_INITIALIZED; + m_cb.op_state = NRF_PDM_STATE_STOPPING; + + nrf_pdm_task_trigger(NRF_PDM_TASK_STOP); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +#endif //NRF_MODULE_ENABLED(PDM) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.h new file mode 100644 index 0000000000..7e718857a6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pdm/nrf_drv_pdm.h @@ -0,0 +1,226 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_pdm PDM HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52 Pulse density modulation (PDM) interface APIs. + * + * The PDM HAL provides basic APIs for accessing the registers of the PDM interface peripheral. + * The PDM driver provides APIs on a higher level. + * + * @defgroup nrf_drv_pdm PDM driver + * @{ + * @ingroup nrf_pdm + * + * @brief @tagAPI52 Pulse density modulation (PDM) interface driver. + */ + + +#ifndef NRF_DRV_PDM_H__ +#define NRF_DRV_PDM_H__ + +#include "sdk_config.h" +#include "nrf_pdm.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_PDM_MAX_BUFFER_SIZE 32767 + + +/** + * @brief PDM error type. + */ +typedef enum +{ + PDM_NO_ERROR = 0, + PDM_ERROR_OVERFLOW = 1 +} nrf_drv_pdm_error_t; + +/** + * @brief PDM event structure. + */ +typedef struct +{ + bool buffer_requested; ///< Buffer request flag. + int16_t * buffer_released; ///< Pointer to the released buffer. Can be NULL. + nrf_drv_pdm_error_t error; ///< Error type. +} nrf_drv_pdm_evt_t; + +/** + * @brief PDM interface driver configuration structure. + */ +typedef struct +{ + nrf_pdm_mode_t mode; ///< Interface operation mode. + nrf_pdm_edge_t edge; ///< Sampling mode. + uint8_t pin_clk; ///< CLK pin. + uint8_t pin_din; ///< DIN pin. + nrf_pdm_freq_t clock_freq; ///< Clock frequency. + nrf_pdm_gain_t gain_l; ///< Left channel gain. + nrf_pdm_gain_t gain_r; ///< Right channel gain. + uint8_t interrupt_priority; ///< Interrupt priority. +} nrf_drv_pdm_config_t; + + +/** + * @brief Macro for setting @ref nrf_drv_pdm_config_t to default settings + * in single ended mode. + * + * @param PIN_CLK CLK output pin. + * @param PIN_DIN DIN input pin. + */ +#define NRF_DRV_PDM_DEFAULT_CONFIG(PIN_CLK, PIN_DIN) \ +{ \ + .mode = (nrf_pdm_mode_t)PDM_CONFIG_MODE, \ + .edge = (nrf_pdm_edge_t)PDM_CONFIG_EDGE, \ + .pin_clk = PIN_CLK, \ + .pin_din = PIN_DIN, \ + .clock_freq = (nrf_pdm_freq_t)PDM_CONFIG_CLOCK_FREQ, \ + .gain_l = NRF_PDM_GAIN_DEFAULT, \ + .gain_r = NRF_PDM_GAIN_DEFAULT, \ + .interrupt_priority = PDM_CONFIG_IRQ_PRIORITY \ +} + + +/** + * @brief Handler for PDM interface ready events. + * + * This event handler is called on buffer request, error or when a buffer is full + * and ready to be processed. + * + * @param[in] evt Pointer to the PDM event structure. + */ +typedef void (*nrf_drv_pdm_event_handler_t)(nrf_drv_pdm_evt_t const * const evt); + + +/** + * @brief Function for initializing the PDM interface. + * + * @param[in] p_config Pointer to a configuration structure. Cannot be NULL. + * @param[in] event_handler Event handler provided by the user. Cannot be NULL. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is already initialized. + * @retval NRF_ERROR_INVALID_PARAM If invalid parameters were specified. + */ +ret_code_t nrf_drv_pdm_init(nrf_drv_pdm_config_t const * p_config, + nrf_drv_pdm_event_handler_t event_handler); + + +/** + * @brief Function for uninitializing the PDM interface. + * + * This function stops PDM sampling, if it is in progress. + */ +void nrf_drv_pdm_uninit(void); + + +/** + * @brief Function for getting the address of a PDM interface task. + * + * @param[in] task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_pdm_task_address_get(nrf_pdm_task_t task) +{ + return nrf_pdm_task_address_get(task); +} + + +/** + * @brief Function for getting the state of the PDM interface. + * + * @retval TRUE If the PDM interface is enabled. + * @retval FALSE If the PDM interface is disabled. + */ +__STATIC_INLINE bool nrf_drv_pdm_enable_check() +{ + return nrf_pdm_enable_check(); +} + + +/** + * @brief Function for starting PDM sampling. + * + * @retval NRF_SUCCESS If sampling was started successfully or was already in progress. + * @retval NRF_ERROR_BUSY If a previous start/stop operation is in progress. + */ +ret_code_t nrf_drv_pdm_start(void); + + +/** + * @brief Function for stopping PDM sampling. + * + * When this function is called, the PDM interface is stopped after finishing + * the current frame. + * The event handler function might be called once more after calling this function. + * + * @retval NRF_SUCCESS If sampling was stopped successfully or was already stopped before. + * @retval NRF_ERROR_BUSY If a previous start/stop operation is in progress. + */ +ret_code_t nrf_drv_pdm_stop(void); + +/** + * @brief Function for supplying the sample buffer. + * + * Call this function after every buffer request event. + * + * @param[in] buffer Pointer to the receive buffer. Cannot be NULL. + * @param[in] buffer_length Length of the receive buffer in 16-bit words. + * + * @retval NRF_SUCCESS If the buffer was applied successfully. + * @retval NRF_ERROR_BUSY If the buffer was already supplied or the peripheral is currently being stopped. + * @retval NRF_ERROR_INVALID_STATE If the driver was not initialized. + * @retval NRF_ERROR_INVALID_PARAM If invalid parameters were provided. + */ +ret_code_t nrf_drv_pdm_buffer_set(int16_t * buffer, uint16_t buffer_length); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_PDM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.c new file mode 100644 index 0000000000..3c1f26818c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.c @@ -0,0 +1,477 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(POWER) + +#include "nrf_drv_power.h" +#include "nrf_assert.h" +#include "nordic_common.h" +#include "app_util_platform.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#include "nrf_soc.h" +#include "nrf_sdh.h" +#include "nrf_sdh_soc.h" +#endif + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(POWER_CONFIG_IRQ_PRIORITY); + +/** + * @internal + * @defgroup nrf_drv_power_internals POWER driver internals + * @ingroup nrf_drv_power + * + * Internal variables, auxiliary macros and functions of POWER driver. + * @{ + */ + +/** + * @brief Default configuration + * + * The structure with default configuration data. + * This structure would be used if configuration pointer given + * to the @ref nrf_drv_power_init is set to NULL. + */ +static const nrf_drv_power_config_t m_drv_power_config_default = +{ + .dcdcen = POWER_CONFIG_DEFAULT_DCDCEN, +#if NRF_POWER_HAS_VDDH + .dcdcenhv = POWER_CONFIG_DEFAULT_DCDCENHV, +#endif +}; + +/** + * @brief The initialization flag + */ +static bool m_initialized; + +/** + * @brief The handler of power fail comparator warning event + */ +static nrf_drv_power_pofwarn_event_handler_t m_pofwarn_handler; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief The handler of sleep event handler + */ +static nrf_drv_power_sleep_event_handler_t m_sleepevt_handler; +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief The handler of USB power events + */ +static nrf_drv_power_usb_event_handler_t m_usbevt_handler; +#endif + +/** @} */ + +bool nrf_drv_power_init_check(void) +{ + return m_initialized; +} + +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config) +{ + nrf_drv_power_config_t const * p_used_config; + if (m_initialized) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + return NRF_ERROR_INVALID_STATE; + } +#endif + + p_used_config = (p_config != NULL) ? + p_config : (&m_drv_power_config_default); +#if NRF_POWER_HAS_VDDH + nrf_power_dcdcen_vddh_set(p_used_config->dcdcenhv); +#endif + nrf_power_dcdcen_set(p_used_config->dcdcen); + + nrf_drv_common_power_clock_irq_init(); + + m_initialized = true; + return NRF_SUCCESS; +} + +void nrf_drv_power_uninit(void) +{ + ASSERT(m_initialized); + nrf_drv_power_pof_uninit(); +#if NRF_POWER_HAS_SLEEPEVT + nrf_drv_power_sleepevt_uninit(); +#endif +#if NRF_POWER_HAS_USBREG + nrf_drv_power_usbevt_uninit(); +#endif + m_initialized = false; +} + +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config) +{ + ASSERT(p_config != NULL); + + nrf_drv_power_pof_uninit(); + +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Currently when SD is enabled - the configuration can be changed + * in very limited range. + * It is the SoftDevice limitation. + */ +#if NRF_POWER_HAS_VDDH + if (p_config->thrvddh != nrf_power_pofcon_vddh_get()) + { + /* Cannot change THRVDDH with current SD API */ + return NRF_ERROR_INVALID_STATE; + } +#endif + if (p_config->thr != nrf_power_pofcon_get(NULL)) + { + /* Only limited number of THR values are supported and + * the values taken by SD is different than the one in hardware + */ + uint8_t thr; + switch (p_config->thr) + { + case NRF_POWER_POFTHR_V21: + thr = NRF_POWER_THRESHOLD_V21; + break; + case NRF_POWER_POFTHR_V23: + thr = NRF_POWER_THRESHOLD_V23; + break; + case NRF_POWER_POFTHR_V25: + thr = NRF_POWER_THRESHOLD_V25; + break; + case NRF_POWER_POFTHR_V27: + thr = NRF_POWER_THRESHOLD_V27; + break; + default: + /* Cannot configure */ + return NRF_ERROR_INVALID_STATE; + } + ASSERT(sd_power_pof_threshold_set(thr)); + } + } + else +#endif /* SOFTDEVICE_PRESENT */ + { + nrf_power_pofcon_set(true, p_config->thr); +#if NRF_POWER_HAS_VDDH + nrf_power_pofcon_vddh_set(p_config->thrvddh); +#endif + } + + if (p_config->handler != NULL) + { + m_pofwarn_handler = p_config->handler; +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void) sd_power_pof_enable(true); + } + else +#endif + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_pof_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + (void) sd_power_pof_enable(false); + } + else +#endif + { + nrf_power_int_disable(NRF_POWER_INT_POFWARN_MASK); + } + m_pofwarn_handler = NULL; +} + +#if NRF_POWER_HAS_SLEEPEVT +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config) +{ + ASSERT(p_config != NULL); + + nrf_drv_power_sleepevt_uninit(); + if (p_config->handler != NULL) + { + uint32_t enmask = 0; + m_sleepevt_handler = p_config->handler; + if (p_config->en_enter) + { + enmask |= NRF_POWER_INT_SLEEPENTER_MASK; + nrf_power_event_clear(NRF_POWER_EVENT_SLEEPENTER); + } + if (p_config->en_exit) + { + enmask |= NRF_POWER_INT_SLEEPEXIT_MASK; + nrf_power_event_clear(NRF_POWER_EVENT_SLEEPEXIT); + } +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + if (enmask != 0) + { + return NRF_ERROR_INVALID_STATE; + } + } + else +#endif + { + nrf_power_int_enable(enmask); + } + } + + return NRF_SUCCESS; +} + +void nrf_drv_power_sleepevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /* Nothing to do */ + } + else +#endif + { + nrf_power_int_disable( + NRF_POWER_INT_SLEEPENTER_MASK | + NRF_POWER_INT_SLEEPEXIT_MASK); + } + m_sleepevt_handler = NULL; +} +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config) +{ + nrf_drv_power_usbevt_uninit(); + if (p_config->handler != NULL) + { + m_usbevt_handler = p_config->handler; +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /** @todo Implement USB power events when SD support it */ + return NRF_ERROR_INVALID_STATE; + } + else +#endif + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } + } + return NRF_SUCCESS; +} + +void nrf_drv_power_usbevt_uninit(void) +{ +#ifdef SOFTDEVICE_PRESENT + if (nrf_sdh_is_enabled()) + { + /** @todo Implement USB power events when SD support it */ + } + else +#endif + { + nrf_power_int_disable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } + m_usbevt_handler = NULL; +} +#endif /* NRF_POWER_HAS_USBREG */ + + +/** + * @ingroup nrf_drv_power_internals + * @brief Interrupt handler + * + * POWER peripheral interrupt handler + */ +#if NRF_DRV_COMMON_POWER_CLOCK_ISR +void nrf_drv_power_onIRQ(void) +#else +void POWER_CLOCK_IRQHandler(void) +#endif +{ + uint32_t enabled = nrf_power_int_enable_get(); + if ((0 != (enabled & NRF_POWER_INT_POFWARN_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_POFWARN)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_pofwarn_handler != NULL); + m_pofwarn_handler(); + } +#if NRF_POWER_HAS_SLEEPEVT + if ((0 != (enabled & NRF_POWER_INT_SLEEPENTER_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPENTER)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_sleepevt_handler != NULL); + m_sleepevt_handler(NRF_DRV_POWER_SLEEP_EVT_ENTER); + } + if ((0 != (enabled & NRF_POWER_INT_SLEEPEXIT_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_SLEEPEXIT)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_sleepevt_handler != NULL); + m_sleepevt_handler(NRF_DRV_POWER_SLEEP_EVT_EXIT); + } +#endif +#if NRF_POWER_HAS_USBREG + if ((0 != (enabled & NRF_POWER_INT_USBDETECTED_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBDETECTED)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_DETECTED); + } + if ((0 != (enabled & NRF_POWER_INT_USBREMOVED_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBREMOVED)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_REMOVED); + } + if ((0 != (enabled & NRF_POWER_INT_USBPWRRDY_MASK)) && + nrf_power_event_get_and_clear(NRF_POWER_EVENT_USBPWRRDY)) + { + /* Cannot be null if event is enabled */ + ASSERT(m_usbevt_handler != NULL); + m_usbevt_handler(NRF_DRV_POWER_USB_EVT_READY); + } +#endif +} + +#ifdef SOFTDEVICE_PRESENT + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context); +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context); + +NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO, + nrf_drv_power_sdh_soc_evt_handler, NULL); + +NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = nrf_drv_power_sdh_state_evt_handler, + .p_context = NULL +}; + +static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context) +{ + if (evt_id == NRF_EVT_POWER_FAILURE_WARNING) + { + /* Cannot be null if event is enabled */ + ASSERT(m_pofwarn_handler != NULL); + m_pofwarn_handler(); + } +} + +static void nrf_drv_power_on_sd_enable(void) +{ + ASSERT(m_initialized); /* This module has to be enabled first */ + CRITICAL_REGION_ENTER(); + if (m_pofwarn_handler != NULL) + { + (void) sd_power_pof_enable(true); + } + CRITICAL_REGION_EXIT(); +} + +static void nrf_drv_power_on_sd_disable(void) +{ + /* Reinit interrupts */ + ASSERT(m_initialized); + nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY); + if (m_pofwarn_handler != NULL) + { + nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK); + } +#if NRF_POWER_HAS_USBREG + if (m_usbevt_handler != NULL) + { + nrf_power_int_enable( + NRF_POWER_INT_USBDETECTED_MASK | + NRF_POWER_INT_USBREMOVED_MASK | + NRF_POWER_INT_USBPWRRDY_MASK); + } +#endif +} + +static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLED: + nrf_drv_power_on_sd_enable(); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + nrf_drv_power_on_sd_disable(); + break; + + default: + break; + } +} + +#endif // SOFTDEVICE_PRESENT + +#endif /* NRF_MODULE_ENABLED(POWER) */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.h new file mode 100644 index 0000000000..bb645e311f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/power/nrf_drv_power.h @@ -0,0 +1,371 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_POWER_H__ +#define NRF_DRV_POWER_H__ + +#include +#include +#include "nrf_power.h" +#include "sdk_config.h" +#include "nrf_drv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_power Power HAL and driver + * @ingroup nrf_drivers + * @brief POWER peripheral APIs. + * + * The power peripheral HAL provides basic APIs for accessing + * the registers of the POWER peripheral. + * The POWER driver provides APIs on a higher level. + */ + +/** + * @defgroup nrf_drv_power POWER driver + * @{ + * @ingroup nrf_power + * @brief Driver for managing events and the state of POWER peripheral. + * + */ + +/** + * @brief Power mode possible configurations + */ +typedef enum +{ + NRF_DRV_POWER_MODE_CONSTLAT, /**< Constant latency mode *///!< NRF_DRV_POWER_MODE_CONSTLAT + NRF_DRV_POWER_MODE_LOWPWR /**< Low power mode *///!< NRF_DRV_POWER_MODE_LOWPWR +}nrf_drv_power_mode_t; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Events from power system + */ +typedef enum +{ + NRF_DRV_POWER_SLEEP_EVT_ENTER, /**< CPU entered WFI/WFE sleep + * + * Keep in mind that if this interrupt is enabled, + * it means that CPU was waken up just after WFI by this interrupt. + */ + NRF_DRV_POWER_SLEEP_EVT_EXIT /**< CPU exited WFI/WFE sleep */ +}nrf_drv_power_sleep_evt_t; +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +/** + * @brief Events from USB power system + */ +typedef enum +{ + NRF_DRV_POWER_USB_EVT_DETECTED, /**< USB power detected on the connector (plugged in). */ + NRF_DRV_POWER_USB_EVT_REMOVED, /**< USB power removed from the connector. */ + NRF_DRV_POWER_USB_EVT_READY /**< USB power regulator ready. */ +}nrf_drv_power_usb_evt_t; + +/** + * @brief USB power state + * + * The single enumerator that holds all data about current state of USB + * related POWER. + * + * Organized this way that higher power state has higher numeric value + */ +typedef enum +{ + NRF_DRV_POWER_USB_STATE_DISCONNECTED, /**< No power on USB lines detected */ + NRF_DRV_POWER_USB_STATE_CONNECTED, /**< The USB power is detected, but USB power regulator is not ready */ + NRF_DRV_POWER_USB_STATE_READY /**< From the power point of view USB is ready for working */ +}nrf_drv_power_usb_state_t; +#endif /* NRF_POWER_HAS_USBREG */ + +/** + * @name Callback types + * + * Defined types of callback functions + * @{ + */ +/** + * @brief Event handler for power failure warning + */ +typedef void (*nrf_drv_power_pofwarn_event_handler_t)(void); + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Event handler for entering/exiting sleep + * + * @param event Event type + */ +typedef void (*nrf_drv_power_sleep_event_handler_t)(nrf_drv_power_sleep_evt_t event); +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief Event handler for USB related power events + * + * @param event Event type + */ +typedef void (*nrf_drv_power_usb_event_handler_t)(nrf_drv_power_usb_evt_t event); +#endif +/** @} */ + +/** + * @brief General power configuration + * + * Parameters required to initialize power driver. + */ +typedef struct +{ + /** + * @brief Enable main DCDC regulator + * + * This bit only informs the driver that elements for DCDC regulator + * are installed and regulator can be used. + * The regulator would be enabled or disabled automatically + * automatically by the hardware, basing on current power requirement. + */ + bool dcdcen:1; + +#if NRF_POWER_HAS_VDDH + /** + * @brief Enable HV DCDC regulator + * + * This bit only informs the driver that elements for DCDC regulator + * are installed and regulator can be used. + * The regulator would be enabled or disabled automatically + * automatically by the hardware, basing on current power requirement. + */ + bool dcdcenhv: 1; +#endif +}nrf_drv_power_config_t; + +/** + * @brief The configuration for power failure comparator + * + * Configuration used to enable and configure power failure comparator + */ +typedef struct +{ + nrf_drv_power_pofwarn_event_handler_t handler; //!< Event handler + nrf_power_pof_thr_t thr; //!< Threshold for power failure detection +#if NRF_POWER_HAS_VDDH + nrf_power_pof_thrvddh_t thrvddh; //!< Threshold for power failure detection on VDDH pin +#endif +}nrf_drv_power_pofwarn_config_t; + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief The configuration of sleep event processing + * + * Configuration used to enable and configure sleep event handling + */ +typedef struct +{ + nrf_drv_power_sleep_event_handler_t handler; //!< Event handler + bool en_enter:1; //!< Enable event on sleep entering + bool en_exit :1; //!< Enable event on sleep exiting +}nrf_drv_power_sleepevt_config_t; +#endif + +#if NRF_POWER_HAS_USBREG +/** + * @brief The configuration of USB related power events + * + * Configuration used to enable and configure USB power event handling + */ +typedef struct +{ + nrf_drv_power_usb_event_handler_t handler; //!< Event processing +}nrf_drv_power_usbevt_config_t; +#endif /* NRF_POWER_HAS_USBREG */ + +/** + * @brief Function for checking if driver is already initialized + * + * This function is used to check whatever common POWER_CLOCK common interrupt + * should be disabled or not if @ref nrf_drv_clock tries to disable the interrupt. + * + * @retval true Driver is initialized + * @retval false Driver is uninitialized + * + * @sa nrf_drv_power_uninit + */ +bool nrf_drv_power_init_check(void); + +/** + * @brief Initialize power module driver + * + * Enabled power module driver would process all the interrupts from power system. + * + * @param[in] p_config Driver configuration. Can be NULL - the default configuration + * from @em sdk_config.h file would be used then. + * + * @retval NRF_ERROR_INVALID_STATE Power driver has to be enabled + * before SoftDevice. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Module is initialized already. + * @retval NRF_SUCCESS Successfully initialized. + */ +ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config); + +/** + * @brief Unintialize power module driver + * + * Disables all the interrupt handling in the module. + * + * @sa nrf_drv_power_init + */ +void nrf_drv_power_uninit(void); + +/** + * @brief Initialize power failure comparator + * + * Configures and setups the power failure comparator and enables it. + * + * @param[in] p_config Configuration with values and event handler. + * If event handler is set to NULL, interrupt would be disabled. + * + * @retval NRF_ERROR_INVALID_STATE POF is initialized when SD is enabled and + * the configuration differs from the old one and + * is not possible to be set using SD interface. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config); + +/** + * @brief Turn off the power failure comparator + * + * Disables and clears the settings of the power failure comparator. + */ +void nrf_drv_power_pof_uninit(void); + +#if NRF_POWER_HAS_SLEEPEVT +/** + * @brief Initialize sleep entering and exiting events processing + * + * Configures and setups the sleep event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_sleepevt_uninit + * + * @note Sleep events are not available when SoftDevice is enabled. + * @note If sleep event is enabled when SoftDevice is initialized, sleep events + * would be automatically disabled - it is the limitation of the + * SoftDevice itself. + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config); + +/** + * @brief Uninitialize sleep entering and exiting events processing + * + * @sa nrf_drv_power_sleepevt_init + */ +void nrf_drv_power_sleepevt_uninit(void); +#endif /* NRF_POWER_HAS_SLEEPEVT */ + +#if NRF_POWER_HAS_USBREG +/** + * @brief Initialize USB power event processing + * + * Configures and setups the USB power event processing. + * + * @param[in] p_config Configuration with values and event handler. + * + * @sa nrf_drv_power_usbevt_uninit + * + * @retval NRF_ERROR_INVALID_STATE This event cannot be initialized + * when SD is enabled and SD does not support + * USB power events. + * @retval NRF_SUCCESS Successfully initialized and configured. + */ +ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config); + +/** + * @brief Uninitalize USB power event processing + * + * @sa nrf_drv_power_usbevt_init + */ +void nrf_drv_power_usbevt_uninit(void); + +/** + * @brief Get the status of USB power + * + * @return Current USB power status + */ +__STATIC_INLINE nrf_drv_power_usb_state_t nrf_drv_power_usbstatus_get(void); + +#endif /* NRF_POWER_HAS_USBREG */ + +/** @} */ + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +#if NRF_POWER_HAS_USBREG +__STATIC_INLINE nrf_drv_power_usb_state_t nrf_drv_power_usbstatus_get(void) +{ + uint32_t status = nrf_power_usbregstatus_get(); + if (0 == (status & NRF_POWER_USBREGSTATUS_VBUSDETECT_MASK)) + { + return NRF_DRV_POWER_USB_STATE_DISCONNECTED; + } + if (0 == (status & NRF_POWER_USBREGSTATUS_OUTPUTRDY_MASK)) + { + return NRF_DRV_POWER_USB_STATE_CONNECTED; + } + return NRF_DRV_POWER_USB_STATE_READY; +} +#endif /* NRF_POWER_HAS_USBREG */ + +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_DRV_POWER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.c new file mode 100644 index 0000000000..54611d809c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.c @@ -0,0 +1,540 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PPI) +#include + +#include "nrf.h" +#include "nrf_drv_ppi.h" +#include "nrf_drv_common.h" +#include "nrf_ppi.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME ppi + +#if PPI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL PPI_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR PPI_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR PPI_CONFIG_DEBUG_COLOR +#else //PPI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //PPI_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +static nrf_drv_state_t m_drv_state; /**< Driver state */ +static uint32_t m_channels_allocated; /**< Bitmap representing channels availability. 1 when a channel is allocated, 0 otherwise. */ +static uint8_t m_groups_allocated; /**< Bitmap representing groups availability. 1 when a group is allocated, 0 otherwise.*/ + + +/**@brief Compute a group mask (needed for driver internals, not used for NRF_PPI registers). + * @param[in] group Group number to transform to a mask. + * @retval Group mask. + */ +__STATIC_INLINE uint32_t group_to_mask(nrf_ppi_channel_group_t group) +{ + return (1uL << (uint32_t) group); +} + + +/**@brief Check whether a channel is a programmable channel and can be used by an application. + * @param[in] channel Channel to check. + * @retval true The channel is a programmable application channel. + * false The channel is used by a SoftDevice or is preprogrammed. + */ +__STATIC_INLINE bool is_programmable_app_channel(nrf_ppi_channel_t channel) +{ + return ((NRF_PPI_PROG_APP_CHANNELS_MASK & nrf_drv_ppi_channel_to_mask(channel)) != 0); +} + + +/**@brief Check whether a channels can be used by an application. + * @param[in] channel Channel mask to check. + * @retval true All specified channels can be used by an application. + * false At least one specified channel is used by a SoftDevice. + */ +__STATIC_INLINE bool are_app_channels(uint32_t channel_mask) +{ + //lint -e(587) + return ((~(NRF_PPI_ALL_APP_CHANNELS_MASK) & channel_mask) == 0); +} + + +/**@brief Check whether a channel can be used by an application. + * @param[in] channel Channel to check. + * @retval true The channel can be used by an application. + * false The channel is used by a SoftDevice. + */ +__STATIC_INLINE bool is_app_channel(nrf_ppi_channel_t channel) +{ + return are_app_channels(nrf_drv_ppi_channel_to_mask(channel)); +} + + +/**@brief Check whether a channel group can be used by an application. + * @param[in] group Group to check. + * @retval true The group is an application group. + * false The group is not an application group (this group either does not exist or + * it is used by a SoftDevice). + */ +__STATIC_INLINE bool is_app_group(nrf_ppi_channel_group_t group) +{ + return ((NRF_PPI_ALL_APP_GROUPS_MASK & group_to_mask(group)) != 0); +} + + +/**@brief Check whether a channel is allocated. + * @param[in] channel_num Channel number to check. + * @retval true The channel is allocated. + * false The channel is not allocated. + */ +__STATIC_INLINE bool is_allocated_channel(nrf_ppi_channel_t channel) +{ + return ((m_channels_allocated & nrf_drv_ppi_channel_to_mask(channel)) != 0); +} + + +/**@brief Set channel allocated indication. + * @param[in] channel_num Specifies the channel to set the "allocated" indication. + */ +__STATIC_INLINE void channel_allocated_set(nrf_ppi_channel_t channel) +{ + m_channels_allocated |= nrf_drv_ppi_channel_to_mask(channel); +} + + +/**@brief Clear channel allocated indication. + * @param[in] channel_num Specifies the channel to clear the "allocated" indication. + */ +__STATIC_INLINE void channel_allocated_clr(nrf_ppi_channel_t channel) +{ + m_channels_allocated &= ~nrf_drv_ppi_channel_to_mask(channel); +} + + +/**@brief Clear all allocated channels. + */ +__STATIC_INLINE void channel_allocated_clr_all(void) +{ + m_channels_allocated &= ~NRF_PPI_ALL_APP_CHANNELS_MASK; +} + + +/**@brief Check whether a group is allocated. + * @param[in] group_num Group number to check. + * @retval true The group is allocated. + * false The group is not allocated. + */ +__STATIC_INLINE bool is_allocated_group(nrf_ppi_channel_group_t group) +{ + return ((m_groups_allocated & group_to_mask(group)) != 0); +} + + +/**@brief Set group allocated indication. + * @param[in] group_num Specifies the group to set the "allocated" indication. + */ +__STATIC_INLINE void group_allocated_set(nrf_ppi_channel_group_t group) +{ + m_groups_allocated |= group_to_mask(group); +} + + +/**@brief Clear group allocated indication. + * @param[in] group_num Specifies the group to clear the "allocated" indication. + */ +__STATIC_INLINE void group_allocated_clr(nrf_ppi_channel_group_t group) +{ + m_groups_allocated &= ~group_to_mask(group); +} + + +/**@brief Clear all allocated groups. + */ +__STATIC_INLINE void group_allocated_clr_all() +{ + m_groups_allocated &= ~NRF_PPI_ALL_APP_GROUPS_MASK; +} + + +uint32_t nrf_drv_ppi_init(void) +{ + uint32_t err_code; + + if (m_drv_state == NRF_DRV_STATE_UNINITIALIZED) + { + m_drv_state = NRF_DRV_STATE_INITIALIZED; + err_code = NRF_SUCCESS; + } + else + { + + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_uninit(void) +{ + ret_code_t err_code = NRF_SUCCESS; + uint32_t mask = NRF_PPI_ALL_APP_GROUPS_MASK; + nrf_ppi_channel_group_t group; + + if (m_drv_state == NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + m_drv_state = NRF_DRV_STATE_UNINITIALIZED; + + // Disable all channels and groups + nrf_ppi_channels_disable(NRF_PPI_ALL_APP_CHANNELS_MASK); + + for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++) + { + if (mask & group_to_mask(group)) + { + nrf_ppi_channel_group_clear(group); + } + } + channel_allocated_clr_all(); + group_allocated_clr_all(); + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_channel_alloc(nrf_ppi_channel_t * p_channel) +{ + uint32_t err_code = NRF_SUCCESS; + nrf_ppi_channel_t channel; + uint32_t mask = 0; + + err_code = NRF_ERROR_NO_MEM; + + mask = NRF_PPI_PROG_APP_CHANNELS_MASK; + for (channel = NRF_PPI_CHANNEL0; mask != 0; mask &= ~nrf_drv_ppi_channel_to_mask(channel), channel++) + { + CRITICAL_REGION_ENTER(); + if ((mask & nrf_drv_ppi_channel_to_mask(channel)) && (!is_allocated_channel(channel))) + { + channel_allocated_set(channel); + *p_channel = channel; + err_code = NRF_SUCCESS; + } + CRITICAL_REGION_EXIT(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_INFO("Allocated channel: %d.", channel); + break; + } + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_channel_free(nrf_ppi_channel_t channel) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_programmable_app_channel(channel)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else + { + // First disable this channel + nrf_ppi_channel_disable(channel); + CRITICAL_REGION_ENTER(); + channel_allocated_clr(channel); + CRITICAL_REGION_EXIT(); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep) +{ + VERIFY_PARAM_NOT_NULL((uint32_t *)eep); + VERIFY_PARAM_NOT_NULL((uint32_t *)tep); + + ret_code_t err_code = NRF_SUCCESS; + + if (!is_programmable_app_channel(channel)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (!is_allocated_channel(channel)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_channel_endpoint_setup(channel, eep, tep); + NRF_LOG_INFO("Assigned channel: %d, event end point: %x, task end point: %x.", channel, eep, tep); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +uint32_t nrf_drv_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep) +{ + ret_code_t err_code = NRF_SUCCESS; +#ifdef PPI_FEATURE_FORKS_PRESENT + if (!is_programmable_app_channel(channel)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (!is_allocated_channel(channel)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_fork_endpoint_setup(channel, fork_tep); + NRF_LOG_INFO("Fork assigned channel: %d, task end point: %d.", channel, fork_tep); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#else + err_code = NRF_ERROR_NOT_SUPPORTED; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +#endif +} + +uint32_t nrf_drv_ppi_channel_enable(nrf_ppi_channel_t channel) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_channel(channel)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_channel_enable(channel); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_channel_disable(nrf_ppi_channel_t channel) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_channel(channel)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_channel_disable(channel); + err_code = NRF_SUCCESS; + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_group_alloc(nrf_ppi_channel_group_t * p_group) +{ + uint32_t err_code; + uint32_t mask = 0; + nrf_ppi_channel_group_t group; + + err_code = NRF_ERROR_NO_MEM; + + mask = NRF_PPI_ALL_APP_GROUPS_MASK; + for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++) + { + CRITICAL_REGION_ENTER(); + if ((mask & group_to_mask(group)) && (!is_allocated_group(group))) + { + group_allocated_set(group); + *p_group = group; + err_code = NRF_SUCCESS; + } + CRITICAL_REGION_EXIT(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_INFO("Allocated group: %d.", group); + break; + } + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_group_free(nrf_ppi_channel_group_t group) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_group(group)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + if (!is_allocated_group(group)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_group_disable(group); + CRITICAL_REGION_ENTER(); + group_allocated_clr(group); + CRITICAL_REGION_EXIT(); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_group_enable(nrf_ppi_channel_group_t group) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_group(group)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (!is_allocated_group(group)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else + { + nrf_ppi_group_enable(group); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_ppi_group_disable(nrf_ppi_channel_group_t group) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_group(group)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else + { + nrf_ppi_group_disable(group); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +uint32_t nrf_drv_ppi_channels_remove_from_group(uint32_t channel_mask, + nrf_ppi_channel_group_t group) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_group(group)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (!is_allocated_group(group)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (!are_app_channels(channel_mask)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else + { + CRITICAL_REGION_ENTER(); + nrf_ppi_channels_remove_from_group(channel_mask, group); + CRITICAL_REGION_EXIT(); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +uint32_t nrf_drv_ppi_channels_include_in_group(uint32_t channel_mask, + nrf_ppi_channel_group_t group) +{ + ret_code_t err_code = NRF_SUCCESS; + + if (!is_app_group(group)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (!is_allocated_group(group)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (!are_app_channels(channel_mask)) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else + { + CRITICAL_REGION_ENTER(); + nrf_ppi_channels_include_in_group(channel_mask, group); + CRITICAL_REGION_EXIT(); + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} +#endif //NRF_MODULE_ENABLED(PPI) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.h new file mode 100644 index 0000000000..91fdf96a36 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/ppi/nrf_drv_ppi.h @@ -0,0 +1,316 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_PPI_H +#define NRF_DRV_PPI_H + +/*lint ++flb "Enter library region" */ +#include "sdk_errors.h" +#include "nrf_ppi.h" +#include +#include + +/** @file + * + * @addtogroup nrf_ppi PPI HAL and driver + * @ingroup nrf_drivers + * @brief Programmable Peripheral Interconnect (PPI) APIs. + * + * @details The PPI HAL provides basic APIs for accessing the registers of the PPI. + * The PPI driver provides APIs on a higher level. + * + * @defgroup nrf_drv_ppi PPI driver + * @{ + * @ingroup nrf_ppi + * + * @brief Programmable Peripheral Interconnect (PPI) driver. + */ + +#include "sdk_resources.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if PPI_CH_NUM > 16 +#define NRF_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFFFFFFFuL & ~(NRF_PPI_CHANNELS_USED)) /**< All PPI channels available to the application. */ +#define NRF_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x000FFFFFuL & ~(NRF_PPI_CHANNELS_USED)) /**< Programmable PPI channels available to the application. */ +#else +#define NRF_PPI_ALL_APP_CHANNELS_MASK ((uint32_t)0xFFF0FFFFuL & ~(NRF_PPI_CHANNELS_USED)) /**< All PPI channels available to the application. */ +#define NRF_PPI_PROG_APP_CHANNELS_MASK ((uint32_t)0x0000FFFFuL & ~(NRF_PPI_CHANNELS_USED)) /**< Programmable PPI channels available to the application. */ +#endif + +#define NRF_PPI_ALL_APP_GROUPS_MASK (((1uL << PPI_GROUP_NUM) - 1) & ~(NRF_PPI_GROUPS_USED)) /**< All PPI groups available to the application. */ + + +/**@brief Function for initializing PPI module. + * + * @retval NRF_SUCCESS If the module was successfully initialized. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the module has already been initialized. + */ +uint32_t nrf_drv_ppi_init(void); + +/**@brief Function for uninitializing the PPI module. + * + * This function also disables all channels and clears the channel groups. + * + * @retval NRF_SUCCESS If the module was successfully uninitialized. + * @retval NRF_ERROR_INVALID_STATE If the module has not been initialized yet. + * @retval NRF_ERROR_INTERNAL If the channels or groups could not be disabled. + */ +uint32_t nrf_drv_ppi_uninit(void); + +/**@brief Function for allocating a PPI channel. + * @details This function allocates the first unused PPI channel. + * + * @param[out] p_channel Pointer to the PPI channel that has been allocated. + * + * @retval NRF_SUCCESS If the channel was successfully allocated. + * @retval NRF_ERROR_NO_MEM If there is no available channel to be used. + */ +uint32_t nrf_drv_ppi_channel_alloc(nrf_ppi_channel_t * p_channel); + +/**@brief Function for freeing a PPI channel. + * @details This function also disables the chosen channel. + * + * @param[in] channel PPI channel to be freed. + * + * @retval NRF_SUCCESS If the channel was successfully freed. + * @retval NRF_ERROR_INVALID_PARAM If the channel is not user-configurable. + */ +uint32_t nrf_drv_ppi_channel_free(nrf_ppi_channel_t channel); + +/**@brief Function for assigning task and event endpoints to the PPI channel. + * + * @param[in] channel PPI channel to be assigned endpoints. + * + * @param[in] eep Event endpoint address. + * + * @param[in] tep Task endpoint address. + * + * @retval NRF_SUCCESS If the channel was successfully assigned. + * @retval NRF_ERROR_INVALID_STATE If the channel is not allocated for the user. + * @retval NRF_ERROR_INVALID_PARAM If the channel is not user-configurable. + */ +uint32_t nrf_drv_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep); + +/**@brief Function for assigning or clearing fork endpoint to the PPI channel. + * + * @param[in] channel PPI channel to be assigned endpoints. + * + * @param[in] fork_tep Fork task endpoint address or 0 to clear. + * + * @retval NRF_SUCCESS If the channel was successfully assigned. + * @retval NRF_ERROR_INVALID_STATE If the channel is not allocated for the user. + * @retval NRF_ERROR_INVALID_PARAM If the channel is not user-configurable. + * @retval NRF_ERROR_NOT_SUPPORTED If function is not supported. + */ +uint32_t nrf_drv_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep); + +/**@brief Function for enabling a PPI channel. + * + * @param[in] channel PPI channel to be enabled. + * + * @retval NRF_SUCCESS If the channel was successfully enabled. + * @retval NRF_ERROR_INVALID_STATE If the user-configurable channel is not allocated. + * @retval NRF_ERROR_INVALID_PARAM If the channel cannot be enabled by the user. + */ +uint32_t nrf_drv_ppi_channel_enable(nrf_ppi_channel_t channel); + +/**@brief Function for disabling a PPI channel. + * + * @param[in] channel PPI channel to be disabled. + * + * @retval NRF_SUCCESS If the channel was successfully disabled. + * @retval NRF_ERROR_INVALID_STATE If the user-configurable channel is not allocated. + * @retval NRF_ERROR_INVALID_PARAM If the channel cannot be disabled by the user. + */ +uint32_t nrf_drv_ppi_channel_disable(nrf_ppi_channel_t channel); + +/**@brief Function for allocating a PPI channel group. + * @details This function allocates the first unused PPI group. + * + * @param[out] p_group Pointer to the PPI channel group that has been allocated. + * + * @retval NRF_SUCCESS If the channel group was successfully allocated. + * @retval NRF_ERROR_NO_MEM If there is no available channel group to be used. + */ +uint32_t nrf_drv_ppi_group_alloc(nrf_ppi_channel_group_t * p_group); + +/**@brief Function for freeing a PPI channel group. + * @details This function also disables the chosen group. + * + * @param[in] group PPI channel group to be freed. + * + * @retval NRF_SUCCESS If the channel group was successfully freed. + * @retval NRF_ERROR_INVALID_PARAM If the channel group is not user-configurable. + */ +uint32_t nrf_drv_ppi_group_free(nrf_ppi_channel_group_t group); + +/**@brief Compute a channel mask for NRF_PPI registers. + * + * @param[in] channel Channel number to transform to a mask. + * + * @retval Channel mask. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_channel_to_mask(nrf_ppi_channel_t channel) +{ + return (1uL << (uint32_t) channel); +} + +/**@brief Function for including multiple PPI channels in a channel group. + * + * @param[in] channel_mask PPI channels to be added. + * @param[in] group Channel group in which to include the channels. + * + * @retval NRF_SUCCESS If the channels was successfully included. + */ +uint32_t nrf_drv_ppi_channels_include_in_group(uint32_t channel_mask, + nrf_ppi_channel_group_t group); + +/**@brief Function for including a PPI channel in a channel group. + * + * @param[in] channel PPI channel to be added. + * @param[in] group Channel group in which to include the channel. + * + * @retval NRF_SUCCESS If the channel was successfully included. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_channel_include_in_group(nrf_ppi_channel_t channel, + nrf_ppi_channel_group_t group) +{ + return nrf_drv_ppi_channels_include_in_group(nrf_drv_ppi_channel_to_mask(channel), group); +} + +/**@brief Function for removing multiple PPI channels from a channel group. + * + * @param[in] channel_mask PPI channels to be removed. + * @param[in] group Channel group from which to remove the channels. + * + * @retval NRF_SUCCESS If the channel was successfully removed. + */ +uint32_t nrf_drv_ppi_channels_remove_from_group(uint32_t channel_mask, + nrf_ppi_channel_group_t group); + +/**@brief Function for removing a PPI channel from a channel group. + * + * @param[in] channel PPI channel to be removed. + * @param[in] group Channel group from which to remove the channel. + * + * @retval NRF_SUCCESS If the channel was successfully removed. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_channel_remove_from_group(nrf_ppi_channel_t channel, + nrf_ppi_channel_group_t group) +{ + return nrf_drv_ppi_channels_remove_from_group(nrf_drv_ppi_channel_to_mask(channel), group); +} + +/**@brief Function for clearing a PPI channel group. + * + * @param[in] group Channel group to be cleared. + * + * @retval NRF_SUCCESS If the group was successfully cleared. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_group_clear(nrf_ppi_channel_group_t group) +{ + return nrf_drv_ppi_channels_remove_from_group(NRF_PPI_ALL_APP_CHANNELS_MASK, group); +} + +/**@brief Function for enabling a PPI channel group. + * + * @param[in] group Channel group to be enabled. + * + * @retval NRF_SUCCESS If the group was successfully enabled. + */ +uint32_t nrf_drv_ppi_group_enable(nrf_ppi_channel_group_t group); + +/**@brief Function for disabling a PPI channel group. + * + * @param[in] group Channel group to be disabled. + * + * @retval NRF_SUCCESS If the group was successfully disabled. + */ +uint32_t nrf_drv_ppi_group_disable(nrf_ppi_channel_group_t group); + +/** + * @brief Function for getting the address of a PPI task. + * + * @param[in] task Task. + * + * @retval Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_task_addr_get(nrf_ppi_task_t task) +{ + return (uint32_t) nrf_ppi_task_address_get(task); +} + +/** + * @brief Function for getting the address of a PPI group enable task. + * + * @param[in] group PPI channel group + * + * @retval Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_task_addr_group_enable_get(nrf_ppi_channel_group_t group) +{ + return (uint32_t) nrf_ppi_task_group_enable_address_get(group); +} + +/** + * @brief Function for getting the address of a PPI group enable task. + * + * @param[in] group PPI channel group + * + * @retval Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_ppi_task_addr_group_disable_get(nrf_ppi_channel_group_t group) +{ + return (uint32_t) nrf_ppi_task_group_disable_address_get(group); +} + +/** + *@} + **/ + +/*lint --flb "Leave library region" */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_PPI_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.c new file mode 100644 index 0000000000..7be306d7e6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.c @@ -0,0 +1,519 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(PWM) +#define ENABLED_PWM_COUNT (PWM0_ENABLED+PWM1_ENABLED+PWM2_ENABLED) +#if ENABLED_PWM_COUNT +#include +#include "nrf_drv_pwm.h" +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME pwm + +#if PWM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL PWM_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR PWM_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR PWM_CONFIG_DEBUG_COLOR +#else //PWM_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //PWM_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if NRF_MODULE_ENABLED(PWM_NRF52_ANOMALY_109_WORKAROUND) +// The workaround uses interrupts to wake up the CPU and ensure it is active +// when PWM is about to start a DMA transfer. For initial transfer, done when +// a playback is started via PPI, a specific EGU instance is used to generate +// an interrupt. During the playback, the PWM interrupt triggered on SEQEND +// event of a preceding sequence is used to protect the transfer done for +// the next sequence to be played. +#include "nrf_egu.h" +#define USE_DMA_ISSUE_WORKAROUND +#endif +#if defined(USE_DMA_ISSUE_WORKAROUND) +#define EGU_IRQn(i) EGU_IRQn_(i) +#define EGU_IRQn_(i) SWI##i##_EGU##i##_IRQn +#define EGU_IRQHandler(i) EGU_IRQHandler_(i) +#define EGU_IRQHandler_(i) SWI##i##_EGU##i##_IRQHandler +#define DMA_ISSUE_EGU_IDX PWM_NRF52_ANOMALY_109_EGU_INSTANCE +#define DMA_ISSUE_EGU CONCAT_2(NRF_EGU, DMA_ISSUE_EGU_IDX) +#define DMA_ISSUE_EGU_IRQn EGU_IRQn(DMA_ISSUE_EGU_IDX) +#define DMA_ISSUE_EGU_IRQHandler EGU_IRQHandler(DMA_ISSUE_EGU_IDX) +#endif + +// Control block - driver instance local data. +typedef struct +{ +#if defined(USE_DMA_ISSUE_WORKAROUND) + uint32_t starting_task_address; +#endif + nrf_drv_pwm_handler_t handler; + nrf_drv_state_t volatile state; + uint8_t flags; +} pwm_control_block_t; +static pwm_control_block_t m_cb[ENABLED_PWM_COUNT]; + +static void configure_pins(nrf_drv_pwm_t const * const p_instance, + nrf_drv_pwm_config_t const * p_config) +{ + uint32_t out_pins[NRF_PWM_CHANNEL_COUNT]; + uint8_t i; + + for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i) + { + uint8_t output_pin = p_config->output_pins[i]; + if (output_pin != NRF_DRV_PWM_PIN_NOT_USED) + { + bool inverted = output_pin & NRF_DRV_PWM_PIN_INVERTED; + out_pins[i] = output_pin & ~NRF_DRV_PWM_PIN_INVERTED; + + if (inverted) + { + nrf_gpio_pin_set(out_pins[i]); + } + else + { + nrf_gpio_pin_clear(out_pins[i]); + } + + nrf_gpio_cfg_output(out_pins[i]); + } + else + { + out_pins[i] = NRF_PWM_PIN_NOT_CONNECTED; + } + } + + nrf_pwm_pins_set(p_instance->p_registers, out_pins); +} + + +ret_code_t nrf_drv_pwm_init(nrf_drv_pwm_t const * const p_instance, + nrf_drv_pwm_config_t const * p_config, + nrf_drv_pwm_handler_t handler) +{ + ASSERT(p_config); + + ret_code_t err_code; + + pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + p_cb->handler = handler; + + configure_pins(p_instance, p_config); + + nrf_pwm_enable(p_instance->p_registers); + nrf_pwm_configure(p_instance->p_registers, + p_config->base_clock, p_config->count_mode, p_config->top_value); + nrf_pwm_decoder_set(p_instance->p_registers, + p_config->load_mode, p_config->step_mode); + + nrf_pwm_shorts_set(p_instance->p_registers, 0); + nrf_pwm_int_set(p_instance->p_registers, 0); + nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_LOOPSDONE); + nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND0); + nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_SEQEND1); + nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED); + + // The workaround for nRF52 Anomaly 109 "protects" DMA transfers by handling + // interrupts generated on SEQEND0 and SEQEND1 events (this ensures that + // the 64 MHz clock is ready when data for the next sequence to be played + // is read). Therefore, the PWM interrupt must be enabled even if the event + // handler is not used. +#if defined(USE_DMA_ISSUE_WORKAROUND) + nrf_drv_common_irq_enable(DMA_ISSUE_EGU_IRQn, p_config->irq_priority); +#else + if (p_cb->handler) +#endif + { + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(p_instance->p_registers), + p_config->irq_priority); + } + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_pwm_uninit(nrf_drv_pwm_t const * const p_instance) +{ + pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_instance->p_registers)); +#if defined(USE_DMA_ISSUE_WORKAROUND) + nrf_drv_common_irq_disable(DMA_ISSUE_EGU_IRQn); +#endif + + nrf_pwm_disable(p_instance->p_registers); + + p_cb->state = NRF_DRV_STATE_UNINITIALIZED; +} + + +static uint32_t start_playback(nrf_drv_pwm_t const * const p_instance, + pwm_control_block_t * p_cb, + uint8_t flags, + nrf_pwm_task_t starting_task) +{ + p_cb->state = NRF_DRV_STATE_POWERED_ON; + p_cb->flags = flags; + + if (p_cb->handler) + { + // The notification about finished playback is by default enabled, + // but this can be suppressed. + // The notification that the peripheral has stopped is always enabled. + uint32_t int_mask = NRF_PWM_INT_LOOPSDONE_MASK | + NRF_PWM_INT_STOPPED_MASK; + + // The workaround for nRF52 Anomaly 109 "protects" DMA transfers by + // handling interrupts generated on SEQEND0 and SEQEND1 events (see + // 'nrf_drv_pwm_init'), hence these events must be always enabled + // to generate interrupts. + // However, the user handler is called for them only when requested + // (see 'irq_handler'). +#if defined(USE_DMA_ISSUE_WORKAROUND) + int_mask |= NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK; +#else + if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0) + { + int_mask |= NRF_PWM_INT_SEQEND0_MASK; + } + if (flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1) + { + int_mask |= NRF_PWM_INT_SEQEND1_MASK; + } +#endif + if (flags & NRF_DRV_PWM_FLAG_NO_EVT_FINISHED) + { + int_mask &= ~NRF_PWM_INT_LOOPSDONE_MASK; + } + + nrf_pwm_int_set(p_instance->p_registers, int_mask); + } +#if defined(USE_DMA_ISSUE_WORKAROUND) + else + { + nrf_pwm_int_set(p_instance->p_registers, + NRF_PWM_INT_SEQEND0_MASK | NRF_PWM_INT_SEQEND1_MASK); + } +#endif + + nrf_pwm_event_clear(p_instance->p_registers, NRF_PWM_EVENT_STOPPED); + + if (flags & NRF_DRV_PWM_FLAG_START_VIA_TASK) + { + uint32_t starting_task_address = + nrf_pwm_task_address_get(p_instance->p_registers, starting_task); + +#if defined(USE_DMA_ISSUE_WORKAROUND) + // To "protect" the initial DMA transfer it is required to start + // the PWM by triggering the proper task from EGU interrupt handler, + // it is not safe to do it directly via PPI. + p_cb->starting_task_address = starting_task_address; + nrf_egu_int_enable(DMA_ISSUE_EGU, + nrf_egu_int_get(DMA_ISSUE_EGU, p_instance->drv_inst_idx)); + return (uint32_t)nrf_egu_task_trigger_address_get(DMA_ISSUE_EGU, + p_instance->drv_inst_idx); +#else + return starting_task_address; +#endif + } + + nrf_pwm_task_trigger(p_instance->p_registers, starting_task); + return 0; +} + + +uint32_t nrf_drv_pwm_simple_playback(nrf_drv_pwm_t const * const p_instance, + nrf_pwm_sequence_t const * p_sequence, + uint16_t playback_count, + uint32_t flags) +{ + pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(playback_count > 0); + ASSERT(nrf_drv_is_in_RAM(p_sequence->values.p_raw)); + + // To take advantage of the looping mechanism, we need to use both sequences + // (single sequence can be played back only once). + nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence); + nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence); + bool odd = (playback_count & 1); + nrf_pwm_loop_set(p_instance->p_registers, + (playback_count / 2) + (odd ? 1 : 0)); + + uint32_t shorts_mask; + if (flags & NRF_DRV_PWM_FLAG_STOP) + { + shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK; + } + else if (flags & NRF_DRV_PWM_FLAG_LOOP) + { + shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK + : NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; + } + else + { + shorts_mask = 0; + } + nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask); + + NRF_LOG_INFO("Function: %s, sequence length: %d.", + (uint32_t)__func__, + p_sequence->length); + NRF_LOG_DEBUG("Sequence data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence->values.p_raw, + p_sequence->length * sizeof(uint16_t)); + return start_playback(p_instance, p_cb, flags, + odd ? NRF_PWM_TASK_SEQSTART1 : NRF_PWM_TASK_SEQSTART0); +} + + +uint32_t nrf_drv_pwm_complex_playback(nrf_drv_pwm_t const * const p_instance, + nrf_pwm_sequence_t const * p_sequence_0, + nrf_pwm_sequence_t const * p_sequence_1, + uint16_t playback_count, + uint32_t flags) +{ + pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(playback_count > 0); + ASSERT(nrf_drv_is_in_RAM(p_sequence_0->values.p_raw)); + ASSERT(nrf_drv_is_in_RAM(p_sequence_1->values.p_raw)); + + nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence_0); + nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence_1); + nrf_pwm_loop_set(p_instance->p_registers, playback_count); + + uint32_t shorts_mask; + if (flags & NRF_DRV_PWM_FLAG_STOP) + { + shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK; + } + else if (flags & NRF_DRV_PWM_FLAG_LOOP) + { + shorts_mask = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; + } + else + { + shorts_mask = 0; + } + nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask); + + NRF_LOG_INFO("Function: %s, sequence 0 length: %d.", + (uint32_t)__func__, + p_sequence_0->length); + NRF_LOG_INFO("Function: %s, sequence 1 length: %d.", + (uint32_t)__func__, + p_sequence_1->length); + NRF_LOG_DEBUG("Sequence 0 data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence_0->values.p_raw, + p_sequence_0->length * sizeof(uint16_t)); + NRF_LOG_DEBUG("Sequence 1 data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence_1->values.p_raw, + p_sequence_1->length * sizeof(uint16_t)); + return start_playback(p_instance, p_cb, flags, NRF_PWM_TASK_SEQSTART0); +} + + +bool nrf_drv_pwm_stop(nrf_drv_pwm_t const * const p_instance, + bool wait_until_stopped) +{ + ASSERT(m_cb[p_instance->drv_inst_idx].state != NRF_DRV_STATE_UNINITIALIZED); + + bool ret_val = false; + + if (nrf_drv_pwm_is_stopped(p_instance)) + { + ret_val = true; + } + else + { + nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_STOP); + + do { + if (nrf_drv_pwm_is_stopped(p_instance)) + { + ret_val = true; + break; + } + } while (wait_until_stopped); + } + + NRF_LOG_INFO("%s returned %d.", (uint32_t)__func__, ret_val); + return ret_val; +} + + +bool nrf_drv_pwm_is_stopped(nrf_drv_pwm_t const * const p_instance) +{ + pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + bool ret_val = false; + + // If the event handler is used (interrupts are enabled), the state will + // be changed in interrupt handler when the STOPPED event occurs. + if (p_cb->state != NRF_DRV_STATE_POWERED_ON) + { + ret_val = true; + } + // If interrupts are disabled, we must check the STOPPED event here. + if (nrf_pwm_event_check(p_instance->p_registers, NRF_PWM_EVENT_STOPPED)) + { + p_cb->state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled."); + ret_val = true; + } + + NRF_LOG_INFO("%s returned %d.", (uint32_t)__func__, ret_val); + return ret_val; +} + + +static void irq_handler(NRF_PWM_Type * p_pwm, pwm_control_block_t * p_cb) +{ + // The user handler is called for SEQEND0 and SEQEND1 events only when the + // user asks for it (by setting proper flags when starting the playback). + if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND0)) + { + nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND0); + if ((p_cb->flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0) && p_cb->handler) + { + p_cb->handler(NRF_DRV_PWM_EVT_END_SEQ0); + } + } + if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_SEQEND1)) + { + nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_SEQEND1); + if ((p_cb->flags & NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1) && p_cb->handler) + { + p_cb->handler(NRF_DRV_PWM_EVT_END_SEQ1); + } + } + // For LOOPSDONE the handler is called by default, but the user can disable + // this (via flags). + if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_LOOPSDONE)) + { + nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_LOOPSDONE); + if (!(p_cb->flags & NRF_DRV_PWM_FLAG_NO_EVT_FINISHED) && p_cb->handler) + { + p_cb->handler(NRF_DRV_PWM_EVT_FINISHED); + } + } + + // The STOPPED event is always propagated to the user handler. + if (nrf_pwm_event_check(p_pwm, NRF_PWM_EVENT_STOPPED)) + { + nrf_pwm_event_clear(p_pwm, NRF_PWM_EVENT_STOPPED); + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + if (p_cb->handler) + { + p_cb->handler(NRF_DRV_PWM_EVT_STOPPED); + } + } +} + + +#if defined(USE_DMA_ISSUE_WORKAROUND) +// See 'start_playback' why this is needed. +void DMA_ISSUE_EGU_IRQHandler(void) +{ + int i; + for (i = 0; i < ENABLED_PWM_COUNT; ++i) + { + volatile uint32_t * p_event_reg = + nrf_egu_event_triggered_address_get(DMA_ISSUE_EGU, i); + if (*p_event_reg) + { + *p_event_reg = 0; + *(volatile uint32_t *)(m_cb[i].starting_task_address) = 1; + } + } +} +#endif + +#if NRF_MODULE_ENABLED(PWM0) && defined (PWM0_CH_NUM) +void PWM0_IRQHandler(void) +{ + irq_handler(NRF_PWM0, &m_cb[PWM0_INSTANCE_INDEX]); +} +#endif + +#if NRF_MODULE_ENABLED(PWM1) && defined (PWM1_CH_NUM) +void PWM1_IRQHandler(void) +{ + irq_handler(NRF_PWM1, &m_cb[PWM1_INSTANCE_INDEX]); +} +#endif + +#if NRF_MODULE_ENABLED(PWM2) && defined (PWM2_CH_NUM) +void PWM2_IRQHandler(void) +{ + irq_handler(NRF_PWM2, &m_cb[PWM2_INSTANCE_INDEX]); +} +#endif + +#if PWM3_ENABLED && defined (PWM3_CH_NUM) +void PWM3_IRQHandler(void) +{ + irq_handler(NRF_PWM3, &m_cb[PWM3_INSTANCE_INDEX]); +} +#endif + +#endif //ENABLED_PWM_COUNT +#endif //NRF_MODULE_ENABLED(PWM) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.h new file mode 100644 index 0000000000..a5cece0c66 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/pwm/nrf_drv_pwm.h @@ -0,0 +1,512 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_pwm PWM HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52 Pulse Width Modulation (PWM) module APIs. + * + * @defgroup nrf_drv_pwm PWM driver + * @{ + * @ingroup nrf_pwm + * @brief @tagAPI52 Pulse Width Modulation (PWM) module driver. + */ + + +#ifndef NRF_DRV_PWM_H__ +#define NRF_DRV_PWM_H__ + +#include "nordic_common.h" +#include "sdk_config.h" +#include "nrf_pwm.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PWM0_ENABLED +#define PWM0_ENABLED 0 +#endif +#ifndef PWM1_ENABLED +#define PWM1_ENABLED 0 +#endif +#ifndef PWM2_ENABLED +#define PWM2_ENABLED 0 +#endif +#ifndef PWM3_ENABLED +#define PWM3_ENABLED 0 +#endif +/** + * @brief PWM driver instance data structure. + */ +typedef struct +{ + NRF_PWM_Type * p_registers; ///< Pointer to the structure with PWM peripheral instance registers. + uint8_t drv_inst_idx; ///< Driver instance index. +} nrf_drv_pwm_t; + +#define PWM0_INSTANCE_INDEX 0 +#define PWM1_INSTANCE_INDEX PWM0_INSTANCE_INDEX+PWM0_ENABLED +#define PWM2_INSTANCE_INDEX PWM1_INSTANCE_INDEX+PWM1_ENABLED +#define PWM3_INSTANCE_INDEX PWM2_INSTANCE_INDEX+PWM2_ENABLED + +/** + * @brief Macro for creating a PWM driver instance. + */ +#define NRF_DRV_PWM_INSTANCE(id) \ +{ \ + .p_registers = CONCAT_2(NRF_PWM, id), \ + .drv_inst_idx = CONCAT_3(PWM, id, _INSTANCE_INDEX), \ +} + + +/** + * @brief This value can be provided instead of a pin number for any channel + * to specify that its output is not used and therefore does not need + * to be connected to a pin. + */ +#define NRF_DRV_PWM_PIN_NOT_USED 0xFF + +/** + * @brief This value can be added to a pin number to inverse its polarity + * (set idle state = 1). + */ +#define NRF_DRV_PWM_PIN_INVERTED 0x80 + +/** + * @brief PWM driver configuration structure. + */ +typedef struct +{ + uint8_t output_pins[NRF_PWM_CHANNEL_COUNT]; ///< Pin numbers for individual output channels (optional). + /**< Use @ref NRF_DRV_PWM_PIN_NOT_USED + * if a given output channel is not needed. */ + uint8_t irq_priority; ///< Interrupt priority. + nrf_pwm_clk_t base_clock; ///< Base clock frequency. + nrf_pwm_mode_t count_mode; ///< Operating mode of the pulse generator counter. + uint16_t top_value; ///< Value up to which the pulse generator counter counts. + nrf_pwm_dec_load_t load_mode; ///< Mode of loading sequence data from RAM. + nrf_pwm_dec_step_t step_mode; ///< Mode of advancing the active sequence. +} nrf_drv_pwm_config_t; + +/** + * @brief PWM driver default configuration. + */ +#define NRF_DRV_PWM_DEFAULT_CONFIG \ +{ \ + .output_pins = {PWM_DEFAULT_CONFIG_OUT0_PIN, \ + PWM_DEFAULT_CONFIG_OUT1_PIN, \ + PWM_DEFAULT_CONFIG_OUT2_PIN, \ + PWM_DEFAULT_CONFIG_OUT3_PIN }, \ + .irq_priority = PWM_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .base_clock = (nrf_pwm_clk_t)PWM_DEFAULT_CONFIG_BASE_CLOCK, \ + .count_mode = (nrf_pwm_mode_t)PWM_DEFAULT_CONFIG_COUNT_MODE, \ + .top_value = PWM_DEFAULT_CONFIG_TOP_VALUE, \ + .load_mode = (nrf_pwm_dec_load_t)PWM_DEFAULT_CONFIG_LOAD_MODE, \ + .step_mode = (nrf_pwm_dec_step_t)PWM_DEFAULT_CONFIG_STEP_MODE, \ +} + + +/** + * @brief PWM flags providing additional playback options. + */ +typedef enum +{ + NRF_DRV_PWM_FLAG_STOP = 0x01, /**< When the requested playback is finished, + the peripheral should be stopped. + @note The STOP task is triggered when + the last value of the final sequence is + loaded from RAM, and the peripheral stops + at the end of the current PWM period. + For sequences with configured repeating + of duty cycle values, this might result in + less than the requested number of repeats + of the last value. */ + NRF_DRV_PWM_FLAG_LOOP = 0x02, /**< When the requested playback is finished, + it should be started from the beginning. + This flag is ignored if used together + with @ref NRF_DRV_PWM_FLAG_STOP. + @note The playback restart is done via a + shortcut configured in the PWM peripheral. + This shortcut triggers the proper starting + task when the final value of previous + playback is read from RAM and applied to + the pulse generator counter. + When this mechanism is used together with + the @ref NRF_PWM_STEP_TRIGGERED mode, + the playback restart will occur right + after switching to the final value (this + final value will be played only once). */ + NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 = 0x04, /**< The event handler should be + called when the last value + from sequence 0 is loaded. */ + NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 = 0x08, /**< The event handler should be + called when the last value + from sequence 1 is loaded. */ + NRF_DRV_PWM_FLAG_NO_EVT_FINISHED = 0x10, /**< The playback finished event + (enabled by default) should be + suppressed. */ + NRF_DRV_PWM_FLAG_START_VIA_TASK = 0x80, /**< The playback should not be + started directly by the called + function. Instead, the function + should only prepare it and + return the address of the task + to be triggered to start the + playback. */ +} nrf_drv_pwm_flag_t; + + +/** + * @brief PWM driver event type. + */ +typedef enum +{ + NRF_DRV_PWM_EVT_FINISHED, ///< Sequence playback finished. + NRF_DRV_PWM_EVT_END_SEQ0, /**< End of sequence 0 reached. Its data can be + safely modified now. */ + NRF_DRV_PWM_EVT_END_SEQ1, /**< End of sequence 1 reached. Its data can be + safely modified now. */ + NRF_DRV_PWM_EVT_STOPPED, ///< The PWM peripheral has been stopped. +} nrf_drv_pwm_evt_type_t; + +/** + * @brief PWM driver event handler type. + */ +typedef void (* nrf_drv_pwm_handler_t)(nrf_drv_pwm_evt_type_t event_type); + + +/** + * @brief Function for initializing the PWM driver. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Pointer to the structure with initial configuration. + * + * @param[in] handler Event handler provided by the user. If NULL is passed + * instead, event notifications are not done and PWM + * interrupts are disabled. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + */ +ret_code_t nrf_drv_pwm_init(nrf_drv_pwm_t const * const p_instance, + nrf_drv_pwm_config_t const * p_config, + nrf_drv_pwm_handler_t handler); + +/** + * @brief Function for uninitializing the PWM driver. + * + * If any sequence playback is in progress, it is stopped immediately. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_pwm_uninit(nrf_drv_pwm_t const * const p_instance); + +/** + * @brief Function for starting a single sequence playback. + * + * To take advantage of the looping mechanism in the PWM peripheral, both + * sequences must be used (single sequence can be played back only once by + * the peripheral). Therefore, the provided sequence is internally set and + * played back as both sequence 0 and sequence 1. Consequently, if end of + * sequence notifications are required, events for both sequences should be + * used (that means that both the @ref NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 flag + * and the @ref NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 flag should be specified and + * the @ref NRF_DRV_PWM_EVT_END_SEQ0 event and the @ref NRF_DRV_PWM_EVT_END_SEQ1 + * event should be handled in the same way). + * + * Use the @ref NRF_DRV_PWM_FLAG_START_VIA_TASK flag if you want the playback + * to be only prepared by this function, and you want to start it later by + * triggering a task (using PPI for instance). The function will then return + * the address of the task to be triggered. + * + * @note The array containing the duty cycle values for the specified sequence + * must be in RAM and cannot be allocated on stack. + * For detailed information, see @ref nrf_pwm_sequence_t. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_sequence Sequence to be played back. + * @param[in] playback_count Number of playbacks to be performed (must not be 0). + * @param[in] flags Additional options. Pass any combination of + * @ref nrf_drv_pwm_flag_t "playback flags", or 0 + * for default settings. + * + * @return Address of the task to be triggered to start the playback if the @ref + * NRF_DRV_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise. + */ +uint32_t nrf_drv_pwm_simple_playback(nrf_drv_pwm_t const * const p_instance, + nrf_pwm_sequence_t const * p_sequence, + uint16_t playback_count, + uint32_t flags); + +/** + * @brief Function for starting a two-sequence playback. + * + * Use the @ref NRF_DRV_PWM_FLAG_START_VIA_TASK flag if you want the playback + * to be only prepared by this function, and you want to start it later by + * triggering a task (using PPI for instance). The function will then return + * the address of the task to be triggered. + * + * @note The array containing the duty cycle values for the specified sequence + * must be in RAM and cannot be allocated on stack. + * For detailed information, see @ref nrf_pwm_sequence_t. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_sequence_0 First sequence to be played back. + * @param[in] p_sequence_1 Second sequence to be played back. + * @param[in] playback_count Number of playbacks to be performed (must not be 0). + * @param[in] flags Additional options. Pass any combination of + * @ref nrf_drv_pwm_flag_t "playback flags", or 0 + * for default settings. + * + * @return Address of the task to be triggered to start the playback if the @ref + * NRF_DRV_PWM_FLAG_START_VIA_TASK flag was used, 0 otherwise. + */ +uint32_t nrf_drv_pwm_complex_playback(nrf_drv_pwm_t const * const p_instance, + nrf_pwm_sequence_t const * p_sequence_0, + nrf_pwm_sequence_t const * p_sequence_1, + uint16_t playback_count, + uint32_t flags); + +/** + * @brief Function for advancing the active sequence. + * + * This function only applies to @ref NRF_PWM_STEP_TRIGGERED mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE void nrf_drv_pwm_step(nrf_drv_pwm_t const * const p_instance); + +/** + * @brief Function for stopping the sequence playback. + * + * The playback is stopped at the end of the current PWM period. + * This means that if the active sequence is configured to repeat each duty + * cycle value for a certain number of PWM periods, the last played value + * might appear on the output less times than requested. + * + * @note This function can be instructed to wait until the playback is stopped + * (by setting @p wait_until_stopped to true). Note that, depending on + * the length of the PMW period, this might take a significant amount of + * time. Alternatively, the @ref nrf_drv_pwm_is_stopped function can be + * used to poll the status, or the @ref NRF_DRV_PWM_EVT_STOPPED event can + * be used to get the notification when the playback is stopped, provided + * the event handler is defined. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] wait_until_stopped If true, the function will not return until + * the playback is stopped. + * + * @retval true If the PWM peripheral is stopped. + * @retval false If the PWM peripheral is not stopped. + */ +bool nrf_drv_pwm_stop(nrf_drv_pwm_t const * const p_instance, + bool wait_until_stopped); + +/** + * @brief Function for checking the status of the PWM peripheral. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If the PWM peripheral is stopped. + * @retval false If the PWM peripheral is not stopped. + */ +bool nrf_drv_pwm_is_stopped(nrf_drv_pwm_t const * const p_instance); + +/** + * @brief Function for updating the sequence data during playback. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] p_sequence Pointer to the new sequence definition. + */ +__STATIC_INLINE void nrf_drv_pwm_sequence_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + nrf_pwm_sequence_t const * p_sequence); + +/** + * @brief Function for updating the pointer to the duty cycle values + * in the specified sequence during playback. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] values New pointer to the duty cycle values. + */ +__STATIC_INLINE void nrf_drv_pwm_sequence_values_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + nrf_pwm_values_t values); + +/** + * @brief Function for updating the number of duty cycle values + * in the specified sequence during playback. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] length New number of the duty cycle values. + */ +__STATIC_INLINE void nrf_drv_pwm_sequence_length_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint16_t length); + +/** + * @brief Function for updating the number of repeats for duty cycle values + * in specified sequence during playback. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] repeats New number of repeats. + */ +__STATIC_INLINE void nrf_drv_pwm_sequence_repeats_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint32_t repeats); + +/** + * @brief Function for updating the additional delay after the specified + * sequence during playback. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] seq_id Identifier of the sequence (0 or 1). + * @param[in] end_delay New end delay value (in PWM periods). + */ +__STATIC_INLINE void nrf_drv_pwm_sequence_end_delay_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint32_t end_delay); + +/** + * @brief Function for returning the address of a specified PWM task that can + * be used in PPI module. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] task Requested task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_pwm_task_address_get( + nrf_drv_pwm_t const * const p_instance, + nrf_pwm_task_t task); + +/**@brief Function for returning the address of a specified PWM event that can + * be used in PPI module. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] event Requested event. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_pwm_event_address_get( + nrf_drv_pwm_t const * const p_instance, + nrf_pwm_event_t event); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_drv_pwm_step(nrf_drv_pwm_t const * const p_instance) +{ + nrf_pwm_task_trigger(p_instance->p_registers, NRF_PWM_TASK_NEXTSTEP); +} + +__STATIC_INLINE void nrf_drv_pwm_sequence_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + nrf_pwm_sequence_t const * p_sequence) +{ + nrf_pwm_sequence_set(p_instance->p_registers, seq_id, p_sequence); +} + +__STATIC_INLINE void nrf_drv_pwm_sequence_values_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + nrf_pwm_values_t values) +{ + nrf_pwm_seq_ptr_set(p_instance->p_registers, seq_id, values.p_raw); +} + +__STATIC_INLINE void nrf_drv_pwm_sequence_length_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint16_t length) +{ + nrf_pwm_seq_cnt_set(p_instance->p_registers, seq_id, length); +} + +__STATIC_INLINE void nrf_drv_pwm_sequence_repeats_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint32_t repeats) +{ + nrf_pwm_seq_refresh_set(p_instance->p_registers, seq_id, repeats); +} + +__STATIC_INLINE void nrf_drv_pwm_sequence_end_delay_update( + nrf_drv_pwm_t const * const p_instance, + uint8_t seq_id, + uint32_t end_delay) +{ + nrf_pwm_seq_end_delay_set(p_instance->p_registers, seq_id, end_delay); +} + +__STATIC_INLINE uint32_t nrf_drv_pwm_task_address_get( + nrf_drv_pwm_t const * const p_instance, + nrf_pwm_task_t task) +{ + return nrf_pwm_task_address_get(p_instance->p_registers, task); +} + +__STATIC_INLINE uint32_t nrf_drv_pwm_event_address_get( + nrf_drv_pwm_t const * const p_instance, + nrf_pwm_event_t event) +{ + return nrf_pwm_event_address_get(p_instance->p_registers, event); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_PWM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.c new file mode 100644 index 0000000000..33fdfafc9d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.c @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(QDEC) +#include +#include + +#include "nrf.h" +#include "nrf_gpio.h" +#include "nrf_error.h" +#include "nrf_assert.h" +#include "nrf_drv_common.h" +#include "nrf_drv_qdec.h" +#include "app_util_platform.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME qdec + +#if QDEC_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL QDEC_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR QDEC_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR QDEC_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_QDEC_EVENT_SAMPLERDY ? "NRF_QDEC_EVENT_SAMPLERDY" : \ + (event == NRF_QDEC_EVENT_REPORTRDY ? "NRF_QDEC_EVENT_REPORTRDY" : \ + (event == NRF_QDEC_EVENT_ACCOF ? "NRF_QDEC_EVENT_ACCOF" : "UNKNOWN EVENT"))) +#else //QDEC_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //QDEC_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +static qdec_event_handler_t m_qdec_event_handler = NULL; +static const nrf_drv_qdec_config_t m_default_config = NRF_DRV_QDEC_DEFAULT_CONFIG; +static nrf_drv_state_t m_state = NRF_DRV_STATE_UNINITIALIZED; + +void QDEC_IRQHandler(void) +{ + nrf_drv_qdec_event_t event; + if ( nrf_qdec_event_check(NRF_QDEC_EVENT_SAMPLERDY) && + nrf_qdec_int_enable_check(NRF_QDEC_INT_SAMPLERDY_MASK) ) + { + nrf_qdec_event_clear(NRF_QDEC_EVENT_SAMPLERDY); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_QDEC_EVENT_SAMPLERDY)); + + event.type = NRF_QDEC_EVENT_SAMPLERDY; + event.data.sample.value = (int8_t)nrf_qdec_sample_get(); + m_qdec_event_handler(event); + } + + if ( nrf_qdec_event_check(NRF_QDEC_EVENT_REPORTRDY) && + nrf_qdec_int_enable_check(NRF_QDEC_INT_REPORTRDY_MASK) ) + { + nrf_qdec_event_clear(NRF_QDEC_EVENT_REPORTRDY); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_QDEC_INT_REPORTRDY_MASK)); + + event.type = NRF_QDEC_EVENT_REPORTRDY; + + event.data.report.acc = (int16_t)nrf_qdec_accread_get(); + event.data.report.accdbl = (uint16_t)nrf_qdec_accdblread_get(); + m_qdec_event_handler(event); + } + + if ( nrf_qdec_event_check(NRF_QDEC_EVENT_ACCOF) && + nrf_qdec_int_enable_check(NRF_QDEC_INT_ACCOF_MASK) ) + { + nrf_qdec_event_clear(NRF_QDEC_EVENT_ACCOF); + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_QDEC_EVENT_ACCOF)); + + event.type = NRF_QDEC_EVENT_ACCOF; + m_qdec_event_handler(event); + } +} + + +ret_code_t nrf_drv_qdec_init(const nrf_drv_qdec_config_t * p_config, + qdec_event_handler_t event_handler) +{ + ret_code_t err_code; + + if (m_state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + + if (event_handler) + { + m_qdec_event_handler = event_handler; + } + else + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_qdec_sampleper_set(p_config->sampleper); + nrf_gpio_cfg_input(p_config->pselled, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(p_config->psela, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(p_config->pselb, NRF_GPIO_PIN_NOPULL); + nrf_qdec_pio_assign( p_config->psela, p_config->pselb, p_config->pselled); + nrf_qdec_ledpre_set(p_config->ledpre); + nrf_qdec_ledpol_set(p_config->ledpol); + nrf_qdec_shorts_enable(NRF_QDEC_SHORT_REPORTRDY_READCLRACC_MASK); + + if (p_config->dbfen) + { + nrf_qdec_dbfen_enable(); + } + else + { + nrf_qdec_dbfen_disable(); + } + + uint32_t int_mask = NRF_QDEC_INT_ACCOF_MASK; + + if (p_config->reportper != NRF_QDEC_REPORTPER_DISABLED) + { + nrf_qdec_reportper_set(p_config->reportper); + int_mask |= NRF_QDEC_INT_REPORTRDY_MASK; + } + + if (p_config->sample_inten) + { + int_mask |= NRF_QDEC_INT_SAMPLERDY_MASK; + } + + nrf_qdec_int_enable(int_mask); + nrf_drv_common_irq_enable(QDEC_IRQn, p_config->interrupt_priority); + + m_state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_qdec_uninit(void) +{ + ASSERT(m_state != NRF_DRV_STATE_UNINITIALIZED); + nrf_drv_qdec_disable(); + nrf_drv_common_irq_disable(QDEC_IRQn); + m_state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_qdec_enable(void) +{ + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + nrf_qdec_enable(); + nrf_qdec_task_trigger(NRF_QDEC_TASK_START); + m_state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled."); +} + +void nrf_drv_qdec_disable(void) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_qdec_task_trigger(NRF_QDEC_TASK_STOP); + nrf_qdec_disable(); + m_state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled."); +} + +void nrf_drv_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_qdec_task_trigger(NRF_QDEC_TASK_READCLRACC); + + *p_acc = (int16_t)nrf_qdec_accread_get(); + *p_accdbl = (int16_t)nrf_qdec_accdblread_get(); + + NRF_LOG_DEBUG("Accumulators data, ACC register:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_acc, sizeof(p_acc[0])); + NRF_LOG_DEBUG("Accumulators data, ACCDBL register:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_accdbl, sizeof(p_accdbl[0])); +} + +void nrf_drv_qdec_task_address_get(nrf_qdec_task_t task, uint32_t * p_task) +{ + *p_task = (uint32_t)nrf_qdec_task_address_get(task); +} + +void nrf_drv_qdec_event_address_get(nrf_qdec_event_t event, uint32_t * p_event) +{ + *p_event = (uint32_t)nrf_qdec_event_address_get(event); +} + +#endif //NRF_MODULE_ENABLED(QDEC) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.h new file mode 100644 index 0000000000..8327d287b1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qdec/nrf_drv_qdec.h @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_QDEC_H__ +#define NRF_DRV_QDEC_H__ + +#include "nrf_qdec.h" +#include "sdk_config.h" +#include "sdk_errors.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup nrf_qdec QDEC HAL and driver + * @ingroup nrf_drivers + * @brief Quadrature decoder (QDEC) APIs. + * @details The QDEC HAL provides basic APIs for accessing the registers of the QDEC. + * The QDEC driver provides APIs on a higher level. + * + * @defgroup nrf_drv_qdec QDEC driver + * @{ + * @ingroup nrf_qdec + * @brief Quadrature decoder (QDEC) driver. + */ + +/**@brief QDEC configuration structure.*/ +typedef struct +{ + nrf_qdec_reportper_t reportper; /**< Report period in samples. */ + nrf_qdec_sampleper_t sampleper; /**< Sampling period in microseconds. */ + uint32_t psela; /**< Pin number for A input. */ + uint32_t pselb; /**< Pin number for B input. */ + uint32_t pselled; /**< Pin number for LED output. */ + uint32_t ledpre; /**< Time (in microseconds) how long LED is switched on before sampling. */ + nrf_qdec_ledpol_t ledpol; /**< Active LED polarity. */ + bool dbfen; /**< State of debouncing filter. */ + bool sample_inten; /**< Enabling sample ready interrupt. */ + uint8_t interrupt_priority; /**< QDEC interrupt priority. */ +} nrf_drv_qdec_config_t; + +/**@brief QDEC default configuration. */ +#define NRF_DRV_QDEC_DEFAULT_CONFIG \ + { \ + .reportper = (nrf_qdec_reportper_t)QDEC_CONFIG_REPORTPER, \ + .sampleper = (nrf_qdec_sampleper_t)QDEC_CONFIG_SAMPLEPER, \ + .psela = QDEC_CONFIG_PIO_A, \ + .pselb = QDEC_CONFIG_PIO_B, \ + .pselled = QDEC_CONFIG_PIO_LED, \ + .ledpre = QDEC_CONFIG_LEDPRE, \ + .ledpol = (nrf_qdec_ledpol_t)QDEC_CONFIG_LEDPOL, \ + .interrupt_priority = QDEC_CONFIG_IRQ_PRIORITY, \ + .dbfen = QDEC_CONFIG_DBFEN, \ + .sample_inten = QDEC_CONFIG_SAMPLE_INTEN \ + } + +/**@brief QDEC sample event data.*/ +typedef struct +{ + int8_t value; /**< Sample value. */ +} nrf_drv_qdec_sample_data_evt_t; + +/**@brief QDEC report event data.*/ +typedef struct +{ + int16_t acc; /**< Accumulated transitions. */ + uint16_t accdbl; /**< Accumulated double transitions. */ +} nrf_drv_qdec_report_data_evt_t; + +/**@brief QDEC event handler structure. */ +typedef struct +{ + nrf_qdec_event_t type; + union + { + nrf_drv_qdec_sample_data_evt_t sample; /**< Sample event data. */ + nrf_drv_qdec_report_data_evt_t report; /**< Report event data. */ + } data; +} nrf_drv_qdec_event_t; + +/**@brief QDEC event handler. + * @param[in] event QDEC event structure. + */ +typedef void (*qdec_event_handler_t)(nrf_drv_qdec_event_t event); + +/**@brief Function for initializing QDEC. + * + * @param[in] p_config Pointer to configuration parameters. + * @param[in] event_handler Event handler function. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_PARAM If invalid parameters were supplied. + * @retval NRF_ERROR_INVALID_STATE If QDEC was already initialized. + */ +ret_code_t nrf_drv_qdec_init(nrf_drv_qdec_config_t const * p_config, + qdec_event_handler_t event_handler); + +/**@brief Function for uninitializing QDEC. + * @note Function asserts if module is uninitialized. + */ +void nrf_drv_qdec_uninit(void); + +/**@brief Function for enabling QDEC. + * @note Function asserts if module is uninitialized or enabled. + */ +void nrf_drv_qdec_enable(void); + +/**@brief Function for disabling QDEC. + * @note Function asserts if module is uninitialized or disabled. + */ +void nrf_drv_qdec_disable(void); + +/**@brief Function for reading accumulated transitions QDEC. + * @note Function asserts if module is not enabled. + * @note Accumulators are cleared after reading. + * + * @param[out] p_acc Pointer to store accumulated transitions. + * @param[out] p_accdbl Pointer to store accumulated double transitions. + */ +void nrf_drv_qdec_accumulators_read(int16_t * p_acc, int16_t * p_accdbl); + +/** + * @brief Function for returning the address of a specific timer task. + * + * @param[in] task QDEC task. + * @param[out] p_task Task address. + */ +void nrf_drv_qdec_task_address_get(nrf_qdec_task_t task, uint32_t * p_task); + +/** + * @brief Function for returning the address of a specific timer event. + * + * @param[in] event QDEC event. + * @param[out] p_event Event address. + */ +void nrf_drv_qdec_event_address_get(nrf_qdec_event_t event, uint32_t * p_event); + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_DRV_QDEC_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c new file mode 100644 index 0000000000..83287313a5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.c @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_config.h" + +#if QSPI_ENABLED + +#include "nrf_drv_qspi.h" +#include "nrf_drv_common.h" +#include "app_util.h" +#include "nrf_gpio.h" +#include "nrf_assert.h" + +/** + * @brief Command byte used to read status register. + * + */ +#define QSPI_STD_CMD_RDSR 0x05 + +/** + * @brief Byte used to mask status register and retrieve the write-in-progess bit. + * + */ +#define QSPI_MEM_STATUSREG_WIP_Pos 0x01 + +#define QSPI_WAIT_READY() do { \ + while (!nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY)); \ + } while (0) + +/** + * @brief Control block - driver instance local data. + * + */ +typedef struct +{ + nrf_drv_qspi_handler_t handler; /**< Handler. */ + nrf_drv_state_t state; /**< Driver state. */ + volatile bool interrupt_driven; /**< Information if the current operation is performed and is interrupt-driven. */ + void * p_context; /**< Driver context used in interrupt. */ +} qspi_control_block_t; + +static qspi_control_block_t m_cb; + +static ret_code_t qspi_task_perform(nrf_qspi_task_t task) +{ + // Wait for peripheral + if (m_cb.interrupt_driven) + { + return NRF_ERROR_BUSY; + } + + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + + if (m_cb.handler) + { + m_cb.interrupt_driven = true; + nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK); + } + + nrf_qspi_task_trigger(NRF_QSPI, task); + + if (m_cb.handler == NULL) + { + QSPI_WAIT_READY(); + } + return NRF_SUCCESS; +} + +static bool qspi_pins_configure(nrf_qspi_pins_t const * p_config) +{ + // Check if the user set meaningful values to struct fields. If not, return false. + if ((p_config->sck_pin == NRF_QSPI_PIN_NOT_CONNECTED) || + (p_config->csn_pin == NRF_QSPI_PIN_NOT_CONNECTED) || + (p_config->io0_pin == NRF_QSPI_PIN_NOT_CONNECTED) || + (p_config->io1_pin == NRF_QSPI_PIN_NOT_CONNECTED)) + { + return false; + } + + nrf_qspi_pins_set(NRF_QSPI, p_config); + + return true; +} + +ret_code_t nrf_drv_qspi_init(nrf_drv_qspi_config_t const * p_config, + nrf_drv_qspi_handler_t handler, + void * p_context) +{ + if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + if (!qspi_pins_configure(&p_config->pins)) + { + return NRF_ERROR_INVALID_PARAM; + } + + nrf_qspi_ifconfig0_set(NRF_QSPI, &p_config->prot_if); + nrf_qspi_ifconfig1_set(NRF_QSPI, &p_config->phy_if); + + m_cb.interrupt_driven = false; + m_cb.handler = handler; + m_cb.p_context = p_context; + + /* QSPI interrupt is disabled because the device should be enabled in polling mode (wait for activate + task event ready)*/ + nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK); + + if (handler) + { + nrf_drv_common_irq_enable(QSPI_IRQn, p_config->irq_priority); + } + + m_cb.state = NRF_DRV_STATE_INITIALIZED; + + nrf_qspi_enable(NRF_QSPI); + + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE); + + // Waiting for the peripheral to activate + QSPI_WAIT_READY(); + + return NRF_SUCCESS; +} + +ret_code_t nrf_drv_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config, + void const * p_tx_buffer, + void * p_rx_buffer) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + if (m_cb.interrupt_driven) + { + return NRF_ERROR_BUSY; + } + + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + /* In some cases, only opcode should be sent. To prevent execution, set function code is + * surrounded by an if. + */ + if (p_tx_buffer) + { + nrf_qspi_cinstrdata_set(NRF_QSPI, p_config->length, p_tx_buffer); + } + nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK); + + nrf_qspi_cinstr_transfer_start(NRF_QSPI, p_config); + + QSPI_WAIT_READY(); + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK); + + if (p_rx_buffer) + { + nrf_qspi_cinstrdata_get(NRF_QSPI, p_config->length, p_rx_buffer); + } + + return NRF_SUCCESS; +} + +ret_code_t nrf_drv_qspi_cinstr_quick_send(uint8_t opcode, + nrf_qspi_cinstr_len_t length, + void const * p_tx_buffer) +{ + nrf_qspi_cinstr_conf_t config = NRF_DRV_QSPI_DEFAULT_CINSTR(opcode, length); + return nrf_drv_qspi_cinstr_xfer(&config, p_tx_buffer, NULL); +} + +ret_code_t nrf_drv_qspi_mem_busy_check(void) +{ + ret_code_t ret_code; + uint8_t status_value = 0; + + nrf_qspi_cinstr_conf_t config = NRF_DRV_QSPI_DEFAULT_CINSTR(QSPI_STD_CMD_RDSR, + NRF_QSPI_CINSTR_LEN_2B); + + ret_code = nrf_drv_qspi_cinstr_xfer(&config, &status_value, &status_value); + + if (ret_code != NRF_SUCCESS) + { + return ret_code; + } + + if ((status_value & QSPI_MEM_STATUSREG_WIP_Pos) != 0x00) + { + return NRF_ERROR_BUSY; + } + + return NRF_SUCCESS; +} + +void nrf_drv_qspi_uninit(void) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK); + + nrf_qspi_disable(NRF_QSPI); + + nrf_drv_common_irq_disable(QSPI_IRQn); + + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + + m_cb.state = NRF_DRV_STATE_UNINITIALIZED; +} + +ret_code_t nrf_drv_qspi_write(void const * p_tx_buffer, + size_t tx_buffer_length, + uint32_t dst_address) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(p_tx_buffer != NULL); + /* Checking word alignment. */ + ASSERT(is_word_aligned(p_tx_buffer)); + + if (!nrf_drv_is_in_RAM(p_tx_buffer)) + { + return NRF_ERROR_INVALID_ADDR; + } + + nrf_qspi_write_buffer_set(NRF_QSPI, p_tx_buffer, tx_buffer_length, dst_address); + return qspi_task_perform(NRF_QSPI_TASK_WRITESTART); + +} + +ret_code_t nrf_drv_qspi_read(void * p_rx_buffer, + size_t rx_buffer_length, + uint32_t src_address) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(p_rx_buffer != NULL); + /* Checking word alignment. */ + ASSERT(is_word_aligned(p_rx_buffer)); + + if (!nrf_drv_is_in_RAM(p_rx_buffer)) + { + return NRF_ERROR_INVALID_ADDR; + } + + nrf_qspi_read_buffer_set(NRF_QSPI, p_rx_buffer, rx_buffer_length, src_address); + return qspi_task_perform(NRF_QSPI_TASK_READSTART); +} + +ret_code_t nrf_drv_qspi_erase(nrf_qspi_erase_len_t length, + uint32_t start_address) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + /* Checking word alignment. */ + ASSERT(is_word_aligned((void *)start_address)); + nrf_qspi_erase_ptr_set(NRF_QSPI, start_address, length); + return qspi_task_perform(NRF_QSPI_TASK_ERASESTART); +} + +ret_code_t nrf_drv_qspi_chip_erase(void) +{ + return nrf_drv_qspi_erase(NRF_QSPI_ERASE_LEN_ALL, 0); +} + +void QSPI_IRQHandler(void) +{ + // Catch Event ready interrupts + if (nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY)) + { + m_cb.interrupt_driven = false; + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + m_cb.handler(NRF_DRV_QSPI_EVENT_DONE, m_cb.p_context); + } +} + +#endif // QSPI_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.h new file mode 100644 index 0000000000..35ce036bcd --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/qspi/nrf_drv_qspi.h @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_qspi QSPI HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52840 Quad serial peripheral interface (QSPI) APIs. + * + * @defgroup nrf_drv_qspi QSPI driver + * @{ + * @ingroup nrf_qspi + * @brief @tagAPI52840 Quad serial peripheral interface (QSPI) driver. + */ + +#ifndef NRF_DRV_QSPI_H__ +#define NRF_DRV_QSPI_H__ + +#include "nordic_common.h" +#include "sdk_config.h" +#include "nrf_qspi.h" +#include "sdk_errors.h" +#include "boards.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief QSPI driver instance configuration structure. + */ +typedef struct +{ + nrf_qspi_pins_t pins; /**< Pins configuration structure. */ + nrf_qspi_prot_conf_t prot_if; /**< Protocol layer interface configuration structure. */ + nrf_qspi_phy_conf_t phy_if; /**< Physical layer interface configuration structure. */ + uint8_t irq_priority; /**< Interrupt priority. */ +} nrf_drv_qspi_config_t; + +#if QSPI_PIN_SCK == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_SCK + #define QSPI_PIN_SCK BSP_QSPI_SCK_PIN +#endif +#if QSPI_PIN_CSN == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_CSN + #define QSPI_PIN_CSN BSP_QSPI_CSN_PIN +#endif +#if QSPI_PIN_IO0 == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_IO0 + #define QSPI_PIN_IO0 BSP_QSPI_IO0_PIN +#endif +#if QSPI_PIN_IO1 == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_IO1 + #define QSPI_PIN_IO1 BSP_QSPI_IO1_PIN +#endif +#if QSPI_PIN_IO2 == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_IO2 + #define QSPI_PIN_IO2 BSP_QSPI_IO2_PIN +#endif +#if QSPI_PIN_IO3 == NRF_QSPI_PIN_NOT_CONNECTED + #undef QSPI_PIN_IO3 + #define QSPI_PIN_IO3 BSP_QSPI_IO3_PIN +#endif +/** + * @brief QSPI instance default configuration. + */ +#define NRF_DRV_QSPI_DEFAULT_CONFIG \ +{ \ + .pins = { \ + .sck_pin = QSPI_PIN_SCK, \ + .csn_pin = QSPI_PIN_CSN, \ + .io0_pin = QSPI_PIN_IO0, \ + .io1_pin = QSPI_PIN_IO1, \ + .io2_pin = QSPI_PIN_IO2, \ + .io3_pin = QSPI_PIN_IO3, \ + }, \ + .irq_priority = (uint8_t)QSPI_CONFIG_IRQ_PRIORITY, \ + .prot_if = { \ + .readoc = (nrf_qspi_readoc_t) QSPI_CONFIG_READOC, \ + .writeoc = (nrf_qspi_writeoc_t) QSPI_CONFIG_WRITEOC, \ + .addrmode = (nrf_qspi_addrmode_t) QSPI_CONFIG_ADDRMODE, \ + .dpmconfig = false, \ + }, \ + .phy_if = { \ + .sck_freq = (nrf_qspi_frequency_t) QSPI_CONFIG_FREQUENCY, \ + .sck_delay = (uint8_t) QSPI_CONFIG_SCK_DELAY, \ + .spi_mode = (nrf_qspi_spi_mode_t) QSPI_CONFIG_MODE, \ + .dpmen = false \ + } \ +} + + +/** + * @brief QSPI custom instruction helper with default configuration. + */ +#define NRF_DRV_QSPI_DEFAULT_CINSTR(opc, len) \ +{ \ + .opcode = (opc), \ + .length = (len), \ + .io2_level = false, \ + .io3_level = false, \ + .wipwait = false, \ + .wren = false \ +} + +/** + * @brief QSPI master driver event types, passed to the handler routine provided + * during initialization. + */ +typedef enum +{ + NRF_DRV_QSPI_EVENT_DONE, /**< Transfer done. */ +} nrf_drv_qspi_evt_t; + +/** + * @brief QSPI driver event handler type. + */ +typedef void (*nrf_drv_qspi_handler_t)(nrf_drv_qspi_evt_t event, void * p_context); + +/** + * @brief Function for initializing the QSPI driver instance. + * + * @param[in] p_config Pointer to the structure with the initial configuration. + * @param[in] handler Event handler provided by the user. If NULL, transfers + * will be performed in blocking mode. + * @param[in] p_context Pointer to context. Use in interrupt handler. + * + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + * @retval NRF_ERROR_INVALID_PARAM If the pin configuration was incorrect. + */ +ret_code_t nrf_drv_qspi_init(nrf_drv_qspi_config_t const * p_config, + nrf_drv_qspi_handler_t handler, + void * p_context); + +/** + * @brief Function for uninitializing the QSPI driver instance. + */ +void nrf_drv_qspi_uninit(void); + +/** + * @brief Function for reading data from QSPI memory. + * + * Write, read, and erase operations check memory device busy state before starting the operation. + * If the memory is busy, the resulting action depends on the mode in which the read operation is used: + * - blocking mode (without handler) - a delay occurs until the last operation still runs and + * until operation data is still being read. + * - interrupt mode (with handler) - event emission occurs after the last operation + * and reading of data are finished. + * + * @param[out] p_rx_buffer Pointer to the receive buffer. + * @param[in] rx_buffer_length Size of the data to read. + * @param[in] src_address Address in memory to read from. + * + * @retval NRF_SUCCESS If the operation was successful (blocking mode) or operation + * was commissioned (handler mode). + * @retval NRF_ERROR_BUSY If the driver currently handles another operation. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffer is not placed in the Data RAM region. + */ +ret_code_t nrf_drv_qspi_read(void * p_rx_buffer, + size_t rx_buffer_length, + uint32_t src_address); + +/** + * @brief Function for writing data to QSPI memory. + * + * Write, read, and erase operations check memory device busy state before starting the operation. + * If the memory is busy, the resulting action depends on the mode in which the write operation is used: + * - blocking mode (without handler) - a delay occurs until the last operation still runs and + * until operation data is still being sent. + * - interrupt mode (with handler) - event emission occurs after the last operation + * and sending of operation data are finished. + * To manually control operation execution in the memory device, use @ref nrf_drv_qspi_mem_busy_check + * after executing the write function. + * Remember that an incoming event signalizes only that data was sent to the memory device and the periheral + * before the write operation checked if memory was busy. + * + * @param[in] p_tx_buffer Pointer to the writing buffer. + * @param[in] tx_buffer_length Size of the data to write. + * @param[in] dst_address Address in memory to write to. + * + * @retval NRF_SUCCESS If the operation was successful (blocking mode) or operation + * was commissioned (handler mode). + * @retval NRF_ERROR_BUSY If the driver currently handles other operation. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffer is not placed in the Data RAM region. + */ +ret_code_t nrf_drv_qspi_write(void const * p_tx_buffer, + size_t tx_buffer_length, + uint32_t dst_address); + +/** + * @brief Function for starting erasing of one memory block - 4KB, 64KB, or the whole chip. + * + * Write, read, and erase operations check memory device busy state before starting the operation. + * If the memory is busy, the resulting action depends on the mode in which the erase operation is used: + * - blocking mode (without handler) - a delay occurs until the last operation still runs and + * until operation data is still being sent. + * - interrupt mode (with handler) - event emission occurs after the last operation + * and sending of operation data are finished. + * To manually control operation execution in the memory device, use @ref nrf_drv_qspi_mem_busy_check + * after executing the erase function. + * Remember that an incoming event signalizes only that data was sent to the memory device and the periheral + * before the erase operation checked if memory was busy. + * + * @param[in] length Size of data to erase. See @ref nrf_qspi_erase_len_t. + * @param[in] start_address Memory address to start erasing. If chip erase is performed, address + * field is ommited. + * + * @retval NRF_SUCCESS If the operation was successful (blocking mode) or operation + * was commissioned (handler mode). + * @retval NRF_ERROR_BUSY If the driver currently handles another operation. + */ +ret_code_t nrf_drv_qspi_erase(nrf_qspi_erase_len_t length, + uint32_t start_address); + +/** + * @brief Function for starting an erase operation of the whole chip. + * + * @retval NRF_SUCCESS If the operation was successful (blocking mode) or operation + * was commissioned (handler mode). + * @retval NRF_ERROR_BUSY If the driver currently handles another operation. + */ +ret_code_t nrf_drv_qspi_chip_erase(void); + +/** + * @brief Function for getting the current driver status and status byte of memory device with + * testing WIP (write in progress) bit. + * + * @retval NRF_SUCCESS If the driver and memory are ready to handle a new operation. + * @retval NRF_ERROR_BUSY If the driver or memory currently handle another operation. + */ +ret_code_t nrf_drv_qspi_mem_busy_check(void); + +/** + * @brief Function for sending operation code, sending data, and receiving data from the memory device. + * + * Use this function to transfer configuration data to memory and to receive data from memory. + * Pointers can be addresses from flash memory. + * This function is a synchronous function and should be used only if necessary. + * See more: @ref hardware_driver_qspi. + * + * @param[in] p_config Pointer to the structure with opcode and transfer configuration. + * @param[in] p_tx_buffer Pointer to the array with data to send. Can be NULL if only opcode is transmitted. + * @param[out] p_rx_buffer Pointer to the array for data to receive. Can be NULL if there is nothing to receive. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_BUSY If the driver currently handles other operation. + */ +ret_code_t nrf_drv_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const * p_config, + void const * p_tx_buffer, + void * p_rx_buffer); +/** + * @brief Function for sending operation code and data to the memory device with simpler configuration. + * + * Use this function to transfer configuration data to memory and to receive data from memory. + * This function is a synchronous function and should be used only if necessary. + * + * @param[in] opcode Operation code. Sending first. + * @param[in] length Length of the data to send and opcode. See @ref nrf_qspi_cinstr_len_t. + * @param[in] p_tx_buffer Pointer to input data array. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_BUSY If the driver currently handles another operation. + */ +ret_code_t nrf_drv_qspi_cinstr_quick_send(uint8_t opcode, + nrf_qspi_cinstr_len_t length, + void const * p_tx_buffer); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_QSPI_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.c new file mode 100644 index 0000000000..5f529a7db7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.c @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2009 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +* @addtogroup nrf_dev_radio_rx_example_main nrf_dev_radio_tx_example_main +* @{ +*/ + +#include "radio_config.h" +#include "nrf_delay.h" + +/* These are set to zero as ShockBurst packets don't have corresponding fields. */ +#define PACKET_S1_FIELD_SIZE (0UL) /**< Packet S1 field size in bits. */ +#define PACKET_S0_FIELD_SIZE (0UL) /**< Packet S0 field size in bits. */ +#define PACKET_LENGTH_FIELD_SIZE (0UL) /**< Packet length field size in bits. */ + +/** + * @brief Function for swapping/mirroring bits in a byte. + * + *@verbatim + * output_bit_7 = input_bit_0 + * output_bit_6 = input_bit_1 + * : + * output_bit_0 = input_bit_7 + *@endverbatim + * + * @param[in] inp is the input byte to be swapped. + * + * @return + * Returns the swapped/mirrored input byte. + */ +static uint32_t swap_bits(uint32_t inp); + +/** + * @brief Function for swapping bits in a 32 bit word for each byte individually. + * + * The bits are swapped as follows: + * @verbatim + * output[31:24] = input[24:31] + * output[23:16] = input[16:23] + * output[15:8] = input[8:15] + * output[7:0] = input[0:7] + * @endverbatim + * @param[in] input is the input word to be swapped. + * + * @return + * Returns the swapped input byte. + */ +static uint32_t bytewise_bitswap(uint32_t inp); + +static uint32_t swap_bits(uint32_t inp) +{ + uint32_t i; + uint32_t retval = 0; + + inp = (inp & 0x000000FFUL); + + for (i = 0; i < 8; i++) + { + retval |= ((inp >> i) & 0x01) << (7 - i); + } + + return retval; +} + + +static uint32_t bytewise_bitswap(uint32_t inp) +{ + return (swap_bits(inp >> 24) << 24) + | (swap_bits(inp >> 16) << 16) + | (swap_bits(inp >> 8) << 8) + | (swap_bits(inp)); +} + + +/** + * @brief Function for configuring the radio to operate in ShockBurst compatible mode. + * + * To configure the application running on nRF24L series devices: + * + * @verbatim + * uint8_t tx_address[5] = { 0xC0, 0x01, 0x23, 0x45, 0x67 }; + * hal_nrf_set_rf_channel(7); + * hal_nrf_set_address_width(HAL_NRF_AW_5BYTES); + * hal_nrf_set_address(HAL_NRF_TX, tx_address); + * hal_nrf_set_address(HAL_NRF_PIPE0, tx_address); + * hal_nrf_open_pipe(0, false); + * hal_nrf_set_datarate(HAL_NRF_1MBPS); + * hal_nrf_set_crc_mode(HAL_NRF_CRC_16BIT); + * hal_nrf_setup_dynamic_payload(0xFF); + * hal_nrf_enable_dynamic_payload(false); + * @endverbatim + * + * When transmitting packets with hal_nrf_write_tx_payload(const uint8_t *tx_pload, uint8_t length), + * match the length with PACKET_STATIC_LENGTH. + * hal_nrf_write_tx_payload(payload, PACKET_STATIC_LENGTH); + * +*/ +void radio_configure() +{ + // Radio config + NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos); + NRF_RADIO->FREQUENCY = 7UL; // Frequency bin 7, 2407MHz + NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos); + + // Radio address config + NRF_RADIO->PREFIX0 = + ((uint32_t)swap_bits(0xC3) << 24) // Prefix byte of address 3 converted to nRF24L series format + | ((uint32_t)swap_bits(0xC2) << 16) // Prefix byte of address 2 converted to nRF24L series format + | ((uint32_t)swap_bits(0xC1) << 8) // Prefix byte of address 1 converted to nRF24L series format + | ((uint32_t)swap_bits(0xC0) << 0); // Prefix byte of address 0 converted to nRF24L series format + + NRF_RADIO->PREFIX1 = + ((uint32_t)swap_bits(0xC7) << 24) // Prefix byte of address 7 converted to nRF24L series format + | ((uint32_t)swap_bits(0xC6) << 16) // Prefix byte of address 6 converted to nRF24L series format + | ((uint32_t)swap_bits(0xC4) << 0); // Prefix byte of address 4 converted to nRF24L series format + + NRF_RADIO->BASE0 = bytewise_bitswap(0x01234567UL); // Base address for prefix 0 converted to nRF24L series format + NRF_RADIO->BASE1 = bytewise_bitswap(0x89ABCDEFUL); // Base address for prefix 1-7 converted to nRF24L series format + + NRF_RADIO->TXADDRESS = 0x00UL; // Set device address 0 to use when transmitting + NRF_RADIO->RXADDRESSES = 0x01UL; // Enable device address 0 to use to select which addresses to receive + + // Packet configuration + NRF_RADIO->PCNF0 = (PACKET_S1_FIELD_SIZE << RADIO_PCNF0_S1LEN_Pos) | + (PACKET_S0_FIELD_SIZE << RADIO_PCNF0_S0LEN_Pos) | + (PACKET_LENGTH_FIELD_SIZE << RADIO_PCNF0_LFLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0" + + // Packet configuration + NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | + (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | + (PACKET_BASE_ADDRESS_LENGTH << RADIO_PCNF1_BALEN_Pos) | + (PACKET_STATIC_LENGTH << RADIO_PCNF1_STATLEN_Pos) | + (PACKET_PAYLOAD_MAXSIZE << RADIO_PCNF1_MAXLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0" + + // CRC Config + NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits + if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos)) + { + NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value + NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16 + x^12^x^5 + 1 + } + else if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_One << RADIO_CRCCNF_LEN_Pos)) + { + NRF_RADIO->CRCINIT = 0xFFUL; // Initial value + NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8 + x^2^x^1 + 1 + } +} + +/** + * @} + */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.h new file mode 100644 index 0000000000..2b4cacd106 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/radio_config/radio_config.h @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2009 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 RADIO_CONFIG_H +#define RADIO_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define PACKET_BASE_ADDRESS_LENGTH (4UL) //!< Packet base address length field size in bytes +#define PACKET_STATIC_LENGTH (1UL) //!< Packet static length in bytes +#define PACKET_PAYLOAD_MAXSIZE (PACKET_STATIC_LENGTH) //!< Packet payload maximum size in bytes + +void radio_configure(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.c new file mode 100644 index 0000000000..8f02e76ab4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.c @@ -0,0 +1,321 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(RNG) + +#include +#include +#include "nrf_drv_rng.h" +#include "nrf_drv_common.h" +#include "nordic_common.h" +#include "app_util_platform.h" +#include "nrf_assert.h" +#include "nrf_queue.h" + +#ifdef SOFTDEVICE_PRESENT + #include "nrf_sdh.h" +#endif // SOFTDEVICE_PRESENT + +#define NRF_LOG_MODULE_NAME rng + +#if RNG_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL RNG_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR RNG_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR RNG_CONFIG_DEBUG_COLOR +#else //RNG_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //RNG_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/* Validate configuration */ +INTERRUPT_PRIORITY_VALIDATION(RNG_CONFIG_IRQ_PRIORITY); + +typedef struct +{ + nrf_drv_state_t state; + nrf_drv_rng_config_t config; +} nrf_drv_rng_cb_t; + +static nrf_drv_rng_cb_t m_rng_cb; +NRF_QUEUE_DEF(uint8_t, m_rand_pool, RNG_CONFIG_POOL_SIZE, NRF_QUEUE_MODE_OVERFLOW); +static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG; + +#ifdef SOFTDEVICE_PRESENT +#ifdef S132 + #define SD_RAND_POOL_SIZE (64) +#else + #define SD_RAND_POOL_SIZE (32) +#endif + STATIC_ASSERT(RNG_CONFIG_POOL_SIZE == SD_RAND_POOL_SIZE); + + #define NRF_DRV_RNG_LOCK() CRITICAL_REGION_ENTER() + #define NRF_DRV_RNG_RELEASE() CRITICAL_REGION_EXIT() + #define NRF_DRV_RNG_SD_IS_ENABLED() nrf_sdh_is_enabled() +#else + #define NRF_DRV_RNG_LOCK() do { } while (0) + #define NRF_DRV_RNG_RELEASE() do { } while (0) + #define NRF_DRV_RNG_SD_IS_ENABLED() false +#endif // SOFTDEVICE_PRESENT + + +/** + * @brief Function for starting generation. + */ +static void nrf_drv_rng_start(void) +{ + ASSERT(!NRF_DRV_RNG_SD_IS_ENABLED()); + + nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY); + nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK); + nrf_rng_task_trigger(NRF_RNG_TASK_START); +} + +/** + * @brief Function for stoping generation. + */ +static void nrf_drv_rng_stop(void) +{ + ASSERT(!NRF_DRV_RNG_SD_IS_ENABLED()); + + nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK); + nrf_rng_task_trigger(NRF_RNG_TASK_STOP); +} + +/** + * @brief Function for setting up RNG hardware. + */ +static void nrf_drv_rng_setup(void) +{ + ASSERT(!NRF_DRV_RNG_SD_IS_ENABLED()); + + if (m_rng_cb.config.error_correction) + { + nrf_rng_error_correction_enable(); + } + nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK); + nrf_drv_common_irq_enable(RNG_IRQn, m_rng_cb.config.interrupt_priority); +} + +ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config) +{ + if (m_rng_cb.state != NRF_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_MODULE_ALREADY_INITIALIZED; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + m_rng_cb.config = *p_config; + + NRF_DRV_RNG_LOCK(); + + if (!NRF_DRV_RNG_SD_IS_ENABLED()) + { + nrf_drv_rng_setup(); + nrf_drv_rng_start(); + } + + NRF_DRV_RNG_RELEASE(); + + m_rng_cb.state = NRF_DRV_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + +void nrf_drv_rng_uninit(void) +{ + ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED); + + NRF_DRV_RNG_LOCK(); + + if (!NRF_DRV_RNG_SD_IS_ENABLED()) + { + nrf_drv_rng_stop(); + nrf_drv_common_irq_disable(RNG_IRQn); + } + + NRF_DRV_RNG_RELEASE(); + + nrf_queue_reset(&m_rand_pool); + m_rng_cb.state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_rng_bytes_available(uint8_t * p_bytes_available) +{ + ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED); + +#ifdef SOFTDEVICE_PRESENT + if (NRF_DRV_RNG_SD_IS_ENABLED()) + { + if (NRF_SUCCESS == sd_rand_application_bytes_available_get(p_bytes_available)) + { + return; + } + } +#endif // SOFTDEVICE_PRESENT + + *p_bytes_available = nrf_queue_utilization_get(&m_rand_pool); + + NRF_LOG_INFO("Function: %s, available bytes: %d.", (uint32_t)__func__, *p_bytes_available); +} + +ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length) +{ + ret_code_t err_code = NRF_SUCCESS; + ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED); + +#ifdef SOFTDEVICE_PRESENT + do { + bool sd_is_enabled; + NRF_DRV_RNG_LOCK(); + sd_is_enabled = NRF_DRV_RNG_SD_IS_ENABLED(); + if (!sd_is_enabled) +#endif // SOFTDEVICE_PRESENT + { + err_code = nrf_queue_read(&m_rand_pool, p_buff, (uint32_t)length); + nrf_drv_rng_start(); + } +#ifdef SOFTDEVICE_PRESENT + NRF_DRV_RNG_RELEASE(); + + if (sd_is_enabled) + { + err_code = sd_rand_application_vector_get(p_buff, length); + if (err_code == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES) + { + err_code = NRF_ERROR_NOT_FOUND; + } + } + } while (err_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED); +#endif // SOFTDEVICE_PRESENT + ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); + +#if defined(RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED) && (RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED != 0) + NRF_LOG_DEBUG("Rand buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_buff, length); +#endif // RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + + return err_code; +} + +void nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length) +{ + ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED); + + while (length) + { + uint32_t len = MIN(length, RNG_CONFIG_POOL_SIZE); + ret_code_t err_code; + + do { + err_code = nrf_drv_rng_rand(p_buff, len); + } while (err_code != NRF_SUCCESS); + + length -= len; + p_buff += len; + } + + NRF_LOG_DEBUG("Rand buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_buff, length); +} + +#ifdef SOFTDEVICE_PRESENT +static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context) +{ + switch (state) + { + case NRF_SDH_EVT_STATE_ENABLE_PREPARE: + NVIC_DisableIRQ(RNG_IRQn); + break; + + case NRF_SDH_EVT_STATE_DISABLED: + NRF_DRV_RNG_LOCK(); + if (m_rng_cb.state == NRF_DRV_STATE_INITIALIZED) + { + nrf_drv_rng_setup(); + nrf_drv_rng_start(); + } + NRF_DRV_RNG_RELEASE(); + break; + + default: + break; + } +} + +NRF_SDH_STATE_OBSERVER(m_sd_state_observer, RNG_CONFIG_STATE_OBSERVER_PRIO) = +{ + .handler = sd_state_evt_handler, + .p_context = NULL, +}; + +#endif // SOFTDEVICE_PRESENT + +void RNG_IRQHandler(void) +{ + NRF_DRV_RNG_LOCK(); + if ( + !NRF_DRV_RNG_SD_IS_ENABLED() && + nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) && + nrf_rng_int_get(NRF_RNG_INT_VALRDY_MASK)) + { + nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY); + + uint8_t new_value = nrf_rng_random_value_get(); + UNUSED_RETURN_VALUE(nrf_queue_push(&m_rand_pool, &new_value)); + + if (nrf_queue_is_full(&m_rand_pool)) + { + nrf_drv_rng_stop(); + } + + NRF_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY."); + } + NRF_DRV_RNG_RELEASE(); +} + +#endif // NRF_MODULE_ENABLED(RNG) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.h new file mode 100644 index 0000000000..7d242d3049 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rng/nrf_drv_rng.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_RNG_H__ +#define NRF_DRV_RNG_H__ + +#include +#include + +#include "nrf_rng.h" +#include "sdk_errors.h" +#include "sdk_config.h" +#include "nrf_drv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup nrf_rng RNG HAL and driver + * @ingroup nrf_drivers + * @brief Random number generator (RNG) APIs. + * @details The RNG HAL provides basic APIs for accessing the registers of the random number + * generator. The RNG driver provides APIs on a higher level. + * + * @defgroup nrf_drv_rng RNG driver + * @{ + * @ingroup nrf_rng + * @brief Driver for managing the random number generator (RNG). + */ + +/**@brief Struct for RNG configuration. */ +typedef struct +{ + bool error_correction : 1; /**< Error correction flag. */ + uint8_t interrupt_priority; /**< interrupt priority */ +} nrf_drv_rng_config_t; + +/**@brief RNG default configuration. */ +#define NRF_DRV_RNG_DEFAULT_CONFIG \ + { \ + .error_correction = RNG_CONFIG_ERROR_CORRECTION, \ + .interrupt_priority = RNG_CONFIG_IRQ_PRIORITY, \ + } + +/** + * @brief Function for initializing the nrf_drv_rng module. + * + * @param[in] p_config Initial configuration. + * + * @retval NRF_SUCCESS Driver was successfully initialized. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED Driver was already initialized. + */ +ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config); + +/** + * @brief Function for uninitializing the nrf_drv_rng module. + */ +void nrf_drv_rng_uninit(void); + +/** + * @brief Function for getting the number of currently available random bytes. + * + * @param[out] p_bytes_available The number of bytes currently available in the pool. + */ +void nrf_drv_rng_bytes_available(uint8_t * p_bytes_available); + +/** + * @brief Function for getting the vector of random numbers. + * + * @param[out] p_buff Pointer to uint8_t buffer for storing the bytes. + * @param[in] length Number of bytes to take from the pool and place in p_buff. + * + * @retval NRF_SUCCESS If the requested bytes were written to p_buff. + * @retval NRF_ERROR_NOT_FOUND If no bytes were written to the buffer because there were + * not enough bytes available in the pool. + */ +ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length); + +/** + * @brief Blocking function for getting an arbitrary array of random numbers. + * + * @note This function may execute for a substantial amount of time depending on the length + * of the buffer required and on the state of the current internal pool of random numbers. + * + * @param[out] p_buff Pointer to uint8_t buffer for storing the bytes. + * @param[in] length Number of bytes place in p_buff. + */ +void nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length); + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_RNG_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.c new file mode 100644 index 0000000000..551580f71e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.c @@ -0,0 +1,356 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(RTC) +#define ENABLED_RTC_COUNT (RTC0_ENABLED+RTC1_ENABLED+RTC2_ENABLED) +#if ENABLED_RTC_COUNT + +#include "nrf_drv_rtc.h" +#include "nrf_rtc.h" +#include "nrf_assert.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME rtc + +#if RTC_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL RTC_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR RTC_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR RTC_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \ + (event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \ + (event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \ + (event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \ + (event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \ + (event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : "UNKNOWN EVENT") +#else //RTC_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //RTC_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@brief RTC driver instance control block structure. */ +typedef struct +{ + nrf_drv_state_t state; /**< Instance state. */ + bool reliable; /**< Reliable mode flag. */ + uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */ +} nrf_drv_rtc_cb_t; + +// User callbacks local storage. +static nrf_drv_rtc_handler_t m_handlers[ENABLED_RTC_COUNT]; +static nrf_drv_rtc_cb_t m_cb[ENABLED_RTC_COUNT]; + +ret_code_t nrf_drv_rtc_init(nrf_drv_rtc_t const * const p_instance, + nrf_drv_rtc_config_t const * p_config, + nrf_drv_rtc_handler_t handler) +{ + ASSERT(p_config != NULL); + + ret_code_t err_code; + + if (handler) + { + m_handlers[p_instance->instance_id] = handler; + } + else + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_drv_common_irq_enable(p_instance->irq, p_config->interrupt_priority); + nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler); + m_cb[p_instance->instance_id].reliable = p_config->reliable; + m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency; + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_rtc_uninit(nrf_drv_rtc_t const * const p_instance) +{ + uint32_t mask = NRF_RTC_INT_TICK_MASK | + NRF_RTC_INT_OVERFLOW_MASK | + NRF_RTC_INT_COMPARE0_MASK | + NRF_RTC_INT_COMPARE1_MASK | + NRF_RTC_INT_COMPARE2_MASK | + NRF_RTC_INT_COMPARE3_MASK; + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_drv_common_irq_disable(p_instance->irq); + + nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP); + nrf_rtc_event_disable(p_instance->p_reg, mask); + nrf_rtc_int_disable(p_instance->p_reg, mask); + + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized."); +} + +void nrf_drv_rtc_enable(nrf_drv_rtc_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_INITIALIZED); + + nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START); + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled."); +} + +void nrf_drv_rtc_disable(nrf_drv_rtc_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP); + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled."); +} + +ret_code_t nrf_drv_rtc_cc_disable(nrf_drv_rtc_t const * const p_instance, uint32_t channel) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(channelcc_channel_count); + + ret_code_t err_code; + uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel); + nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel); + + nrf_rtc_event_disable(p_instance->p_reg,int_mask); + if (nrf_rtc_int_is_enabled(p_instance->p_reg,int_mask)) + { + nrf_rtc_int_disable(p_instance->p_reg,int_mask); + if (nrf_rtc_event_pending(p_instance->p_reg,event)) + { + nrf_rtc_event_clear(p_instance->p_reg,event); + err_code = NRF_ERROR_TIMEOUT; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + } + NRF_LOG_INFO("RTC id: %d, channel disabled: %d.", p_instance->instance_id, channel); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +ret_code_t nrf_drv_rtc_cc_set(nrf_drv_rtc_t const * const p_instance, + uint32_t channel, + uint32_t val, + bool enable_irq) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(channelcc_channel_count); + + ret_code_t err_code; + uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel); + nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel); + + nrf_rtc_event_disable(p_instance->p_reg, int_mask); + nrf_rtc_int_disable(p_instance->p_reg, int_mask); + + val = RTC_WRAP(val); + if (m_cb[p_instance->instance_id].reliable) + { + nrf_rtc_cc_set(p_instance->p_reg,channel,val); + uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg); + int32_t diff = cnt - val; + if (cnt < val) + { + diff += RTC_COUNTER_COUNTER_Msk; + } + if (diff < m_cb[p_instance->instance_id].tick_latency) + { + err_code = NRF_ERROR_TIMEOUT; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + } + else + { + nrf_rtc_cc_set(p_instance->p_reg,channel,val); + } + + if (enable_irq) + { + nrf_rtc_event_clear(p_instance->p_reg,event); + nrf_rtc_int_enable(p_instance->p_reg, int_mask); + } + nrf_rtc_event_enable(p_instance->p_reg,int_mask); + + NRF_LOG_INFO("RTC id: %d, channel enabled: %d, compare value: %d.", p_instance->instance_id, channel, val); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_rtc_tick_enable(nrf_drv_rtc_t const * const p_instance, bool enable_irq) +{ + nrf_rtc_event_t event = NRF_RTC_EVENT_TICK; + uint32_t mask = NRF_RTC_INT_TICK_MASK; + + nrf_rtc_event_clear(p_instance->p_reg, event); + nrf_rtc_event_enable(p_instance->p_reg, mask); + if (enable_irq) + { + nrf_rtc_int_enable(p_instance->p_reg, mask); + } + NRF_LOG_INFO("Tick events enabled."); +} + +void nrf_drv_rtc_tick_disable(nrf_drv_rtc_t const * const p_instance) +{ + uint32_t mask = NRF_RTC_INT_TICK_MASK; + + nrf_rtc_event_disable(p_instance->p_reg, mask); + nrf_rtc_int_disable(p_instance->p_reg, mask); + NRF_LOG_INFO("Tick events disabled."); +} + +void nrf_drv_rtc_overflow_enable(nrf_drv_rtc_t const * const p_instance, bool enable_irq) +{ + nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW; + uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK; + + nrf_rtc_event_clear(p_instance->p_reg, event); + nrf_rtc_event_enable(p_instance->p_reg, mask); + if (enable_irq) + { + nrf_rtc_int_enable(p_instance->p_reg, mask); + } +} +void nrf_drv_rtc_overflow_disable(nrf_drv_rtc_t const * const p_instance) +{ + uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK; + nrf_rtc_event_disable(p_instance->p_reg, mask); + nrf_rtc_int_disable(p_instance->p_reg, mask); +} + +uint32_t nrf_drv_rtc_max_ticks_get(nrf_drv_rtc_t const * const p_instance) +{ + uint32_t ticks; + if (m_cb[p_instance->instance_id].reliable) + { + ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency; + } + else + { + ticks = RTC_COUNTER_COUNTER_Msk; + } + return ticks; +} + +/**@brief Generic function for handling RTC interrupt + * + * @param[in] p_reg Pointer to instance register structure. + * @param[in] instance_id Index of instance. + */ +__STATIC_INLINE void nrf_drv_rtc_int_handler(NRF_RTC_Type * p_reg, + uint32_t instance_id, + uint32_t channel_count) +{ + uint32_t i; + uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK; + nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0; + + for (i = 0; i < channel_count; i++) + { + if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event)) + { + nrf_rtc_event_disable(p_reg,int_mask); + nrf_rtc_int_disable(p_reg,int_mask); + nrf_rtc_event_clear(p_reg,event); + NRF_LOG_DEBUG("Event: %s, instance id: %d.", + (uint32_t)EVT_TO_STR(event), (uint32_t)instance_id); + m_handlers[instance_id]((nrf_drv_rtc_int_type_t)i); + } + int_mask <<= 1; + event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t)); + } + event = NRF_RTC_EVENT_TICK; + if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) && + nrf_rtc_event_pending(p_reg, event)) + { + nrf_rtc_event_clear(p_reg, event); + NRF_LOG_DEBUG("Event: %s, instance id: %d.", (uint32_t)EVT_TO_STR(event), instance_id); + m_handlers[instance_id](NRF_DRV_RTC_INT_TICK); + } + + event = NRF_RTC_EVENT_OVERFLOW; + if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) && + nrf_rtc_event_pending(p_reg, event)) + { + nrf_rtc_event_clear(p_reg,event); + NRF_LOG_DEBUG("Event: %s, instance id: %d.", (uint32_t)EVT_TO_STR(event), instance_id); + m_handlers[instance_id](NRF_DRV_RTC_INT_OVERFLOW); + } +} + +#if NRF_MODULE_ENABLED(RTC0) +void RTC0_IRQHandler(void) +{ + nrf_drv_rtc_int_handler(NRF_RTC0,RTC0_INSTANCE_INDEX, NRF_RTC_CC_CHANNEL_COUNT(0)); +} +#endif + +#if NRF_MODULE_ENABLED(RTC1) +void RTC1_IRQHandler(void) +{ + nrf_drv_rtc_int_handler(NRF_RTC1,RTC1_INSTANCE_INDEX, NRF_RTC_CC_CHANNEL_COUNT(1)); +} +#endif + +#if NRF_MODULE_ENABLED(RTC2) +void RTC2_IRQHandler(void) +{ + nrf_drv_rtc_int_handler(NRF_RTC2,RTC2_INSTANCE_INDEX, NRF_RTC_CC_CHANNEL_COUNT(2)); +} +#endif +#endif //ENABLED_RTC_COUNT +#endif //NRF_MODULE_ENABLED(RTC) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.h new file mode 100644 index 0000000000..8e55c765bf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/rtc/nrf_drv_rtc.h @@ -0,0 +1,365 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_RTC_H +#define NRF_DRV_RTC_H + + +#include "sdk_config.h" +#include "nordic_common.h" +#include "nrf_drv_common.h" +#include "nrf_rtc.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup nrf_rtc RTC HAL and driver + * @ingroup nrf_drivers + * @brief Real timer counter (RTC) APIs. + * @details The RTC HAL provides basic APIs for accessing the registers of the real time counter (RTC). + * The RTC driver provides APIs on a higher level. + * + * @defgroup nrf_drv_rtc RTC driver + * @{ + * @ingroup nrf_rtc + * @brief Real timer counter (RTC) driver. + */ + +/**@brief Macro to convert microseconds into ticks. */ +#define RTC_US_TO_TICKS(us,freq) (((us) * (freq)) / 1000000U) + +/** + * @enum nrf_drv_rtc_int_type_t + * @brief RTC driver interrupt types. + */ +typedef enum +{ + NRF_DRV_RTC_INT_COMPARE0 = 0, /**< Interrupt from COMPARE0 event. */ + NRF_DRV_RTC_INT_COMPARE1 = 1, /**< Interrupt from COMPARE1 event. */ + NRF_DRV_RTC_INT_COMPARE2 = 2, /**< Interrupt from COMPARE2 event. */ + NRF_DRV_RTC_INT_COMPARE3 = 3, /**< Interrupt from COMPARE3 event. */ + NRF_DRV_RTC_INT_TICK = 4, /**< Interrupt from TICK event. */ + NRF_DRV_RTC_INT_OVERFLOW = 5 /**< Interrupt from OVERFLOW event. */ +} nrf_drv_rtc_int_type_t; + +/**@brief RTC driver instance structure. */ +typedef struct +{ + NRF_RTC_Type * p_reg; /**< Pointer to instance register set. */ + IRQn_Type irq; /**< Instance IRQ ID. */ + uint8_t instance_id; /**< Instance index. */ + uint8_t cc_channel_count; /**< Number of capture/compare channels. */ +} nrf_drv_rtc_t; + +#define RTC0_INSTANCE_INDEX 0 +#define RTC1_INSTANCE_INDEX RTC0_INSTANCE_INDEX+RTC0_ENABLED +#define RTC2_INSTANCE_INDEX RTC1_INSTANCE_INDEX+RTC1_ENABLED + +/**@brief Macro for creating RTC driver instance.*/ +#define NRF_DRV_RTC_INSTANCE(id) \ +{ \ + .p_reg = CONCAT_2(NRF_RTC, id), \ + .irq = CONCAT_3(RTC, id, _IRQn), \ + .instance_id = CONCAT_3(RTC, id, _INSTANCE_INDEX),\ + .cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id), \ +} + +/**@brief RTC driver instance configuration structure. */ +typedef struct +{ + uint16_t prescaler; /**< Prescaler. */ + uint8_t interrupt_priority; /**< Interrupt priority. */ + uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */ + bool reliable; /**< Reliable mode flag. */ +} nrf_drv_rtc_config_t; + +/**@brief RTC instance default configuration. */ +#define NRF_DRV_RTC_DEFAULT_CONFIG \ +{ \ + .prescaler = RTC_FREQ_TO_PRESCALER(RTC_DEFAULT_CONFIG_FREQUENCY), \ + .interrupt_priority = RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .reliable = RTC_DEFAULT_CONFIG_RELIABLE, \ + .tick_latency = RTC_US_TO_TICKS(NRF_MAXIMUM_LATENCY_US, RTC_DEFAULT_CONFIG_FREQUENCY), \ +} + +/**@brief RTC driver instance handler type. */ +typedef void (*nrf_drv_rtc_handler_t)(nrf_drv_rtc_int_type_t int_type); + +/**@brief Function for initializing the RTC driver instance. + * + * After initialization, the instance is in power off state. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] handler User's event handler. + * + * @retval NRF_SUCCESS If successfully initialized. + * @retval NRF_ERROR_INVALID_PARAM If no handler was provided. + * @retval NRF_ERROR_INVALID_STATE If the instance is already initialized. + */ +ret_code_t nrf_drv_rtc_init(nrf_drv_rtc_t const * const p_instance, + nrf_drv_rtc_config_t const * p_config, + nrf_drv_rtc_handler_t handler); + +/**@brief Function for uninitializing the RTC driver instance. + * + * After uninitialization, the instance is in idle state. The hardware should return to the state + * before initialization. The function asserts if the instance is in idle state. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_rtc_uninit(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for enabling the RTC driver instance. + * + * @note Function asserts if instance is enabled. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_rtc_enable(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for disabling the RTC driver instance. + * + * @note Function asserts if instance is disabled. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_rtc_disable(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for setting a compare channel. + * + * The function asserts if the instance is not initialized or if the channel parameter is + * wrong. The function powers on the instance if the instance was in power off state. + * + * The driver is not entering a critical section when configuring RTC, which means that it can be + * preempted for a certain amount of time. When the driver was preempted and the value to be set + * is short in time, there is a risk that the driver sets a compare value that is + * behind. If RTCn_CONFIG_RELIABLE is 1 for the given instance, the Reliable mode handles that case. + * However, to detect if the requested value is behind, this mode makes the following assumptions: + * - The maximum preemption time in ticks (8 - bit value) is known and is less than 7.7 ms + * (for prescaler = 0, RTC frequency 32 kHz). + * - The requested absolute compare value is not bigger than (0x00FFFFFF) - tick_latency. It is + * the user's responsibility to ensure that. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel One of the instance's channels. + * @param[in] val Absolute value to be set in the compare register. + * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_TIMEOUT If the compare was not set because the request value is behind the current counter + * value. This error can only be reported if RTCn_CONFIG_RELIABLE = 1. + */ +ret_code_t nrf_drv_rtc_cc_set(nrf_drv_rtc_t const * const p_instance, + uint32_t channel, + uint32_t val, + bool enable_irq); + +/**@brief Function for disabling a channel. + * + * This function disables channel events and channel interrupts. The function asserts if the instance is not + * initialized or if the channel parameter is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel One of the instance's channels. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_TIMEOUT If an interrupt was pending on the requested channel. + */ +ret_code_t nrf_drv_rtc_cc_disable(nrf_drv_rtc_t const * const p_instance, uint32_t channel); + +/**@brief Function for enabling tick. + * + * This function enables the tick event and optionally the interrupt. The function asserts if the instance is not + * powered on. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt. + */ +void nrf_drv_rtc_tick_enable(nrf_drv_rtc_t const * const p_instance, bool enable_irq); + +/**@brief Function for disabling tick. + * + * This function disables the tick event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_rtc_tick_disable(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for enabling overflow. + * + * This function enables the overflow event and optionally the interrupt. The function asserts if the instance is + * not powered on. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt. + */ +void nrf_drv_rtc_overflow_enable(nrf_drv_rtc_t const * const p_instance, bool enable_irq); + +/**@brief Function for disabling overflow. + * + * This function disables the overflow event and interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_rtc_overflow_disable(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for getting the maximum relative ticks value that can be set in the compare channel. + * + * When a SoftDevice is used, it occupies the highest level interrupt, so that the application code can be + * interrupted at any moment for a certain period of time. If Reliable mode is enabled, the provided + * maximum latency is taken into account and the return value is smaller than the RTC counter + * resolution. If Reliable mode is disabled, the return value equals the counter resolution. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval ticks Maximum ticks value. + */ +uint32_t nrf_drv_rtc_max_ticks_get(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for disabling all instance interrupts. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_mask Pointer to the location where the mask is filled. + */ +__STATIC_INLINE void nrf_drv_rtc_int_disable(nrf_drv_rtc_t const * const p_instance, + uint32_t * p_mask); + +/**@brief Function for enabling instance interrupts. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] mask Mask of interrupts to enable. + */ +__STATIC_INLINE void nrf_drv_rtc_int_enable(nrf_drv_rtc_t const * const p_instance, uint32_t mask); + +/**@brief Function for retrieving the current counter value. + * + * This function asserts if the instance is not powered on or if p_val is NULL. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval value Counter value. + */ +__STATIC_INLINE uint32_t nrf_drv_rtc_counter_get(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for clearing the counter value. + * + * This function asserts if the instance is not powered on. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +__STATIC_INLINE void nrf_drv_rtc_counter_clear(nrf_drv_rtc_t const * const p_instance); + +/**@brief Function for returning a requested task address for the RTC driver instance. + * + * This function asserts if the output pointer is NULL. The task address can be used by the PPI module. + * + * @param[in] p_instance Pointer to the instance. + * @param[in] task One of the peripheral tasks. + * + * @retval Address of task register. + */ +__STATIC_INLINE uint32_t nrf_drv_rtc_task_address_get(nrf_drv_rtc_t const * const p_instance, + nrf_rtc_task_t task); + +/**@brief Function for returning a requested event address for the RTC driver instance. + * + * This function asserts if the output pointer is NULL. The event address can be used by the PPI module. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] event One of the peripheral events. + * + * @retval Address of event register. + */ +__STATIC_INLINE uint32_t nrf_drv_rtc_event_address_get(nrf_drv_rtc_t const * const p_instance, + nrf_rtc_event_t event); +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE void nrf_drv_rtc_int_disable(nrf_drv_rtc_t const * const p_instance, + uint32_t * p_mask) +{ + *p_mask = nrf_rtc_int_get(p_instance->p_reg); + nrf_rtc_int_disable(p_instance->p_reg, NRF_RTC_INT_TICK_MASK | + NRF_RTC_INT_OVERFLOW_MASK | + NRF_RTC_INT_COMPARE0_MASK | + NRF_RTC_INT_COMPARE1_MASK | + NRF_RTC_INT_COMPARE2_MASK | + NRF_RTC_INT_COMPARE3_MASK); +} + +__STATIC_INLINE void nrf_drv_rtc_int_enable(nrf_drv_rtc_t const * const p_instance, uint32_t mask) +{ + nrf_rtc_int_enable(p_instance->p_reg, mask); +} + +__STATIC_INLINE uint32_t nrf_drv_rtc_counter_get(nrf_drv_rtc_t const * const p_instance) +{ + return nrf_rtc_counter_get(p_instance->p_reg); +} + +__STATIC_INLINE void nrf_drv_rtc_counter_clear(nrf_drv_rtc_t const * const p_instance) +{ + nrf_rtc_task_trigger(p_instance->p_reg,NRF_RTC_TASK_CLEAR); +} + +__STATIC_INLINE uint32_t nrf_drv_rtc_task_address_get(nrf_drv_rtc_t const * const p_instance, + nrf_rtc_task_t task) +{ + return nrf_rtc_task_address_get(p_instance->p_reg, task); +} + +__STATIC_INLINE uint32_t nrf_drv_rtc_event_address_get(nrf_drv_rtc_t const * const p_instance, + nrf_rtc_event_t event) +{ + return nrf_rtc_event_address_get(p_instance->p_reg, event); +} +#endif /* SUPPRESS_INLINE_IMPLEMENTATION */ + +/** + *@} + **/ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_DRV_RTC_H */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.c new file mode 100644 index 0000000000..804f46ef30 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.c @@ -0,0 +1,647 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(SAADC) +#include "nrf_drv_saadc.h" +#include "nrf_assert.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME saadc + +#if SAADC_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL SAADC_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR SAADC_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR SAADC_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \ + (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \ + (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \ + (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \ + (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \ + (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : "UNKNOWN EVENT")))))) +#else //SAADC_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //SAADC_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +typedef enum +{ + NRF_SAADC_STATE_IDLE = 0, + NRF_SAADC_STATE_BUSY = 1, + NRF_SAADC_STATE_CALIBRATION = 2 +} nrf_saadc_state_t; + + +typedef struct +{ + nrf_saadc_input_t pselp; + nrf_saadc_input_t pseln; +} nrf_saadc_psel_buffer; + +static const nrf_drv_saadc_config_t m_default_config = NRF_DRV_SAADC_DEFAULT_CONFIG; + +/** @brief SAADC control block.*/ +typedef struct +{ + nrf_drv_saadc_event_handler_t event_handler; ///< Event handler function pointer. + volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer. + volatile uint16_t buffer_size; ///< Size of the sample buffer. + volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer. + volatile nrf_saadc_state_t adc_state; ///< State of the SAADC. + uint32_t limits_enabled_flags; ///< Enabled limits flags. + uint16_t secondary_buffer_size; ///< Size of the secondary buffer. + uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer. + nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels. + nrf_drv_state_t state; ///< Driver initialization state. + uint8_t active_channels; ///< Number of enabled SAADC channels. + bool low_power_mode; ///< Indicates if low power mode is active. + bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer. +} nrf_drv_saadc_cb_t; + +static nrf_drv_saadc_cb_t m_cb; + +#define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1)) +#define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel)) +#define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \ + 4 * idx)) +#define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \ + (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8) +#define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \ + ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH) +#define HW_TIMEOUT 10000 + +void SAADC_IRQHandler(void) +{ + if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END)); + + if (!m_cb.low_power_mode || m_cb.conversions_end) + { + nrf_drv_saadc_evt_t evt; + evt.type = NRF_DRV_SAADC_EVT_DONE; + evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer; + evt.data.done.size = m_cb.buffer_size; + + if (m_cb.p_secondary_buffer == NULL) + { + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + m_cb.buffer_size_left = m_cb.secondary_buffer_size; + m_cb.p_buffer = m_cb.p_secondary_buffer; + m_cb.buffer_size = m_cb.secondary_buffer_size; + m_cb.p_secondary_buffer = NULL; + if (!m_cb.low_power_mode) + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + } + m_cb.event_handler(&evt); + m_cb.conversions_end = false; + } + } + if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED)); + + if (m_cb.buffer_size_left > m_cb.active_channels) + { + // More samples to convert than for single event. + m_cb.buffer_size_left -= m_cb.active_channels; + nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - + m_cb.buffer_size_left], + m_cb.active_channels); + } + else if ((m_cb.buffer_size_left == m_cb.active_channels) && + + (m_cb.p_secondary_buffer != NULL)) + { + // Samples to convert for one event, prepare next buffer. + m_cb.conversions_end = true; + m_cb.buffer_size_left = 0; + nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer, + m_cb.active_channels); + } + else if (m_cb.buffer_size_left == m_cb.active_channels) + { + // Samples to convert for one event, but no second buffer. + m_cb.conversions_end = true; + m_cb.buffer_size_left = 0; + } + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + } + if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); + NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE)); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + nrf_drv_saadc_evt_t evt; + evt.type = NRF_DRV_SAADC_EVT_CALIBRATEDONE; + m_cb.event_handler(&evt); + } + if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); + NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED)); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + uint32_t limit_flags = m_cb.limits_enabled_flags; + uint32_t flag_idx; + nrf_saadc_event_t event; + + while (limit_flags) + { + flag_idx = __CLZ(limit_flags); + limit_flags &= ~((1UL << 31) >> flag_idx); + event = FLAG_IDX_TO_EVENT(flag_idx); + if (nrf_saadc_event_check(event)) + { + nrf_saadc_event_clear(event); + nrf_drv_saadc_evt_t evt; + evt.type = NRF_DRV_SAADC_EVT_LIMIT; + evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); + evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); + NRF_LOG_DEBUG("Event limit, channel: %d, limit type: %d.", + evt.data.limit.channel, + evt.data.limit.limit_type); + m_cb.event_handler(&evt); + } + } + } +} + + +ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config, + nrf_drv_saadc_event_handler_t event_handler) +{ + ret_code_t err_code; + + if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if (event_handler == NULL) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + + m_cb.event_handler = event_handler; + nrf_saadc_resolution_set(p_config->resolution); + nrf_saadc_oversample_set(p_config->oversample); + m_cb.low_power_mode = p_config->low_power_mode; + m_cb.state = NRF_DRV_STATE_INITIALIZED; + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + m_cb.active_channels = 0; + m_cb.limits_enabled_flags = 0; + m_cb.conversions_end = false; + + nrf_saadc_int_disable(NRF_SAADC_INT_ALL); + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_drv_common_irq_enable(SAADC_IRQn, p_config->interrupt_priority); + nrf_saadc_int_enable(NRF_SAADC_INT_END); + + if (m_cb.low_power_mode) + { + nrf_saadc_int_enable(NRF_SAADC_INT_STARTED); + } + + nrf_saadc_enable(); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + + return err_code; +} + + +void nrf_drv_saadc_uninit(void) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_saadc_int_disable(NRF_SAADC_INT_ALL); + nrf_drv_common_irq_disable(SAADC_IRQn); + nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); + + // Wait for ADC being stopped. + uint32_t timeout = HW_TIMEOUT; + + while (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED) == 0 && timeout > 0) + { + --timeout; + } + ASSERT(timeout > 0); + + nrf_saadc_disable(); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel) + { + if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) + { + (void)nrf_drv_saadc_channel_uninit(channel); + } + } + + m_cb.state = NRF_DRV_STATE_UNINITIALIZED; +} + + +ret_code_t nrf_drv_saadc_channel_init(uint8_t channel, + nrf_saadc_channel_config_t const * const p_config) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); + // Oversampling can be used only with one channel. + ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) || + (m_cb.active_channels == 0)); + ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) && + (p_config->pin_p > NRF_SAADC_INPUT_DISABLED)); + ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD); + + ret_code_t err_code; + + // A channel can only be initialized if the driver is in the idle state. + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#ifdef NRF52_PAN_74 + if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) + { + nrf_saadc_disable(); + } +#endif //NRF52_PAN_74 + + if (!m_cb.psel[channel].pselp) + { + ++m_cb.active_channels; + } + m_cb.psel[channel].pselp = p_config->pin_p; + m_cb.psel[channel].pseln = p_config->pin_n; + nrf_saadc_channel_init(channel, p_config); + nrf_saadc_channel_input_set(channel, p_config->pin_p, p_config->pin_n); + +#ifdef NRF52_PAN_74 + if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) + { + nrf_saadc_enable(); + } +#endif //NRF52_PAN_74 + + NRF_LOG_INFO("Channel initialized: %d.", channel); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +ret_code_t nrf_drv_saadc_channel_uninit(uint8_t channel) +{ + ASSERT(channel < NRF_SAADC_CHANNEL_COUNT) + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + ret_code_t err_code; + + // A channel can only be uninitialized if the driver is in the idle state. + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (m_cb.psel[channel].pselp) + { + --m_cb.active_channels; + } + m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED; + m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED; + nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); + nrf_drv_saadc_limits_set(channel, NRF_DRV_SAADC_LIMITL_DISABLED, NRF_DRV_SAADC_LIMITH_DISABLED); + NRF_LOG_INFO("Channel denitialized: %d.", channel); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrf_drv_saadc_sample_task_get(void) +{ + return nrf_saadc_task_address_get( + m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE); +} + + +ret_code_t nrf_drv_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value) +{ + ret_code_t err_code; + + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + m_cb.adc_state = NRF_SAADC_STATE_BUSY; + nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); + nrf_saadc_buffer_init(p_value, 1); + if (m_cb.active_channels > 1) + { + for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) + { + nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); + } + } + nrf_saadc_channel_input_set(channel, + m_cb.psel[channel].pselp, m_cb.psel[channel].pseln); + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + + uint32_t timeout = HW_TIMEOUT; + + while (0 == nrf_saadc_event_check(NRF_SAADC_EVENT_END) && timeout > 0) + { + timeout--; + } + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + + NRF_LOG_INFO("Conversion value: %d, channel: %d.", *p_value & 0x0000FFFF, channel); + + if (m_cb.active_channels > 1) + { + for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) + { + nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln); + } + } + + if (m_cb.low_power_mode) + { + nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); + } + else + { + nrf_saadc_int_enable(NRF_SAADC_INT_END); + } + + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + err_code = NRF_SUCCESS; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +ret_code_t nrf_drv_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT((size % m_cb.active_channels) == 0); + ret_code_t err_code; + + + nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); + if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) + { + nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if (m_cb.adc_state == NRF_SAADC_STATE_BUSY) + { + if ( m_cb.p_secondary_buffer) + { + nrf_saadc_int_enable(NRF_SAADC_INT_END); + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + else + { + m_cb.p_secondary_buffer = p_buffer; + m_cb.secondary_buffer_size = size; + if (!m_cb.low_power_mode) + { + while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_buffer_init(p_buffer, size); + } + nrf_saadc_int_enable(NRF_SAADC_INT_END); + err_code = NRF_SUCCESS; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + } + nrf_saadc_int_enable(NRF_SAADC_INT_END); + m_cb.adc_state = NRF_SAADC_STATE_BUSY; + + m_cb.p_buffer = p_buffer; + m_cb.buffer_size = size; + m_cb.p_secondary_buffer = NULL; + + NRF_LOG_INFO("Function: %d, buffer length: %d, active channels: %d.", + (uint32_t)__func__, size, m_cb.active_channels); + + if (m_cb.low_power_mode) + { + m_cb.buffer_size_left = size; + nrf_saadc_buffer_init(p_buffer, m_cb.active_channels); + } + else + { + nrf_saadc_buffer_init(p_buffer, size); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +ret_code_t nrf_drv_saadc_sample() +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + ret_code_t err_code = NRF_SUCCESS; + if (m_cb.adc_state != NRF_SAADC_STATE_BUSY) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (m_cb.low_power_mode) + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + else + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + } + + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +ret_code_t nrf_drv_saadc_calibrate_offset() +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + + ret_code_t err_code; + + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION; + + nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); + nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE); + nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +bool nrf_drv_saadc_is_busy(void) +{ + return (m_cb.adc_state != NRF_SAADC_STATE_IDLE); +} + + +void nrf_drv_saadc_abort(void) +{ + if (nrf_drv_saadc_is_busy()) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); + nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); + + if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) + { + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + // Wait for ADC being stopped. + uint32_t timeout = HW_TIMEOUT; + + while ((m_cb.adc_state != NRF_SAADC_STATE_IDLE) && (timeout > 0)) + { + --timeout; + } + ASSERT(timeout > 0); + } + + m_cb.p_buffer = 0; + m_cb.p_secondary_buffer = 0; + NRF_LOG_INFO("Conversion aborted."); + } +} + + +void nrf_drv_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high) +{ + ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(m_cb.event_handler); // only non blocking mode supported + ASSERT(limit_low >= NRF_DRV_SAADC_LIMITL_DISABLED); + ASSERT(limit_high <= NRF_DRV_SAADC_LIMITH_DISABLED); + ASSERT(limit_low < limit_high); + nrf_saadc_channel_limits_set(channel, limit_low, limit_high); + + uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW); + if (limit_low == NRF_DRV_SAADC_LIMITL_DISABLED) + { + m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_disable(int_mask); + } + else + { + m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_enable(int_mask); + } + + int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH); + if (limit_high == NRF_DRV_SAADC_LIMITH_DISABLED) + { + m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_disable(int_mask); + } + else + { + m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_enable(int_mask); + } +} +#endif //NRF_MODULE_ENABLED(SAADC) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.h new file mode 100644 index 0000000000..45b4204e70 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/saadc/nrf_drv_saadc.h @@ -0,0 +1,326 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_saadc SAADC HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52 Successive Approximation Analog-to-Digital Converter (SAADC) APIs. + * @details The SAADC HAL provides basic APIs for accessing the registers of the SAADC peripheral. + * The SAADC driver provides APIs on a higher level. + * + * @defgroup nrf_drv_saadc SAADC driver + * @{ + * @ingroup nrf_saadc + * + * @brief @tagAPI52 Successive Approximation Analog-to-Digital Converter (SAADC) driver. + */ + +#ifndef NRF_DRV_SAADC_H__ +#define NRF_DRV_SAADC_H__ + +#include "sdk_config.h" +#include "nrf_saadc.h" +#include "sdk_errors.h" +#include "nrf_drv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Value that should be set as high limit to disable limit detection. + */ +#define NRF_DRV_SAADC_LIMITH_DISABLED (2047) +/** + * @brief Value that should be set as low limit to disable limit detection. + */ +#define NRF_DRV_SAADC_LIMITL_DISABLED (-2048) + +/** + * @brief Macro for setting @ref nrf_drv_saadc_config_t to default settings. + */ +#define NRF_DRV_SAADC_DEFAULT_CONFIG \ + { \ + .resolution = (nrf_saadc_resolution_t)SAADC_CONFIG_RESOLUTION, \ + .oversample = (nrf_saadc_oversample_t)SAADC_CONFIG_OVERSAMPLE, \ + .interrupt_priority = SAADC_CONFIG_IRQ_PRIORITY, \ + .low_power_mode = SAADC_CONFIG_LP_MODE \ + } + +/** + * @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings + * in single ended mode. + * + * @param PIN_P Analog input. + */ +#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \ + { \ + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \ + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \ + .gain = NRF_SAADC_GAIN1_6, \ + .reference = NRF_SAADC_REFERENCE_INTERNAL, \ + .acq_time = NRF_SAADC_ACQTIME_10US, \ + .mode = NRF_SAADC_MODE_SINGLE_ENDED, \ + .burst = NRF_SAADC_BURST_DISABLED, \ + .pin_p = (nrf_saadc_input_t)(PIN_P), \ + .pin_n = NRF_SAADC_INPUT_DISABLED \ + } + +/** + * @brief Macro for setting @ref nrf_saadc_channel_config_t to default settings + * in differential mode. + * + * @param PIN_P Positive analog input. + * @param PIN_N Negative analog input. + */ +#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \ + { \ + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \ + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \ + .gain = NRF_SAADC_GAIN1_6, \ + .reference = NRF_SAADC_REFERENCE_INTERNAL, \ + .acq_time = NRF_SAADC_ACQTIME_10US, \ + .mode = NRF_SAADC_MODE_DIFFERENTIAL, \ + .pin_p = (nrf_saadc_input_t)(PIN_P), \ + .pin_n = (nrf_saadc_input_t)(PIN_N) \ + } + +/** + * @brief Analog-to-digital converter driver configuration structure. + */ +typedef struct +{ + nrf_saadc_resolution_t resolution; ///< Resolution configuration. + nrf_saadc_oversample_t oversample; ///< Oversampling configuration. + uint8_t interrupt_priority; ///< Interrupt priority. + bool low_power_mode; ///< Indicates if low power mode is active. +} nrf_drv_saadc_config_t; + +/** + * @brief Driver event types. + */ +typedef enum +{ + NRF_DRV_SAADC_EVT_DONE, ///< Event generated when the buffer is filled with samples. + NRF_DRV_SAADC_EVT_LIMIT, ///< Event generated after one of the limits is reached. + NRF_DRV_SAADC_EVT_CALIBRATEDONE ///< Event generated when the calibration is complete. +} nrf_drv_saadc_evt_type_t; + +/** + * @brief Analog-to-digital converter driver done event data. + */ +typedef struct +{ + nrf_saadc_value_t * p_buffer; ///< Pointer to buffer with converted samples. + uint16_t size; ///< Number of samples in the buffer. +} nrf_drv_saadc_done_evt_t; + +/** + * @brief Analog-to-digital converter driver limit event data. + */ +typedef struct +{ + uint8_t channel; ///< Channel on which the limit was detected. + nrf_saadc_limit_t limit_type; ///< Type of limit detected. +} nrf_drv_saadc_limit_evt_t; + +/** + * @brief Analog-to-digital converter driver event structure. + */ +typedef struct +{ + nrf_drv_saadc_evt_type_t type; ///< Event type. + union + { + nrf_drv_saadc_done_evt_t done; ///< Data for @ref NRF_DRV_SAADC_EVT_DONE event. + nrf_drv_saadc_limit_evt_t limit; ///< Data for @ref NRF_DRV_SAADC_EVT_LIMIT event. + } data; +} nrf_drv_saadc_evt_t; + +/** + * @brief ADC event handler. + * + * @param[in] p_event Pointer to an ADC event. The event structure is allocated on + * the stack, so it is valid only within the context of + * the event handler. + */ +typedef void (* nrf_drv_saadc_event_handler_t)(nrf_drv_saadc_evt_t const * p_event); + +/** + * @brief Function for initializing the SAADC. + * + * @param[in] p_config Pointer to a configuration structure. If NULL, the default one is used. + * @param[in] event_handler Event handler provided by the user. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is already initialized. + * @retval NRF_ERROR_INVALID_PARAM If event_handler is NULL. + */ +ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config, + nrf_drv_saadc_event_handler_t event_handler); + +/** + * @brief Function for uninitializing the SAADC. + * + * This function stops all ongoing conversions and disables all channels. + */ +void nrf_drv_saadc_uninit(void); + + +/** + * @brief Function for getting the address of a SAMPLE SAADC task. + * + * @return Task address. + */ +uint32_t nrf_drv_saadc_sample_task_get(void); + +/** + * @brief Function for initializing an SAADC channel. + * + * This function configures and enables the channel. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the ADC was not initialized. + * @retval NRF_ERROR_NO_MEM If the specified channel was already allocated. + */ +ret_code_t nrf_drv_saadc_channel_init(uint8_t channel, + nrf_saadc_channel_config_t const * const p_config); + + +/** + * @brief Function for uninitializing an SAADC channel. + * + * @retval NRF_SUCCESS If uninitialization was successful. + * @retval NRF_ERROR_BUSY If the ADC is busy. + */ +ret_code_t nrf_drv_saadc_channel_uninit(uint8_t channel); + +/** + * @brief Function for starting SAADC sampling. + * + * @retval NRF_SUCCESS If ADC sampling was triggered. + * @retval NRF_ERROR_INVALID_STATE If ADC is in idle state. + */ +ret_code_t nrf_drv_saadc_sample(void); + +/** + * @brief Blocking function for executing a single ADC conversion. + * + * This function selects the desired input, starts a single conversion, + * waits for it to finish, and returns the result. + * + * The function will fail if ADC is busy. + * + * @param[in] channel Channel. + * @param[out] p_value Pointer to the location where the result should be placed. + * + * @retval NRF_SUCCESS If conversion was successful. + * @retval NRF_ERROR_BUSY If the ADC driver is busy. + */ +ret_code_t nrf_drv_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value); + +/** + * @brief Function for issuing conversion of data to the buffer. + * + * This function is non-blocking. The application is notified about filling the buffer by the event handler. + * Conversion will be done on all enabled channels. If the ADC is in idle state, the function will set up Easy + * DMA for the conversion. The ADC will be ready for sampling and wait for the SAMPLE task. It can be + * triggered manually by the @ref nrf_drv_saadc_sample function or by PPI using the @ref NRF_SAADC_TASK_SAMPLE + * task. If one buffer is already set and the conversion is ongoing, calling this function will + * result in queuing the given buffer. The driver will start filling the issued buffer when the first one is + * completed. If the function is called again before the first buffer is filled or calibration is in progress, + * it will return with error. + * + * @param[in] buffer Result buffer. + * @param[in] size Buffer size in words. + * + * @retval NRF_SUCCESS If conversion was successful. + * @retval NRF_ERROR_BUSY If the driver already has two buffers set or calibration is in progress. + */ +ret_code_t nrf_drv_saadc_buffer_convert(nrf_saadc_value_t * buffer, uint16_t size); + +/** + * @brief Function for triggering the ADC offset calibration. + * + * This function is non-blocking. The application is notified about completion by the event handler. + * Calibration will also trigger DONE and RESULTDONE events. + * + * The function will fail if ADC is busy or calibration is already in progress. + * + * @retval NRF_SUCCESS If calibration was started successfully. + * @retval NRF_ERROR_BUSY If the ADC driver is busy. + */ +ret_code_t nrf_drv_saadc_calibrate_offset(void); + +/** + * @brief Function for retrieving the SAADC state. + * + * @retval true If the ADC is busy. + * @retval false If the ADC is ready. + */ +bool nrf_drv_saadc_is_busy(void); + +/** + * @brief Function for aborting ongoing and buffered conversions. + * @note @ref NRF_DRV_SAADC_EVT_DONE event will be generated if there is a conversion in progress. + * Event will contain number of words in the sample buffer. + */ +void nrf_drv_saadc_abort(void); + +/** + * @brief Function for setting the SAADC channel limits. + * When limits are enabled and the result exceeds the defined bounds, the limit handler function is called. + * + * @param[in] channel SAADC channel number. + * @param[in] limit_low Lower limit (valid values from @ref NRF_DRV_SAADC_LIMITL_DISABLED to + * @ref NRF_DRV_SAADC_LIMITH_DISABLED). Conversion results below this value will trigger + * the handler function. Set to @ref NRF_DRV_SAADC_LIMITL_DISABLED to disable this limit. + * @param[in] limit_high Upper limit (valid values from @ref NRF_DRV_SAADC_LIMITL_DISABLED to + * @ref NRF_DRV_SAADC_LIMITH_DISABLED). Conversion results above this value will trigger + * the handler function. Set to @ref NRF_DRV_SAADC_LIMITH_DISABLED to disable this limit. + */ +void nrf_drv_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SAADC_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/config/sdio_config.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/config/sdio_config.h new file mode 100644 index 0000000000..f59e553c3d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/config/sdio_config.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDIO_CONFIG_H +#define SDIO_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDIO_CONFIG_CLOCK_PIN_NUMBER 24 +#define SDIO_CONFIG_DATA_PIN_NUMBER 25 + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.c new file mode 100644 index 0000000000..381c77d36a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2009 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + +#include "nrf.h" +#include "nrf_delay.h" +#include "sdio.h" +#include "nrf_gpio.h" + +#include "sdio_config.h" + +/*lint ++flb "Enter library region" */ + +/*lint -e717 -save "Suppress do {} while (0) for these macros" */ +#define SDIO_CLOCK_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line high */ +#define SDIO_CLOCK_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Pulls SCL line low */ +#define SDIO_DATA_HIGH() do { NRF_GPIO->OUTSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line high */ +#define SDIO_DATA_LOW() do { NRF_GPIO->OUTCLR = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Pulls SDA line low */ +#define SDIO_DATA_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_DATA_PIN_NUMBER); } while (0) /*!< Configures SDA pin as output */ +#define SDIO_CLOCK_OUTPUT() do { NRF_GPIO->DIRSET = (1UL << SDIO_CONFIG_CLOCK_PIN_NUMBER); } while (0) /*!< Configures SCL pin as output */ +/*lint -restore */ + +/*lint -emacro(845,SDIO_DATA_INPUT) // A zero has been given as right argument to operator '|'" */ + +#define SDIO_DATA_INPUT() do { \ + nrf_gpio_cfg_input(25, NRF_GPIO_PIN_NOPULL); \ +} while (0) + +#define SDIO_DATA_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_DATA_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SDA */ +#define SDIO_CLOCK_READ() ((NRF_GPIO->IN >> SDIO_CONFIG_CLOCK_PIN_NUMBER) & 0x1UL) /*!< Reads current state of SCL */ +#define SDIO_DELAY() nrf_delay_us(10) /*!< Time to wait when pin states are changed. For fast-mode the delay can be zero and for standard-mode 4 us delay is sufficient. */ + +void sdio_init(void) +{ + SDIO_CLOCK_HIGH(); + SDIO_DATA_HIGH(); + SDIO_CLOCK_OUTPUT(); + SDIO_DATA_INPUT(); + + // If slave is stuck in the middle of transfer, clock out bits until the slave ACKs the transfer + for (uint_fast8_t i = 16; i--;) + { + SDIO_DELAY(); + SDIO_CLOCK_LOW(); + SDIO_DELAY(); + SDIO_CLOCK_HIGH(); + SDIO_DELAY(); + + if (SDIO_DATA_READ()) + { + break; + } + } + + for (uint_fast8_t i = 5; i--;) + { + SDIO_DELAY(); + SDIO_CLOCK_LOW(); + SDIO_DELAY(); + SDIO_CLOCK_HIGH(); + } + + SDIO_DATA_OUTPUT(); + SDIO_DATA_HIGH(); + + SDIO_DELAY(); +} + +uint8_t sdio_read_byte(uint8_t address) +{ + uint8_t data_byte = 0; + + SDIO_DATA_OUTPUT(); + + for (uint_fast8_t i = 8; i--;) + { + SDIO_DELAY(); + + SDIO_CLOCK_LOW(); + + if (address & (1U << i)) + { + SDIO_DATA_HIGH(); + } + else + { + SDIO_DATA_LOW(); + } + + SDIO_DELAY(); + + SDIO_CLOCK_HIGH(); + } + + nrf_delay_us(20); + + SDIO_DATA_INPUT(); + + for (uint_fast8_t i = 8; i--;) + { + SDIO_CLOCK_LOW(); + SDIO_DELAY(); + SDIO_CLOCK_HIGH(); + SDIO_DELAY(); + data_byte |= (uint8_t)(SDIO_DATA_READ() << i); + } + + SDIO_DATA_HIGH(); + SDIO_DATA_OUTPUT(); + + SDIO_DELAY(); + + return data_byte; +} + +void sdio_read_burst(uint8_t * target_buffer, uint8_t target_buffer_size) +{ + uint_fast8_t address = 0x63; + + SDIO_DATA_OUTPUT(); + + for (uint_fast8_t bit_index=8; bit_index--;) + { + SDIO_CLOCK_LOW(); + + if (address & (1U << bit_index)) + { + SDIO_DATA_HIGH(); + } + else + { + SDIO_DATA_LOW(); + } + + SDIO_CLOCK_HIGH(); + } + + SDIO_DATA_INPUT(); + + for (uint_fast8_t target_buffer_index = 0; target_buffer_index < target_buffer_size; target_buffer_index++) + { + target_buffer[target_buffer_index] = 0; + + for (uint_fast8_t bit_index = 8; bit_index--;) + { + SDIO_CLOCK_LOW(); + SDIO_CLOCK_HIGH(); + target_buffer[target_buffer_index] |= (uint8_t)(SDIO_DATA_READ() << bit_index); + } + } +} + +void sdio_write_byte(uint8_t address, uint8_t data_byte) +{ + // Add write indication bit + address |= 0x80; + + SDIO_DATA_OUTPUT(); + + for (uint_fast8_t i = 8; i--;) + { + SDIO_DELAY(); + + SDIO_CLOCK_LOW(); + + if (address & (1U << i)) + { + SDIO_DATA_HIGH(); + } + else + { + SDIO_DATA_LOW(); + } + + SDIO_DELAY(); + + SDIO_CLOCK_HIGH(); + } + + SDIO_DELAY(); + + for (uint_fast8_t i = 8; i--;) + { + SDIO_CLOCK_LOW(); + + if (data_byte & (1U << i)) + { + SDIO_DATA_HIGH(); + } + else + { + SDIO_DATA_LOW(); + } + + SDIO_DELAY(); + + SDIO_CLOCK_HIGH(); + + SDIO_DELAY(); + } + + SDIO_DATA_HIGH(); + + SDIO_DELAY(); +} + +/*lint --flb "Leave library region" */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.h new file mode 100644 index 0000000000..e52e7e9872 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/sdio/sdio.h @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2009 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDIO_H +#define SDIO_H + +/*lint ++flb "Enter library region" */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file +* @brief 2-wire serial interface driver (compatible with ADNS2080 mouse sensor driver) +* +* +* @defgroup nrf_drivers_sdio SDIO driver +* @{ +* @ingroup nrf_drivers +* @brief 2-wire serial interface driver. +*/ + +/** + * @brief Function for initializing 2-wire serial interface and trying to handle stuck slaves. + * + */ +void sdio_init(void); + +/** + * @brief Function for reading a byte over 2-wire serial interface. + * + * Developer needs to implement this function in a way that suits the hardware. + * @param address Register address to read from + * @return Byte read + */ +uint8_t sdio_read_byte(uint8_t address); + +/** + * @brief Function for reading several bytes over 2-wire serial interface using burst mode. + * + * Developer needs to implement this function in a way that suits the hardware. + * @param target_buffer Buffer location to store read bytes to + * @param target_buffer_size Bytes allocated for target_buffer + */ +void sdio_read_burst(uint8_t *target_buffer, uint8_t target_buffer_size); + +/** + * @brief Function for writing a byte over 2-wire serial interface. + * + * Developer needs to implement this function in a way that suits the hardware. + * @param address Register address to write to + * @param data_byte Data byte to write + */ +void sdio_write_byte(uint8_t address, uint8_t data_byte); + +/** + *@} + **/ + +/*lint --flb "Leave library region" */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.c new file mode 100644 index 0000000000..88459e5b53 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.c @@ -0,0 +1,774 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(SPI) +#include "nrf_drv_spi.h" +#if ENABLED_SPI_COUNT +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "nrf_assert.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME spi + + +#if SPI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL SPI_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR SPI_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR SPI_CONFIG_DEBUG_COLOR + +#else //SPI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //SPI_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +#define SPIM_ONLY ( defined(SPIM_PRESENT) && !defined(SPI_PRESENT)) +#define SPI_SPIM_PRESENT ( defined(SPIM_PRESENT) && defined(SPI_PRESENT)) +#define SPI_ONLY (!defined(SPIM_PRESENT) && defined(SPI_PRESENT)) + +#define SPI0_WITH_DMA (defined(SPI0_USE_EASY_DMA) && SPI0_USE_EASY_DMA && SPI0_ENABLED) +#define SPI1_WITH_DMA (defined(SPI1_USE_EASY_DMA) && SPI1_USE_EASY_DMA && SPI1_ENABLED) +#define SPI2_WITH_DMA (defined(SPI2_USE_EASY_DMA) && SPI2_USE_EASY_DMA && SPI2_ENABLED) + +#define SPI0_WITHOUT_DMA (defined(SPI0_USE_EASY_DMA) && !SPI0_USE_EASY_DMA && SPI0_ENABLED) +#define SPI1_WITHOUT_DMA (defined(SPI1_USE_EASY_DMA) && !SPI1_USE_EASY_DMA && SPI1_ENABLED) +#define SPI2_WITHOUT_DMA (defined(SPI2_USE_EASY_DMA) && !SPI2_USE_EASY_DMA && SPI2_ENABLED) + +// suppress: non-standard use of 'defined' preprocessor operator +/*lint -save -e491*/ +#if (SPI_ONLY && ENABLED_SPI_COUNT) || ((SPI_SPIM_PRESENT) && \ + (SPI0_WITHOUT_DMA || SPI1_WITHOUT_DMA || SPI2_WITHOUT_DMA)) + #define SPI_IN_USE 1 +#endif + +#if (SPIM_ONLY && ENABLED_SPI_COUNT) || ((SPI_SPIM_PRESENT) && \ + (SPI0_WITH_DMA || SPI1_WITH_DMA || SPI2_WITH_DMA)) + #define SPIM_IN_USE 1 +#endif + + +#if defined(SPIM_IN_USE) && defined(SPI_IN_USE) + // SPIM and SPI combined + #define CODE_FOR_SPIM(code) if (p_instance->use_easy_dma) { code } + #define CODE_FOR_SPI(code) else { code } +#elif defined(SPIM_IN_USE) && !defined(SPI_IN_USE) + // SPIM only + #define CODE_FOR_SPIM(code) { code } + #define CODE_FOR_SPI(code) +#elif !defined(SPIM_IN_USE) && defined(SPI_IN_USE) + // SPI only + #define CODE_FOR_SPIM(code) + #define CODE_FOR_SPI(code) { code } +#else + #error "Wrong configuration." +#endif + +#ifdef SPIM_IN_USE +#define END_INT_MASK NRF_SPIM_INT_END_MASK +#endif + +// Control block - driver instance local data. +typedef struct +{ + nrf_drv_spi_evt_handler_t handler; + void * p_context; + nrf_drv_spi_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy. + nrf_drv_state_t state; + volatile bool transfer_in_progress; + + // [no need for 'volatile' attribute for the following members, as they + // are not concurrently used in IRQ handlers and main line code] + uint8_t ss_pin; + uint8_t orc; + uint8_t bytes_transferred; + +#if NRF_MODULE_ENABLED(SPIM_NRF52_ANOMALY_109_WORKAROUND) + uint8_t tx_length; + uint8_t rx_length; +#endif + + bool tx_done : 1; + bool rx_done : 1; + bool abort : 1; +} spi_control_block_t; +static spi_control_block_t m_cb[ENABLED_SPI_COUNT]; + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n + #define IRQ_HANDLER(n) static void IRQ_HANDLER_NAME(n)(void) + + #if NRF_MODULE_ENABLED(SPI0) + IRQ_HANDLER(0); + #endif + #if NRF_MODULE_ENABLED(SPI1) + IRQ_HANDLER(1); + #endif + #if NRF_MODULE_ENABLED(SPI2) + IRQ_HANDLER(2); + #endif + static nrf_drv_irq_handler_t const m_irq_handlers[ENABLED_SPI_COUNT] = { + #if NRF_MODULE_ENABLED(SPI0) + IRQ_HANDLER_NAME(0), + #endif + #if NRF_MODULE_ENABLED(SPI1) + IRQ_HANDLER_NAME(1), + #endif + #if NRF_MODULE_ENABLED(SPI2) + IRQ_HANDLER_NAME(2), + #endif + }; +#else + #define IRQ_HANDLER(n) void SPI##n##_IRQ_HANDLER(void) +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +ret_code_t nrf_drv_spi_init(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_config_t const * p_config, + nrf_drv_spi_evt_handler_t handler, + void * p_context) +{ + ASSERT(p_config); + spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ret_code_t err_code; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(p_instance->p_registers, + m_irq_handlers[p_instance->drv_inst_idx]) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif + + p_cb->handler = handler; + p_cb->p_context = p_context; + + uint32_t mosi_pin; + uint32_t miso_pin; + // Configure pins used by the peripheral: + // - SCK - output with initial value corresponding with the SPI mode used: + // 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1); + // according to the reference manual guidelines this pin and its input + // buffer must always be connected for the SPI to work. + if (p_config->mode <= NRF_DRV_SPI_MODE_1) + { + nrf_gpio_pin_clear(p_config->sck_pin); + } + else + { + nrf_gpio_pin_set(p_config->sck_pin); + } + nrf_gpio_cfg(p_config->sck_pin, + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + // - MOSI (optional) - output with initial value 0, + if (p_config->mosi_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + mosi_pin = p_config->mosi_pin; + nrf_gpio_pin_clear(mosi_pin); + nrf_gpio_cfg_output(mosi_pin); + } + else + { + mosi_pin = NRF_SPI_PIN_NOT_CONNECTED; + } + // - MISO (optional) - input, + if (p_config->miso_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + miso_pin = p_config->miso_pin; + nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRF_SPI_DRV_MISO_PULLUP_CFG); + } + else + { + miso_pin = NRF_SPI_PIN_NOT_CONNECTED; + } + // - Slave Select (optional) - output with initial value 1 (inactive). + if (p_config->ss_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + nrf_gpio_pin_set(p_config->ss_pin); + nrf_gpio_cfg_output(p_config->ss_pin); + } + m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin; + + CODE_FOR_SPIM + ( + NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_registers; + nrf_spim_pins_set(p_spim, p_config->sck_pin, mosi_pin, miso_pin); + nrf_spim_frequency_set(p_spim, + (nrf_spim_frequency_t)p_config->frequency); + nrf_spim_configure(p_spim, + (nrf_spim_mode_t)p_config->mode, + (nrf_spim_bit_order_t)p_config->bit_order); + + nrf_spim_orc_set(p_spim, p_config->orc); + + if (p_cb->handler) + { + nrf_spim_int_enable(p_spim, END_INT_MASK); + } + + nrf_spim_enable(p_spim); + ) + CODE_FOR_SPI + ( + NRF_SPI_Type * p_spi = p_instance->p_registers; + nrf_spi_pins_set(p_spi, p_config->sck_pin, mosi_pin, miso_pin); + nrf_spi_frequency_set(p_spi, + (nrf_spi_frequency_t)p_config->frequency); + nrf_spi_configure(p_spi, + (nrf_spi_mode_t)p_config->mode, + (nrf_spi_bit_order_t)p_config->bit_order); + + m_cb[p_instance->drv_inst_idx].orc = p_config->orc; + + if (p_cb->handler) + { + nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK); + } + + nrf_spi_enable(p_spi); + ) + + if (p_cb->handler) + { + nrf_drv_common_irq_enable(p_instance->irq, p_config->irq_priority); + } + + p_cb->transfer_in_progress = false; + p_cb->state = NRF_DRV_STATE_INITIALIZED; + + NRF_LOG_INFO("Init"); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_spi_uninit(nrf_drv_spi_t const * const p_instance) +{ + spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + if (p_cb->handler) + { + nrf_drv_common_irq_disable(p_instance->irq); + } + + #define DISABLE_ALL 0xFFFFFFFF + + CODE_FOR_SPIM + ( + NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_registers; + if (p_cb->handler) + { + nrf_spim_int_disable(p_spim, DISABLE_ALL); + if (p_cb->transfer_in_progress) + { + // Ensure that SPI is not performing any transfer. + nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP); + while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED)) {} + p_cb->transfer_in_progress = false; + } + } + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + nrf_spim_disable(p_spim); + ) + CODE_FOR_SPI + ( + NRF_SPI_Type * p_spi = p_instance->p_registers; + if (p_cb->handler) + { + nrf_spi_int_disable(p_spi, DISABLE_ALL); + } + nrf_spi_disable(p_spi); + ) + #undef DISABLE_ALL + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(p_instance->p_registers); +#endif + + p_cb->state = NRF_DRV_STATE_UNINITIALIZED; +} + +ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance, + uint8_t const * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length) +{ + nrf_drv_spi_xfer_desc_t xfer_desc; + xfer_desc.p_tx_buffer = p_tx_buffer; + xfer_desc.p_rx_buffer = p_rx_buffer; + xfer_desc.tx_length = tx_buffer_length; + xfer_desc.rx_length = rx_buffer_length; + + NRF_LOG_INFO("Transfer tx_len:%d, rx_len:%d.", tx_buffer_length, rx_buffer_length); + NRF_LOG_DEBUG("Tx data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_tx_buffer, tx_buffer_length * sizeof(p_tx_buffer[0])); + return nrf_drv_spi_xfer(p_instance, &xfer_desc, 0); +} + +static void finish_transfer(spi_control_block_t * p_cb) +{ + // If Slave Select signal is used, this is the time to deactivate it. + if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + nrf_gpio_pin_set(p_cb->ss_pin); + } + + // By clearing this flag before calling the handler we allow subsequent + // transfers to be started directly from the handler function. + p_cb->transfer_in_progress = false; + p_cb->evt.type = NRF_DRV_SPI_EVENT_DONE; + NRF_LOG_INFO("Transfer completed rx_len:%d.", p_cb->evt.data.done.rx_length); + NRF_LOG_DEBUG("Rx data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_cb->evt.data.done.p_rx_buffer, + p_cb->evt.data.done.rx_length * + sizeof(p_cb->evt.data.done.p_rx_buffer[0])); + p_cb->handler(&p_cb->evt, p_cb->p_context); +} + +#ifdef SPI_IN_USE +// This function is called from IRQ handler or, in blocking mode, directly +// from the 'nrf_drv_spi_transfer' function. +// It returns true as long as the transfer should be continued, otherwise (when +// there is nothing more to send/receive) it returns false. +static bool transfer_byte(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb) +{ + // Read the data byte received in this transfer and store it in RX buffer, + // if needed. + volatile uint8_t rx_data = nrf_spi_rxd_get(p_spi); + if (p_cb->bytes_transferred < p_cb->evt.data.done.rx_length) + { + p_cb->evt.data.done.p_rx_buffer[p_cb->bytes_transferred] = rx_data; + } + + ++p_cb->bytes_transferred; + + // Check if there are more bytes to send or receive and write proper data + // byte (next one from TX buffer or over-run character) to the TXD register + // when needed. + // NOTE - we've already used 'p_cb->bytes_transferred + 1' bytes from our + // buffers, because we take advantage of double buffering of TXD + // register (so in effect one byte is still being transmitted now); + // see how the transfer is started in the 'nrf_drv_spi_transfer' + // function. + uint16_t bytes_used = p_cb->bytes_transferred + 1; + + if (p_cb->abort) + { + if (bytes_used < p_cb->evt.data.done.tx_length) + { + p_cb->evt.data.done.tx_length = bytes_used; + } + if (bytes_used < p_cb->evt.data.done.rx_length) + { + p_cb->evt.data.done.rx_length = bytes_used; + } + } + + if (bytes_used < p_cb->evt.data.done.tx_length) + { + nrf_spi_txd_set(p_spi, p_cb->evt.data.done.p_tx_buffer[bytes_used]); + return true; + } + else if (bytes_used < p_cb->evt.data.done.rx_length) + { + nrf_spi_txd_set(p_spi, p_cb->orc); + return true; + } + + return (p_cb->bytes_transferred < p_cb->evt.data.done.tx_length || + p_cb->bytes_transferred < p_cb->evt.data.done.rx_length); +} + +static void spi_xfer(NRF_SPI_Type * p_spi, + spi_control_block_t * p_cb, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc) +{ + p_cb->bytes_transferred = 0; + nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK); + + nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); + + // Start the transfer by writing some byte to the TXD register; + // if TX buffer is not empty, take the first byte from this buffer, + // otherwise - use over-run character. + nrf_spi_txd_set(p_spi, + (p_xfer_desc->tx_length > 0 ? p_xfer_desc->p_tx_buffer[0] : p_cb->orc)); + + // TXD register is double buffered, so next byte to be transmitted can + // be written immediately, if needed, i.e. if TX or RX transfer is to + // be more that 1 byte long. Again - if there is something more in TX + // buffer send it, otherwise use over-run character. + if (p_xfer_desc->tx_length > 1) + { + nrf_spi_txd_set(p_spi, p_xfer_desc->p_tx_buffer[1]); + } + else if (p_xfer_desc->rx_length > 1) + { + nrf_spi_txd_set(p_spi, p_cb->orc); + } + + // For blocking mode (user handler not provided) wait here for READY + // events (indicating that the byte from TXD register was transmitted + // and a new incoming byte was moved to the RXD register) and continue + // transaction until all requested bytes are transferred. + // In non-blocking mode - IRQ service routine will do this stuff. + if (p_cb->handler) + { + nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK); + } + else + { + do { + while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {} + nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); + NRF_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY."); + } while (transfer_byte(p_spi, p_cb)); + if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + nrf_gpio_pin_set(p_cb->ss_pin); + } + } +} +#endif // SPI_IN_USE + +#ifdef SPIM_IN_USE +__STATIC_INLINE void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable) +{ + if (!enable) + { + nrf_spim_int_disable(p_spim, END_INT_MASK); + } + else + { + nrf_spim_int_enable(p_spim, END_INT_MASK); + } +} + +__STATIC_INLINE void spim_list_enable_handle(NRF_SPIM_Type * p_spim, uint32_t flags) +{ + if (NRF_DRV_SPI_FLAG_TX_POSTINC & flags) + { + nrf_spim_tx_list_enable(p_spim); + } + else + { + nrf_spim_tx_list_disable(p_spim); + } + + if (NRF_DRV_SPI_FLAG_RX_POSTINC & flags) + { + nrf_spim_rx_list_enable(p_spim); + } + else + { + nrf_spim_rx_list_disable(p_spim); + } +} + +static ret_code_t spim_xfer(NRF_SPIM_Type * p_spim, + spi_control_block_t * p_cb, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + ret_code_t err_code; + // EasyDMA requires that transfer buffers are placed in Data RAM region; + // signal error if they are not. + if ((p_xfer_desc->p_tx_buffer != NULL && !nrf_drv_is_in_RAM(p_xfer_desc->p_tx_buffer)) || + (p_xfer_desc->p_rx_buffer != NULL && !nrf_drv_is_in_RAM(p_xfer_desc->p_rx_buffer))) + { + p_cb->transfer_in_progress = false; + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#if NRF_MODULE_ENABLED(SPIM_NRF52_ANOMALY_109_WORKAROUND) + p_cb->tx_length = 0; + p_cb->rx_length = 0; +#endif + + nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length); + nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length); + + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + + spim_list_enable_handle(p_spim, flags); + + if (!(flags & NRF_DRV_SPI_FLAG_HOLD_XFER)) + { + nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); + } +#if NRF_MODULE_ENABLED(SPIM_NRF52_ANOMALY_109_WORKAROUND) + if (flags & NRF_DRV_SPI_FLAG_HOLD_XFER) + { + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED); + p_cb->tx_length = p_xfer_desc->tx_length; + p_cb->rx_length = p_xfer_desc->rx_length; + nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0); + nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0); + nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK); + } +#endif + + if (!p_cb->handler) + { + while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){} + if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + nrf_gpio_pin_set(p_cb->ss_pin); + } + } + else + { + spim_int_enable(p_spim, !(flags & NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER)); + } + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} +#endif + +ret_code_t nrf_drv_spi_xfer(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0); + ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0); + + ret_code_t err_code = NRF_SUCCESS; + + if (p_cb->transfer_in_progress) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + else + { + if (p_cb->handler && !(flags & (NRF_DRV_SPI_FLAG_REPEATED_XFER | + NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER))) + { + p_cb->transfer_in_progress = true; + } + } + + p_cb->evt.data.done = *p_xfer_desc; + p_cb->tx_done = false; + p_cb->rx_done = false; + p_cb->abort = false; + + if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED) + { + nrf_gpio_pin_clear(p_cb->ss_pin); + } + CODE_FOR_SPIM + ( + return spim_xfer(p_instance->p_registers, p_cb, p_xfer_desc, flags); + ) + CODE_FOR_SPI + ( + if (flags) + { + p_cb->transfer_in_progress = false; + err_code = NRF_ERROR_NOT_SUPPORTED; + } + else + { + spi_xfer(p_instance->p_registers, p_cb, p_xfer_desc); + } + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + ) +} + + +void nrf_drv_spi_abort(nrf_drv_spi_t const * p_instance) +{ + spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + CODE_FOR_SPIM + ( + nrf_spim_task_trigger(p_instance->p_registers, NRF_SPIM_TASK_STOP); + while (!nrf_spim_event_check(p_instance->p_registers, NRF_SPIM_EVENT_STOPPED)) {} + p_cb->transfer_in_progress = false; + ) + CODE_FOR_SPI + ( + p_cb->abort = true; + ) +} + + +#ifdef SPIM_IN_USE +static void irq_handler_spim(NRF_SPIM_Type * p_spim, spi_control_block_t * p_cb) +{ + +#if NRF_MODULE_ENABLED(SPIM_NRF52_ANOMALY_109_WORKAROUND) + if ((nrf_spim_int_enable_check(p_spim, NRF_SPIM_INT_STARTED_MASK)) && + (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STARTED)) ) + { + /* Handle first, zero-length, auxiliary transmission. */ + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED); + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + + ASSERT(p_spim->TXD.MAXCNT == 0); + p_spim->TXD.MAXCNT = p_cb->tx_length; + + ASSERT(p_spim->RXD.MAXCNT == 0); + p_spim->RXD.MAXCNT = p_cb->rx_length; + + /* Disable STARTED interrupt, used only in auxiliary transmission. */ + nrf_spim_int_disable(p_spim, NRF_SPIM_INT_STARTED_MASK); + + /* Start the actual, glitch-free transmission. */ + nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START); + return; + } +#endif + + if (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)) + { + nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END); + ASSERT(p_cb->handler); + NRF_LOG_DEBUG("SPIM: Event: NRF_SPIM_EVENT_END."); + finish_transfer(p_cb); + } +} + +uint32_t nrf_drv_spi_start_task_get(nrf_drv_spi_t const * p_instance) +{ + NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_registers; + return nrf_spim_task_address_get(p_spim, NRF_SPIM_TASK_START); +} + +uint32_t nrf_drv_spi_end_event_get(nrf_drv_spi_t const * p_instance) +{ + NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_registers; + return nrf_spim_event_address_get(p_spim, NRF_SPIM_EVENT_END); +} +#endif // SPIM_IN_USE + +#ifdef SPI_IN_USE +static void irq_handler_spi(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb) +{ + ASSERT(p_cb->handler); + + nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); + NRF_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY."); + + if (!transfer_byte(p_spi, p_cb)) + { + finish_transfer(p_cb); + } +} +#endif // SPI_IN_USE + +#if NRF_MODULE_ENABLED(SPI0) +IRQ_HANDLER(0) +{ + spi_control_block_t * p_cb = &m_cb[SPI0_INSTANCE_INDEX]; + #if (SPI0_WITH_DMA || SPIM_ONLY) + irq_handler_spim(NRF_SPIM0, p_cb); + #else + irq_handler_spi(NRF_SPI0, p_cb); + #endif +} +#endif // NRF_MODULE_ENABLED(SPI0) + +#if NRF_MODULE_ENABLED(SPI1) +IRQ_HANDLER(1) +{ + spi_control_block_t * p_cb = &m_cb[SPI1_INSTANCE_INDEX]; + #if (SPI1_WITH_DMA || SPIM_ONLY) + irq_handler_spim(NRF_SPIM1, p_cb); + #else + irq_handler_spi(NRF_SPI1, p_cb); + #endif +} +#endif // NRF_MODULE_ENABLED(SPI1) + +#if NRF_MODULE_ENABLED(SPI2) +IRQ_HANDLER(2) +{ + spi_control_block_t * p_cb = &m_cb[SPI2_INSTANCE_INDEX]; + #if (SPI2_WITH_DMA || SPIM_ONLY) + irq_handler_spim(NRF_SPIM2, p_cb); + #else + irq_handler_spi(NRF_SPI2, p_cb); + #endif +} +/*lint -restore*/ +#endif // NRF_MODULE_ENABLED(SPI2) +#endif // ENABLED_SPI_COUNT +#endif // NRF_MODULE_ENABLED(SPI) + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.h new file mode 100644 index 0000000000..01eb9198be --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_master/nrf_drv_spi.h @@ -0,0 +1,468 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_spi Serial peripheral interface (SPI/SPIM) + * @ingroup nrf_drivers + * @brief Serial peripheral interface (SPI/SPIM) APIs. + * + */ + +#ifndef NRF_DRV_SPI_H__ +#define NRF_DRV_SPI_H__ + +#include "nordic_common.h" +#include "sdk_config.h" +#include "nrf_peripherals.h" +#include "sdk_errors.h" + +#ifdef SPI0_ENABLED +#define SPI0_INCR SPI0_ENABLED +#else +#define SPI0_INCR 0 +#endif + +#ifdef SPI1_ENABLED +#define SPI1_INCR SPI1_ENABLED +#else +#define SPI1_INCR 0 +#endif + +#ifdef SPI2_ENABLED +#define SPI2_INCR SPI2_ENABLED +#else +#define SPI2_INCR 0 +#endif + +#ifdef SPI3_ENABLED +#define SPI3_INCR SPI3_ENABLED +#else +#define SPI3_INCR 0 +#endif + +#define ENABLED_SPI_COUNT (SPI0_INCR + SPI1_INCR + SPI2_INCR + SPI3_INCR) + +#ifdef SPI_PRESENT +#include "nrf_spi.h" +#endif + +#ifdef SPIM_PRESENT +#include "nrf_spim.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SPIM_PRESENT) && defined(SPI_PRESENT) + #define NRF_DRV_SPI_PERIPHERAL(id) \ + (CONCAT_3(SPI, id, _USE_EASY_DMA) == 1 ? \ + (void *)CONCAT_2(NRF_SPIM, id) \ + : (void *)CONCAT_2(NRF_SPI, id)) + #define SPI2_IRQ SPIM2_SPIS2_SPI2_IRQn + #define SPI2_IRQ_HANDLER SPIM2_SPIS2_SPI2_IRQHandler +#elif defined (SPI_PRESENT) + #define NRF_DRV_SPI_PERIPHERAL(id) (void *)CONCAT_2(NRF_SPI, id) +#elif defined (SPIM_PRESENT) + #define NRF_DRV_SPI_PERIPHERAL(id) (void *)CONCAT_2(NRF_SPIM, id) +#endif + +#ifndef SPI_PRESENT +typedef nrf_spim_frequency_t nrf_spi_frequency_t; +typedef nrf_spim_mode_t nrf_spi_mode_t; +typedef nrf_spim_bit_order_t nrf_spi_bit_order_t; +#define NRF_SPI_PIN_NOT_CONNECTED 0xFFFFFFFF +#endif + +#ifdef NRF52810_XXAA +#define SPI0_IRQ SPIM0_SPIS0_IRQn +#define SPI0_IRQ_HANDLER SPIM0_SPIS0_IRQHandler +#else +#define SPI0_IRQ SPI0_TWI0_IRQn +#define SPI0_IRQ_HANDLER SPI0_TWI0_IRQHandler +#define SPI1_IRQ SPI1_TWI1_IRQn +#define SPI1_IRQ_HANDLER SPI1_TWI1_IRQHandler +#endif +/** + * @defgroup nrf_drv_spi SPI master driver + * @{ + * @ingroup nrf_spi + * + * @brief Multi-instance SPI master driver. + */ + +/** + * @brief SPI master driver instance data structure. + */ +typedef struct +{ + void * p_registers; ///< Pointer to the structure with SPI/SPIM peripheral instance registers. + IRQn_Type irq; ///< SPI/SPIM peripheral instance IRQ number. + uint8_t drv_inst_idx; ///< Driver instance index. + bool use_easy_dma; ///< True if the peripheral with EasyDMA (SPIM) shall be used. +} nrf_drv_spi_t; + +#define SPI0_INSTANCE_INDEX 0 +#define SPI1_INSTANCE_INDEX SPI0_INSTANCE_INDEX+SPI0_ENABLED +#define SPI2_INSTANCE_INDEX SPI1_INSTANCE_INDEX+SPI1_ENABLED + +#if defined(SPIM_PRESENT) && defined(SPI_PRESENT) +#define SPI_N_USE_EASY_DMA(_id) CONCAT_3(SPI, _id, _USE_EASY_DMA) +#elif defined(SPIM_PRESENT) && !defined(SPI_PRESENT) +#define SPI_N_USE_EASY_DMA(_id) true +#else +#define SPI_N_USE_EASY_DMA(_id) false +#endif + +/** + * @brief Macro for creating an SPI master driver instance. + */ +#define NRF_DRV_SPI_INSTANCE(id) \ +{ \ + .p_registers = NRF_DRV_SPI_PERIPHERAL(id), \ + .irq = CONCAT_3(SPI, id, _IRQ), \ + .drv_inst_idx = CONCAT_3(SPI, id, _INSTANCE_INDEX), \ + .use_easy_dma = SPI_N_USE_EASY_DMA(id) \ +} +/** + * @brief This value can be provided instead of a pin number for signals MOSI, + * MISO, and Slave Select to specify that the given signal is not used and + * therefore does not need to be connected to a pin. + */ +#define NRF_DRV_SPI_PIN_NOT_USED 0xFF + +/** + * @brief SPI data rates. + */ +typedef enum +{ + NRF_DRV_SPI_FREQ_125K = NRF_SPI_FREQ_125K, ///< 125 kbps. + NRF_DRV_SPI_FREQ_250K = NRF_SPI_FREQ_250K, ///< 250 kbps. + NRF_DRV_SPI_FREQ_500K = NRF_SPI_FREQ_500K, ///< 500 kbps. + NRF_DRV_SPI_FREQ_1M = NRF_SPI_FREQ_1M, ///< 1 Mbps. + NRF_DRV_SPI_FREQ_2M = NRF_SPI_FREQ_2M, ///< 2 Mbps. + NRF_DRV_SPI_FREQ_4M = NRF_SPI_FREQ_4M, ///< 4 Mbps. + NRF_DRV_SPI_FREQ_8M = NRF_SPI_FREQ_8M ///< 8 Mbps. +} nrf_drv_spi_frequency_t; + +/** + * @brief SPI modes. + */ +typedef enum +{ + NRF_DRV_SPI_MODE_0 = NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock. + NRF_DRV_SPI_MODE_1 = NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock. + NRF_DRV_SPI_MODE_2 = NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock. + NRF_DRV_SPI_MODE_3 = NRF_SPI_MODE_3 ///< SCK active low, sample on trailing edge of clock. +} nrf_drv_spi_mode_t; + +/** + * @brief SPI bit orders. + */ +typedef enum +{ + NRF_DRV_SPI_BIT_ORDER_MSB_FIRST = NRF_SPI_BIT_ORDER_MSB_FIRST, ///< Most significant bit shifted out first. + NRF_DRV_SPI_BIT_ORDER_LSB_FIRST = NRF_SPI_BIT_ORDER_LSB_FIRST ///< Least significant bit shifted out first. +} nrf_drv_spi_bit_order_t; + +/** + * @brief SPI master driver instance configuration structure. + */ +typedef struct +{ + uint8_t sck_pin; ///< SCK pin number. + uint8_t mosi_pin; ///< MOSI pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t miso_pin; ///< MISO pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. */ + uint8_t ss_pin; ///< Slave Select pin number (optional). + /**< Set to @ref NRF_DRV_SPI_PIN_NOT_USED + * if this signal is not needed. The driver + * supports only active low for this signal. + * If the signal should be active high, + * it must be controlled externally. */ + uint8_t irq_priority; ///< Interrupt priority. + uint8_t orc; ///< Over-run character. + /**< This character is used when all bytes from the TX buffer are sent, + but the transfer continues due to RX. */ + nrf_drv_spi_frequency_t frequency; ///< SPI frequency. + nrf_drv_spi_mode_t mode; ///< SPI mode. + nrf_drv_spi_bit_order_t bit_order; ///< SPI bit order. +} nrf_drv_spi_config_t; + +/** + * @brief SPI master instance default configuration. + */ +#define NRF_DRV_SPI_DEFAULT_CONFIG \ +{ \ + .sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \ + .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .orc = 0xFF, \ + .frequency = NRF_DRV_SPI_FREQ_4M, \ + .mode = NRF_DRV_SPI_MODE_0, \ + .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \ +} + +#define NRF_DRV_SPI_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */ +#define NRF_DRV_SPI_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */ +#define NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */ +#define NRF_DRV_SPI_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */ +#define NRF_DRV_SPI_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */ + +/** + * @brief Single transfer descriptor structure. + */ +typedef struct +{ + uint8_t const * p_tx_buffer; ///< Pointer to TX buffer. + uint8_t tx_length; ///< TX buffer length. + uint8_t * p_rx_buffer; ///< Pointer to RX buffer. + uint8_t rx_length; ///< RX buffer length. +}nrf_drv_spi_xfer_desc_t; + +/** + * @brief Macro for setting up single transfer descriptor. + * + * This macro is for internal use only. + */ +#define NRF_DRV_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \ + { \ + .p_tx_buffer = (uint8_t const *)(p_tx), \ + .tx_length = (tx_len), \ + .p_rx_buffer = (p_rx), \ + .rx_length = (rx_len), \ + } + +/** + * @brief Macro for setting duplex TX RX transfer. + */ +#define NRF_DRV_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \ + NRF_DRV_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length) + +/** + * @brief Macro for setting TX transfer. + */ +#define NRF_DRV_SPI_XFER_TX(p_buf, length) \ + NRF_DRV_SPI_SINGLE_XFER(p_buf, length, NULL, 0) + +/** + * @brief Macro for setting RX transfer. + */ +#define NRF_DRV_SPI_XFER_RX(p_buf, length) \ + NRF_DRV_SPI_SINGLE_XFER(NULL, 0, p_buf, length) + +/** + * @brief SPI master driver event types, passed to the handler routine provided + * during initialization. + */ +typedef enum +{ + NRF_DRV_SPI_EVENT_DONE, ///< Transfer done. +} nrf_drv_spi_evt_type_t; + +typedef struct +{ + nrf_drv_spi_evt_type_t type; ///< Event type. + union + { + nrf_drv_spi_xfer_desc_t done; ///< Event data for DONE event. + } data; +} nrf_drv_spi_evt_t; + +/** + * @brief SPI master driver event handler type. + */ +typedef void (* nrf_drv_spi_evt_handler_t)(nrf_drv_spi_evt_t const * p_event, + void * p_context); + +/** + * @brief Function for initializing the SPI master driver instance. + * + * This function configures and enables the specified peripheral. + * + * @note MISO pin has pull down enabled. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Pointer to the structure with the initial configuration. + * + * @param handler Event handler provided by the user. If NULL, transfers + * will be performed in blocking mode. + * @param p_context Context passed to event handler. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver was already initialized. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + */ +ret_code_t nrf_drv_spi_init(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_config_t const * p_config, + nrf_drv_spi_evt_handler_t handler, + void * p_context); + +/** + * @brief Function for uninitializing the SPI master driver instance. + * + * @note Configuration of pins is kept. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_spi_uninit(nrf_drv_spi_t const * const p_instance); + +/** + * @brief Function for starting the SPI data transfer. + * + * If an event handler was provided in the @ref nrf_drv_spi_init call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, which means that this function + * returns when the transfer is finished. + * + * @note Peripherals using EasyDMA (for example, SPIM) require the transfer buffers + * to be placed in the Data RAM region. If they are not and an SPIM instance is + * used, this function will fail with the error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_tx_buffer Pointer to the transmit buffer. Can be NULL + * if there is nothing to send. + * @param tx_buffer_length Length of the transmit buffer. + * @param[in] p_rx_buffer Pointer to the receive buffer. Can be NULL + * if there is nothing to receive. + * @param rx_buffer_length Length of the receive buffer. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_BUSY If a previously started transfer has not finished + * yet. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data + * RAM region. + */ +ret_code_t nrf_drv_spi_transfer(nrf_drv_spi_t const * const p_instance, + uint8_t const * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length); + +/** + * @brief Function for starting the SPI data transfer with additional option flags. + * + * Function enables customizing the transfer by using option flags. + * + * Additional options are provided using the flags parameter: + * + * - @ref NRF_DRV_SPI_FLAG_TX_POSTINC and @ref NRF_DRV_SPI_FLAG_RX_POSTINC: + * Post-incrementation of buffer addresses. Supported only by SPIM. + * - @ref NRF_DRV_SPI_FLAG_HOLD_XFER: Driver is not starting the transfer. Use this + * flag if the transfer is triggered externally by PPI. Supported only by SPIM. Use + * @ref nrf_drv_spi_start_task_get to get the address of the start task. + * - @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER: No user event handler after transfer + * completion. This also means no interrupt at the end of the transfer. Supported only by SPIM. + * If @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into + * busy state, so you must ensure that the next transfers are set up when SPIM is not active. + * @ref nrf_drv_spi_end_event_get function can be used to detect end of transfer. Option can be used + * together with @ref NRF_DRV_SPI_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers + * without interruptions. + * - @ref NRF_DRV_SPI_FLAG_REPEATED_XFER: Prepare for repeated transfers. You can set + * up a number of transfers that will be triggered externally (for example by PPI). An example is + * a TXRX transfer with the options @ref NRF_DRV_SPI_FLAG_RX_POSTINC, + * @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER, and @ref NRF_DRV_SPI_FLAG_REPEATED_XFER. After the + * transfer is set up, a set of transfers can be triggered by PPI that will read, for example, + * the same register of an external component and put it into a RAM buffer without any interrupts. + * @ref nrf_drv_spi_end_event_get can be used to get the address of the END event, which can be + * used to count the number of transfers. If @ref NRF_DRV_SPI_FLAG_REPEATED_XFER is used, + * the driver does not set the instance into busy state, so you must ensure that the next + * transfers are set up when SPIM is not active. Supported only by SPIM. + * @note Function is intended to be used only in non-blocking mode. + * + * @param p_instance Pointer to the driver instance structure. + * @param p_xfer_desc Pointer to the transfer descriptor. + * @param flags Transfer options (0 for default settings). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_NOT_SUPPORTED If the provided parameters are not supported. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data + * RAM region. + */ +ret_code_t nrf_drv_spi_xfer(nrf_drv_spi_t const * const p_instance, + nrf_drv_spi_xfer_desc_t const * p_xfer_desc, + uint32_t flags); + +/** + * @brief Function for returning the address of a SPIM start task. + * + * This function should be used if @ref nrf_drv_spi_xfer was called with the flag @ref NRF_DRV_SPI_FLAG_HOLD_XFER. + * In that case, the transfer is not started by the driver, but it must be started externally by PPI. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Start task address. + */ +uint32_t nrf_drv_spi_start_task_get(nrf_drv_spi_t const * p_instance); + +/** + * @brief Function for returning the address of a END SPIM event. + * + * A END event can be used to detect the end of a transfer if the @ref NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER + * option is used. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return END event address. + */ +uint32_t nrf_drv_spi_end_event_get(nrf_drv_spi_t const * p_instance); + +/** + * @brief Function for aborting ongoing transfer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_spi_abort(nrf_drv_spi_t const * p_instance); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SPI_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.c new file mode 100644 index 0000000000..9470baf482 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.c @@ -0,0 +1,493 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(SPIS) +#include "nrf_drv_spis.h" +#if ENABLED_SPIS_COUNT +#include +#include +#include "nrf.h" +#include "nrf_gpio.h" +#include "app_error.h" +#include "app_util_platform.h" +#include "nrf_drv_common.h" +#include "nrf_assert.h" + +#define NRF_LOG_MODULE_NAME spis + +#if SPIS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL SPIS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR SPIS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR SPIS_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) \ + (event == NRF_SPIS_EVENT_ACQUIRED ? "NRF_SPIS_EVENT_ACQUIRED" : \ + (event == NRF_SPIS_EVENT_END ? "NRF_SPIS_EVENT_END" : \ + "UNKNOWN ERROR")) + +#else //SPIS_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //SPIS_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if NRF_MODULE_ENABLED(SPIS_NRF52_ANOMALY_109_WORKAROUND) +#include "nrf_drv_gpiote.h" +#define USE_DMA_ISSUE_WORKAROUND +// This handler is called by the GPIOTE driver when a falling edge is detected +// on the CSN line. There is no need to do anything here. The handling of the +// interrupt itself provides a protection for DMA transfers. +static void csn_event_handler(nrf_drv_gpiote_pin_t pin, + nrf_gpiote_polarity_t action) +{ +} +#endif + + +/**@brief States of the SPI transaction state machine. */ +typedef enum +{ + SPIS_STATE_INIT, /**< Initialization state. In this state the module waits for a call to @ref spi_slave_buffers_set. */ + SPIS_BUFFER_RESOURCE_REQUESTED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has started. */ + SPIS_BUFFER_RESOURCE_CONFIGURED, /**< State where the configuration of the memory buffers, which are to be used in SPI transaction, has completed. */ + SPIS_XFER_COMPLETED /**< State where SPI transaction has been completed. */ +} nrf_drv_spis_state_t; + + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n + #define IRQ_HANDLER(n) static void IRQ_HANDLER_NAME(n)(void) + + #if NRF_MODULE_ENABLED(SPIS0) + IRQ_HANDLER(0); + #endif + #if NRF_MODULE_ENABLED(SPIS1) + IRQ_HANDLER(1); + #endif + #if NRF_MODULE_ENABLED(SPIS2) + IRQ_HANDLER(2); + #endif + static nrf_drv_irq_handler_t const m_irq_handlers[ENABLED_SPIS_COUNT] = { + #if NRF_MODULE_ENABLED(SPIS0) + IRQ_HANDLER_NAME(0), + #endif + #if NRF_MODULE_ENABLED(SPIS1) + IRQ_HANDLER_NAME(1), + #endif + #if NRF_MODULE_ENABLED(SPIS2) + IRQ_HANDLER_NAME(2), + #endif + }; +#else + #define IRQ_HANDLER(n) void SPIS##n##_IRQ_HANDLER(void) +#endif // PERIPHERAL_RESOURCE_SHARING_ENABLED + +#define SPIS_IRQHANDLER_TEMPLATE(NUM) \ + IRQ_HANDLER(NUM) \ + { \ + spis_irq_handler(NRF_SPIS##NUM, &m_cb[SPIS##NUM##_INSTANCE_INDEX]); \ + } + + +/**@brief SPIS control block - driver instance local data. */ +typedef struct +{ + volatile uint32_t tx_buffer_size; //!< SPI slave TX buffer size in bytes. + volatile uint32_t rx_buffer_size; //!< SPI slave RX buffer size in bytes. + nrf_drv_spis_event_handler_t handler; //!< SPI event handler. + volatile const uint8_t * tx_buffer; //!< SPI slave TX buffer. + volatile uint8_t * rx_buffer; //!< SPI slave RX buffer. + nrf_drv_state_t state; //!< driver initialization state. + volatile nrf_drv_spis_state_t spi_state; //!< SPI slave state. +} spis_cb_t; + +static spis_cb_t m_cb[ENABLED_SPIS_COUNT]; + +ret_code_t nrf_drv_spis_init(nrf_drv_spis_t const * const p_instance, + nrf_drv_spis_config_t const * p_config, + nrf_drv_spis_event_handler_t event_handler) +{ + ASSERT(p_config); + spis_cb_t * p_cb = &m_cb[p_instance->instance_id]; + ret_code_t err_code; + + NRF_SPIS_Type * p_spis = p_instance->p_reg; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if ((uint32_t)p_config->mode > (uint32_t)NRF_DRV_SPIS_MODE_3) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if (!event_handler) + { + err_code = NRF_ERROR_NULL; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(p_spis, + m_irq_handlers[p_instance->instance_id]) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif + + // Configure the SPI pins for input. + uint32_t mosi_pin; + uint32_t miso_pin; + + if (p_config->miso_pin != NRF_DRV_SPIS_PIN_NOT_USED) + { + nrf_gpio_cfg(p_config->miso_pin, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, + p_config->miso_drive, + NRF_GPIO_PIN_NOSENSE); + miso_pin = p_config->miso_pin; + } + else + { + miso_pin = NRF_SPIS_PIN_NOT_CONNECTED; + } + + if (p_config->mosi_pin != NRF_DRV_SPIS_PIN_NOT_USED) + { + nrf_gpio_cfg(p_config->mosi_pin, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + mosi_pin = p_config->mosi_pin; + } + else + { + mosi_pin = NRF_SPIS_PIN_NOT_CONNECTED; + } + + nrf_gpio_cfg(p_config->csn_pin, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + p_config->csn_pullup, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + + nrf_gpio_cfg(p_config->sck_pin, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_CONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + + nrf_spis_pins_set(p_spis, p_config->sck_pin, mosi_pin, miso_pin, p_config->csn_pin); + + nrf_spis_rx_buffer_set(p_spis, NULL, 0); + nrf_spis_tx_buffer_set(p_spis, NULL, 0); + + // Configure SPI mode. + nrf_spis_configure(p_spis, (nrf_spis_mode_t) p_config->mode, + (nrf_spis_bit_order_t) p_config->bit_order); + + // Configure DEF and ORC characters. + nrf_spis_def_set(p_spis, p_config->def); + nrf_spis_orc_set(p_spis, p_config->orc); + + // Clear possible pending events. + nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END); + nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED); + + // Enable END_ACQUIRE shortcut. + nrf_spis_shorts_enable(p_spis, NRF_SPIS_SHORT_END_ACQUIRE); + + m_cb[p_instance->instance_id].spi_state = SPIS_STATE_INIT; + m_cb[p_instance->instance_id].handler = event_handler; + +#if defined(USE_DMA_ISSUE_WORKAROUND) + // Configure a GPIOTE channel to generate interrupts on each falling edge + // on the CSN line. Handling of these interrupts will make the CPU active, + // and thus will protect the DMA transfers started by SPIS right after it + // is selected for communication. + // [the GPIOTE driver may be already initialized at this point (by this + // driver when another SPIS instance is used, or by an application code), + // so just ignore the returned value] + (void)nrf_drv_gpiote_init(); + static nrf_drv_gpiote_in_config_t const csn_gpiote_config = + GPIOTE_CONFIG_IN_SENSE_HITOLO(true); + ret_code_t gpiote_err_code = nrf_drv_gpiote_in_init(p_config->csn_pin, + &csn_gpiote_config, csn_event_handler); + if (gpiote_err_code != NRF_SUCCESS) + { + err_code = NRF_ERROR_INTERNAL; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + nrf_drv_gpiote_in_event_enable(p_config->csn_pin, true); +#endif + + // Enable IRQ. + nrf_spis_int_enable(p_spis, NRF_SPIS_INT_ACQUIRED_MASK | NRF_SPIS_INT_END_MASK); + nrf_drv_common_irq_enable(p_instance->irq, p_config->irq_priority); + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + + // Enable SPI slave device. + nrf_spis_enable(p_spis); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_spis_uninit(nrf_drv_spis_t const * const p_instance) +{ + spis_cb_t * p_cb = &m_cb[p_instance->instance_id]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + NRF_SPIS_Type * p_spis = p_instance->p_reg; + + #define DISABLE_ALL 0xFFFFFFFF + nrf_spis_disable(p_spis); + nrf_drv_common_irq_disable(p_instance->irq); + nrf_spis_int_disable(p_spis, DISABLE_ALL); + #undef DISABLE_ALL + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(p_spis); +#endif + + p_cb->state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Initialized."); +} + + +/**@brief Function for executing the state entry action. */ +static void spis_state_entry_action_execute(NRF_SPIS_Type * p_spis, + spis_cb_t * p_cb) +{ + nrf_drv_spis_event_t event; + + switch (p_cb->spi_state) + { + case SPIS_BUFFER_RESOURCE_REQUESTED: + nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_ACQUIRE); + break; + + case SPIS_BUFFER_RESOURCE_CONFIGURED: + event.evt_type = NRF_DRV_SPIS_BUFFERS_SET_DONE; + event.rx_amount = 0; + event.tx_amount = 0; + + APP_ERROR_CHECK_BOOL(p_cb->handler != NULL); + p_cb->handler(event); + break; + + case SPIS_XFER_COMPLETED: + event.evt_type = NRF_DRV_SPIS_XFER_DONE; + event.rx_amount = nrf_spis_rx_amount_get(p_spis); + event.tx_amount = nrf_spis_tx_amount_get(p_spis); + NRF_LOG_INFO("Transfer rx_len:%d.", event.rx_amount); + NRF_LOG_DEBUG("Rx data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_cb->rx_buffer, + event.rx_amount * sizeof(p_cb->rx_buffer[0])); + APP_ERROR_CHECK_BOOL(p_cb->handler != NULL); + p_cb->handler(event); + break; + + default: + // No implementation required. + break; + } +} + +/**@brief Function for changing the state of the SPI state machine. + * + * @param[in] p_spis SPIS instance register. + * @param[in] p_cb SPIS instance control block. + * @param[in] new_state State where the state machine transits to. + */ +static void spis_state_change(NRF_SPIS_Type * p_spis, + spis_cb_t * p_cb, + nrf_drv_spis_state_t new_state) +{ + p_cb->spi_state = new_state; + spis_state_entry_action_execute(p_spis, p_cb); +} + + +ret_code_t nrf_drv_spis_buffers_set(nrf_drv_spis_t const * const p_instance, + const uint8_t * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length) +{ + spis_cb_t * p_cb = &m_cb[p_instance->instance_id]; + uint32_t err_code; + + VERIFY_PARAM_NOT_NULL(p_rx_buffer); + VERIFY_PARAM_NOT_NULL(p_tx_buffer); + + // EasyDMA requires that transfer buffers are placed in Data RAM region; + // signal error if they are not. + if (!nrf_drv_is_in_RAM(p_tx_buffer) || !nrf_drv_is_in_RAM(p_rx_buffer)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + switch (p_cb->spi_state) + { + case SPIS_STATE_INIT: + case SPIS_XFER_COMPLETED: + case SPIS_BUFFER_RESOURCE_CONFIGURED: + p_cb->tx_buffer = p_tx_buffer; + p_cb->rx_buffer = p_rx_buffer; + p_cb->tx_buffer_size = tx_buffer_length; + p_cb->rx_buffer_size = rx_buffer_length; + err_code = NRF_SUCCESS; + + spis_state_change(p_instance->p_reg, p_cb, SPIS_BUFFER_RESOURCE_REQUESTED); + break; + + case SPIS_BUFFER_RESOURCE_REQUESTED: + err_code = NRF_ERROR_INVALID_STATE; + break; + + default: + // @note: execution of this code path would imply internal error in the design. + err_code = NRF_ERROR_INTERNAL; + break; + } + + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb) +{ + // @note: as multiple events can be pending for processing, the correct event processing order + // is as follows: + // - SPI semaphore acquired event. + // - SPI transaction complete event. + + // Check for SPI semaphore acquired event. + if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED)) + { + nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED); + NRF_LOG_DEBUG("SPIS: Event: %s.", (uint32_t)EVT_TO_STR(NRF_SPIS_EVENT_ACQUIRED)); + + switch (p_cb->spi_state) + { + case SPIS_BUFFER_RESOURCE_REQUESTED: + nrf_spis_tx_buffer_set(p_spis, (uint8_t *)p_cb->tx_buffer, p_cb->tx_buffer_size); + nrf_spis_rx_buffer_set(p_spis, (uint8_t *)p_cb->rx_buffer, p_cb->rx_buffer_size); + + nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE); + + spis_state_change(p_spis, p_cb, SPIS_BUFFER_RESOURCE_CONFIGURED); + break; + + default: + // No implementation required. + break; + } + } + + // Check for SPI transaction complete event. + if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_END)) + { + nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_END); + NRF_LOG_DEBUG("SPIS: Event: %s.", (uint32_t)EVT_TO_STR(NRF_SPIS_EVENT_END)); + + switch (p_cb->spi_state) + { + case SPIS_BUFFER_RESOURCE_CONFIGURED: + spis_state_change(p_spis, p_cb, SPIS_XFER_COMPLETED); + break; + + default: + // No implementation required. + break; + } + } +} + +#if NRF_MODULE_ENABLED(SPIS0) + SPIS_IRQHANDLER_TEMPLATE(0) +#endif + +#if NRF_MODULE_ENABLED(SPIS1) + SPIS_IRQHANDLER_TEMPLATE(1) +#endif + +#if NRF_MODULE_ENABLED(SPIS2) + SPIS_IRQHANDLER_TEMPLATE(2) +#endif + +#endif // SPI_COUNT > 0 +#endif // NRF_MODULE_ENABLED(SPIS) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.h new file mode 100644 index 0000000000..069773d3b9 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/spi_slave/nrf_drv_spis.h @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_spis SPIS HAL and driver + * @ingroup nrf_drivers + * @brief SPIS APIs. + * + */ + +#ifndef SPI_SLAVE_H__ +#define SPI_SLAVE_H__ + +#include +#include "nrf.h" +#include "nrf_error.h" +#include "sdk_config.h" +#include "nrf_spis.h" +#include "nrf_gpio.h" +#include "sdk_common.h" +#include "app_util_platform.h" +#include "nrf_peripherals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SPIS0_ENABLED +#define SPIS0_INCR SPIS0_ENABLED +#else +#define SPIS0_INCR 0 +#endif + +#ifdef SPIS1_ENABLED +#define SPIS1_INCR SPIS1_ENABLED +#else +#define SPIS1_INCR 0 +#endif + +#ifdef SPIS2_ENABLED +#define SPIS2_INCR SPIS2_ENABLED +#else +#define SPIS2_INCR 0 +#endif + +#define ENABLED_SPIS_COUNT (SPIS0_INCR + SPIS1_INCR + SPIS2_INCR) + +#ifdef NRF52810_XXAA + #define SPIS0_IRQ SPIM0_SPIS0_IRQn + #define SPIS0_IRQ_HANDLER SPIM0_SPIS0_IRQHandler +#else + #define SPIS0_IRQ SPI0_TWI0_IRQn + #define SPIS0_IRQ_HANDLER SPI0_TWI0_IRQHandler + #define SPIS1_IRQ SPI1_TWI1_IRQn + #define SPIS1_IRQ_HANDLER SPI1_TWI1_IRQHandler +#if SPIS_COUNT > 2 + #define SPIS2_IRQ SPIM2_SPIS2_SPI2_IRQn + #define SPIS2_IRQ_HANDLER SPIM2_SPIS2_SPI2_IRQHandler +#endif +#endif // NRF52810_XXAA +/** + * @defgroup nrf_drv_spis SPI slave driver + * @{ + * @ingroup nrf_spis + * @brief Multi-instance SPI slave driver. + */ + +#define NRF_DRV_SPIS_DEFAULT_CSN_PULLUP NRF_GPIO_PIN_NOPULL /**< Default pull-up configuration of the SPI CS. */ +#define NRF_DRV_SPIS_DEFAULT_MISO_DRIVE NRF_GPIO_PIN_S0S1 /**< Default drive configuration of the SPI MISO. */ + +/** +* @brief This value can be provided instead of a pin number for the signals MOSI +* and MISO to specify that the given signal is not used and therefore +* does not need to be connected to a pin. +*/ +#define NRF_DRV_SPIS_PIN_NOT_USED 0xFF + +/** @brief SPIS transaction bit order definitions. */ +typedef enum +{ + NRF_DRV_SPIS_BIT_ORDER_LSB_FIRST = NRF_SPIS_BIT_ORDER_LSB_FIRST, /**< Least significant bit shifted out first. */ + NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST = NRF_SPIS_BIT_ORDER_MSB_FIRST /**< Most significant bit shifted out first. */ +} nrf_drv_spis_endian_t; + +/** @brief SPIS mode definitions for clock polarity and phase. */ +typedef enum +{ + NRF_DRV_SPIS_MODE_0 = NRF_SPIS_MODE_0, /**< (CPOL = 0, CPHA = 0). */ + NRF_DRV_SPIS_MODE_1 = NRF_SPIS_MODE_1, /**< (CPOL = 0, CPHA = 1). */ + NRF_DRV_SPIS_MODE_2 = NRF_SPIS_MODE_2, /**< (CPOL = 1, CPHA = 0). */ + NRF_DRV_SPIS_MODE_3 = NRF_SPIS_MODE_3 /**< (CPOL = 1, CPHA = 1). */ +} nrf_drv_spis_mode_t; + +/** @brief Event callback function event definitions. */ +typedef enum +{ + NRF_DRV_SPIS_BUFFERS_SET_DONE, /**< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transactions can be done. */ + NRF_DRV_SPIS_XFER_DONE, /**< SPI transaction event. SPI transaction has been completed. */ + NRF_DRV_SPIS_EVT_TYPE_MAX /**< Enumeration upper bound. */ +} nrf_drv_spis_event_type_t; + +/** @brief Structure containing the event context from the SPI slave driver. */ +typedef struct +{ + nrf_drv_spis_event_type_t evt_type; //!< Type of event. + uint32_t rx_amount; //!< Number of bytes received in last transaction. This parameter is only valid for @ref NRF_DRV_SPIS_XFER_DONE events. + uint32_t tx_amount; //!< Number of bytes transmitted in last transaction. This parameter is only valid for @ref NRF_DRV_SPIS_XFER_DONE events. +} nrf_drv_spis_event_t; + +/** @brief SPI slave driver instance data structure. */ +typedef struct +{ + NRF_SPIS_Type * p_reg; //!< SPIS instance register. + uint8_t instance_id; //!< SPIS instance ID. + IRQn_Type irq; //!< IRQ of the specific instance. +} nrf_drv_spis_t; + +#define SPIS0_INSTANCE_INDEX 0 +#define SPIS1_INSTANCE_INDEX SPIS0_INSTANCE_INDEX+SPIS0_ENABLED +#define SPIS2_INSTANCE_INDEX SPIS1_INSTANCE_INDEX+SPIS1_ENABLED + +/** @brief Macro for creating an SPI slave driver instance. */ +#define NRF_DRV_SPIS_INSTANCE(id) \ +{ \ + .p_reg = CONCAT_2(NRF_SPIS, id), \ + .irq = CONCAT_3(SPIS, id, _IRQ), \ + .instance_id = CONCAT_3(SPIS, id, _INSTANCE_INDEX), \ +} + +/** @brief SPI slave instance default configuration. */ +#define NRF_DRV_SPIS_DEFAULT_CONFIG \ +{ \ + .sck_pin = NRF_DRV_SPIS_PIN_NOT_USED, \ + .mosi_pin = NRF_DRV_SPIS_PIN_NOT_USED, \ + .miso_pin = NRF_DRV_SPIS_PIN_NOT_USED, \ + .csn_pin = NRF_DRV_SPIS_PIN_NOT_USED, \ + .miso_drive = NRF_DRV_SPIS_DEFAULT_MISO_DRIVE, \ + .csn_pullup = NRF_DRV_SPIS_DEFAULT_CSN_PULLUP, \ + .orc = SPIS_DEFAULT_ORC, \ + .def = SPIS_DEFAULT_DEF, \ + .mode = (nrf_drv_spis_mode_t)SPIS_DEFAULT_MODE, \ + .bit_order = (nrf_drv_spis_endian_t)SPIS_DEFAULT_BIT_ORDER, \ + .irq_priority = SPIS_DEFAULT_CONFIG_IRQ_PRIORITY, \ +} + +/** @brief SPI peripheral device configuration data. */ +typedef struct +{ + uint32_t miso_pin; //!< SPI MISO pin (optional). + /**< Set @ref NRF_DRV_SPIS_PIN_NOT_USED + * if this signal is not needed. */ + uint32_t mosi_pin; //!< SPI MOSI pin (optional). + /**< Set @ref NRF_DRV_SPIS_PIN_NOT_USED + * if this signal is not needed. */ + uint32_t sck_pin; //!< SPI SCK pin. + uint32_t csn_pin; //!< SPI CSN pin. + nrf_drv_spis_mode_t mode; //!< SPI mode. + nrf_drv_spis_endian_t bit_order; //!< SPI transaction bit order. + nrf_gpio_pin_pull_t csn_pullup; //!< CSN pin pull-up configuration. + nrf_gpio_pin_drive_t miso_drive; //!< MISO pin drive configuration. + uint8_t def; //!< Character clocked out in case of an ignored transaction. + uint8_t orc; //!< Character clocked out after an over-read of the transmit buffer. + uint8_t irq_priority; //!< Interrupt priority. +} nrf_drv_spis_config_t; + + +/** @brief SPI slave event callback function type. + * + * @param[in] event SPI slave driver event. + */ +typedef void (*nrf_drv_spis_event_handler_t)(nrf_drv_spis_event_t event); + +/** @brief Function for initializing the SPI slave driver instance. + * + * @note When the nRF52 Anomaly 109 workaround for SPIS is enabled, this function + * initializes the GPIOTE driver as well, and uses one of GPIOTE channels + * to detect falling edges on CSN pin. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Pointer to the structure with the initial configuration. + * If NULL, the default configuration will be used. + * @param[in] event_handler Function to be called by the SPI slave driver upon event. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INVALID_PARAM If an invalid parameter is supplied. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + * @retval NRF_ERROR_INTERNAL GPIOTE channel for detecting falling edges + * on CSN pin cannot be initialized. Possible + * only when using nRF52 Anomaly 109 workaround. + */ +ret_code_t nrf_drv_spis_init(nrf_drv_spis_t const * const p_instance, + nrf_drv_spis_config_t const * p_config, + nrf_drv_spis_event_handler_t event_handler); + +/** + * @brief Function for uninitializing the SPI slave driver instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_spis_uninit(nrf_drv_spis_t const * const p_instance); + +/** @brief Function for preparing the SPI slave instance for a single SPI transaction. + * + * This function prepares the SPI slave device to be ready for a single SPI transaction. It configures + * the SPI slave device to use the memory supplied with the function call in SPI transactions. + * + * When either the memory buffer configuration or the SPI transaction has been + * completed, the event callback function will be called with the appropriate event + * @ref nrf_drv_spis_event_type_t. Note that the callback function can be called before returning from + * this function, because it is called from the SPI slave interrupt context. + * + * @note This function can be called from the callback function context. + * + * @note Client applications must call this function after every @ref NRF_DRV_SPIS_XFER_DONE event if + * the SPI slave driver should be prepared for a possible new SPI transaction. + * + * @note Peripherals that are using EasyDMA (for example, SPIS) require the transfer buffers + * to be placed in the Data RAM region. Otherwise, this function will fail + * with the error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_tx_buffer Pointer to the TX buffer. + * @param[in] p_rx_buffer Pointer to the RX buffer. + * @param[in] tx_buffer_length Length of the TX buffer in bytes. + * @param[in] rx_buffer_length Length of the RX buffer in bytes. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If the operation failed because a NULL pointer was supplied. + * @retval NRF_ERROR_INVALID_STATE If the operation failed because the SPI slave device is in an incorrect state. + * @retval NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data + * RAM region. + * @retval NRF_ERROR_INTERNAL If the operation failed because of an internal error. + */ +ret_code_t nrf_drv_spis_buffers_set(nrf_drv_spis_t const * const p_instance, + const uint8_t * p_tx_buffer, + uint8_t tx_buffer_length, + uint8_t * p_rx_buffer, + uint8_t rx_buffer_length); + + +#ifdef __cplusplus +} +#endif + +#endif // SPI_SLAVE_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.c new file mode 100644 index 0000000000..0d1ad30a42 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.c @@ -0,0 +1,508 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_drv_common.h" +#include "nrf_error.h" +#include "nrf_assert.h" +#include +#include +#include +#include "nrf_drv_swi.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME swi + +#if EGU_ENABLED +#if SWI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL SWI_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR SWI_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR SWI_CONFIG_DEBUG_COLOR +#else //SWI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //SWI_CONFIG_LOG_ENABLED +#endif //EGU_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +STATIC_ASSERT(SWI_COUNT > 0); + +#ifdef SWI_DISABLE0 + #undef SWI_DISABLE0 + #define SWI_DISABLE0 1uL +#else + #if SWI_COUNT > 0 + #define SWI_DISABLE0 0uL + #else + #define SWI_DISABLE0 1uL + #endif +#endif + +#ifdef SWI_DISABLE1 + #undef SWI_DISABLE1 + #define SWI_DISABLE1 1uL +#else + #if SWI_COUNT > 1 + #define SWI_DISABLE1 0uL + #else + #define SWI_DISABLE1 1uL + #endif +#endif + +#ifdef SWI_DISABLE2 + #undef SWI_DISABLE2 + #define SWI_DISABLE2 1uL +#else + #if SWI_COUNT > 2 + #define SWI_DISABLE2 0uL + #else + #define SWI_DISABLE2 1uL + #endif +#endif + +#ifdef SWI_DISABLE3 + #undef SWI_DISABLE3 + #define SWI_DISABLE3 1uL +#else + #if SWI_COUNT > 3 + #define SWI_DISABLE3 0uL + #else + #define SWI_DISABLE3 1uL + #endif +#endif + +#ifdef SWI_DISABLE4 + #undef SWI_DISABLE4 + #define SWI_DISABLE4 1uL +#else + #if SWI_COUNT > 4 + #define SWI_DISABLE4 0uL + #else + #define SWI_DISABLE4 1uL + #endif +#endif + +#ifdef SWI_DISABLE5 + #undef SWI_DISABLE5 + #define SWI_DISABLE5 1uL +#else + #if SWI_COUNT > 5 + #define SWI_DISABLE5 0uL + #else + #define SWI_DISABLE5 1uL + #endif +#endif + +#define SWI_START_NUMBER ( (SWI_DISABLE0) \ + + (SWI_DISABLE0 * SWI_DISABLE1) \ + + (SWI_DISABLE0 * SWI_DISABLE1 * SWI_DISABLE2) \ + + (SWI_DISABLE0 * SWI_DISABLE1 * SWI_DISABLE2 * SWI_DISABLE3) \ + + (SWI_DISABLE0 * SWI_DISABLE1 * SWI_DISABLE2 * SWI_DISABLE3 * SWI_DISABLE4) \ + + (SWI_DISABLE0 * SWI_DISABLE1 * SWI_DISABLE2 * SWI_DISABLE3 * SWI_DISABLE4 \ + * SWI_DISABLE5) ) + +#if (SWI_COUNT <= SWI_START_NUMBER) + #define SWI_ARRAY_SIZE 1 +#else + #define SWI_ARRAY_SIZE (SWI_COUNT - SWI_START_NUMBER) +#endif + +static nrf_drv_state_t m_drv_state = NRF_DRV_STATE_UNINITIALIZED; +static nrf_swi_handler_t m_swi_handlers[SWI_ARRAY_SIZE]; + +#if !EGU_ENABLED + static nrf_swi_flags_t m_swi_flags[SWI_ARRAY_SIZE]; + #define SWI_EGU_MIXED (0) + #define SWI_MAX_FLAGS (16u) +#elif ((SWI_ARRAY_SIZE > EGU_COUNT) && (SWI_COUNT > EGU_COUNT)) + #define SWI_EGU_MIXED (1u) + #define SWI_MAX_FLAGS (16u) + static nrf_swi_flags_t m_swi_flags[SWI_ARRAY_SIZE - EGU_COUNT]; +#else + #define SWI_EGU_MIXED (0) +#endif + +#if NRF_MODULE_ENABLED(EGU) +#define SWI_EGU_CH_DEF(_idx_, _arg_) CONCAT_3(EGU, _idx_, _CH_NUM), +#endif +/**@brief Function for getting max channel number of given SWI. + * + * @param[in] swi SWI number. + * @return number of available channels. + */ +uint32_t swi_channel_number(nrf_swi_t swi) +{ +#if NRF_MODULE_ENABLED(EGU) + static uint8_t const egu_ch_count[] = {MACRO_REPEAT_FOR(EGU_COUNT, SWI_EGU_CH_DEF)}; + + if (swi < EGU_COUNT) + { + return (uint32_t)egu_ch_count[swi]; + } + #if SWI_EGU_MIXED + if (swi < SWI_COUNT) + { + return (uint32_t)SWI_MAX_FLAGS; + } + #endif +#else // only SWI + if (swi < SWI_COUNT) + { + return (uint32_t)SWI_MAX_FLAGS; + } +#endif // NRF_MODULE_ENABLED(EGU) + + return 0; +} + +#if NRF_MODULE_ENABLED(EGU) +/**@brief Get the specific EGU instance. */ +__STATIC_INLINE NRF_EGU_Type * egu_instance_get(nrf_swi_t swi) +{ +#if SWI_EGU_MIXED + if (!(swi < EGU_COUNT)) + { + return NULL; + } +#endif + return (NRF_EGU_Type*) (NRF_EGU0_BASE + + (((uint32_t) swi) * (NRF_EGU1_BASE - NRF_EGU0_BASE))); +} + +/**@brief Software interrupt handler (can be using EGU). */ +static void nrf_drv_swi_process(nrf_swi_t swi, nrf_swi_flags_t flags) +{ + ASSERT(swi < SWI_COUNT); + + ASSERT(m_swi_handlers[swi - SWI_START_NUMBER]); + NRF_EGU_Type * NRF_EGUx = egu_instance_get(swi); + + if (NRF_EGUx != NULL) + { + flags = 0; + for (uint8_t i = 0; i < swi_channel_number(swi); ++i) + { + nrf_egu_event_t egu_event = nrf_egu_event_triggered_get(NRF_EGUx, i); + if (nrf_egu_event_check(NRF_EGUx, egu_event)) + { + flags |= (1u << i); + nrf_egu_event_clear(NRF_EGUx, egu_event); + } + } + } +#if SWI_EGU_MIXED // this code is needed to handle SWI instances without EGU + else + { + m_swi_flags[swi - SWI_START_NUMBER - EGU_COUNT] &= ~flags; + } +#endif + m_swi_handlers[swi - SWI_START_NUMBER](swi, flags); +} + +#else +/**@brief Software interrupt handler (without EGU). */ +static void nrf_drv_swi_process(nrf_swi_t swi, nrf_swi_flags_t flags) +{ + ASSERT(m_swi_handlers[swi - SWI_START_NUMBER]); + m_swi_flags[swi - SWI_START_NUMBER] &= ~flags; + m_swi_handlers[swi - SWI_START_NUMBER](swi, flags); +} +#endif + +#if NRF_MODULE_ENABLED(EGU) + #if SWI_EGU_MIXED + #define SWI_EGU_HANDLER_TEMPLATE(NUM) void SWI##NUM##_EGU##NUM##_IRQHandler(void) \ + { \ + nrf_drv_swi_process(NUM, 0); \ + } + #define SWI_HANDLER_TEMPLATE(NUM) void SWI##NUM##_IRQHandler(void) \ + { \ + nrf_drv_swi_process((NUM), \ + m_swi_flags[(NUM) - SWI_START_NUMBER - EGU_COUNT]);\ + } + #else + #define SWI_HANDLER_TEMPLATE(NUM) void SWI##NUM##_EGU##NUM##_IRQHandler(void) \ + { \ + nrf_drv_swi_process(NUM, 0); \ + } + #endif // SWI_EGU_MIXED +#else + #define SWI_HANDLER_TEMPLATE(NUM) void SWI##NUM##_IRQHandler(void) \ + { \ + nrf_drv_swi_process((NUM), m_swi_flags[(NUM) - SWI_START_NUMBER]); \ + } +#endif // NRF_MODULE_ENABLED(EGU) + + +#if SWI_EGU_MIXED == 0 + #if SWI_DISABLE0 == 0 + SWI_HANDLER_TEMPLATE(0) + #endif + + #if SWI_DISABLE1 == 0 + SWI_HANDLER_TEMPLATE(1) + #endif + + #if SWI_DISABLE2 == 0 + SWI_HANDLER_TEMPLATE(2) + #endif + + #if SWI_DISABLE3 == 0 + SWI_HANDLER_TEMPLATE(3) + #endif + + #if SWI_DISABLE4 == 0 + SWI_HANDLER_TEMPLATE(4) + #endif + + #if SWI_DISABLE5 == 0 + SWI_HANDLER_TEMPLATE(5) + #endif +#else // SWI_EGU_MIXED == 1: SWI and SWI_EGU handlers + #if SWI_DISABLE0 == 0 + SWI_EGU_HANDLER_TEMPLATE(0) + #endif + + #if SWI_DISABLE1 == 0 + SWI_EGU_HANDLER_TEMPLATE(1) // NRF52810_XXAA has 2xSWI-EGU and 4xSWI + #endif + + #if SWI_DISABLE2 == 0 + SWI_HANDLER_TEMPLATE(2) + #endif + + #if SWI_DISABLE3 == 0 + SWI_HANDLER_TEMPLATE(3) + #endif + + #if SWI_DISABLE4 == 0 + SWI_HANDLER_TEMPLATE(4) + #endif + + #if SWI_DISABLE5 == 0 + SWI_HANDLER_TEMPLATE(5) + #endif +#endif // SWI_EGU_MIXED == 0 + +#define AVAILABLE_SWI (0x3FuL & ~( \ + (SWI_DISABLE0 << 0) | (SWI_DISABLE1 << 1) | (SWI_DISABLE2 << 2) \ + | (SWI_DISABLE3 << 3) | (SWI_DISABLE4 << 4) | (SWI_DISABLE5 << 5) \ + )) + +#if (AVAILABLE_SWI == 0) + #warning No available SWIs. +#endif + +/**@brief Function for converting SWI number to system interrupt number. + * + * @param[in] swi SWI number. + * + * @retval IRQ number. + */ +__STATIC_INLINE IRQn_Type nrf_drv_swi_irq_of(nrf_swi_t swi) +{ + return (IRQn_Type)((uint32_t)SWI0_IRQn + (uint32_t)swi); +} + + +/**@brief Function for checking if given SWI is allocated. + * + * @param[in] swi SWI number. + */ +__STATIC_INLINE bool swi_is_allocated(nrf_swi_t swi) +{ + ASSERT(swi < SWI_COUNT); +#if SWI_START_NUMBER > 0 + if (swi < SWI_START_NUMBER) + { + return false; + } +#endif + /*lint -e(661) out of range case handled by assert above*/ + return m_swi_handlers[swi - SWI_START_NUMBER]; +} + +ret_code_t nrf_drv_swi_init(void) +{ + ret_code_t err_code; + + if (m_drv_state == NRF_DRV_STATE_UNINITIALIZED) + { + m_drv_state = NRF_DRV_STATE_INITIALIZED; + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_swi_uninit(void) +{ + ASSERT(m_drv_state != NRF_DRV_STATE_UNINITIALIZED) + + for (uint32_t i = SWI_START_NUMBER; i < SWI_COUNT; ++i) + { + m_swi_handlers[i - SWI_START_NUMBER] = NULL; + nrf_drv_common_irq_disable(nrf_drv_swi_irq_of((nrf_swi_t) i)); +#if NRF_MODULE_ENABLED(EGU) + NRF_EGU_Type * NRF_EGUx = egu_instance_get(i); + if (NRF_EGUx != NULL) + { + nrf_egu_int_disable(NRF_EGUx, NRF_EGU_INT_ALL); + } +#endif + } + m_drv_state = NRF_DRV_STATE_UNINITIALIZED; + return; +} + + +void nrf_drv_swi_free(nrf_swi_t * p_swi) +{ + ASSERT(swi_is_allocated(*p_swi)); + nrf_drv_common_irq_disable(nrf_drv_swi_irq_of(*p_swi)); + m_swi_handlers[(*p_swi) - SWI_START_NUMBER] = NULL; + *p_swi = NRF_SWI_UNALLOCATED; +} + + +ret_code_t nrf_drv_swi_alloc(nrf_swi_t * p_swi, nrf_swi_handler_t event_handler, uint32_t priority) +{ +#if !NRF_MODULE_ENABLED(EGU) + ASSERT(event_handler); +#endif + uint32_t err_code = NRF_ERROR_NO_MEM; + + for (uint32_t i = SWI_START_NUMBER; i < SWI_COUNT; i++) + { + CRITICAL_REGION_ENTER(); + if ((!swi_is_allocated(i)) && (AVAILABLE_SWI & (1 << i))) + { + m_swi_handlers[i - SWI_START_NUMBER] = event_handler; + *p_swi = (nrf_swi_t) i; + nrf_drv_common_irq_enable(nrf_drv_swi_irq_of(*p_swi), priority); +#if NRF_MODULE_ENABLED(EGU) + if ((event_handler != NULL) && (i < EGU_COUNT)) + { + NRF_EGU_Type * NRF_EGUx = egu_instance_get(i); + if (NRF_EGUx != NULL) + { + nrf_egu_int_enable(NRF_EGUx, NRF_EGU_INT_ALL); + } + } + #if SWI_EGU_MIXED + if (i >= EGU_COUNT) + { + ASSERT(event_handler); + } + #endif +#endif // NRF_MODULE_ENABLED(EGU) + err_code = NRF_SUCCESS; + } + CRITICAL_REGION_EXIT(); + if (err_code == NRF_SUCCESS) + { + NRF_LOG_INFO("SWI channel allocated: %d.", (*p_swi)); + break; + } + } + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_swi_trigger(nrf_swi_t swi, uint8_t flag_number) +{ + ASSERT(swi_is_allocated((uint32_t) swi)); + ASSERT(flag_number < swi_channel_number(swi)); +#if NRF_MODULE_ENABLED(EGU) + NRF_EGU_Type * NRF_EGUx = egu_instance_get(swi); + if (NRF_EGUx != NULL) + { + nrf_egu_task_trigger(NRF_EGUx, nrf_egu_task_trigger_get(NRF_EGUx, flag_number)); + } +#if SWI_EGU_MIXED + else + { + if (swi < SWI_COUNT) + { + /* for swi < EGU_COUNT above code will be executed */ + m_swi_flags[swi - SWI_START_NUMBER - EGU_COUNT] |= (1 << flag_number); + NVIC_SetPendingIRQ(nrf_drv_swi_irq_of(swi)); + } + } +#endif // SWI_EGU_MIXED +#else + m_swi_flags[swi - SWI_START_NUMBER] |= (1 << flag_number); + NVIC_SetPendingIRQ(nrf_drv_swi_irq_of(swi)); +#endif // NRF_MODULE_ENABLED(EGU) +} + + +#if NRF_MODULE_ENABLED(EGU) + +uint32_t nrf_drv_swi_task_trigger_address_get(nrf_swi_t swi, uint8_t channel) +{ + NRF_EGU_Type * NRF_EGUx = egu_instance_get(swi); + if (NRF_EGUx != NULL) + { + return (uint32_t)nrf_egu_task_trigger_address_get(NRF_EGUx, channel); + } + else + { + return 0; + } +} + +uint32_t nrf_drv_swi_event_triggered_address_get(nrf_swi_t swi, uint8_t channel) +{ + NRF_EGU_Type * NRF_EGUx = egu_instance_get(swi); + if (NRF_EGUx != NULL) + { + return (uint32_t)nrf_egu_event_triggered_address_get(NRF_EGUx, channel); + } + else + { + return 0; + } +} + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.h new file mode 100644 index 0000000000..a3a4a0e043 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/swi/nrf_drv_swi.h @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_drv_swi SWI driver + * @{ + * @ingroup nrf_drivers + * + * @brief Driver for software interrupts (SWI). + * @details The SWI driver allows the user to allocate SWIs and pass extra flags to interrupt handler functions. + */ + +#ifndef NRF_DRV_SWI_H__ +#define NRF_DRV_SWI_H__ + +#include +#include +#include "sdk_config.h" +#include "app_util.h" +#include "app_util_platform.h" +#include "sdk_common.h" +#include "sdk_errors.h" +#include "nrf_peripherals.h" + +#ifndef EGU_ENABLED + #define EGU_ENABLED 0 +#endif + +#if NRF_MODULE_ENABLED(EGU) +#include "nrf_egu.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t nrf_swi_t; ///< @brief SWI channel (unsigned integer). + +/** @brief SWI user flags (unsigned integer). + * + * User flags are set during the SWI trigger and passed to the callback function as an argument. + */ +typedef uint16_t nrf_swi_flags_t; + +/** @brief Unallocated channel value. */ +#define NRF_SWI_UNALLOCATED ((nrf_swi_t) 0xFFFFFFFFuL) + +/** @brief SWI handler function. + * + * Takes two arguments: SWI number (nrf_swi_t) and flags (nrf_swi_flags_t). + */ +typedef void (* nrf_swi_handler_t)(nrf_swi_t, nrf_swi_flags_t); + +#ifdef SOFTDEVICE_PRESENT + #if SWI_COUNT > 2 + #undef SWI_COUNT + #ifdef NRF52810_XXAA + #define SWI_COUNT 3 // SoftDevice for NRF52810_XXAA utilizes 3 SWIs + #else + #define SWI_COUNT 2 // usually, SoftDevice utilizes 4 SWIs + #endif + #endif +#else + #ifdef SVCALL_AS_NORMAL_FUNCTION + // Serialization is enabled. + #if SWI_COUNT > 2 + #undef SWI_COUNT + #ifdef NRF52810_XXAA + #define SWI_COUNT 3 // SoftDevice for NRF52810_XXAA will utilize 3 SWIs + #else + #define SWI_COUNT 2 // usually, SoftDevice utilizes 4 SWIs + #endif + #endif + #endif +#endif + +#if NRF_MODULE_ENABLED(PWM_NRF52_ANOMALY_109_WORKAROUND) + #if (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 0) + #define SWI_DISABLE0 + #elif (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 1) + #define SWI_DISABLE1 + #elif (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 2) + #define SWI_DISABLE2 + #elif (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 3) + #define SWI_DISABLE3 + #elif (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 4) + #define SWI_DISABLE4 + #elif (PWM_NRF52_ANOMALY_109_EGU_INSTANCE == 5) + #define SWI_DISABLE5 + #endif +#endif + +/**@brief Default SWI priority. */ +#define SWI_DEFAULT_PRIORITY APP_IRQ_PRIORITY_LOWEST + + +/**@brief Function for initializing the SWI module. + * + * @retval NRF_SUCCESS If the module was successfully initialized. + * @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the module has already been initialized. + */ +ret_code_t nrf_drv_swi_init(void); + + +/**@brief Function for uninitializing the SWI module. + * + * This function also disables all SWIs. + */ +void nrf_drv_swi_uninit(void); + + +/**@brief Function for allocating a first unused SWI instance and setting a handler. + * @details The event handler function returns void and takes one uint32_t argument (SWI number). + * + * @param[out] p_swi Pointer to the SWI that has been allocated. + * @param[in] event_handler Event handler function. + * If NULL, no interrupt will be enabled (can be NULL only if the EGU + driver is enabled and available. For some microcontrollers, it is + possible that number of EGUs and SWIs differ). + * For classic SWI, must be a valid handler pointer. + * @param[in] priority Interrupt priority. + * + * @retval NRF_SUCCESS If the SWI was successfully allocated. + * @retval NRF_ERROR_NO_MEM If there is no available SWI to be used. + */ +ret_code_t nrf_drv_swi_alloc(nrf_swi_t * p_swi, nrf_swi_handler_t event_handler, uint32_t priority); + + +/**@brief Function for freeing a previously allocated SWI. + * + * @param[in,out] p_swi SWI to free. The value is changed to NRF_SWI_UNALLOCATED on success. + */ +void nrf_drv_swi_free(nrf_swi_t * p_swi); + + +/**@brief Function for triggering the SWI. + * + * @param[in] swi SWI to trigger. + * @param[in] flag_number Number of user flag to trigger. + */ +void nrf_drv_swi_trigger(nrf_swi_t swi, uint8_t flag_number); + + +#if (EGU_ENABLED > 0) || defined(__SDK_DOXYGEN__) + + +/**@brief Function for returning the EGU trigger task address. + * + * @param[in] swi SWI instance. + * @param[in] channel Number of the EGU channel. + * + * @returns EGU trigger task address. + */ +uint32_t nrf_drv_swi_task_trigger_address_get(nrf_swi_t swi, uint8_t channel); + +/**@brief Function for returning the EGU triggered event address. + * + * @param[in] swi SWI instance. + * @param[in] channel Number of the EGU channel. + * + * @returns EGU triggered event address. + */ +uint32_t nrf_drv_swi_event_triggered_address_get(nrf_swi_t swi, uint8_t channel); + +#endif // NRF_MODULE_ENABLED(EGU) + + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_SWI_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.c new file mode 100644 index 0000000000..041c41f1dc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.c @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(SYSTICK) +#include "nrf_drv_systick.h" +#include "nrf_systick.h" +#include "nrf.h" +#include "nrf_assert.h" + +/** + * @brief Maximum number of ticks to delay + * + * The maximum number of ticks should be much lower than + * Physical maximum count of the SysTick timer. + * It is dictated by the fact that it would be impossible to detect delay + * properly when the timer value warps around the starting point. + */ +#define NRF_DRV_SYSTICK_TICKS_MAX (NRF_SYSTICK_VAL_MASK / 2UL) + +/** + * @brief Number of milliseconds in a second + */ +#define NRF_DRV_SYSTICK_MS (1000UL) + +/** + * @brief Number of microseconds in a second + */ +#define NRF_DRV_SYSTICK_US (1000UL * NRF_DRV_SYSTICK_MS) + +/** + * @brief Number of milliseconds to wait in single loop + * + * Constant used by @ref nrd_drv_systick_delay_ms function + * to split waiting into loops and rest. + * + * It describes the number of milliseconds to wait in single loop. + * + * See @ref nrf_drv_systick_delay_ms source code for details. + */ +#define NRF_DRV_SYSTICK_MS_STEP (64U) + +/** + * @brief Checks if the given time is in correct range + * + * Function tests given time is not to big for this library. + * Assertion is used for testing. + * + * @param us Time in microseconds to check + */ +#define NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us) \ + ASSERT(us <= (NRF_DRV_SYSTICK_TICKS_MAX / ((SystemCoreClock) / NRF_DRV_SYSTICK_US))); + +/** + * @brief Function that converts microseconds to ticks + * + * Function converts from microseconds to CPU ticks. + * + * @param us Number of microseconds + * + * @return Number of ticks + * + * @sa nrf_drv_systick_ms_tick + */ +static inline uint32_t nrf_drv_systick_us_tick(uint32_t us) +{ + return us * ((SystemCoreClock) / NRF_DRV_SYSTICK_US); +} + +/** + * @brief Function that converts milliseconds to ticks + * + * Function converts from milliseconds to CPU ticks. + * + * @param us Number of milliseconds + * + * @return Number of ticks + * + * @sa nrf_drv_systick_us_tick + */ +static inline uint32_t nrf_drv_systick_ms_tick(uint32_t ms) +{ + return ms * ((SystemCoreClock) / NRF_DRV_SYSTICK_MS); +} + +void nrf_drv_systick_init(void) +{ + nrf_systick_load_set(NRF_SYSTICK_VAL_MASK); + nrf_systick_csr_set( + NRF_SYSTICK_CSR_CLKSOURCE_CPU | + NRF_SYSTICK_CSR_TICKINT_DISABLE | + NRF_SYSTICK_CSR_ENABLE); +} + +void nrf_drv_systick_get(nrf_drv_systick_state_t * p_state) +{ + p_state->time = nrf_systick_val_get(); +} + +bool nrf_drv_systick_test(nrf_drv_systick_state_t const * p_state, uint32_t us) +{ + NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us); + + const uint32_t diff = NRF_SYSTICK_VAL_MASK & ((p_state->time) - nrf_systick_val_get()); + return (diff >= nrf_drv_systick_us_tick(us)); +} + +void nrf_drv_systick_delay_ticks(uint32_t ticks) +{ + ASSERT(ticks <= NRF_DRV_SYSTICK_TICKS_MAX) + + const uint32_t start = nrf_systick_val_get(); + while ((NRF_SYSTICK_VAL_MASK & (start - nrf_systick_val_get())) < ticks) + { + /* Nothing to do */ + } +} + +void nrf_drv_systick_delay_us(uint32_t us) +{ + NRF_DRV_SYSTICK_ASSERT_TIMEOUT(us); + nrf_drv_systick_delay_ticks(nrf_drv_systick_us_tick(us)); +} + +void nrf_drv_systick_delay_ms(uint32_t ms) +{ + uint32_t n = ms / NRF_DRV_SYSTICK_MS_STEP; + uint32_t r = ms % NRF_DRV_SYSTICK_MS_STEP; + while (0 != (n--)) + { + nrf_drv_systick_delay_ticks(nrf_drv_systick_ms_tick(NRF_DRV_SYSTICK_MS_STEP)); + } + nrf_drv_systick_delay_ticks(nrf_drv_systick_ms_tick(r)); +} + +#endif // NRF_MODULE_ENABLED(SYSTICK) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.h new file mode 100644 index 0000000000..34492af2a1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/systick/nrf_drv_systick.h @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_SYSTICK_H__ +#define NRF_DRV_SYSTICK_H__ +#include +#include + + +/** + * @addtogroup nrf_systick SysTick HAL and driver + * @ingroup nrf_drivers + * @brief System Timer (SysTick) APIs + * + * The SysTick HAL provides basic APIs for accessing the registers of the system timer (SysTick). + * The SysTick driver provides APIs on a higher level. + */ + +/** + * @defgroup nrf_drv_systick SysTick driver + * @{ + * @ingroup nrf_systick + * + * This library configures SysTick as a free-running timer. + * This timer is used to generate delays and pool for timeouts. + * Only relatively short timeouts are supported. + * The SysTick works on 64MHz and is 24-bits wide. + * It means that it overflows around 4 times per second and around 250 ms + * would be the highest supported time in the library. + * But it would be really hard to detect if overflow was generated without + * using interrupts. For safely we would limit the maximum delay range by half. + */ + +/** + * @brief The value type that holds the SysTick state + * + * This variable is used to count the requested timeout. + * @sa nrf_drv_systick_get + */ +typedef struct { + uint32_t time; //!< Registered time value +}nrf_drv_systick_state_t; + +/** + * @brief Configure and start the timer + * + * Function configures SysTick as a free-running timer without interrupt. + */ +void nrf_drv_systick_init(void); + +/** + * @brief Get current SysTick state + * + * Function gets current state of the SysTick timer. + * It can be used to check time-out by @ref nrf_drv_systick_test. + * + * @param[out] p_state The pointer to the state variable to be filled + */ +void nrf_drv_systick_get(nrf_drv_systick_state_t * p_state); + +/** + * @brief Test if specified time is up in relation to remembered state + * + * @param[in] p_state Remembered state set by @ref nrf_drv_systick_get + * @param[in] us Required time-out. + * + * @retval true If current time is higher than specified state plus given time-out. + * @retval false If current time is lower than specified state plus given time-out + */ +bool nrf_drv_systick_test(nrf_drv_systick_state_t const * p_state, uint32_t us); + +/** + * @brief Blocking delay in CPU ticks + * + * @param[in] ticks Number of CPU ticks to delay. + */ +void nrf_drv_systick_delay_ticks(uint32_t ticks); + +/** + * @brief Blocking delay in us + * + * @param[in] us Number of microseconds to delay. + */ +void nrf_drv_systick_delay_us(uint32_t us); + +/** + * @brief Blocking delay in ms + * + * This delay function removes the limits of the highest possible delay value. + * + * @param[in] ms Number of milliseconds to delay. + */ +void nrf_drv_systick_delay_ms(uint32_t ms); + + +/** @} */ +#endif /* NRF_DRV_SYSTICK_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.c new file mode 100644 index 0000000000..5aa048b48c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.c @@ -0,0 +1,339 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(TIMER) +#define ENABLED_TIMER_COUNT (TIMER0_ENABLED+TIMER1_ENABLED+TIMER2_ENABLED+TIMER3_ENABLED+TIMER4_ENABLED) +#if ENABLED_TIMER_COUNT +#include "nrf_drv_timer.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME timer + +#if TIMER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL TIMER_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR TIMER_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR TIMER_CONFIG_DEBUG_COLOR +#else //TIMER_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //TIMER_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@brief Timer control block. */ +typedef struct +{ + nrf_timer_event_handler_t handler; + void * context; + nrf_drv_state_t state; +} timer_control_block_t; + +static timer_control_block_t m_cb[ENABLED_TIMER_COUNT]; + +ret_code_t nrf_drv_timer_init(nrf_drv_timer_t const * const p_instance, + nrf_drv_timer_config_t const * p_config, + nrf_timer_event_handler_t timer_event_handler) +{ + timer_control_block_t * p_cb = &m_cb[p_instance->instance_id]; + ASSERT(((p_instance->p_reg == NRF_TIMER0) && TIMER0_ENABLED) || (p_instance->p_reg != NRF_TIMER0)); + ASSERT(((p_instance->p_reg == NRF_TIMER1) && TIMER1_ENABLED) || (p_instance->p_reg != NRF_TIMER1)); + ASSERT(((p_instance->p_reg == NRF_TIMER2) && TIMER2_ENABLED) || (p_instance->p_reg != NRF_TIMER2)); +#if defined (NRF_TIMER3) + ASSERT(((p_instance->p_reg == NRF_TIMER3) && TIMER3_ENABLED) || (p_instance->p_reg != NRF_TIMER3)); +#endif +#if defined (NRF_TIMER4) + ASSERT(((p_instance->p_reg == NRF_TIMER4) && TIMER4_ENABLED) || (p_instance->p_reg != NRF_TIMER4)); +#endif +#ifdef SOFTDEVICE_PRESENT + ASSERT(p_instance->p_reg != NRF_TIMER0); +#endif + ASSERT(p_config); + + ret_code_t err_code; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (timer_event_handler == NULL) + { + err_code = NRF_ERROR_INVALID_PARAM; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + /* Warning 685: Relational operator '<=' always evaluates to 'true'" + * Warning in NRF_TIMER_IS_BIT_WIDTH_VALID macro. Macro validate timers resolution. + * Not necessary in nRF52 based systems. Obligatory in nRF51 based systems. + */ + + /*lint -save -e685 */ + + ASSERT(NRF_TIMER_IS_BIT_WIDTH_VALID(p_instance->p_reg, p_config->bit_width)); + + //lint -restore + + p_cb->handler = timer_event_handler; + p_cb->context = p_config->p_context; + + uint8_t i; + for (i = 0; i < p_instance->cc_channel_count; ++i) + { + nrf_timer_event_clear(p_instance->p_reg, + nrf_timer_compare_event_get(i)); + } + + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(p_instance->p_reg), + p_config->interrupt_priority); + + nrf_timer_mode_set(p_instance->p_reg, p_config->mode); + nrf_timer_bit_width_set(p_instance->p_reg, p_config->bit_width); + nrf_timer_frequency_set(p_instance->p_reg, p_config->frequency); + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_timer_uninit(nrf_drv_timer_t const * const p_instance) +{ + nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_instance->p_reg)); + + #define DISABLE_ALL UINT32_MAX + nrf_timer_shorts_disable(p_instance->p_reg, DISABLE_ALL); + nrf_timer_int_disable(p_instance->p_reg, DISABLE_ALL); + #undef DISABLE_ALL + + if (m_cb[p_instance->instance_id].state == NRF_DRV_STATE_POWERED_ON) + { + nrf_drv_timer_disable(p_instance); + } + + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Uninitialized instance: %d.", p_instance->instance_id); +} + +void nrf_drv_timer_enable(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_INITIALIZED); + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START); + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled instance: %d.", p_instance->instance_id); +} + +void nrf_drv_timer_disable(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_POWERED_ON); + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_SHUTDOWN); + m_cb[p_instance->instance_id].state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Disabled instance: %d.", p_instance->instance_id); +} + +void nrf_drv_timer_resume(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_POWERED_ON); + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_START); + NRF_LOG_INFO("Resumed instance: %d.", p_instance->instance_id); +} + +void nrf_drv_timer_pause(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_POWERED_ON); + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_STOP); + NRF_LOG_INFO("Paused instance: %d.", p_instance->instance_id); +} + +void nrf_drv_timer_clear(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_CLEAR); +} + +void nrf_drv_timer_increment(nrf_drv_timer_t const * const p_instance) +{ + ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_POWERED_ON); + ASSERT(nrf_timer_mode_get(p_instance->p_reg) != NRF_TIMER_MODE_TIMER); + + nrf_timer_task_trigger(p_instance->p_reg, NRF_TIMER_TASK_COUNT); +} + +uint32_t nrf_drv_timer_capture(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(cc_channel < p_instance->cc_channel_count); + + nrf_timer_task_trigger(p_instance->p_reg, + nrf_timer_capture_task_get(cc_channel)); + return nrf_timer_cc_read(p_instance->p_reg, cc_channel); +} + +void nrf_drv_timer_compare(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value, + bool enable_int) +{ + nrf_timer_int_mask_t timer_int = nrf_timer_compare_int_get(cc_channel); + + if (enable_int) + { + nrf_timer_int_enable(p_instance->p_reg, timer_int); + } + else + { + nrf_timer_int_disable(p_instance->p_reg, timer_int); + } + + nrf_timer_cc_write(p_instance->p_reg, cc_channel, cc_value); + NRF_LOG_INFO("Timer id: %d, capture value set: %d, channel: %d.", p_instance->instance_id, cc_value, cc_channel); +} + +void nrf_drv_timer_extended_compare(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value, + nrf_timer_short_mask_t timer_short_mask, + bool enable_int) +{ + nrf_timer_shorts_disable(p_instance->p_reg, + (TIMER_SHORTS_COMPARE0_STOP_Msk << cc_channel) | + (TIMER_SHORTS_COMPARE0_CLEAR_Msk << cc_channel)); + + nrf_timer_shorts_enable(p_instance->p_reg, timer_short_mask); + + (void)nrf_drv_timer_compare(p_instance, + cc_channel, + cc_value, + enable_int); + NRF_LOG_INFO("Timer id: %d, capture value set: %d, channel: %d.", p_instance->instance_id, cc_value, cc_channel); +} + +void nrf_drv_timer_compare_int_enable(nrf_drv_timer_t const * const p_instance, + uint32_t channel) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(channel < p_instance->cc_channel_count); + + nrf_timer_event_clear(p_instance->p_reg, + nrf_timer_compare_event_get(channel)); + nrf_timer_int_enable(p_instance->p_reg, + nrf_timer_compare_int_get(channel)); +} + +void nrf_drv_timer_compare_int_disable(nrf_drv_timer_t const * const p_instance, + uint32_t channel) +{ + ASSERT(m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED); + ASSERT(channel < p_instance->cc_channel_count); + + nrf_timer_int_disable(p_instance->p_reg, + nrf_timer_compare_int_get(channel)); +} + +static void irq_handler(NRF_TIMER_Type * p_reg, + timer_control_block_t * p_cb, + uint8_t channel_count) +{ + uint8_t i; + for (i = 0; i < channel_count; ++i) + { + nrf_timer_event_t event = nrf_timer_compare_event_get(i); + nrf_timer_int_mask_t int_mask = nrf_timer_compare_int_get(i); + + if (nrf_timer_event_check(p_reg, event) && + nrf_timer_int_enable_check(p_reg, int_mask)) + { + nrf_timer_event_clear(p_reg, event); + NRF_LOG_DEBUG("Compare event, channel: %d.", i); + p_cb->handler(event, p_cb->context); + } + } +} + +#if NRF_MODULE_ENABLED(TIMER0) +void TIMER0_IRQHandler(void) +{ + irq_handler(NRF_TIMER0, &m_cb[TIMER0_INSTANCE_INDEX], + NRF_TIMER_CC_CHANNEL_COUNT(0)); +} +#endif + +#if NRF_MODULE_ENABLED(TIMER1) +void TIMER1_IRQHandler(void) +{ + irq_handler(NRF_TIMER1, &m_cb[TIMER1_INSTANCE_INDEX], + NRF_TIMER_CC_CHANNEL_COUNT(1)); +} +#endif + +#if NRF_MODULE_ENABLED(TIMER2) +void TIMER2_IRQHandler(void) +{ + irq_handler(NRF_TIMER2, &m_cb[TIMER2_INSTANCE_INDEX], + NRF_TIMER_CC_CHANNEL_COUNT(2)); +} +#endif + +#if defined (NRF_TIMER3) +#if NRF_MODULE_ENABLED(TIMER3) +void TIMER3_IRQHandler(void) +{ + irq_handler(NRF_TIMER3, &m_cb[TIMER3_INSTANCE_INDEX], + NRF_TIMER_CC_CHANNEL_COUNT(3)); +} +#endif +#endif + +#if defined (NRF_TIMER4) +#if NRF_MODULE_ENABLED(TIMER4) +void TIMER4_IRQHandler(void) +{ + irq_handler(NRF_TIMER4, &m_cb[TIMER4_INSTANCE_INDEX], + NRF_TIMER_CC_CHANNEL_COUNT(4)); +} +#endif +#endif + +#endif // ENABLED_TIMER_COUNT +#endif // NRF_MODULE_ENABLED(TIMER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.h new file mode 100644 index 0000000000..8d8cba0543 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/timer/nrf_drv_timer.h @@ -0,0 +1,410 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_timer Timer HAL and driver + * @ingroup nrf_drivers + * @brief Timer APIs. + * @details The timer HAL provides basic APIs for accessing the registers + * of the timer. The timer driver provides APIs on a higher level. + * + * @defgroup nrf_drv_timer Timer driver + * @{ + * @ingroup nrf_timer + * @brief Multi-instance timer driver. + */ + +#ifndef NRF_DRV_TIMER_H__ +#define NRF_DRV_TIMER_H__ + +#include "nordic_common.h" +#include "sdk_config.h" +#include "nrf_timer.h" +#include "sdk_errors.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Timer driver instance data structure. + */ +typedef struct +{ + NRF_TIMER_Type * p_reg; ///< Pointer to the structure with TIMER peripheral instance registers. + uint8_t instance_id; ///< Driver instance index. + uint8_t cc_channel_count; ///< Number of capture/compare channels. +} nrf_drv_timer_t; + +#define ENABLED_TIMER_COUNT (TIMER0_ENABLED+TIMER1_ENABLED+TIMER2_ENABLED+TIMER3_ENABLED+TIMER4_ENABLED) + +#define TIMER0_INSTANCE_INDEX 0 +#define TIMER1_INSTANCE_INDEX TIMER0_INSTANCE_INDEX+TIMER0_ENABLED +#define TIMER2_INSTANCE_INDEX TIMER1_INSTANCE_INDEX+TIMER1_ENABLED +#define TIMER3_INSTANCE_INDEX TIMER2_INSTANCE_INDEX+TIMER2_ENABLED +#define TIMER4_INSTANCE_INDEX TIMER3_INSTANCE_INDEX+TIMER3_ENABLED + +/** + * @brief Macro for creating a timer driver instance. + */ +#define NRF_DRV_TIMER_INSTANCE(id) \ +{ \ + .p_reg = CONCAT_2(NRF_TIMER, id), \ + .instance_id = CONCAT_3(TIMER, id, _INSTANCE_INDEX), \ + .cc_channel_count = NRF_TIMER_CC_CHANNEL_COUNT(id), \ +} + +/** + * @brief Timer driver instance configuration structure. + */ +typedef struct +{ + nrf_timer_frequency_t frequency; ///< Frequency. + nrf_timer_mode_t mode; ///< Mode of operation. + nrf_timer_bit_width_t bit_width; ///< Bit width. + uint8_t interrupt_priority; ///< Interrupt priority. + void * p_context; ///< Context passed to interrupt handler. +} nrf_drv_timer_config_t; + +/** + * @brief Timer driver instance default configuration. + */ +#define NRF_DRV_TIMER_DEFAULT_CONFIG \ +{ \ + .frequency = (nrf_timer_frequency_t)TIMER_DEFAULT_CONFIG_FREQUENCY,\ + .mode = (nrf_timer_mode_t)TIMER_DEFAULT_CONFIG_MODE, \ + .bit_width = (nrf_timer_bit_width_t)TIMER_DEFAULT_CONFIG_BIT_WIDTH,\ + .interrupt_priority = TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .p_context = NULL \ +} + +/** + * @brief Timer driver event handler type. + * + * @param[in] event_type Timer event. + * @param[in] p_context General purpose parameter set during initialization of + * the timer. This parameter can be used to pass + * additional information to the handler function, for + * example, the timer ID. + */ +typedef void (* nrf_timer_event_handler_t)(nrf_timer_event_t event_type, + void * p_context); + +/** + * @brief Function for initializing the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. Must not be NULL. + * @param[in] timer_event_handler Event handler provided by the user. + * Must not be NULL. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the instance is already initialized. + * @retval NRF_ERROR_INVALID_PARAM If no handler was provided. + */ +ret_code_t nrf_drv_timer_init(nrf_drv_timer_t const * const p_instance, + nrf_drv_timer_config_t const * p_config, + nrf_timer_event_handler_t timer_event_handler); + +/** + * @brief Function for uninitializing the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_uninit(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for turning on the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_enable(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for turning off the timer. + * + * Note that the timer will allow to enter the lowest possible SYSTEM_ON state + * only after this function is called. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_disable(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for pausing the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_pause(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for resuming the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_resume(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for clearing the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_clear(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for incrementing the timer. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_timer_increment(nrf_drv_timer_t const * const p_instance); + +/** + * @brief Function for returning the address of a specific timer task. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] timer_task Timer task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_task_address_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_task_t timer_task); + +/** + * @brief Function for returning the address of a specific timer capture task. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel Capture channel number. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_capture_task_address_get( + nrf_drv_timer_t const * const p_instance, + uint32_t channel); + +/** + * @brief Function for returning the address of a specific timer event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] timer_event Timer event. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_event_address_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_event_t timer_event); + +/** + * @brief Function for returning the address of a specific timer compare event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel Compare channel number. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_compare_event_address_get( + nrf_drv_timer_t const * const p_instance, + uint32_t channel); + +/** + * @brief Function for capturing the timer value. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc_channel Capture channel number. + * + * @return Captured value. + */ +uint32_t nrf_drv_timer_capture(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel); + +/** + * @brief Function for returning the capture value from a specific channel. + * + * Use this function to read channel values when PPI is used for capturing. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc_channel Capture channel number. + * + * @return Captured value. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_capture_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel); + +/** + * @brief Function for setting the timer channel in compare mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc_channel Compare channel number. + * @param[in] cc_value Compare value. + * @param[in] enable_int Enable or disable the interrupt for the compare channel. + */ +void nrf_drv_timer_compare(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value, + bool enable_int); + +/** + * @brief Function for setting the timer channel in extended compare mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] cc_channel Compare channel number. + * @param[in] cc_value Compare value. + * @param[in] timer_short_mask Shortcut between the compare event on the channel + * and the timer task (STOP or CLEAR). + * @param[in] enable_int Enable or disable the interrupt for the compare + * channel. + */ +void nrf_drv_timer_extended_compare(nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel, + uint32_t cc_value, + nrf_timer_short_mask_t timer_short_mask, + bool enable_int); + +/** + * @brief Function for converting time in microseconds to timer ticks. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] time_us Time in microseconds. + * + * @return Number of ticks. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_us_to_ticks( + nrf_drv_timer_t const * const p_instance, + uint32_t time_us); + +/** + * @brief Function for converting time in milliseconds to timer ticks. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] time_ms Time in milliseconds. + * + * @return Number of ticks. + */ +__STATIC_INLINE uint32_t nrf_drv_timer_ms_to_ticks( + nrf_drv_timer_t const * const p_instance, + uint32_t time_ms); + +/** + * @brief Function for enabling timer compare interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel Compare channel. + */ +void nrf_drv_timer_compare_int_enable(nrf_drv_timer_t const * const p_instance, + uint32_t channel); + +/** + * @brief Function for disabling timer compare interrupt. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] channel Compare channel. + */ +void nrf_drv_timer_compare_int_disable(nrf_drv_timer_t const * const p_instance, + uint32_t channel); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION + +__STATIC_INLINE uint32_t nrf_drv_timer_task_address_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_task_t timer_task) +{ + return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg, timer_task); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_capture_task_address_get( + nrf_drv_timer_t const * const p_instance, + uint32_t channel) +{ + ASSERT(channel < p_instance->cc_channel_count); + return (uint32_t)nrf_timer_task_address_get(p_instance->p_reg, + nrf_timer_capture_task_get(channel)); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_event_address_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_event_t timer_event) +{ + return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg, timer_event); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_compare_event_address_get( + nrf_drv_timer_t const * const p_instance, + uint32_t channel) +{ + ASSERT(channel < p_instance->cc_channel_count); + return (uint32_t)nrf_timer_event_address_get(p_instance->p_reg, + nrf_timer_compare_event_get(channel)); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_capture_get( + nrf_drv_timer_t const * const p_instance, + nrf_timer_cc_channel_t cc_channel) +{ + return nrf_timer_cc_read(p_instance->p_reg, cc_channel); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_us_to_ticks( + nrf_drv_timer_t const * const p_instance, + uint32_t timer_us) +{ + return nrf_timer_us_to_ticks(timer_us, + nrf_timer_frequency_get(p_instance->p_reg)); +} + +__STATIC_INLINE uint32_t nrf_drv_timer_ms_to_ticks( + nrf_drv_timer_t const * const p_instance, + uint32_t timer_ms) +{ + return nrf_timer_ms_to_ticks(timer_ms, + nrf_timer_frequency_get(p_instance->p_reg)); +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_TIMER_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.c new file mode 100644 index 0000000000..c321de8dda --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.c @@ -0,0 +1,1267 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(TWI) +#include "nrf_drv_twi.h" +#if ENABLED_TWI_COUNT +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "nrf_assert.h" +#include "app_util_platform.h" +#include "nrf_delay.h" + +#include + +#define NRF_LOG_MODULE_NAME twi + +/*lint -save -e491*/ + +#if TWI_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL TWI_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR TWI_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR TWI_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_DRV_TWI_EVT_DONE ? "EVT_DONE" : \ + (event == NRF_DRV_TWI_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \ + (event == NRF_DRV_TWI_EVT_DATA_NACK ? "EVT_DATA_NACK" : "UNKNOWN ERROR"))) +#define EVT_TO_STR_TWI(event) (event == NRF_TWI_EVENT_STOPPED ? "NRF_TWI_EVENT_STOPPED" : \ + (event == NRF_TWI_EVENT_RXDREADY ? "NRF_TWI_EVENT_RXDREADY" : \ + (event == NRF_TWI_EVENT_TXDSENT ? "NRF_TWI_EVENT_TXDSENT" : \ + (event == NRF_TWI_EVENT_ERROR ? "NRF_TWI_EVENT_ERROR" : \ + (event == NRF_TWI_EVENT_BB ? "NRF_TWI_EVENT_BB" : \ + (event == NRF_TWI_EVENT_SUSPENDED ? "NRF_TWI_EVENT_SUSPENDED" : "UNKNOWN ERROR")))))) +#define EVT_TO_STR_TWIM(event) (event == NRF_TWIM_EVENT_STOPPED ? "NRF_TWIM_EVENT_STOPPED" : \ + (event == NRF_TWIM_EVENT_ERROR ? "NRF_TWIM_EVENT_ERROR" : \ + (event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \ + (event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \ + (event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \ + (event == NRF_TWIM_EVENT_LASTRX ? "NRF_TWIM_EVENT_LASTRX" : \ + (event == NRF_TWIM_EVENT_LASTTX ? "NRF_TWIM_EVENT_LASTTX" : "UNKNOWN ERROR"))))))) +#define TRANSFER_TO_STR(type) (type == NRF_DRV_TWI_XFER_TX ? "XFER_TX" : \ + (type == NRF_DRV_TWI_XFER_RX ? "XFER_RX" : \ + (type == NRF_DRV_TWI_XFER_TXRX ? "XFER_TXRX" : \ + (type == NRF_DRV_TWI_XFER_TXTX ? "XFER_TXTX" : "UNKNOWN TRANSFER TYPE")))) +#else //TWI_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define EVT_TO_STR_TWI(event) "" +#define EVT_TO_STR_TWIM(event) "" +#define TRANSFER_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //TWI_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if (defined(TWIM_IN_USE) && defined(TWI_IN_USE)) + // TWIM and TWI combined + #define CODE_FOR_TWIM(code) if (p_instance->use_easy_dma) { code } + #define CODE_FOR_TWI(code) else { code } +#elif (defined(TWIM_IN_USE) && !defined(TWI_IN_USE)) + // TWIM only + #define CODE_FOR_TWIM(code) { code } + #define CODE_FOR_TWI(code) +#elif (!defined(TWIM_IN_USE) && defined(TWI_IN_USE)) + // TWI only + #define CODE_FOR_TWIM(code) + #define CODE_FOR_TWI(code) { code } +#else + #error "Wrong configuration." +#endif + +// All interrupt flags +#define DISABLE_ALL_INT_SHORT 0xFFFFFFFF + +#define SCL_PIN_INIT_CONF ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) \ + | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \ + | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)) +#define SDA_PIN_INIT_CONF SCL_PIN_INIT_CONF + +#define SDA_PIN_UNINIT_CONF ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) \ + | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) \ + | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)) +#define SCL_PIN_UNINIT_CONF SDA_PIN_UNINIT_CONF + +#define SCL_PIN_INIT_CONF_CLR ( (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \ + | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \ + | (GPIO_PIN_CNF_PULL_Pullup << 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)) +#define SDA_PIN_INIT_CONF_CLR SCL_PIN_INIT_CONF_CLR + +#define HW_TIMEOUT 10000 + +// Control block - driver instance local data. +typedef struct +{ + nrf_drv_twi_evt_handler_t handler; + void * p_context; + volatile uint32_t int_mask; + nrf_drv_twi_xfer_desc_t xfer_desc; + uint32_t flags; + uint8_t * p_curr_buf; + uint8_t curr_length; + bool curr_no_stop; + nrf_drv_state_t state; + bool error; + volatile bool busy; + bool repeated; + uint8_t bytes_transferred; + bool hold_bus_uninit; +#if NRF_MODULE_ENABLED(TWIM_NRF52_ANOMALY_109_WORKAROUND) + nrf_twim_frequency_t bus_frequency; +#endif +} twi_control_block_t; + +static twi_control_block_t m_cb[ENABLED_TWI_COUNT]; + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n + #define IRQ_HANDLER(n) static void IRQ_HANDLER_NAME(n)(void) + + #if NRF_MODULE_ENABLED(TWI0) + IRQ_HANDLER(0); + #endif + #if NRF_MODULE_ENABLED(TWI1) + IRQ_HANDLER(1); + #endif + static nrf_drv_irq_handler_t const m_irq_handlers[ENABLED_TWI_COUNT] = { + #if NRF_MODULE_ENABLED(TWI0) + IRQ_HANDLER_NAME(0), + #endif + #if NRF_MODULE_ENABLED(TWI1) + IRQ_HANDLER_NAME(1), + #endif + }; +#else + #if defined (NRF52810_XXAA) + #define IRQ_HANDLER(n) void TWIM##n##_TWIS##n##_IRQHandler(void) + #else + #define IRQ_HANDLER(n) void SPI##n##_TWI##n##_IRQHandler(void) + #endif +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +static ret_code_t twi_process_error(uint32_t errorsrc) +{ + ret_code_t ret = NRF_ERROR_INTERNAL; +#ifdef TWI_IN_USE + if (errorsrc & NRF_TWI_ERROR_OVERRUN) + { + ret = NRF_ERROR_DRV_TWI_ERR_OVERRUN; + } +#endif + if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK) + { + ret = NRF_ERROR_DRV_TWI_ERR_ANACK; + } + + if (errorsrc & NRF_TWI_ERROR_DATA_NACK) + { + ret = NRF_ERROR_DRV_TWI_ERR_DNACK; + } + + return ret; +} + +static void twi_clear_bus(nrf_drv_twi_config_t const * p_config) +{ + NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF; + NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF; + + nrf_gpio_pin_set(p_config->scl); + nrf_gpio_pin_set(p_config->sda); + + NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF_CLR; + NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF_CLR; + + nrf_delay_us(4); + + for (int i = 0; i < 9; i++) + { + if (nrf_gpio_pin_read(p_config->sda)) + { + if (i == 0) + { + return; + } + else + { + break; + } + } + nrf_gpio_pin_clear(p_config->scl); + nrf_delay_us(4); + nrf_gpio_pin_set(p_config->scl); + nrf_delay_us(4); + } + nrf_gpio_pin_clear(p_config->sda); + nrf_delay_us(4); + nrf_gpio_pin_set(p_config->sda); +} + +ret_code_t nrf_drv_twi_init(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_config_t const * p_config, + nrf_drv_twi_evt_handler_t event_handler, + void * p_context) +{ + ASSERT(p_config); + ASSERT(p_config->scl != p_config->sda); + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ret_code_t err_code; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(p_instance->reg.p_regs, + m_irq_handlers[p_instance->drv_inst_idx]) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + + p_cb->handler = event_handler; + p_cb->p_context = p_context; + p_cb->int_mask = 0; + p_cb->repeated = false; + p_cb->busy = false; + p_cb->hold_bus_uninit = p_config->hold_bus_uninit; +#if NRF_MODULE_ENABLED(TWIM_NRF52_ANOMALY_109_WORKAROUND) + p_cb->bus_frequency = (nrf_twim_frequency_t)p_config->frequency; +#endif + + if (p_config->clear_bus_init) + { + /* Send clocks (max 9) until slave device back from stuck mode */ + twi_clear_bus(p_config); + } + + /* To secure correct signal levels on the pins used by the TWI + master when the system is in OFF mode, and when the TWI master is + disabled, these pins must be configured in the GPIO peripheral. + */ + NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_INIT_CONF; + NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_INIT_CONF; + + CODE_FOR_TWIM + ( + NRF_TWIM_Type * p_twim = p_instance->reg.p_twim; + nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda); + nrf_twim_frequency_set(p_twim, + (nrf_twim_frequency_t)p_config->frequency); + ) + CODE_FOR_TWI + ( + NRF_TWI_Type * p_twi = p_instance->reg.p_twi; + nrf_twi_pins_set(p_twi, p_config->scl, p_config->sda); + nrf_twi_frequency_set(p_twi, + (nrf_twi_frequency_t)p_config->frequency); + ) + + if (p_cb->handler) + { + CODE_FOR_TWIM + ( + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twim), + p_config->interrupt_priority); + ) + CODE_FOR_TWI + ( + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twi), + p_config->interrupt_priority); + ) + } + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance) +{ + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + if (p_cb->handler) + { + CODE_FOR_TWIM + ( + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twim)); + ) + CODE_FOR_TWI + ( + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twi)); + ) + } + nrf_drv_twi_disable(p_instance); + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(p_instance->reg.p_regs); +#endif + + if (!p_cb->hold_bus_uninit) + { + CODE_FOR_TWIM + ( + NRF_GPIO->PIN_CNF[p_instance->reg.p_twim->PSEL.SCL] = SCL_PIN_UNINIT_CONF; + NRF_GPIO->PIN_CNF[p_instance->reg.p_twim->PSEL.SDA] = SDA_PIN_UNINIT_CONF; + ) + CODE_FOR_TWI + ( + NRF_GPIO->PIN_CNF[p_instance->reg.p_twi->PSELSCL] = SCL_PIN_UNINIT_CONF; + NRF_GPIO->PIN_CNF[p_instance->reg.p_twi->PSELSDA] = SDA_PIN_UNINIT_CONF; + ) + } + + p_cb->state = NRF_DRV_STATE_UNINITIALIZED; + NRF_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx); +} + +void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance) +{ + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state == NRF_DRV_STATE_INITIALIZED); + + CODE_FOR_TWIM + ( + NRF_TWIM_Type * p_twim = p_instance->reg.p_twim; + + nrf_twim_enable(p_twim); + ) + CODE_FOR_TWI + ( + NRF_TWI_Type * p_twi = p_instance->reg.p_twi; + + nrf_twi_enable(p_twi); + ) + + p_cb->state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx); +} + +void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance) +{ + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); + + CODE_FOR_TWIM + ( + NRF_TWIM_Type * p_twim = p_instance->reg.p_twim; + p_cb->int_mask = 0; + nrf_twim_int_disable(p_twim, DISABLE_ALL_INT_SHORT); + nrf_twim_shorts_disable(p_twim, DISABLE_ALL_INT_SHORT); + nrf_twim_disable(p_twim); + ) + CODE_FOR_TWI + ( + NRF_TWI_Type * p_twi = p_instance->reg.p_twi; + nrf_twi_int_disable(p_twi, DISABLE_ALL_INT_SHORT); + nrf_twi_shorts_disable(p_twi, DISABLE_ALL_INT_SHORT); + nrf_twi_disable(p_twi); + ) + + p_cb->state = NRF_DRV_STATE_INITIALIZED; + NRF_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx); +} + +#ifdef TWI_IN_USE +static bool twi_send_byte(NRF_TWI_Type * p_twi, + uint8_t const * p_data, + uint8_t length, + uint8_t * p_bytes_transferred, + bool no_stop) +{ + if (*p_bytes_transferred < length) + { + nrf_twi_txd_set(p_twi, p_data[*p_bytes_transferred]); + ++(*p_bytes_transferred); + } + else + { + if (no_stop) + { + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND); + return false; + } + else + { + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP); + } + } + return true; +} + +static void twi_receive_byte(NRF_TWI_Type * p_twi, + uint8_t * p_data, + uint8_t length, + uint8_t * p_bytes_transferred) +{ + if (*p_bytes_transferred < length) + { + p_data[*p_bytes_transferred] = nrf_twi_rxd_get(p_twi); + + ++(*p_bytes_transferred); + + if (*p_bytes_transferred == length - 1) + { + nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK); + } + else if (*p_bytes_transferred == length) + { + return; + } + + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME); + } +} + +static bool twi_transfer(NRF_TWI_Type * p_twi, + bool * p_error, + uint8_t * p_bytes_transferred, + uint8_t * p_data, + uint8_t length, + bool no_stop) +{ + bool do_stop_check = ((*p_error) || ((*p_bytes_transferred) == length)); + + if (*p_error) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY); + } + else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR)) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR)); + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP); + *p_error = true; + } + else + { + if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_TXDSENT)) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT); + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_TXDSENT)); + if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR)) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR)); + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP); + *p_error = true; + } + else + { + if (!twi_send_byte(p_twi, p_data, length, p_bytes_transferred, no_stop)) + { + return false; + } + } + } + else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_RXDREADY)) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY); + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_RXDREADY)); + if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR)) + { + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR)); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP); + *p_error = true; + } + else + { + twi_receive_byte(p_twi, p_data, length, p_bytes_transferred); + } + } + } + + if (do_stop_check && nrf_twi_event_check(p_twi, NRF_TWI_EVENT_STOPPED)) + { + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED); + NRF_LOG_DEBUG("TWI: Event: %s.", (uint32_t)EVT_TO_STR_TWI(NRF_TWI_EVENT_STOPPED)); + return false; + } + + return true; +} + +static ret_code_t twi_tx_start_transfer(twi_control_block_t * p_cb, + NRF_TWI_Type * p_twi, + uint8_t const * p_data, + uint8_t length, + bool no_stop) +{ + ret_code_t ret_code = NRF_SUCCESS; + volatile int32_t hw_timeout; + + hw_timeout = HW_TIMEOUT; + + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY); + nrf_twi_shorts_set(p_twi, 0); + + p_cb->bytes_transferred = 0; + p_cb->error = false; + + // In case TWI is suspended resume its operation. + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME); + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX); + + (void)twi_send_byte(p_twi, p_data, length, &p_cb->bytes_transferred, no_stop); + + if (p_cb->handler) + { + p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK | + NRF_TWI_INT_ERROR_MASK | + NRF_TWI_INT_TXDSENT_MASK | + NRF_TWI_INT_RXDREADY_MASK; + nrf_twi_int_enable(p_twi, p_cb->int_mask); + } + else + { + while ((hw_timeout > 0) && + twi_transfer(p_twi, + &p_cb->error, + &p_cb->bytes_transferred, + (uint8_t *)p_data, + length, + no_stop)) + { + hw_timeout--; + } + + if (p_cb->error) + { + uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi); + + if (errorsrc) + { + ret_code = twi_process_error(errorsrc); + } + } + + if (hw_timeout <= 0) + { + nrf_twi_disable(p_twi); + nrf_twi_enable(p_twi); + ret_code = NRF_ERROR_INTERNAL; + } + + } + return ret_code; +} + +static ret_code_t twi_rx_start_transfer(twi_control_block_t * p_cb, + NRF_TWI_Type * p_twi, + uint8_t const * p_data, + uint8_t length) +{ + ret_code_t ret_code = NRF_SUCCESS; + volatile int32_t hw_timeout; + + hw_timeout = HW_TIMEOUT; + + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT); + nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY); + + p_cb->bytes_transferred = 0; + p_cb->error = false; + + if (length == 1) + { + nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK); + } + else + { + nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK); + } + // In case TWI is suspended resume its operation. + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME); + nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX); + + if (p_cb->handler) + { + p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK | + NRF_TWI_INT_ERROR_MASK | + NRF_TWI_INT_TXDSENT_MASK | + NRF_TWI_INT_RXDREADY_MASK; + nrf_twi_int_enable(p_twi, p_cb->int_mask); + } + else + { + while ((hw_timeout > 0) && + twi_transfer(p_twi, + &p_cb->error, + &p_cb->bytes_transferred, + (uint8_t*)p_data, + length, + false)) + { + hw_timeout--; + } + + if (p_cb->error) + { + uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi); + + if (errorsrc) + { + ret_code = twi_process_error(errorsrc); + } + } + if (hw_timeout <= 0) + { + nrf_twi_disable(p_twi); + nrf_twi_enable(p_twi); + ret_code = NRF_ERROR_INTERNAL; + } + } + return ret_code; +} + +__STATIC_INLINE ret_code_t twi_xfer(twi_control_block_t * p_cb, + NRF_TWI_Type * p_twi, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + + ret_code_t err_code = NRF_SUCCESS; + + /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */ + nrf_twi_int_disable(p_twi, DISABLE_ALL_INT_SHORT); + + if (p_cb->busy) + { + nrf_twi_int_enable(p_twi, p_cb->int_mask); + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + else + { + p_cb->busy = (NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ? false : true; + } + + if (flags & NRF_DRV_TWI_FLAG_HOLD_XFER) + { + err_code = NRF_ERROR_NOT_SUPPORTED; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + p_cb->flags = flags; + p_cb->xfer_desc = *p_xfer_desc; + p_cb->curr_length = p_xfer_desc->primary_length; + p_cb->p_curr_buf = p_xfer_desc->p_primary_buf; + nrf_twi_address_set(p_twi, p_xfer_desc->address); + + if (p_xfer_desc->type != NRF_DRV_TWI_XFER_RX) + { + p_cb->curr_no_stop = ((p_xfer_desc->type == NRF_DRV_TWI_XFER_TX) && + !(flags & NRF_DRV_TWI_FLAG_TX_NO_STOP)) ? false : true; + + err_code = twi_tx_start_transfer(p_cb, + p_twi, + p_xfer_desc->p_primary_buf, + p_xfer_desc->primary_length, + p_cb->curr_no_stop); + } + else + { + p_cb->curr_no_stop = false; + + err_code = twi_rx_start_transfer(p_cb, + p_twi, + p_xfer_desc->p_primary_buf, + p_xfer_desc->primary_length); + } + if (p_cb->handler == NULL) + { + p_cb->busy = false; + } + return err_code; +} +#endif + + +bool nrf_drv_twi_is_busy(nrf_drv_twi_t const * p_instance) +{ + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + return p_cb->busy; +} + + +#ifdef TWIM_IN_USE +__STATIC_INLINE void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags) +{ + if (NRF_DRV_TWI_FLAG_TX_POSTINC & flags) + { + nrf_twim_tx_list_enable(p_twim); + } + else + { + nrf_twim_tx_list_disable(p_twim); + } + + if (NRF_DRV_TWI_FLAG_RX_POSTINC & flags) + { + nrf_twim_rx_list_enable(p_twim); + } + else + { + nrf_twim_rx_list_disable(p_twim); + } +} +__STATIC_INLINE ret_code_t twim_xfer(twi_control_block_t * p_cb, + NRF_TWIM_Type * p_twim, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + ret_code_t err_code = NRF_SUCCESS; + nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX; + nrf_twim_event_t evt_to_wait = NRF_TWIM_EVENT_STOPPED; + + if (!nrf_drv_is_in_RAM(p_xfer_desc->p_primary_buf)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */ + nrf_twim_int_disable(p_twim, DISABLE_ALL_INT_SHORT); + if (p_cb->busy) + { + nrf_twim_int_enable(p_twim, p_cb->int_mask); + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + else + { + p_cb->busy = ((NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) || + (NRF_DRV_TWI_FLAG_REPEATED_XFER & flags)) ? false: true; + } + + p_cb->xfer_desc = *p_xfer_desc; + p_cb->repeated = (flags & NRF_DRV_TWI_FLAG_REPEATED_XFER) ? true : false; + nrf_twim_address_set(p_twim, p_xfer_desc->address); + + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR); + + twim_list_enable_handle(p_twim, flags); + switch (p_xfer_desc->type) + { + case NRF_DRV_TWI_XFER_TXTX: + ASSERT(!(flags & NRF_DRV_TWI_FLAG_REPEATED_XFER)); + ASSERT(!(flags & NRF_DRV_TWI_FLAG_HOLD_XFER)); + ASSERT(!(flags & NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER)); + if (!nrf_drv_is_in_RAM(p_xfer_desc->p_secondary_buf)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK); + nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX); + while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED)) + {} + NRF_LOG_DEBUG("TWIM: Event: %s.", (uint32_t)EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED)); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); + nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length); + p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK; + break; + case NRF_DRV_TWI_XFER_TXRX: + nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); + if (!nrf_drv_is_in_RAM(p_xfer_desc->p_secondary_buf)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length); + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK | + NRF_TWIM_SHORT_LASTRX_STOP_MASK); + p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; + break; + case NRF_DRV_TWI_XFER_TX: + nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); + if (NRF_DRV_TWI_FLAG_TX_NO_STOP & flags) + { + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK); + p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK; + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED); + evt_to_wait = NRF_TWIM_EVENT_SUSPENDED; + } + else + { + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK); + p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; + } + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + break; + case NRF_DRV_TWI_XFER_RX: + nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK); + p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; + start_task = NRF_TWIM_TASK_STARTRX; + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + break; + default: + err_code = NRF_ERROR_INVALID_PARAM; + break; + } + + if (!(flags & NRF_DRV_TWI_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRF_DRV_TWI_XFER_TXTX)) + { + nrf_twim_task_trigger(p_twim, start_task); + } + + if (p_cb->handler) + { + if (flags & NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER) + { + p_cb->int_mask = NRF_TWIM_INT_ERROR_MASK; + } + nrf_twim_int_enable(p_twim, p_cb->int_mask); + +#if NRF_MODULE_ENABLED(TWIM_NRF52_ANOMALY_109_WORKAROUND) + if ((flags & NRF_DRV_TWI_FLAG_HOLD_XFER) && ((p_xfer_desc->type == NRF_DRV_TWI_XFER_TX) || + (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXRX))) + { + p_cb->flags = flags; + twim_list_enable_handle(p_twim, 0); + p_twim->FREQUENCY = 0; + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); + nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK); + } +#endif + } + else + { + while (!nrf_twim_event_check(p_twim, evt_to_wait)) + { + if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR)) + { + NRF_LOG_DEBUG("TWIM: Event: %s.", + (uint32_t)EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR)); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP); + evt_to_wait = NRF_TWIM_EVENT_STOPPED; + } + } + + uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim); + + p_cb->busy = false; + + if (errorsrc) + { + err_code = twi_process_error(errorsrc); + } + } + return err_code; +} +#endif + +ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags) +{ + + ret_code_t err_code = NRF_SUCCESS; + twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + // TXRX and TXTX transfers are support only in non-blocking mode. + ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXRX))); + ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXTX))); + + NRF_LOG_INFO("Transfer type: %s.", (uint32_t)TRANSFER_TO_STR(p_xfer_desc->type)); + NRF_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.", + p_xfer_desc->primary_length, p_xfer_desc->secondary_length); + NRF_LOG_DEBUG("Primary buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_xfer_desc->p_primary_buf, + p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0])); + NRF_LOG_DEBUG("Secondary buffer data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_xfer_desc->p_secondary_buf, + p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0])); + + CODE_FOR_TWIM + ( + + err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->reg.p_twim, p_xfer_desc, flags); + ) + CODE_FOR_TWI + ( + if ( (NRF_DRV_TWI_FLAG_TX_POSTINC | NRF_DRV_TWI_FLAG_RX_POSTINC) & flags) + { + err_code = NRF_ERROR_NOT_SUPPORTED; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + err_code = twi_xfer(p_cb, (NRF_TWI_Type *)p_instance->reg.p_twi, p_xfer_desc, flags); + ) + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + +ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t const * p_data, + uint8_t length, + bool no_stop) +{ + nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length); + + return nrf_drv_twi_xfer(p_instance, &xfer, no_stop ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0); +} + +ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t * p_data, + uint8_t length) +{ + nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_RX(address, p_data, length); + return nrf_drv_twi_xfer(p_instance, &xfer, 0); +} + +uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance) +{ + CODE_FOR_TWIM + ( + ASSERT(false); + return 0; + ) + CODE_FOR_TWI + ( + return m_cb[p_instance->drv_inst_idx].bytes_transferred; + ) +} + +uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_type_t xfer_type) +{ + CODE_FOR_TWIM + ( + return (uint32_t)nrf_twim_task_address_get(p_instance->reg.p_twim, + (xfer_type != NRF_DRV_TWI_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX); + ) + CODE_FOR_TWI + ( + return (uint32_t)nrf_twi_task_address_get(p_instance->reg.p_twi, + (xfer_type != NRF_DRV_TWI_XFER_RX) ? NRF_TWI_TASK_STARTTX : NRF_TWI_TASK_STARTRX); + ) +} + +uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance) +{ + CODE_FOR_TWIM + ( + return (uint32_t)nrf_twim_event_address_get(p_instance->reg.p_twim, NRF_TWIM_EVENT_STOPPED); + ) + CODE_FOR_TWI + ( + return (uint32_t)nrf_twi_event_address_get(p_instance->reg.p_twi, NRF_TWI_EVENT_STOPPED); + ) +} + +#ifdef TWIM_IN_USE +static void irq_handler_twim(NRF_TWIM_Type * p_twim, twi_control_block_t * p_cb) +{ + +#if NRF_MODULE_ENABLED(TWIM_NRF52_ANOMALY_109_WORKAROUND) + /* Handle only workaround case. Can be used without TWIM handler in IRQs. */ + if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED)) + { + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); + nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK); + if (p_twim->FREQUENCY == 0) + { + // Set enable to zero to reset TWIM internal state. + nrf_twim_disable(p_twim); + nrf_twim_enable(p_twim); + + // Set proper frequency. + nrf_twim_frequency_set(p_twim, p_cb->bus_frequency); + twim_list_enable_handle(p_twim, p_cb->flags); + + // Start proper transmission. + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX); + return; + } + } +#endif + + ASSERT(p_cb->handler); + + if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR)) + { + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR); + NRF_LOG_DEBUG("TWIM: Event: %s.", (uint32_t)EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR)); + if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED)) + { + nrf_twim_int_disable(p_twim, p_cb->int_mask); + p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK; + nrf_twim_int_enable(p_twim, p_cb->int_mask); + + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP); + return; + } + } + + nrf_drv_twi_evt_t event; + + if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED)) + { + NRF_LOG_DEBUG("TWIM: Event: %s.", (uint32_t)EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED)); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED); + event.xfer_desc = p_cb->xfer_desc; + if (p_cb->error) + { + + event.xfer_desc.primary_length = (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_RX) ? + (uint8_t)nrf_twim_rxd_amount_get(p_twim) : (uint8_t)nrf_twim_txd_amount_get(p_twim); + event.xfer_desc.secondary_length = (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX) ? + (uint8_t)nrf_twim_rxd_amount_get(p_twim) : (uint8_t)nrf_twim_txd_amount_get(p_twim); + + } + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX); + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX); + if (!p_cb->repeated || p_cb->error) + { + nrf_twim_shorts_set(p_twim, 0); + p_cb->int_mask = 0; + nrf_twim_int_disable(p_twim, DISABLE_ALL_INT_SHORT); + } + } + else + { + nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED); + NRF_LOG_DEBUG("TWIM: Event: %s.", (uint32_t)EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED)); + if (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TX) + { + event.xfer_desc = p_cb->xfer_desc; + if (!p_cb->repeated) + { + nrf_twim_shorts_set(p_twim, 0); + p_cb->int_mask = 0; + nrf_twim_int_disable(p_twim, DISABLE_ALL_INT_SHORT); + } + } + else + { + nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK); + p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; + nrf_twim_int_disable(p_twim, DISABLE_ALL_INT_SHORT); + nrf_twim_int_enable(p_twim, p_cb->int_mask); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX); + nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); + return; + } + } + + uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim); + if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK) + { + event.type = NRF_DRV_TWI_EVT_ADDRESS_NACK; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_ADDRESS_NACK)); + } + else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK) + { + event.type = NRF_DRV_TWI_EVT_DATA_NACK; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_DATA_NACK)); + } + else + { + event.type = NRF_DRV_TWI_EVT_DONE; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_DONE)); + } + + if (!p_cb->repeated) + { + p_cb->busy = false; + } + p_cb->handler(&event, p_cb->p_context); +} +#endif // TWIM_IN_USE + +#ifdef TWI_IN_USE +static void irq_handler_twi(NRF_TWI_Type * p_twi, twi_control_block_t * p_cb) +{ + ASSERT(p_cb->handler); + + if (twi_transfer(p_twi, + &p_cb->error, + &p_cb->bytes_transferred, + p_cb->p_curr_buf, + p_cb->curr_length, + p_cb->curr_no_stop )) + { + return; + } + + if (!p_cb->error && + ((p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX) || + (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)) && + p_cb->p_curr_buf == p_cb->xfer_desc.p_primary_buf) + { + p_cb->p_curr_buf = p_cb->xfer_desc.p_secondary_buf; + p_cb->curr_length = p_cb->xfer_desc.secondary_length; + p_cb->curr_no_stop = (p_cb->flags & NRF_DRV_TWI_FLAG_TX_NO_STOP); + + if (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX) + { + (void)twi_tx_start_transfer(p_cb, + p_twi, + p_cb->p_curr_buf, + p_cb->curr_length, + p_cb->curr_no_stop); + } + else + { + (void)twi_rx_start_transfer(p_cb, p_twi, p_cb->p_curr_buf, p_cb->curr_length); + } + } + else + { + nrf_drv_twi_evt_t event; + event.xfer_desc = p_cb->xfer_desc; + + if (p_cb->error) + { + uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi); + if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK) + { + event.type = NRF_DRV_TWI_EVT_ADDRESS_NACK; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_ADDRESS_NACK)); + } + else if (errorsrc & NRF_TWI_ERROR_DATA_NACK) + { + event.type = NRF_DRV_TWI_EVT_DATA_NACK; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_DATA_NACK)); + } + } + else + { + event.type = NRF_DRV_TWI_EVT_DONE; + NRF_LOG_DEBUG("Event: %s.", (uint32_t)EVT_TO_STR(NRF_DRV_TWI_EVT_DONE)); + } + + p_cb->busy = false; + + if (!(NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & p_cb->flags)) + { + p_cb->handler(&event, p_cb->p_context); + } + } + +} +#endif // TWI_IN_USE + +#if NRF_MODULE_ENABLED(TWI0) +IRQ_HANDLER(0) +{ + #if (TWIM_ONLY || TWI0_WITH_DMA) + irq_handler_twim(NRF_TWIM0, + #else + irq_handler_twi(NRF_TWI0, + #endif + &m_cb[TWI0_INSTANCE_INDEX]); +} +#endif // NRF_MODULE_ENABLED(TWI0) + +#if NRF_MODULE_ENABLED(TWI1) +IRQ_HANDLER(1) +{ + #if (TWIM_ONLY || TWI1_WITH_DMA) + irq_handler_twim(NRF_TWIM1, + #else + irq_handler_twi(NRF_TWI1, + #endif + &m_cb[TWI1_INSTANCE_INDEX]); +} +#endif // NRF_MODULE_ENABLED(TWI1) +#endif // TWI_COUNT +/*lint -restore*/ +#endif // NRF_MODULE_ENABLED(TWI) + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.h new file mode 100644 index 0000000000..0a73c88d96 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twi_master/nrf_drv_twi.h @@ -0,0 +1,497 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_twi Two Wire master interface (TWI/TWIM) + * @ingroup nrf_drivers + * @brief Two Wire master interface (TWI/TWIM) APIs. + * + * + * @defgroup nrf_drv_twi TWI driver + * @{ + * @ingroup nrf_twi + * @brief TWI master APIs. + */ +#ifndef NRF_DRV_TWI_H__ +#define NRF_DRV_TWI_H__ + +#include "sdk_common.h" +#include "nrf_peripherals.h" + +#ifdef TWI0_ENABLED +#define TWI0_INCR TWI0_ENABLED +#else +#define TWI0_INCR 0 +#endif + +#ifdef TWI1_ENABLED +#define TWI1_INCR TWI1_ENABLED +#else +#define TWI1_INCR 0 +#endif + +#define ENABLED_TWI_COUNT (TWI0_INCR + TWI1_INCR) + +#define TWIM_ONLY ( defined(TWIM_PRESENT) && !defined(TWI_PRESENT)) +#define TWI_TWIM_PRESENT ( defined(TWIM_PRESENT) && defined(TWI_PRESENT)) +#define TWI_ONLY (!defined(TWIM_PRESENT) && defined(TWI_PRESENT)) + +#define TWI0_WITH_DMA (defined(TWI0_USE_EASY_DMA) && TWI0_USE_EASY_DMA && TWI0_ENABLED) +#define TWI1_WITH_DMA (defined(TWI1_USE_EASY_DMA) && TWI1_USE_EASY_DMA && TWI1_ENABLED) + +#define TWI0_WITHOUT_DMA (defined(TWI0_USE_EASY_DMA) && !TWI0_USE_EASY_DMA && TWI0_ENABLED) +#define TWI1_WITHOUT_DMA (defined(TWI1_USE_EASY_DMA) && !TWI1_USE_EASY_DMA && TWI1_ENABLED) + +// suppress: non-standard use of 'defined' preprocessor operator +/*lint -save -e491*/ +// Too complex macros for Doxygen +// This set of macros makes it possible to exclude parts of code when one type +// of supported peripherals is not used. +#ifndef DOXYGEN + +#if (TWI_ONLY && ENABLED_TWI_COUNT) || \ + ((TWI_TWIM_PRESENT) && (TWI0_WITHOUT_DMA || TWI1_WITHOUT_DMA)) +#define TWI_IN_USE 1 +#endif + +#if (TWIM_ONLY && ENABLED_TWI_COUNT) || \ + ((TWI_TWIM_PRESENT) && (TWI0_WITH_DMA || TWI1_WITH_DMA)) +#define TWIM_IN_USE 1 +#endif + +#endif // DOXYGEN + +#ifdef TWI_PRESENT + #include "nrf_twi.h" +#endif + +#ifdef TWIM_PRESENT + #include "nrf_twim.h" +#endif + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(TWIM_IN_USE) && defined(TWI_IN_USE) + #define NRF_DRV_TWI_PERIPHERAL(id) \ + (CONCAT_3(TWI, id, _USE_EASY_DMA) == 1 ? \ + (void *)CONCAT_2(NRF_TWIM, id) \ + : (void *)CONCAT_2(NRF_TWI, id)) +#elif defined(TWIM_IN_USE) && !defined(TWI_IN_USE) + #define NRF_DRV_TWI_PERIPHERAL(id) (void *)CONCAT_2(NRF_TWIM, id) +#else + #define NRF_DRV_TWI_PERIPHERAL(id) (void *)CONCAT_2(NRF_TWI, id) +#endif + +#ifndef TWI_PRESENT +typedef nrf_twim_frequency_t nrf_twi_frequency_t; +typedef nrf_twim_error_t nrf_twi_error_t; +#endif + +/** + * @brief Structure for the TWI master driver instance. + */ +typedef struct +{ + union + { +#ifdef TWIM_IN_USE + NRF_TWIM_Type * p_twim; ///< Pointer to a structure with TWIM registers. +#endif +#ifdef TWI_IN_USE + NRF_TWI_Type * p_twi; ///< Pointer to a structure with TWI registers. +#endif + void * p_regs; + } reg; + uint8_t drv_inst_idx; ///< Driver instance index. + bool use_easy_dma; ///< True if the peripheral with EasyDMA (TWIM) shall be used. +} nrf_drv_twi_t; + +#define TWI0_INSTANCE_INDEX 0 +#define TWI1_INSTANCE_INDEX TWI0_INSTANCE_INDEX+TWI0_INCR + +#ifndef DOXYGEN +#if defined(TWIM_IN_USE) + #if TWIM_ONLY + #define TWI_USE_EASY_DMA(_id) true + #else + #define TWI_USE_EASY_DMA(_id) CONCAT_3(TWI, _id, _USE_EASY_DMA) + #endif +#else + #define TWI_USE_EASY_DMA(_id) false +#endif +#endif // DOXYGEN + +/** + * @brief Macro for creating a TWI master driver instance. + */ +#define NRF_DRV_TWI_INSTANCE(id) \ +{ \ + .reg = {NRF_DRV_TWI_PERIPHERAL(id)}, \ + .drv_inst_idx = CONCAT_3(TWI, id, _INSTANCE_INDEX), \ + .use_easy_dma = TWI_USE_EASY_DMA(id) \ +} + +/** + * @brief Structure for the TWI master driver instance configuration. + */ +typedef struct +{ + uint32_t scl; ///< SCL pin number. + uint32_t sda; ///< SDA pin number. + nrf_twi_frequency_t frequency; ///< TWI frequency. + uint8_t interrupt_priority; ///< Interrupt priority. + bool clear_bus_init; ///< Clear bus during init. + bool hold_bus_uninit; ///< Hold pull up state on gpio pins after uninit. +} nrf_drv_twi_config_t; + +/** + * @brief TWI master driver instance default configuration. + */ +#define NRF_DRV_TWI_DEFAULT_CONFIG \ +{ \ + .frequency = (nrf_twi_frequency_t)TWI_DEFAULT_CONFIG_FREQUENCY, \ + .scl = 31, \ + .sda = 31, \ + .interrupt_priority = TWI_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .clear_bus_init = TWI_DEFAULT_CONFIG_CLR_BUS_INIT, \ + .hold_bus_uninit = TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT, \ +} + +#define NRF_DRV_TWI_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */ +#define NRF_DRV_TWI_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */ +#define NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */ +#define NRF_DRV_TWI_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */ +#define NRF_DRV_TWI_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */ +#define NRF_DRV_TWI_FLAG_TX_NO_STOP (1UL << 5) /**< Flag indicating that the TX transfer will not end with a stop condition. */ + +/** + * @brief TWI master driver event types. + */ +typedef enum +{ + NRF_DRV_TWI_EVT_DONE, ///< Transfer completed event. + NRF_DRV_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address. + NRF_DRV_TWI_EVT_DATA_NACK ///< Error event: NACK received after sending a data byte. +} nrf_drv_twi_evt_type_t; + +/** + * @brief TWI master driver transfer types. + */ +typedef enum +{ + NRF_DRV_TWI_XFER_TX, ///< TX transfer. + NRF_DRV_TWI_XFER_RX, ///< RX transfer. + NRF_DRV_TWI_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start. + NRF_DRV_TWI_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start. +} nrf_drv_twi_xfer_type_t; + +/** + * @brief Structure for a TWI transfer descriptor. + */ +typedef struct +{ + nrf_drv_twi_xfer_type_t type; ///< Type of transfer. + uint8_t address; ///< Slave address. + uint8_t primary_length; ///< Number of bytes transferred. + uint8_t secondary_length; ///< Number of bytes transferred. + uint8_t * p_primary_buf; ///< Pointer to transferred data. + uint8_t * p_secondary_buf; ///< Pointer to transferred data. +} nrf_drv_twi_xfer_desc_t; + + +/**@brief Macro for setting the TX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TX(addr, p_data, length) \ + { \ + .type = NRF_DRV_TWI_XFER_TX, \ + .address = addr, \ + .primary_length = length, \ + .p_primary_buf = p_data, \ + } + +/**@brief Macro for setting the RX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_RX(addr, p_data, length) \ + { \ + .type = NRF_DRV_TWI_XFER_RX, \ + .address = addr, \ + .primary_length = length, \ + .p_primary_buf = p_data, \ + } + +/**@brief Macro for setting the TXRX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len) \ + { \ + .type = NRF_DRV_TWI_XFER_TXRX, \ + .address = addr, \ + .primary_length = tx_len, \ + .secondary_length = rx_len, \ + .p_primary_buf = p_tx, \ + .p_secondary_buf = p_rx, \ + } + +/**@brief Macro for setting the TXTX transfer descriptor. */ +#define NRF_DRV_TWI_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \ + { \ + .type = NRF_DRV_TWI_XFER_TXTX, \ + .address = addr, \ + .primary_length = tx_len, \ + .secondary_length = tx_len2, \ + .p_primary_buf = p_tx, \ + .p_secondary_buf = p_tx2, \ + } + +/** + * @brief Structure for a TWI event. + */ +typedef struct +{ + nrf_drv_twi_evt_type_t type; ///< Event type. + nrf_drv_twi_xfer_desc_t xfer_desc; ///< Transfer details. +} nrf_drv_twi_evt_t; + +/** + * @brief TWI event handler prototype. + */ +typedef void (* nrf_drv_twi_evt_handler_t)(nrf_drv_twi_evt_t const * p_event, + void * p_context); + +/** + * @brief Function for initializing the TWI driver instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. If NULL, blocking mode is enabled. + * @param[in] p_context Context passed to event handler. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is in invalid state. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + */ +ret_code_t nrf_drv_twi_init(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_config_t const * p_config, + nrf_drv_twi_evt_handler_t event_handler, + void * p_context); + +/** + * @brief Function for uninitializing the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for enabling the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for disabling the TWI instance. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for sending data to a TWI slave. + * + * The transmission will be stopped when an error occurs. If a transfer is ongoing, + * the function returns the error code @ref NRF_ERROR_BUSY. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] address Address of a specific slave device (only 7 LSB). + * @param[in] p_data Pointer to a transmit buffer. + * @param[in] length Number of bytes to send. + * @param[in] no_stop If set, the stop condition is not generated on the bus + * after the transfer has completed successfully (allowing + * for a repeated start in the next transfer). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_INVALID_ADDR If the EasyDMA is used and memory adress in not in RAM. + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode. + */ +ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t const * p_data, + uint8_t length, + bool no_stop); + +/** + * @brief Function for reading data from a TWI slave. + * + * The transmission will be stopped when an error occurs. If a transfer is ongoing, + * the function returns the error code @ref NRF_ERROR_BUSY. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] address Address of a specific slave device (only 7 LSB). + * @param[in] p_data Pointer to a receive buffer. + * @param[in] length Number of bytes to be received. + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address in polling mode. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte in polling mode. + */ +ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance, + uint8_t address, + uint8_t * p_data, + uint8_t length); + +/** + * @brief Function for preparing a TWI transfer. + * + * The following transfer types can be configured (@ref nrf_drv_twi_xfer_desc_t::type): + * - @ref NRF_DRV_TWI_XFER_TXRX: Write operation followed by a read operation (without STOP condition in between). + * - @ref NRF_DRV_TWI_XFER_TXTX: Write operation followed by a write operation (without STOP condition in between). + * - @ref NRF_DRV_TWI_XFER_TX: Write operation (with or without STOP condition). + * - @ref NRF_DRV_TWI_XFER_RX: Read operation (with STOP condition). + * + * Additional options are provided using the flags parameter: + * - @ref NRF_DRV_TWI_FLAG_TX_POSTINC and @ref NRF_DRV_TWI_FLAG_RX_POSTINC: Post-incrementation of buffer addresses. Supported only by TWIM. + * - @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER: No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer. + * - @ref NRF_DRV_TWI_FLAG_HOLD_XFER: Driver is not starting the transfer. Use this flag if the transfer is triggered externally by PPI. Supported only by TWIM. + * Use @ref nrf_drv_twi_start_task_get to get the address of the start task. + * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER: Prepare for repeated transfers. You can set up a number of transfers that will be triggered externally (for example by PPI). + * An example is a TXRX transfer with the options @ref NRF_DRV_TWI_FLAG_RX_POSTINC, @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER, and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER. + * After the transfer is set up, a set of transfers can be triggered by PPI that will read, for example, the same register of an + * external component and put it into a RAM buffer without any interrupts. @ref nrf_drv_twi_stopped_event_get can be used to get the + * address of the STOPPED event, which can be used to count the number of transfers. If @ref NRF_DRV_TWI_FLAG_REPEATED_XFER is used, + * the driver does not set the driver instance into busy state, so you must ensure that the next transfers are set up + * when TWIM is not active. Supported only by TWIM. + * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP: No stop condition after TX transfer. + * + * @note + * Some flag combinations are invalid: + * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP with @ref nrf_drv_twi_xfer_desc_t::type different than @ref NRF_DRV_TWI_XFER_TX + * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER with @ref nrf_drv_twi_xfer_desc_t::type set to @ref NRF_DRV_TWI_XFER_TXTX + * + * If @ref nrf_drv_twi_xfer_desc_t::type is set to @ref NRF_DRV_TWI_XFER_TX and the @ref NRF_DRV_TWI_FLAG_TX_NO_STOP and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER + * flags are set, two tasks must be used to trigger a transfer: TASKS_RESUME followed by TASKS_STARTTX. If no stop condition is generated, + * TWIM is in SUSPENDED state. Therefore, it must be resumed before the transfer can be started. + * + * @note + * This function should be used only if the instance is configured to work in non-blocking mode. If the function is used in blocking mode, the driver asserts. + * @note If you are using this function with TWI, the only supported flag is @ref NRF_DRV_TWI_FLAG_TX_NO_STOP. All other flags require TWIM. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_xfer_desc Pointer to the transfer descriptor. + * @param[in] flags Transfer options (0 for default settings). + * + * @retval NRF_SUCCESS If the procedure was successful. + * @retval NRF_ERROR_BUSY If the driver is not ready for a new transfer. + * @retval NRF_ERROR_NOT_SUPPORTED If the provided parameters are not supported. + * @retval NRF_ERROR_INTERNAL If an error was detected by hardware. + * @retval NRF_ERROR_INVALID_ADDR If the EasyDMA is used and memory adress in not in RAM + * @retval NRF_ERROR_DRV_TWI_ERR_OVERRUN If the unread data was replaced by new data (TXRX and RX) + * @retval NRF_ERROR_DRV_TWI_ERR_ANACK If NACK received after sending the address. + * @retval NRF_ERROR_DRV_TWI_ERR_DNACK If NACK received after sending a data byte. + */ +ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t const * p_instance, + nrf_drv_twi_xfer_desc_t const * p_xfer_desc, + uint32_t flags); + +/** + * @brief Function for checking the TWI driver state. + * + * @param[in] p_instance TWI instance. + * + * @retval true If the TWI driver is currently busy performing a transfer. + * @retval false If the TWI driver is ready for a new transfer. + */ +bool nrf_drv_twi_is_busy(nrf_drv_twi_t const * p_instance); + +/** + * @brief Function for getting the transferred data count. + * + * This function provides valid results only in legacy mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Data count. + */ +uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance); + +/** + * @brief Function for returning the address of a TWI/TWIM start task. + * + * This function should be used if @ref nrf_drv_twi_xfer was called with the flag @ref NRF_DRV_TWI_FLAG_HOLD_XFER. + * In that case, the transfer is not started by the driver, but it must be started externally by PPI. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] xfer_type Transfer type used in the last call of the @ref nrf_drv_twi_xfer function. + * + * @return Start task address (TX or RX) depending on the value of xfer_type. + */ +uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, nrf_drv_twi_xfer_type_t xfer_type); + +/** + * @brief Function for returning the address of a STOPPED TWI/TWIM event. + * + * A STOPPED event can be used to detect the end of a transfer if the @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER + * option is used. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return STOPPED event address. + */ +uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance); +/** + *@} + **/ + +/*lint -restore*/ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DRV_TWI_H__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.c new file mode 100644 index 0000000000..d06dec9bcd --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.c @@ -0,0 +1,977 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(TWIS) +#include "nrf_drv_twis.h" +#if ENABLED_TWIS_COUNT +#include "nrf_assert.h" +#include "app_util_platform.h" +#include "compiler_abstraction.h" + +#define NRF_LOG_MODULE_NAME twis + +#if TWIS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL TWIS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR TWIS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR TWIS_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \ + (event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \ + (event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \ + (event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \ + (event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \ + (event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : "UNKNOWN EVENT")))))) +#else //TWIS_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //TWIS_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/** + * @internal + * @ingroup lib_twis_drv + * @defgroup lib_twis_drv_ivars Software controlled TWI Slave internal variables + * + * Internal variables for TWIS. + * @{ + */ + +/** + * @brief Actual state of internal state machine + * + * Current substate of powered on state. + */ +typedef enum +{ + NRF_DRV_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission + NRF_DRV_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data + NRF_DRV_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending) + NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer + NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving) +}nrf_drv_twis_substate_t; + +/** + * @brief Constant instance part + * + * Instance data that have not to change. + * It may be placed in FLASH memory. + */ +typedef struct +{ + NRF_TWIS_Type * const p_reg; ///< Peripheral registry address +} nrf_drv_twis_const_inst_t; + +/** + * @brief Variable instance part + * + * There are all informations for the instance that may change. + */ +typedef struct +{ + nrf_drv_state_t state; ///< Actual driver state + volatile nrf_drv_twis_substate_t substate; ///< Actual driver substate + nrf_drv_twis_event_handler_t ev_handler; ///< Event handler functiomn + volatile uint32_t error; ///< Internal error flags + /**< Internal copy of hardware errors flags merged + * with specific internal driver errors flags. + * + * @note This value can be changed in the interrupt + * and cleared in the main program. + * Always use Atomic load-store when updating + * this value in main loop. + */ +}nrf_drv_twis_var_inst_t; + + +/** The constant instance part implementation */ +static const nrf_drv_twis_const_inst_t m_const_inst[ENABLED_TWIS_COUNT] = +{ + #define X(n) { .p_reg = NRF_TWIS##n }, + #include "nrf_drv_twis_inst.def" +}; + +/** The variable instance part implementation */ +static nrf_drv_twis_var_inst_t m_var_inst[ENABLED_TWIS_COUNT] = +{ + #define X(n) { .state = NRF_DRV_STATE_UNINITIALIZED, \ + .substate = NRF_DRV_TWIS_SUBSTATE_IDLE, \ + .ev_handler = NULL, \ + .error = 0 }, + #include "nrf_drv_twis_inst.def" +}; + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n + #define IRQ_HANDLER(n) static void IRQ_HANDLER_NAME(n)(void) + + #if NRF_MODULE_ENABLED(TWIS0) + IRQ_HANDLER(0); + #endif + #if NRF_MODULE_ENABLED(TWIS1) + IRQ_HANDLER(1); + #endif + static nrf_drv_irq_handler_t const m_irq_handlers[ENABLED_TWIS_COUNT] = { + #if NRF_MODULE_ENABLED(TWIS0) + IRQ_HANDLER_NAME(0), + #endif + #if NRF_MODULE_ENABLED(TWIS1) + IRQ_HANDLER_NAME(1), + #endif + }; +#else + #if defined (NRF52810_XXAA) + #define IRQ_HANDLER(n) void TWIM##n##_TWIS##n##_IRQHandler(void) + #else + #define IRQ_HANDLER(n) \ + void SPIM##n##_SPIS##n##_TWIM##n##_TWIS##n##_SPI##n##_TWI##n##_IRQHandler(void) + #endif +#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + +/** + * @brief State processing semaphore + * + * There are semaphores used when when working in synchronous mode (without interrupts activated). + * @note + * In synchronous mode before every state checking the state machine is executed. + * But the situation where state checking function is called from main task and in the same from + * interrupt task has to be considered. + * In such a situation the @ref nrf_drv_twis_state_machine function may be interrupted by second + * call to the same function. + * If in this second call any event will be detected it may be lost because new substate would be + * overwritten when interrupted function finishes. + * In the same time information about event would be lost because it is cleared in interrupting + * function. + * @note + * To make situation described above safe, simple semaphore is implemented. + * It is just a binary flag that informs that state machine is actually executing and should not + * be processed in any interrupting function. + * Because of how it is used no atomic instructions are required to support this kind of semaphore. + * It is not waitable semaphore - function executed or not depending of its state. + */ +static uint8_t m_sm_semaphore[ENABLED_TWIS_COUNT]; + +/** + * @brief Used interrupts mask + * + * Mask for all interrupts used by this library + */ +static const uint32_t m_used_ints_mask = + NRF_TWIS_INT_STOPPED_MASK | + NRF_TWIS_INT_ERROR_MASK | + NRF_TWIS_INT_RXSTARTED_MASK | + NRF_TWIS_INT_TXSTARTED_MASK | + NRF_TWIS_INT_WRITE_MASK | + NRF_TWIS_INT_READ_MASK; + + +/** @} */ /* End of lib_driver_twis_slave_ivars */ + +/** + * @internal + * @ingroup lib_twis_drv + * @defgroup lib_twis_drv_ifunc Software controlled TWI Slave auxiliary internal functions + * + * Internal variables for TWIS. + * @{ + */ + +/** + * @brief Clear all events + * + * Function clears all actually pending events + */ +static void nrf_drv_twis_clear_all_events(NRF_TWIS_Type * const p_reg) +{ + /* Clear all events */ + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED); + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR); + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED); + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED); + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE); + nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ); +} + +/** + * @brief Reset all the registers to known state + * + * This function clears all registers that requires it to known state. + * TWIS is left disabled after this function. + * All events are cleared. + * @param[out] p_reg TWIS to reset register address + */ +static inline void nrf_drv_twis_swreset(NRF_TWIS_Type * const p_reg) +{ + /* Disable TWIS */ + nrf_twis_disable(p_reg); + + /* Disconnect pins */ + nrf_twis_pins_set(p_reg, ~0U, ~0U); + + /* Disable interrupt global for the instance */ + nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_reg)); + + /* Disable interrupts */ + nrf_twis_int_disable(p_reg, ~0U); +} + +/** + * @brief Configure pin + * + * Function configures selected for work as SDA or SCL. + * @param pin Pin number to configure + */ +static inline void nrf_drv_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull) +{ + nrf_gpio_cfg(pin, + NRF_GPIO_PIN_DIR_INPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + pull, + NRF_GPIO_PIN_S0D1, + NRF_GPIO_PIN_NOSENSE); +} + +/** + * @brief Call event handler + * + * Function that calls event handler. + * The event handler would be only called if its value is != NULL. + * @param instNr Driver instance number that has called this runtime. + * @param[in] pev Event structure to pass to event handler + * @note + * Remember about possible multithreading. + * It is acceptable to call old event function if it was already disabled. + * What is unacceptable is jump into NULL pointer. + */ +static void nrf_drv_call_event_handler(uint8_t instNr, nrf_drv_twis_evt_t const * const pev) +{ + nrf_drv_twis_event_handler_t evh = m_var_inst[instNr].ev_handler; + if (NULL != evh) + { + evh(pev); + } +} + +/** + * @brief Auxiliary function for getting event state on right bit possition + * + * This function calls @ref nrf_twis_event_get function but the the result + * is shifted to match INTEN register scheme. + * + * @param[in,out] p_reg TWIS to read event from + * @param ev Event code + * + * @return Selected event state shifted by @ref nrf_drv_event_to_bitpos + * + * @sa nrf_twis_event_get + * @sa nrf_drv_event_to_bitpos + */ +static inline uint32_t nrf_drv_twis_event_bit_get(NRF_TWIS_Type * const p_reg, nrf_twis_event_t ev) +{ + return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrf_drv_event_to_bitpos(ev); +} + +/** + * @brief Auxiliary function for checking event bit inside given flags value + * + * Function used here to check presence of the event inside given flags value. + * It transforms given event to bit possition and then checks if in given variable it is cleared. + * + * @param flags Flags to test + * @param ev Event code + * + * @retval true Flag for selected event is set + * @retval false Flag for selected event is cleared + */ +static inline bool nrf_drv_twis_check_bit(uint32_t flags, nrf_twis_event_t ev) +{ + return 0 != (flags & (1U<TXD.PTR, + evdata.data.tx_amount * sizeof(uint8_t)); + nrf_drv_call_event_handler(instNr, &evdata); + /* Go to idle and repeat the state machine if READ or WRITE events detected. + * This time READ or WRITE would be started */ + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED); + } + else + { + nrf_drv_twis_process_error(instNr, + TWIS_EVT_READ_ERROR, + nrf_twis_error_source_get_and_clear(p_reg)); + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + ev = 0; + } + break; + case NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING: + if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) || + nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || + nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || + nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) + { + substate = NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING; + /* Any other bits requires further processing in PENDING substate */ + ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED); + } + else + { + nrf_drv_twis_process_error(instNr, + TWIS_EVT_WRITE_ERROR, + nrf_twis_error_source_get_and_clear(p_reg)); + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + ev = 0; + } + break; + case NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING: + if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || + nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || + nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) + { + evdata.type = TWIS_EVT_WRITE_DONE; + evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg); + nrf_drv_call_event_handler(instNr, &evdata); + /* Go to idle and repeat the state machine if READ or WRITE events detected. + * This time READ or WRITE would be started */ + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED); + } + else + { + nrf_drv_twis_process_error(instNr, + TWIS_EVT_WRITE_ERROR, + nrf_twis_error_source_get_and_clear(p_reg)); + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + ev = 0; + } + break; + default: + substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + /* Do not clear any events and repeat the machine */ + break; + } + } + + m_var_inst[instNr].substate = substate; + if (!TWIS_NO_SYNC_MODE) + { + m_sm_semaphore[instNr] = 0; + } +} + +/** + * @brief This function + */ +static inline void nrf_drv_twis_preprocess_status(uint8_t instNr) +{ + if (!TWIS_NO_SYNC_MODE) + { + if (NULL == m_var_inst[instNr].ev_handler) + { + nrf_drv_twis_state_machine(instNr); + } + } +} + +/** + * @brief Interrupt service + * + * This function is called by all interrupts runtime for instances enabled in this library. + * @param instNr Driver instance number that has called this runtime. + */ +static inline void nrf_drv_twis_on_ISR(uint8_t instNr) +{ + nrf_drv_twis_state_machine(instNr); +} + +/** @} */ /* End of lib_driver_twis_slave_ifunc */ + + +/* ------------------------------------------------------------------------- + * Implementation of IRQ Handlers + */ +#define X(n) \ + IRQ_HANDLER(n) \ + { \ + nrf_drv_twis_on_ISR(TWIS##n##_INSTANCE_INDEX); \ + } +#include "nrf_drv_twis_inst.def" + +/* ------------------------------------------------------------------------- + * Implementation of interface functions + * + */ + + +ret_code_t nrf_drv_twis_init( + nrf_drv_twis_t const * const p_instance, + nrf_drv_twis_config_t const * p_config, + nrf_drv_twis_event_handler_t const event_handler) +{ + ASSERT(p_config); + ASSERT(p_config->scl != p_config->sda); + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + nrf_twis_config_addr_mask_t addr_mask = (nrf_twis_config_addr_mask_t)0; + ret_code_t err_code; + + if (m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + if (nrf_drv_common_per_res_acquire(p_reg, m_irq_handlers[instNr]) != NRF_SUCCESS) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } +#endif + + if (!TWIS_ASSUME_INIT_AFTER_RESET_ONLY) + { + nrf_drv_twis_swreset(p_reg); + } + + nrf_drv_twis_config_pin(p_config->scl, p_config->scl_pull); + nrf_drv_twis_config_pin(p_config->sda, p_config->sda_pull); + + if (0 == (p_config->addr[0] | p_config->addr[1])) + addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK; + else + { + if (0 != p_config->addr[0]) + { + addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK; + } + if (0 != p_config->addr[1]) + { + addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK; + } + } + + /* Peripheral interrupt configure + * (note - interrupts still needs to be configured in INTEN register. + * This is done in enable function) */ + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(p_reg), p_config->interrupt_priority); + + /* Configure */ + nrf_twis_pins_set (p_reg, p_config->scl, p_config->sda); + nrf_twis_address_set (p_reg, 0, p_config->addr[0]); + nrf_twis_address_set (p_reg, 1, p_config->addr[1]); + nrf_twis_config_address_set(p_reg, addr_mask); + + /* Clear semaphore */ + if (!TWIS_NO_SYNC_MODE) + { + m_sm_semaphore[instNr] = 0; + } + /* Set internal instance variables */ + m_var_inst[instNr].substate = NRF_DRV_TWIS_SUBSTATE_IDLE; + m_var_inst[instNr].ev_handler = event_handler; + m_var_inst[instNr].state = NRF_DRV_STATE_INITIALIZED; + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_twis_uninit(nrf_drv_twis_t const * const p_instance) +{ + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + TWIS_PSEL_Type psel = p_reg->PSEL; + + ASSERT(m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_drv_twis_swreset(p_reg); + + /* Clear pins state if */ + if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL)) + { + nrf_gpio_cfg_default(psel.SCL); + } + if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA)) + { + nrf_gpio_cfg_default(psel.SDA); + } + +#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING) + nrf_drv_common_per_res_release(p_reg); +#endif + + /* Clear variables */ + m_var_inst[instNr].ev_handler = NULL; + m_var_inst[instNr].state = NRF_DRV_STATE_UNINITIALIZED; +} + + +void nrf_drv_twis_enable(nrf_drv_twis_t const * const p_instance) +{ + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr]; + + ASSERT(m_var_inst[instNr].state == NRF_DRV_STATE_INITIALIZED); + + nrf_drv_twis_clear_all_events(p_reg); + + /* Enable interrupts */ + if (NULL != p_var_inst->ev_handler) + { + nrf_twis_int_enable(p_reg, m_used_ints_mask); + } + + nrf_twis_enable(p_reg); + p_var_inst->error = 0; + p_var_inst->state = NRF_DRV_STATE_POWERED_ON; + p_var_inst->substate = NRF_DRV_TWIS_SUBSTATE_IDLE; +} + + +void nrf_drv_twis_disable(nrf_drv_twis_t const * const p_instance) +{ + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + + ASSERT(m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED); + + nrf_twis_int_disable(p_reg, m_used_ints_mask); + + nrf_twis_disable(p_reg); + m_var_inst[instNr].state = NRF_DRV_STATE_INITIALIZED; +} + +/* ARM recommends not using the LDREX and STREX instructions in C code. + * This is because the compiler might generate loads and stores between + * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX. + * This recommendation also applies to the byte, halfword, and doubleword + * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD. + * + * This is the reason for the function below to be implemented in assembly. + */ +//lint -save -e578 +#if defined (__CC_ARM ) +static __ASM uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror) +{ + mov r3, r0 + mov r1, #0 +nrf_drv_twis_error_get_and_clear_internal_try + ldrex r0, [r3] + strex r2, r1, [r3] + cmp r2, r1 /* did this succeed? */ + bne nrf_drv_twis_error_get_and_clear_internal_try /* no – try again */ + bx lr +} +#elif defined ( __GNUC__ ) +static uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror) +{ + uint32_t ret; + uint32_t temp; + __ASM volatile( + " .syntax unified \n" + "nrf_drv_twis_error_get_and_clear_internal_try: \n" + " ldrex %[ret], [%[perror]] \n" + " strex %[temp], %[zero], [%[perror]] \n" + " cmp %[temp], %[zero] \n" + " bne nrf_drv_twis_error_get_and_clear_internal_try \n" + : /* Output */ + [ret]"=&l"(ret), + [temp]"=&l"(temp) + : /* Input */ + [zero]"l"(0), + [perror]"l"(perror) + ); + UNUSED_VARIABLE(temp); + return ret; +} +#elif defined ( __ICCARM__ ) +static uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror) +{ + uint32_t ret; + uint32_t temp; + __ASM volatile( + "1: \n" + " ldrex %[ret], [%[perror]] \n" + " strex %[temp], %[zero], [%[perror]] \n" + " cmp %[temp], %[zero] \n" + " bne.n 1b \n" + : /* Output */ + [ret]"=&l"(ret), + [temp]"=&l"(temp) + : /* Input */ + [zero]"l"(0), + [perror]"l"(perror) + ); + UNUSED_VARIABLE(temp); + return ret; +} +#else + #error Unknown compiler +#endif +//lint -restore + +uint32_t nrf_drv_twis_error_get_and_clear(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[p_instance->instNr]; + nrf_drv_twis_preprocess_status(p_instance->instNr); + /* Make sure that access to error member is atomic + * so there is no bit that is cleared if it is not copied to local variable already. */ + return nrf_drv_twis_error_get_and_clear_internal(&p_var_inst->error); +} + + +ret_code_t nrf_drv_twis_tx_prepare( + nrf_drv_twis_t const * const p_instance, + void const * const p_buf, + size_t size) +{ + ret_code_t err_code = NRF_SUCCESS; + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr]; + + /* Check power state*/ + if (p_var_inst->state != NRF_DRV_STATE_POWERED_ON) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + /* Check data address */ + if (!nrf_drv_is_in_RAM(p_buf)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + /* Check data size */ + if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size) + { + err_code = NRF_ERROR_INVALID_LENGTH; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_twis_tx_prepare(p_reg, (uint8_t const *)p_buf, (nrf_twis_amount_t)size); + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + +} + + +size_t nrf_drv_twis_tx_amount(nrf_drv_twis_t const * const p_instance) +{ + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type const * const p_reg = m_const_inst[instNr].p_reg; + + return nrf_twis_tx_amount_get(p_reg); +} + + +ret_code_t nrf_drv_twis_rx_prepare( + nrf_drv_twis_t const * const p_instance, + void * const p_buf, + size_t size) +{ + ret_code_t err_code; + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg; + nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr]; + + /* Check power state*/ + if (p_var_inst->state != NRF_DRV_STATE_POWERED_ON) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + /* Check data address */ + if (!nrf_drv_is_in_RAM(p_buf)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + /* Check data size */ + if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size) + { + err_code = NRF_ERROR_INVALID_LENGTH; + NRF_LOG_WARNING("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + nrf_twis_rx_prepare(p_reg, (uint8_t *)p_buf, (nrf_twis_amount_t)size); + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", + (uint32_t)__func__, + (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +size_t nrf_drv_twis_rx_amount(nrf_drv_twis_t const * const p_instance) +{ + uint8_t instNr = p_instance->instNr; + NRF_TWIS_Type const * const p_reg = m_const_inst[instNr].p_reg; + + return nrf_twis_rx_amount_get(p_reg); +} + + +bool nrf_drv_twis_is_busy(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_preprocess_status(p_instance->instNr); + return NRF_DRV_TWIS_SUBSTATE_IDLE != m_var_inst[(p_instance->instNr)].substate; +} + +bool nrf_drv_twis_is_waiting_tx_buff(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_preprocess_status(p_instance->instNr); + return NRF_DRV_TWIS_SUBSTATE_READ_WAITING == m_var_inst[(p_instance->instNr)].substate; +} + +bool nrf_drv_twis_is_waiting_rx_buff(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_preprocess_status(p_instance->instNr); + return NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING == m_var_inst[(p_instance->instNr)].substate; +} + +bool nrf_drv_twis_is_pending_tx(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_preprocess_status(p_instance->instNr); + return NRF_DRV_TWIS_SUBSTATE_READ_PENDING == m_var_inst[(p_instance->instNr)].substate; +} + +bool nrf_drv_twis_is_pending_rx(nrf_drv_twis_t const * const p_instance) +{ + nrf_drv_twis_preprocess_status(p_instance->instNr); + return NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING == m_var_inst[(p_instance->instNr)].substate; +} +#endif // TWIS_COUNT +#endif // NRF_MODULE_ENABLED(TWIS) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.h new file mode 100644 index 0000000000..aa70da2a2e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis.h @@ -0,0 +1,409 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_TWIS_H__ +#define NRF_DRV_TWIS_H__ + +#include "sdk_config.h" +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "sdk_errors.h" +#include "nrf_twis.h" +#include +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif +/**@file + * @addtogroup nrf_twis Two Wire slave interface (TWIS) + * @ingroup nrf_drivers + * @brief Two Wire slave interface (TWIS) APIs. + * + * + * @defgroup nrf_drv_twis TWIS driver + * @{ + * @ingroup nrf_twis + * @brief TWI slave APIs. + */ + +#ifdef TWIS0_ENABLED +#define TWIS0_INCR TWIS0_ENABLED +#else +#define TWIS0_INCR 0 +#endif + +#ifdef TWIS1_ENABLED +#define TWIS1_INCR TWIS1_ENABLED +#else +#define TWIS1_INCR 0 +#endif + +#define ENABLED_TWIS_COUNT (TWIS0_INCR + TWIS1_INCR) +/** + * @brief Event callback function event definitions. + */ +typedef enum +{ + TWIS_EVT_READ_REQ, ///< Read request detected + /**< If there is no buffer prepared, buf_req flag in the even will be set. + Call then @ref nrf_drv_twis_tx_prepare to give parameters for buffer. + */ + TWIS_EVT_READ_DONE, ///< Read request has finished - free any data + TWIS_EVT_READ_ERROR, ///< Read request finished with error + TWIS_EVT_WRITE_REQ, ///< Write request detected + /**< If there is no buffer prepared, buf_req flag in the even will be set. + Call then @ref nrf_drv_twis_rx_prepare to give parameters for buffer. + */ + TWIS_EVT_WRITE_DONE, ///< Write request has finished - process data + TWIS_EVT_WRITE_ERROR, ///< Write request finished with error + TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction +} nrf_drv_twis_evt_type_t; + +/** + * @brief TWIS driver instance structure + * + * @note We only need instance number here so we could really use just a number + * that would be send to every driver function. + * But for compatibility reason this number is inserted into the structure. + */ +typedef struct +{ + uint8_t instNr; /**< Instance number */ +}nrf_drv_twis_t; + +/** + * @brief TWIS driver event structure + */ +typedef struct +{ + nrf_drv_twis_evt_type_t type; ///< Event type + union + { + bool buf_req; ///< Flag for @ref TWIS_EVT_READ_REQ and @ref TWIS_EVT_WRITE_REQ + /**< Information if transmission buffer requires to be prepared */ + uint32_t tx_amount; ///< Data for @ref TWIS_EVT_READ_DONE + uint32_t rx_amount; ///< Data for @ref TWIS_EVT_WRITE_DONE + uint32_t error; ///< Data for @ref TWIS_EVT_GENERAL_ERROR + }data; +}nrf_drv_twis_evt_t; + +/** + * @brief TWI slave event callback function type. + * + * @param[in] p_event Event information structure. + */ +typedef void (*nrf_drv_twis_event_handler_t)(nrf_drv_twis_evt_t const * const p_event); + +/** + * @brief Structure for TWIS configuration + */ +typedef struct +{ + uint32_t addr[2]; //!< Set addresses that this slave should respond. Set 0 to disable. + uint32_t scl; //!< SCL pin number + nrf_gpio_pin_pull_t scl_pull; //!< SCL pin pull + uint32_t sda; //!< SDA pin number + nrf_gpio_pin_pull_t sda_pull; //!< SDA pin pull + uint8_t interrupt_priority; //!< The priority of interrupt for the module to set +}nrf_drv_twis_config_t; + +/** + * @brief Possible error sources + * + * This is flag enum - values from this enum can be connected using logical or operator. + * @note + * We could use directly @ref nrf_twis_error_t. Error type enum is redefined here becouse + * of possible future extension (eg. supporting timeouts and synchronous mode). + */ +typedef enum +{ + NRF_DRV_TWIS_ERROR_OVERFLOW = NRF_TWIS_ERROR_OVERFLOW, /**< RX buffer overflow detected, and prevented */ + NRF_DRV_TWIS_ERROR_DATA_NACK = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte */ + NRF_DRV_TWIS_ERROR_OVERREAD = NRF_TWIS_ERROR_OVERREAD, /**< TX buffer over-read detected, and prevented */ + NRF_DRV_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8 /**< Unexpected event detected by state machine */ +}nrf_drv_twis_error_t; + +/** + * @internal + * @brief Internal macro for creating TWIS driver instance + * + * Second level of indirection in creating the instance. + * Do not use this macro directly. + * Use @ref NRF_DRV_TWIS_INSTANCE instead. + */ +#define NRF_DRV_TWIS_INSTANCE_x(id) \ + { \ + TWIS##id##_INSTANCE_INDEX \ + } + +/** + * @brief Macro for creating TWIS driver instance + * + * @param[in] id Instance index. Use 0 for TWIS0 and 1 for TWIS1 + */ +#define NRF_DRV_TWIS_INSTANCE(id) NRF_DRV_TWIS_INSTANCE_x(id) + +#define TWIS0_INSTANCE_INDEX 0 +#define TWIS1_INSTANCE_INDEX TWIS0_INSTANCE_INDEX+TWIS0_ENABLED + +/** + * @brief Generate default configuration for TWIS driver instance + */ +#define NRF_DRV_TWIS_DEFAULT_CONFIG \ +{ \ + .addr = { TWIS_DEFAULT_CONFIG_ADDR0, TWIS_DEFAULT_CONFIG_ADDR1 }, \ + .scl = 31, \ + .scl_pull = (nrf_gpio_pin_pull_t)TWIS_DEFAULT_CONFIG_SCL_PULL, \ + .sda = 31, \ + .sda_pull = (nrf_gpio_pin_pull_t)TWIS_DEFAULT_CONFIG_SDA_PULL, \ + .interrupt_priority = TWIS_DEFAULT_CONFIG_IRQ_PRIORITY \ +} + +/** + * @brief Function for initializing the TWIS driver instance. + * + * Function initializes and enables TWIS driver. + * @attention After driver initialization enable it by @ref nrf_drv_twis_enable + * + * @param[in] p_instance Pointer to the driver instance structure. + * @attention @em p_instance has to be global object. + * It would be used by interrupts so make it sure that object + * would not be destroyed when function is leaving. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If the driver is already initialized. + * @retval NRF_ERROR_BUSY If some other peripheral with the same + * instance ID is already in use. This is + * possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED + * is set to a value other than zero. + */ +ret_code_t nrf_drv_twis_init( + nrf_drv_twis_t const * const p_instance, + nrf_drv_twis_config_t const * p_config, + nrf_drv_twis_event_handler_t const event_handler); + +/** + * @brief Function for uninitializing the TWIS driver instance. + * + * Function initializes the peripheral and resets all registers to default values. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @note + * It is safe to call nrf_drv_twis_uninit even before initialization. + * Actually @ref nrf_drv_twis_init function calls this function to + * make sure that TWIS state is known. + * @note + * If TWIS driver was in uninitialized state before calling this function, + * selected pins would not be reset to default configuration. + */ +void nrf_drv_twis_uninit(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Enable TWIS instance + * + * This function enables TWIS instance. + * Function defined if there is needs for dynamically enabling and disabling the peripheral. + * Use @ref nrf_drv_twis_enable and @ref nrf_drv_twis_disable functions. + * They do not change any configuration registers. + * + * @param p_instance Pointer to the driver instance structure. + */ +void nrf_drv_twis_enable(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Disable TWIS instance + * + * Disabling TWIS instance gives possibility to turn off the TWIS while + * holding configuration done by @ref nrf_drv_twis_init + * + * @param p_instance Pointer to the driver instance structure. + */ +void nrf_drv_twis_disable(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Get and clear last error flags + * + * Function gets information about errors. + * This is also the only possibility to exit from error substate of the internal state machine. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @return Error flags defined in @ref nrf_drv_twis_error_t + * @attention + * This function clears error state and flags. + */ +uint32_t nrf_drv_twis_error_get_and_clear(nrf_drv_twis_t const * const p_instance); + + +/** + * @brief Prepare data for sending + * + * This function should be used in response for @ref TWIS_EVT_READ_REQ event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_buf Transmission buffer + * @attention Transmission buffer has to be placed in RAM. + * @param size Maximum number of bytes that master may read from buffer given. + * + * @retval NRF_SUCCESS Preparation finished properly + * @retval NRF_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM + * @retval NRF_ERROR_INVALID_LENGTH Wrong value in @em size parameter + * @retval NRF_ERROR_INVALID_STATE Module not initialized or not enabled + */ +ret_code_t nrf_drv_twis_tx_prepare( + nrf_drv_twis_t const * const p_instance, + void const * const p_buf, + size_t size); + +/** + * @brief Get number of transmitted bytes + * + * Function returns number of bytes sent. + * This function may be called after @ref TWIS_EVT_READ_DONE or @ref TWIS_EVT_READ_ERROR events. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Number of bytes sent. + */ +size_t nrf_drv_twis_tx_amount(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Prepare data for receiving + * + * This function should be used in response for @ref TWIS_EVT_WRITE_REQ event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_buf Buffer that would be filled with received data + * @attention Receiving buffer has to be placed in RAM. + * @param size Size of the buffer (maximum amount of data to receive) + * + * @retval NRF_SUCCESS Preparation finished properly + * @retval NRF_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM + * @retval NRF_ERROR_INVALID_LENGTH Wrong value in @em size parameter + * @retval NRF_ERROR_INVALID_STATE Module not initialized or not enabled + */ +ret_code_t nrf_drv_twis_rx_prepare( + nrf_drv_twis_t const * const p_instance, + void * const p_buf, + size_t size); + +/** + * @brief Get number of received bytes + * + * Function returns number of bytes received. + * This function may be called after @ref TWIS_EVT_WRITE_DONE or @ref TWIS_EVT_WRITE_ERROR events. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @return Number of bytes received. + */ +size_t nrf_drv_twis_rx_amount(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Function checks if driver is busy right now + * + * Actual driver substate is tested. + * If driver is in any other state than IDLE or ERROR this function returns true. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true Driver is in state other than ERROR or IDLE + * @retval false There is no transmission pending. + */ +bool nrf_drv_twis_is_busy(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Function checks if driver is waiting for tx buffer + * + * If this function returns true, it means that driver is stalled expecting + * of the @ref nrf_drv_twis_tx_prepare function call. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true Driver waits for @ref nrf_drv_twis_tx_prepare + * @retval false Driver is not in the state where it waits for preparing tx buffer. + */ +bool nrf_drv_twis_is_waiting_tx_buff(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Function checks if driver is waiting for rx buffer + * + * If this function returns true, it means that driver is staled expecting + * of the @ref nrf_drv_twis_rx_prepare function call. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true Driver waits for @ref nrf_drv_twis_rx_prepare + * @retval false Driver is not in the state where it waits for preparing rx buffer. + */ +bool nrf_drv_twis_is_waiting_rx_buff(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Check if driver is sending data + * + * If this function returns true, it means that there is ongoing output transmission. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true There is ongoing output transmission. + * @retval false Driver is in other state. + */ +bool nrf_drv_twis_is_pending_tx(nrf_drv_twis_t const * const p_instance); + +/** + * @brief Check if driver is receiving data + * + * If this function returns true, it means that there is ongoing input transmission. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true There is ongoing input transmission. + * @retval false Driver is in other state. + */ +bool nrf_drv_twis_is_pending_rx(nrf_drv_twis_t const * const p_instance); + +/** @} */ /* End of lib_twis_drv group */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_DRV_TWIS_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis_inst.def b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis_inst.def new file mode 100644 index 0000000000..419b23f68c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/twis_slave/nrf_drv_twis_inst.def @@ -0,0 +1,20 @@ +/** + * @file + * @brief Xmacro file with contains enumeration of TWIS instances to implement + * + * Use this file everywhere where anything has to be generated for all active TWIS instances. + * Xmacro format: + * + * @code + X(n) + * @endcode + * + * Where @em n is number of the instance itself (0 for NRF_TWIS0). + */ +#if (TWIS0_ENABLED == 1) + X(0) +#endif +#if (TWIS1_ENABLED == 1) + X(1) +#endif +#undef X diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.c new file mode 100644 index 0000000000..495a92b22c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.c @@ -0,0 +1,990 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(UART) +#include "nrf_drv_uart.h" +#include "nrf_assert.h" +#include "nrf_drv_common.h" +#include "nrf_gpio.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME uart + +#if UART_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL UART_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR UART_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR UART_CONFIG_DEBUG_COLOR +#define EVT_TO_STR(event) (event == NRF_UART_EVENT_ERROR ? "NRF_UART_EVENT_ERROR" : "UNKNOWN EVENT") +#else //UART_CONFIG_LOG_ENABLED +#define EVT_TO_STR(event) "" +#define NRF_LOG_LEVEL 0 +#endif //UART_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#if (defined(UARTE_IN_USE) && defined(UART_IN_USE)) + // UARTE and UART combined + #define CODE_FOR_UARTE(code) if (m_cb[p_instance->drv_inst_idx].use_easy_dma) { code } + #define CODE_FOR_UARTE_INT(idx, code) if (m_cb[idx].use_easy_dma) { code } + #define CODE_FOR_UART(code) else { code } +#elif (defined(UARTE_IN_USE) && !defined(UART_IN_USE)) + // UARTE only + #define CODE_FOR_UARTE(code) { code } + #define CODE_FOR_UARTE_INT(idx, code) { code } + #define CODE_FOR_UART(code) +#elif (!defined(UARTE_IN_USE) && defined(UART_IN_USE)) + // UART only + #define CODE_FOR_UARTE(code) + #define CODE_FOR_UARTE_INT(idx, code) + #define CODE_FOR_UART(code) { code } +#else + #error "Wrong configuration." +#endif + +#define TX_COUNTER_ABORT_REQ_VALUE 256 + +typedef struct +{ + void * p_context; + nrf_uart_event_handler_t handler; + uint8_t const * p_tx_buffer; + uint8_t * p_rx_buffer; + uint8_t * p_rx_secondary_buffer; + volatile uint16_t tx_counter; + uint8_t tx_buffer_length; + uint8_t rx_buffer_length; + uint8_t rx_secondary_buffer_length; + volatile uint8_t rx_counter; + bool rx_enabled; + nrf_drv_state_t state; +#if (defined(UARTE_IN_USE) && defined(UART_IN_USE)) + bool use_easy_dma; +#endif +} uart_control_block_t; + +static uart_control_block_t m_cb[UART_ENABLED_COUNT]; + +#ifdef NRF52810_XXAA + #define IRQ_HANDLER(n) void UARTE##n##_IRQHandler(void) +#else + #define IRQ_HANDLER(n) void UART##n##_IRQHandler(void) +#endif + +__STATIC_INLINE void apply_config(nrf_drv_uart_t const * p_instance, nrf_drv_uart_config_t const * p_config) +{ + if (p_config->pseltxd != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_pin_set(p_config->pseltxd); + nrf_gpio_cfg_output(p_config->pseltxd); + } + if (p_config->pselrxd != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL); + } + + CODE_FOR_UARTE + ( + nrf_uarte_baudrate_set(p_instance->reg.p_uarte, (nrf_uarte_baudrate_t)p_config->baudrate); + nrf_uarte_configure(p_instance->reg.p_uarte, (nrf_uarte_parity_t)p_config->parity, + (nrf_uarte_hwfc_t)p_config->hwfc); + nrf_uarte_txrx_pins_set(p_instance->reg.p_uarte, p_config->pseltxd, p_config->pselrxd); + if (p_config->hwfc == NRF_UART_HWFC_ENABLED) + { + if (p_config->pselcts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL); + } + if (p_config->pselrts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_pin_set(p_config->pselrts); + nrf_gpio_cfg_output(p_config->pselrts); + } + nrf_uarte_hwfc_pins_set(p_instance->reg.p_uarte, p_config->pselrts, p_config->pselcts); + } + ) + CODE_FOR_UART + ( + nrf_uart_baudrate_set(p_instance->reg.p_uart, p_config->baudrate); + nrf_uart_configure(p_instance->reg.p_uart, p_config->parity, p_config->hwfc); + nrf_uart_txrx_pins_set(p_instance->reg.p_uart, p_config->pseltxd, p_config->pselrxd); + if (p_config->hwfc == NRF_UART_HWFC_ENABLED) + { + if (p_config->pselcts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL); + } + if (p_config->pselrts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_pin_set(p_config->pselrts); + nrf_gpio_cfg_output(p_config->pselrts); + } + nrf_uart_hwfc_pins_set(p_instance->reg.p_uart, p_config->pselrts, p_config->pselcts); + } + ) +} + +__STATIC_INLINE void interrupts_enable(const nrf_drv_uart_t * p_instance, uint8_t interrupt_priority) +{ + CODE_FOR_UARTE + ( + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDRX); + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDTX); + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ERROR); + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_RXTO); + nrf_uarte_int_enable(p_instance->reg.p_uarte, NRF_UARTE_INT_ENDRX_MASK | + NRF_UARTE_INT_ENDTX_MASK | + NRF_UARTE_INT_ERROR_MASK | + NRF_UARTE_INT_RXTO_MASK); + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_uarte), interrupt_priority); + ) + CODE_FOR_UART + ( + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_TXDRDY); + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_RXTO); + nrf_uart_int_enable(p_instance->reg.p_uart, NRF_UART_INT_MASK_TXDRDY | + NRF_UART_INT_MASK_RXTO); + nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_uart), interrupt_priority); + ) +} + +__STATIC_INLINE void interrupts_disable(const nrf_drv_uart_t * p_instance) +{ + CODE_FOR_UARTE + ( + nrf_uarte_int_disable(p_instance->reg.p_uarte, NRF_UARTE_INT_ENDRX_MASK | + NRF_UARTE_INT_ENDTX_MASK | + NRF_UARTE_INT_ERROR_MASK | + NRF_UARTE_INT_RXTO_MASK); + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_uarte)); + ) + CODE_FOR_UART + ( + nrf_uart_int_disable(p_instance->reg.p_uart, NRF_UART_INT_MASK_RXDRDY | + NRF_UART_INT_MASK_TXDRDY | + NRF_UART_INT_MASK_ERROR | + NRF_UART_INT_MASK_RXTO); + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_uart)); + ) + +} + +__STATIC_INLINE void pins_to_default(const nrf_drv_uart_t * p_instance) +{ + /* Reset pins to default states */ + uint32_t txd; + uint32_t rxd; + uint32_t rts; + uint32_t cts; + + CODE_FOR_UARTE + ( + txd = nrf_uarte_tx_pin_get(p_instance->reg.p_uarte); + rxd = nrf_uarte_rx_pin_get(p_instance->reg.p_uarte); + rts = nrf_uarte_rts_pin_get(p_instance->reg.p_uarte); + cts = nrf_uarte_cts_pin_get(p_instance->reg.p_uarte); + nrf_uarte_txrx_pins_disconnect(p_instance->reg.p_uarte); + nrf_uarte_hwfc_pins_disconnect(p_instance->reg.p_uarte); + ) + CODE_FOR_UART + ( + txd = nrf_uart_tx_pin_get(p_instance->reg.p_uart); + rxd = nrf_uart_rx_pin_get(p_instance->reg.p_uart); + rts = nrf_uart_rts_pin_get(p_instance->reg.p_uart); + cts = nrf_uart_cts_pin_get(p_instance->reg.p_uart); + nrf_uart_txrx_pins_disconnect(p_instance->reg.p_uart); + nrf_uart_hwfc_pins_disconnect(p_instance->reg.p_uart); + ) + + if (txd != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_default(txd); + } + + if (rxd != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_default(rxd); + } + + if (cts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_default(cts); + } + + if (rts != NRF_UART_PSEL_DISCONNECTED) + { + nrf_gpio_cfg_default(rts); + } + +} + +__STATIC_INLINE void uart_enable(const nrf_drv_uart_t * p_instance) +{ + CODE_FOR_UARTE(nrf_uarte_enable(p_instance->reg.p_uarte);) + CODE_FOR_UART(nrf_uart_enable(p_instance->reg.p_uart);); +} + +__STATIC_INLINE void uart_disable(const nrf_drv_uart_t * p_instance) +{ + CODE_FOR_UARTE(nrf_uarte_disable(p_instance->reg.p_uarte);) + CODE_FOR_UART(nrf_uart_disable(p_instance->reg.p_uart);); +} + +ret_code_t nrf_drv_uart_init(const nrf_drv_uart_t * p_instance, nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler) +{ + ASSERT(p_config); + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ret_code_t err_code = NRF_SUCCESS; + + if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_ERROR("Init failed. id:%d in wrong state", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); + return err_code; + } + +#if (defined(UARTE_IN_USE) && defined(UART_IN_USE)) + p_cb->use_easy_dma = p_config->use_easy_dma; +#endif + apply_config(p_instance, p_config); + + p_cb->handler = event_handler; + p_cb->p_context = p_config->p_context; + + if (p_cb->handler) + { + interrupts_enable(p_instance, p_config->interrupt_priority); + } + + uart_enable(p_instance); + p_cb->rx_buffer_length = 0; + p_cb->rx_secondary_buffer_length = 0; + p_cb->tx_buffer_length = 0; + p_cb->state = NRF_DRV_STATE_INITIALIZED; + p_cb->rx_enabled = false; + return err_code; +} + +void nrf_drv_uart_uninit(const nrf_drv_uart_t * p_instance) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + uart_disable(p_instance); + + if (p_cb->handler) + { + interrupts_disable(p_instance); + } + + pins_to_default(p_instance); + + p_cb->state = NRF_DRV_STATE_UNINITIALIZED; + p_cb->handler = NULL; + NRF_LOG_INFO("Uninit id: %d.", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); +} + +#if defined(UART_IN_USE) +__STATIC_INLINE void tx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb) +{ + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY); + uint8_t txd = p_cb->p_tx_buffer[p_cb->tx_counter]; + p_cb->tx_counter++; + nrf_uart_txd_set(p_uart, txd); +} + +__STATIC_INLINE ret_code_t nrf_drv_uart_tx_for_uart(const nrf_drv_uart_t * p_instance) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ret_code_t err_code = NRF_SUCCESS; + + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_TXDRDY); + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STARTTX); + + tx_byte(p_instance->reg.p_uart, p_cb); + + if (p_cb->handler == NULL) + { + while (p_cb->tx_counter < (uint16_t) p_cb->tx_buffer_length) + { + while (!nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_TXDRDY) && + p_cb->tx_counter != TX_COUNTER_ABORT_REQ_VALUE) + { + } + if (p_cb->tx_counter != TX_COUNTER_ABORT_REQ_VALUE) + { + tx_byte(p_instance->reg.p_uart, p_cb); + } + } + + if (p_cb->tx_counter == TX_COUNTER_ABORT_REQ_VALUE) + { + err_code = NRF_ERROR_FORBIDDEN; + } + else + { + while (!nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_TXDRDY)) + { + } + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STOPTX); + } + p_cb->tx_buffer_length = 0; + } + return err_code; +} +#endif + +#if defined(UARTE_IN_USE) +__STATIC_INLINE ret_code_t nrf_drv_uart_tx_for_uarte(const nrf_drv_uart_t * p_instance) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ret_code_t err_code = NRF_SUCCESS; + + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDTX); + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_TXSTOPPED); + nrf_uarte_tx_buffer_set(p_instance->reg.p_uarte, p_cb->p_tx_buffer, p_cb->tx_buffer_length); + nrf_uarte_task_trigger(p_instance->reg.p_uarte, NRF_UARTE_TASK_STARTTX); + + if (p_cb->handler == NULL) + { + bool endtx; + bool txstopped; + do + { + endtx = nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDTX); + txstopped = nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_TXSTOPPED); + } + while ((!endtx) && (!txstopped)); + + if (txstopped) + { + err_code = NRF_ERROR_FORBIDDEN; + } + p_cb->tx_buffer_length = 0; + } + return err_code; +} +#endif + +ret_code_t nrf_drv_uart_tx(const nrf_drv_uart_t * p_instance, uint8_t const * const p_data, uint8_t length) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + ASSERT(p_cb->state == NRF_DRV_STATE_INITIALIZED); + ASSERT(length>0); + ASSERT(p_data); + + ret_code_t err_code; + + CODE_FOR_UARTE + ( + // EasyDMA requires that transfer buffers are placed in DataRAM, + // signal error if the are not. + if (!nrf_drv_is_in_RAM(p_data)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_ERROR("Id:%d, Easy-DMA buffer not in RAM: %08x", + nrf_drv_get_IRQn((void *)p_instance->reg.p_reg), p_data); + return err_code; + } + ) + + if (nrf_drv_uart_tx_in_progress(p_instance)) + { + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("Id:%d busy",nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); + return err_code; + } + p_cb->tx_buffer_length = length; + p_cb->p_tx_buffer = p_data; + p_cb->tx_counter = 0; + + NRF_LOG_INFO("TX req id:%d length: %d.", + nrf_drv_get_IRQn((void *)p_instance->reg.p_reg), + p_cb->tx_buffer_length); + NRF_LOG_DEBUG("Tx data:"); + NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_cb->p_tx_buffer, + p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0])); + + CODE_FOR_UARTE + ( + return nrf_drv_uart_tx_for_uarte(p_instance); + ) + CODE_FOR_UART + ( + return nrf_drv_uart_tx_for_uart(p_instance); + ) +} + +bool nrf_drv_uart_tx_in_progress(const nrf_drv_uart_t * p_instance) +{ + return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0); +} + +#if defined(UART_IN_USE) +__STATIC_INLINE void rx_enable(const nrf_drv_uart_t * p_instance) +{ + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_ERROR); + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_RXDRDY); + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STARTRX); +} + +__STATIC_INLINE void rx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb) +{ + if (!p_cb->rx_buffer_length) + { + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY); + // Byte received when buffer is not set - data lost. + (void) nrf_uart_rxd_get(p_uart); + return; + } + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY); + p_cb->p_rx_buffer[p_cb->rx_counter] = nrf_uart_rxd_get(p_uart); + p_cb->rx_counter++; +} + +__STATIC_INLINE ret_code_t nrf_drv_uart_rx_for_uart(const nrf_drv_uart_t * p_instance, uint8_t * p_data, uint8_t length, bool second_buffer) +{ + ret_code_t err_code; + + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + if ((!p_cb->rx_enabled) && (!second_buffer)) + { + rx_enable(p_instance); + } + + if (p_cb->handler == NULL) + { + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_RXTO); + + bool rxrdy; + bool rxto; + bool error; + do + { + do + { + error = nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_ERROR); + rxrdy = nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_RXDRDY); + rxto = nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_RXTO); + } while ((!rxrdy) && (!rxto) && (!error)); + + if (error || rxto) + { + break; + } + rx_byte(p_instance->reg.p_uart, p_cb); + } while (p_cb->rx_buffer_length > p_cb->rx_counter); + + p_cb->rx_buffer_length = 0; + if (error) + { + err_code = NRF_ERROR_INTERNAL; + NRF_LOG_WARNING("RX Id: %d, transfer error.", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); + return err_code; + } + + if (rxto) + { + NRF_LOG_WARNING("RX Id: %d, aborted.", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); + err_code = NRF_ERROR_FORBIDDEN; + return err_code; + } + + if (p_cb->rx_enabled) + { + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STARTRX); + } + else + { + // Skip stopping RX if driver is forced to be enabled. + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STOPRX); + } + } + else + { + nrf_uart_int_enable(p_instance->reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + } + err_code = NRF_SUCCESS; + return err_code; +} +#endif + +#if defined(UARTE_IN_USE) +__STATIC_INLINE ret_code_t nrf_drv_uart_rx_for_uarte(const nrf_drv_uart_t * p_instance, uint8_t * p_data, uint8_t length, bool second_buffer) +{ + ret_code_t err_code = NRF_SUCCESS; + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDRX); + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_RXTO); + nrf_uarte_rx_buffer_set(p_instance->reg.p_uarte, p_data, length); + if (!second_buffer) + { + nrf_uarte_task_trigger(p_instance->reg.p_uarte, NRF_UARTE_TASK_STARTRX); + } + else + { + nrf_uarte_shorts_enable(p_instance->reg.p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + } + + if (m_cb[p_instance->drv_inst_idx].handler == NULL) + { + bool endrx; + bool rxto; + bool error; + do { + endrx = nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDRX); + rxto = nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_RXTO); + error = nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ERROR); + }while ((!endrx) && (!rxto) && (!error)); + + m_cb[p_instance->drv_inst_idx].rx_buffer_length = 0; + + if (error) + { + err_code = NRF_ERROR_INTERNAL; + } + + if (rxto) + { + err_code = NRF_ERROR_FORBIDDEN; + } + } + else + { + nrf_uarte_int_enable(p_instance->reg.p_uarte, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); + } + return err_code; +} +#endif + +ret_code_t nrf_drv_uart_rx(const nrf_drv_uart_t * p_instance, uint8_t * p_data, uint8_t length) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + ASSERT(m_cb[p_instance->drv_inst_idx].state == NRF_DRV_STATE_INITIALIZED); + ASSERT(length>0); + + ret_code_t err_code; + + CODE_FOR_UARTE + ( + // EasyDMA requires that transfer buffers are placed in DataRAM, + // signal error if the are not. + if (!nrf_drv_is_in_RAM(p_data)) + { + err_code = NRF_ERROR_INVALID_ADDR; + NRF_LOG_ERROR("Id:%d, Easy-DMA buffer not in RAM: %08x", + nrf_drv_get_IRQn((void *)p_instance->reg.p_reg), p_data); + return err_code; + } + ) + + bool second_buffer = false; + + if (p_cb->handler) + { + CODE_FOR_UARTE + ( + nrf_uarte_int_disable(p_instance->reg.p_uarte, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); + ) + CODE_FOR_UART + ( + nrf_uart_int_disable(p_instance->reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + ) + } + if (p_cb->rx_buffer_length != 0) + { + if (p_cb->rx_secondary_buffer_length != 0) + { + if (p_cb->handler) + { + CODE_FOR_UARTE + ( + nrf_uarte_int_enable(p_instance->reg.p_uarte, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); + ) + CODE_FOR_UART + ( + nrf_uart_int_enable(p_instance->reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + ) + } + err_code = NRF_ERROR_BUSY; + NRF_LOG_WARNING("RX Id:%d, busy", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); + return err_code; + } + second_buffer = true; + } + + if (!second_buffer) + { + p_cb->rx_buffer_length = length; + p_cb->p_rx_buffer = p_data; + p_cb->rx_counter = 0; + p_cb->rx_secondary_buffer_length = 0; + } + else + { + p_cb->p_rx_secondary_buffer = p_data; + p_cb->rx_secondary_buffer_length = length; + } + + NRF_LOG_INFO("RX Id:%d len:%d", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg), length); + + CODE_FOR_UARTE + ( + return nrf_drv_uart_rx_for_uarte(p_instance, p_data, length, second_buffer); + ) + CODE_FOR_UART + ( + return nrf_drv_uart_rx_for_uart(p_instance, p_data, length, second_buffer); + ) +} + +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance) +{ + CODE_FOR_UARTE + ( + return nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ENDRX); + ) + CODE_FOR_UART + ( + return nrf_uart_event_check(p_instance->reg.p_uart, NRF_UART_EVENT_RXDRDY); + ) +} + +void nrf_drv_uart_rx_enable(const nrf_drv_uart_t * p_instance) +{ + //Easy dma mode does not support enabling receiver without setting up buffer. + CODE_FOR_UARTE + ( + ASSERT(false); + ) + CODE_FOR_UART + ( + if (!m_cb[p_instance->drv_inst_idx].rx_enabled) + { + rx_enable(p_instance); + m_cb[p_instance->drv_inst_idx].rx_enabled = true; + } + ) +} + +void nrf_drv_uart_rx_disable(const nrf_drv_uart_t * p_instance) +{ + //Easy dma mode does not support enabling receiver without setting up buffer. + CODE_FOR_UARTE + ( + ASSERT(false); + ) + CODE_FOR_UART + ( + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STOPRX); + m_cb[p_instance->drv_inst_idx].rx_enabled = false; + ) +} + +uint32_t nrf_drv_uart_errorsrc_get(const nrf_drv_uart_t * p_instance) +{ + uint32_t errsrc; + CODE_FOR_UARTE + ( + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_ERROR); + errsrc = nrf_uarte_errorsrc_get_and_clear(p_instance->reg.p_uarte); + ) + CODE_FOR_UART + ( + nrf_uart_event_clear(p_instance->reg.p_uart, NRF_UART_EVENT_ERROR); + errsrc = nrf_uart_errorsrc_get_and_clear(p_instance->reg.p_uart); + ) + return errsrc; +} + +__STATIC_INLINE void rx_done_event(uart_control_block_t * p_cb, uint8_t bytes, uint8_t * p_data) +{ + nrf_drv_uart_event_t event; + + event.type = NRF_DRV_UART_EVT_RX_DONE; + event.data.rxtx.bytes = bytes; + event.data.rxtx.p_data = p_data; + + p_cb->handler(&event, p_cb->p_context); +} + +__STATIC_INLINE void tx_done_event(uart_control_block_t * p_cb, uint8_t bytes) +{ + nrf_drv_uart_event_t event; + + event.type = NRF_DRV_UART_EVT_TX_DONE; + event.data.rxtx.bytes = bytes; + event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer; + + p_cb->tx_buffer_length = 0; + + NRF_LOG_INFO("TX done len:%d", bytes); + p_cb->handler(&event, p_cb->p_context); +} + +void nrf_drv_uart_tx_abort(const nrf_drv_uart_t * p_instance) +{ + uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + + CODE_FOR_UARTE + ( + nrf_uarte_event_clear(p_instance->reg.p_uarte, NRF_UARTE_EVENT_TXSTOPPED); + nrf_uarte_task_trigger(p_instance->reg.p_uarte, NRF_UARTE_TASK_STOPTX); + if (p_cb->handler == NULL) + { + while (!nrf_uarte_event_check(p_instance->reg.p_uarte, NRF_UARTE_EVENT_TXSTOPPED)); + } + ) + CODE_FOR_UART + ( + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STOPTX); + if (p_cb->handler) + { + tx_done_event(p_cb, p_cb->tx_counter); + } + else + { + p_cb->tx_counter = TX_COUNTER_ABORT_REQ_VALUE; + } + ) + NRF_LOG_INFO("TX abort Id:%d", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); +} + +void nrf_drv_uart_rx_abort(const nrf_drv_uart_t * p_instance) +{ + CODE_FOR_UARTE + ( + nrf_uarte_task_trigger(p_instance->reg.p_uarte, NRF_UARTE_TASK_STOPRX); + ) + CODE_FOR_UART + ( + nrf_uart_int_disable(p_instance->reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + nrf_uart_task_trigger(p_instance->reg.p_uart, NRF_UART_TASK_STOPRX); + ) + NRF_LOG_INFO("RX abort Id:%d", nrf_drv_get_IRQn((void *)p_instance->reg.p_reg)); +} + + +#if defined(UART_IN_USE) +__STATIC_INLINE void uart_irq_handler(NRF_UART_Type * p_uart, uart_control_block_t * p_cb) +{ + if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) && + nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR)) + { + nrf_drv_uart_event_t event; + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR); + nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + if (!p_cb->rx_enabled) + { + nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX); + } + event.type = NRF_DRV_UART_EVT_ERROR; + event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(p_uart); + event.data.error.rxtx.bytes = p_cb->rx_buffer_length; + event.data.error.rxtx.p_data = p_cb->p_rx_buffer; + + //abort transfer + p_cb->rx_buffer_length = 0; + p_cb->rx_secondary_buffer_length = 0; + + p_cb->handler(&event,p_cb->p_context); + } + else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) && + nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY)) + { + rx_byte(p_uart, p_cb); + if (p_cb->rx_buffer_length == p_cb->rx_counter) + { + if (p_cb->rx_secondary_buffer_length) + { + uint8_t * p_data = p_cb->p_rx_buffer; + uint8_t rx_counter = p_cb->rx_counter; + + //Switch to secondary buffer. + p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length; + p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer; + p_cb->rx_secondary_buffer_length = 0; + p_cb->rx_counter = 0; + rx_done_event(p_cb, rx_counter, p_data); + } + else + { + if (!p_cb->rx_enabled) + { + nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX); + } + nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); + p_cb->rx_buffer_length = 0; + rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer); + } + } + } + + if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY)) + { + if (p_cb->tx_counter < (uint16_t) p_cb->tx_buffer_length) + { + tx_byte(p_uart, p_cb); + } + else + { + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY); + if (p_cb->tx_buffer_length) + { + tx_done_event(p_cb, p_cb->tx_buffer_length); + } + } + } + + if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO)) + { + nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO); + + // RXTO event may be triggered as a result of abort call. In th + if (p_cb->rx_enabled) + { + nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX); + } + if (p_cb->rx_buffer_length) + { + p_cb->rx_buffer_length = 0; + rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer); + } + } +} +#endif + +#if defined(UARTE_IN_USE) +__STATIC_INLINE void uarte_irq_handler(NRF_UARTE_Type * p_uarte, uart_control_block_t * p_cb) +{ + if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ERROR)) + { + nrf_drv_uart_event_t event; + + nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ERROR); + + event.type = NRF_DRV_UART_EVT_ERROR; + event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(p_uarte); + event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(p_uarte); + event.data.error.rxtx.p_data = p_cb->p_rx_buffer; + + //abort transfer + p_cb->rx_buffer_length = 0; + p_cb->rx_secondary_buffer_length = 0; + + p_cb->handler(&event, p_cb->p_context); + } + else if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDRX)) + { + nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDRX); + uint8_t amount = nrf_uarte_rx_amount_get(p_uarte); + // If the transfer was stopped before completion, amount of transfered bytes + // will not be equal to the buffer length. Interrupted trunsfer is ignored. + if (amount == p_cb->rx_buffer_length) + { + if (p_cb->rx_secondary_buffer_length) + { + uint8_t * p_data = p_cb->p_rx_buffer; + nrf_uarte_shorts_disable(p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length; + p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer; + p_cb->rx_secondary_buffer_length = 0; + rx_done_event(p_cb, amount, p_data); + } + else + { + p_cb->rx_buffer_length = 0; + rx_done_event(p_cb, amount, p_cb->p_rx_buffer); + } + } + } + + if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_RXTO)) + { + nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_RXTO); + if (p_cb->rx_buffer_length) + { + p_cb->rx_buffer_length = 0; + rx_done_event(p_cb, nrf_uarte_rx_amount_get(p_uarte), p_cb->p_rx_buffer); + } + } + + if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDTX)) + { + nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDTX); + if (p_cb->tx_buffer_length) + { + tx_done_event(p_cb, nrf_uarte_tx_amount_get(p_uarte)); + } + } +} +#endif + +#if UART0_ENABLED +IRQ_HANDLER(0) +{ + CODE_FOR_UARTE_INT + ( + UART0_INSTANCE_INDEX, + uarte_irq_handler(NRF_UARTE0, &m_cb[UART0_INSTANCE_INDEX]); + ) + CODE_FOR_UART + ( + uart_irq_handler(NRF_UART0, &m_cb[UART0_INSTANCE_INDEX]); + ) +} +#endif + +#if UART1_ENABLED +void UARTE1_IRQHandler(void) +{ + CODE_FOR_UARTE_INT + ( + UART1_INSTANCE_INDEX, + uarte_irq_handler(NRF_UARTE1, &m_cb[UART1_INSTANCE_INDEX]); + ) + CODE_FOR_UART + ( + uart_irq_handler(NRF_UART1, &m_cb[UART1_INSTANCE_INDEX]); + ) +} +#endif +#endif //NRF_MODULE_ENABLED(UART) + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.h new file mode 100644 index 0000000000..3821922178 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/uart/nrf_drv_uart.h @@ -0,0 +1,465 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_uart UART driver and HAL + * @ingroup nrf_drivers + * @brief UART API. + * @details The UART driver provides APIs for utilizing the UART peripheral. + * + * @defgroup nrf_drv_uart UART driver + * @{ + * @ingroup nrf_uart + * + * @brief UART driver. + */ + +#ifndef NRF_DRV_UART_H +#define NRF_DRV_UART_H + +#include "nrf_peripherals.h" + +#ifdef UART_PRESENT +#include "nrf_uart.h" +#endif + +#ifdef UARTE_PRESENT +#include "nrf_uarte.h" +#endif + +#include "sdk_errors.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef UART1_ENABLED +#define UART1_ENABLED 0 +#endif + +#ifndef UART0_ENABLED +#define UART0_ENABLED 0 +#endif + +#define UART0_INSTANCE_INDEX 0 +#define UART1_INSTANCE_INDEX UART0_ENABLED +#define UART_ENABLED_COUNT UART0_ENABLED + UART1_ENABLED + +#if defined(UARTE_PRESENT) && defined(UART_PRESENT) + #define NRF_DRV_UART_PERIPHERAL(id) \ + (CONCAT_3(UART, id, _CONFIG_USE_EASY_DMA) == 1 ? \ + (void *)CONCAT_2(NRF_UARTE, id) \ + : (void *)CONCAT_2(NRF_UART, id)) +#elif defined(UART_PRESENT) + #define NRF_DRV_UART_PERIPHERAL(id) (void *)CONCAT_2(NRF_UART, id) +#else //UARTE_PRESENT !UART_PRESENT + #define NRF_DRV_UART_PERIPHERAL(id) (void *)CONCAT_2(NRF_UARTE, id) +#endif + +// This set of macros makes it possible to exclude parts of code, when one type +// of supported peripherals is not used. + +#if defined(UARTE_PRESENT) && defined(UART_PRESENT) + +#if (UART_EASY_DMA_SUPPORT == 1) +#define UARTE_IN_USE +#endif + +#if (UART_LEGACY_SUPPORT == 1) +#define UART_IN_USE +#endif + +#if (UART_ENABLED == 1) && ((!defined(UARTE_IN_USE) && !defined(UART_IN_USE)) || ((UART_EASY_DMA_SUPPORT == 0) && (UART_LEGACY_SUPPORT == 0))) +#error "Illegal settings in uart module!" +#endif + +#elif defined(UART_PRESENT) +#define UART_IN_USE +#elif defined(UARTE_PRESENT) +#define UARTE_IN_USE +#endif + +#if defined(UARTE_PRESENT) && !defined(UART_PRESENT) +typedef nrf_uarte_hwfc_t nrf_uart_hwfc_t; +typedef nrf_uarte_parity_t nrf_uart_parity_t; +typedef nrf_uarte_baudrate_t nrf_uart_baudrate_t; +typedef nrf_uarte_error_mask_t nrf_uart_error_mask_t; +typedef nrf_uarte_task_t nrf_uart_task_t; +typedef nrf_uarte_event_t nrf_uart_event_t; +#ifndef NRF_UART_PSEL_DISCONNECTED +#define NRF_UART_PSEL_DISCONNECTED 0xFFFFFFFF +#endif +#endif + +/** + * @brief Structure for the UART driver instance. + */ +typedef struct +{ + union + { +#if (defined(UARTE_IN_USE)) + NRF_UARTE_Type * p_uarte; ///< Pointer to a structure with UARTE registers. +#endif +#if (defined(UART_IN_USE) || (UART_ENABLED == 0)) + NRF_UART_Type * p_uart; ///< Pointer to a structure with UART registers. +#endif + void * p_reg; + } reg; + uint8_t drv_inst_idx; ///< Driver instance index. +} nrf_drv_uart_t; + +/** + * @brief Macro for creating an UART driver instance. + */ +#define NRF_DRV_UART_INSTANCE(id) \ +{ \ + .reg = {NRF_DRV_UART_PERIPHERAL(id)}, \ + .drv_inst_idx = CONCAT_3(UART, id, _INSTANCE_INDEX),\ +} + +/** + * @brief Types of UART driver events. + */ +typedef enum +{ + NRF_DRV_UART_EVT_TX_DONE, ///< Requested TX transfer completed. + NRF_DRV_UART_EVT_RX_DONE, ///< Requested RX transfer completed. + NRF_DRV_UART_EVT_ERROR, ///< Error reported by UART peripheral. +} nrf_drv_uart_evt_type_t; + +/**@brief Structure for UART configuration. */ +typedef struct +{ + uint32_t pseltxd; ///< TXD pin number. + uint32_t pselrxd; ///< RXD pin number. + uint32_t pselcts; ///< CTS pin number. + uint32_t pselrts; ///< RTS pin number. + void * p_context; ///< Context passed to interrupt handler. + nrf_uart_hwfc_t hwfc; ///< Flow control configuration. + nrf_uart_parity_t parity; ///< Parity configuration. + nrf_uart_baudrate_t baudrate; ///< Baudrate. + uint8_t interrupt_priority; ///< Interrupt priority. +#ifdef UARTE_PRESENT + bool use_easy_dma; +#endif +} nrf_drv_uart_config_t; + +/**@brief UART default configuration. */ +#ifdef UARTE_PRESENT +#if !UART_LEGACY_SUPPORT +#define DEFAULT_CONFIG_USE_EASY_DMA true +#elif !UART_EASY_DMA_SUPPORT +#define DEFAULT_CONFIG_USE_EASY_DMA false +#else +#define DEFAULT_CONFIG_USE_EASY_DMA UART0_USE_EASY_DMA +#endif +#define NRF_DRV_UART_DEFAULT_CONFIG \ + { \ + .pseltxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselrxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselcts = NRF_UART_PSEL_DISCONNECTED, \ + .pselrts = NRF_UART_PSEL_DISCONNECTED, \ + .p_context = NULL, \ + .hwfc = (nrf_uart_hwfc_t)UART_DEFAULT_CONFIG_HWFC, \ + .parity = (nrf_uart_parity_t)UART_DEFAULT_CONFIG_PARITY, \ + .baudrate = (nrf_uart_baudrate_t)UART_DEFAULT_CONFIG_BAUDRATE, \ + .interrupt_priority = UART_DEFAULT_CONFIG_IRQ_PRIORITY, \ + .use_easy_dma = true \ + } +#else +#define NRF_DRV_UART_DEFAULT_CONFIG \ + { \ + .pseltxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselrxd = NRF_UART_PSEL_DISCONNECTED, \ + .pselcts = NRF_UART_PSEL_DISCONNECTED, \ + .pselrts = NRF_UART_PSEL_DISCONNECTED, \ + .p_context = NULL, \ + .hwfc = (nrf_uart_hwfc_t)UART_DEFAULT_CONFIG_HWFC, \ + .parity = (nrf_uart_parity_t)UART_DEFAULT_CONFIG_PARITY, \ + .baudrate = (nrf_uart_baudrate_t)UART_DEFAULT_CONFIG_BAUDRATE, \ + .interrupt_priority = UART_DEFAULT_CONFIG_IRQ_PRIORITY, \ + } +#endif + +/**@brief Structure for UART transfer completion event. */ +typedef struct +{ + uint8_t * p_data; ///< Pointer to memory used for transfer. + uint8_t bytes; ///< Number of bytes transfered. +} nrf_drv_uart_xfer_evt_t; + +/**@brief Structure for UART error event. */ +typedef struct +{ + nrf_drv_uart_xfer_evt_t rxtx; ///< Transfer details includes number of bytes transfered. + uint32_t error_mask;///< Mask of error flags that generated the event. +} nrf_drv_uart_error_evt_t; + +/**@brief Structure for UART event. */ +typedef struct +{ + nrf_drv_uart_evt_type_t type; ///< Event type. + union + { + nrf_drv_uart_xfer_evt_t rxtx; ///< Data provided for transfer completion events. + nrf_drv_uart_error_evt_t error;///< Data provided for error event. + } data; +} nrf_drv_uart_event_t; + +/** + * @brief UART interrupt event handler. + * + * @param[in] p_event Pointer to event structure. Event is allocated on the stack so it is available + * only within the context of the event handler. + * @param[in] p_context Context passed to interrupt handler, set on initialization. + */ +typedef void (*nrf_uart_event_handler_t)(nrf_drv_uart_event_t * p_event, void * p_context); + +/** + * @brief Function for initializing the UART driver. + * + * This function configures and enables UART. After this function GPIO pins are controlled by UART. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_config Initial configuration. + * @param[in] event_handler Event handler provided by the user. If not provided driver works in + * blocking mode. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_INVALID_STATE If driver is already initialized. + */ +ret_code_t nrf_drv_uart_init(nrf_drv_uart_t const * p_instance, + nrf_drv_uart_config_t const * p_config, + nrf_uart_event_handler_t event_handler); + +/** + * @brief Function for uninitializing the UART driver. + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_uart_uninit(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for getting the address of a specific UART task. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] task Task. + * + * @return Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task); + +/** + * @brief Function for getting the address of a specific UART event. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] event Event. + * + * @return Event address. + */ +__STATIC_INLINE uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event); + +/** + * @brief Function for sending data over UART. + * + * If an event handler was provided in nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE instance is + * used, this function will fail with error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to send. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_BUSY If driver is already transferring. + * @retval NRF_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRF_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +ret_code_t nrf_drv_uart_tx(nrf_drv_uart_t const * p_instance, + uint8_t const * const p_data, uint8_t length); + +/** + * @brief Function for checking if UART is currently transmitting. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If UART is transmitting. + * @retval false If UART is not transmitting. + */ +bool nrf_drv_uart_tx_in_progress(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing transmission. + * @note @ref NRF_DRV_UART_EVT_TX_DONE event will be generated in non-blocking mode. Event will + * contain number of bytes sent until abort was called. If Easy DMA is not used event will be + * called from the function context. If Easy DMA is used it will be called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_uart_tx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for receiving data over UART. + * + * If an event handler was provided in the nrf_drv_uart_init() call, this function + * returns immediately and the handler is called when the transfer is done. + * Otherwise, the transfer is performed in blocking mode, i.e. this function + * returns when the transfer is finished. Blocking mode is not using interrupt so + * there is no context switching inside the function. + * The receive buffer pointer is double buffered in non-blocking mode. The secondary + * buffer can be set immediately after starting the transfer and will be filled + * when the primary buffer is full. The double buffering feature allows + * receiving data continuously. + * + * @note Peripherals using EasyDMA (i.e. UARTE) require that the transfer buffers + * are placed in the Data RAM region. If they are not and UARTE driver instance + * is used, this function will fail with error code NRF_ERROR_INVALID_ADDR. + * + * @param[in] p_instance Pointer to the driver instance structure. + * @param[in] p_data Pointer to data. + * @param[in] length Number of bytes to receive. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_BUSY If the driver is already receiving + * (and the secondary buffer has already been set + * in non-blocking mode). + * @retval NRF_ERROR_FORBIDDEN If the transfer was aborted from a different context + * (blocking mode only, also see @ref nrf_drv_uart_rx_disable). + * @retval NRF_ERROR_INTERNAL If UART peripheral reported an error. + * @retval NRF_ERROR_INVALID_ADDR If p_data does not point to RAM buffer (UARTE only). + */ +ret_code_t nrf_drv_uart_rx(nrf_drv_uart_t const * p_instance, + uint8_t * p_data, uint8_t length); + + + +/** + * @brief Function for testing the receiver state in blocking mode. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval true If the receiver has at least one byte of data to get. + * @retval false If the receiver is empty. + */ +bool nrf_drv_uart_rx_ready(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for enabling the receiver. + * + * UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the + * UART receive function before the FIFO is filled, an overrun error will appear. Enabling the receiver + * without specifying an RX buffer is supported only in UART mode (without Easy DMA). The receiver must be + * explicitly closed by the user @sa nrf_drv_uart_rx_disable. This function asserts if the mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_uart_rx_enable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for disabling the receiver. + * + * This function must be called to close the receiver after it has been explicitly enabled by + * @sa nrf_drv_uart_rx_enable. The feature is supported only in UART mode (without Easy DMA). The function + * asserts if mode is wrong. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_uart_rx_disable(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for aborting any ongoing reception. + * @note @ref NRF_DRV_UART_EVT_RX_DONE event will be generated in non-blocking mode. The event will + * contain the number of bytes received until abort was called. The event is called from UART interrupt + * context. + * + * @param[in] p_instance Pointer to the driver instance structure. + */ +void nrf_drv_uart_rx_abort(nrf_drv_uart_t const * p_instance); + +/** + * @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t. + * @note Function should be used in blocking mode only. In case of non-blocking mode, an error event is + * generated. Function clears error sources after reading. + * + * @param[in] p_instance Pointer to the driver instance structure. + * + * @retval Mask of reported errors. + */ +uint32_t nrf_drv_uart_errorsrc_get(nrf_drv_uart_t const * p_instance); + + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint32_t nrf_drv_uart_task_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_task_t task) +{ +#ifdef UART_IN_USE + return nrf_uart_task_address_get(p_instance->reg.p_uart, task); +#else + return nrf_uarte_task_address_get(p_instance->reg.p_uarte, (nrf_uarte_task_t)task); +#endif +} + +__STATIC_INLINE uint32_t nrf_drv_uart_event_address_get(nrf_drv_uart_t const * p_instance, + nrf_uart_event_t event) +{ +#ifdef UART_IN_USE + return nrf_uart_event_address_get(p_instance->reg.p_uart, event); +#else + return nrf_uarte_event_address_get(p_instance->reg.p_uarte, (nrf_uarte_event_t)event); +#endif +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif //NRF_DRV_UART_H +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.c new file mode 100644 index 0000000000..3b6a151d7a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.c @@ -0,0 +1,2220 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_config.h" +#if USBD_ENABLED +#include "nrf_drv_usbd.h" +#include "nrf.h" +#include "nordic_common.h" +#include "nrf_drv_common.h" +#include "nrf_atomic.h" +#include "nrf_delay.h" +#include "app_util_platform.h" +#include "nrf_drv_systick.h" /* Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE << */ + +#include +#include + +#define NRF_LOG_MODULE_NAME USBD + +#if USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL USBD_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR USBD_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR USBD_CONFIG_DEBUG_COLOR +#else //USBD_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //USBD_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef NRF_DRV_USBD_EARLY_DMA_PROCESS +/* Try to process DMA request when endpoint transmission has been detected + * and just after last EasyDMA has been processed. + * It speeds up the transmission a little (about 10% measured) + * with a cost of more CPU power used. + */ +#define NRF_DRV_USBD_EARLY_DMA_PROCESS 1 +#endif + +#ifndef NRF_DRV_USBD_PROTO1_FIX_DEBUG +/* Debug information when events are fixed*/ +#define NRF_DRV_USBD_PROTO1_FIX_DEBUG 1 +#endif + +#define NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(...) \ + do{ \ + if (NRF_DRV_USBD_PROTO1_FIX_DEBUG){ NRF_LOG_DEBUG(__VA_ARGS__); }\ + } while (0) + +#ifndef NRF_DRV_USBD_STARTED_EV_ENABLE +#define NRF_DRV_USBD_STARTED_EV_ENABLE 1 +#endif + +#ifndef NRF_USBD_ISO_DEBUG +/* Also generate information about ISOCHRONOUS events and transfers. + * Turn this off if no ISOCHRONOUS transfers are going to be debugged and this + * option generates a lot of useless messages. */ +#define NRF_USBD_ISO_DEBUG 1 +#endif + +#ifndef NRF_USBD_FAILED_TRANSFERS_DEBUG +/* Also generate debug information for failed transfers. + * It might be useful but may generate a lot of useless debug messages + * in some library usages (for example when transfer is generated and the + * result is used to check whatever endpoint was busy. */ +#define NRF_USBD_FAILED_TRANSFERS_DEBUG 1 +#endif + +#ifndef NRF_USBD_DMAREQ_PROCESS_DEBUG +/* Generate additional messages that mark the status inside + * @ref usbd_dmareq_process. + * It is useful to debug library internals but may generate a lot of + * useless debug messages. */ +#define NRF_USBD_DMAREQ_PROCESS_DEBUG 1 +#endif + + +/** + * @defgroup nrf_drv_usbd_int USB Device driver internal part + * @internal + * @ingroup nrf_drv_usbd + * + * This part contains auxiliary internal macros, variables and functions. + * @{ + */ + +/** + * @brief Assert endpoint number validity + * + * Internal macro to be used during program creation in debug mode. + * Generates assertion if endpoint number is not valid. + * + * @param ep Endpoint number to validity check + */ +#define USBD_ASSERT_EP_VALID(ep) ASSERT( \ + ((NRF_USBD_EPIN_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPIN_CNT )) \ + || \ + (NRF_USBD_EPOUT_CHECK(ep) && (NRF_USBD_EP_NR_GET(ep) < NRF_USBD_EPOUT_CNT))) \ +); + +/** + * @brief Lowest position of bit for IN endpoint + * + * The first bit position corresponding to IN endpoint. + * @sa ep2bit bit2ep + */ +#define USBD_EPIN_BITPOS_0 0 + +/** + * @brief Lowest position of bit for OUT endpoint + * + * The first bit position corresponding to OUT endpoint + * @sa ep2bit bit2ep + */ +#define USBD_EPOUT_BITPOS_0 16 + +/** + * @brief Input endpoint bits mask + */ +#define USBD_EPIN_BIT_MASK (0xFFFFU << USBD_EPIN_BITPOS_0) + +/** + * @brief Output endpoint bits mask + */ +#define USBD_EPOUT_BIT_MASK (0xFFFFU << USBD_EPOUT_BITPOS_0) + +/** + * @brief Auxiliary macro to change EP number into bit position + * + * This macro is used by @ref ep2bit function but also for statically check + * the bitpos values integrity during compilation. + * + * @param[in] ep Endpoint number. + * @return Endpoint bit position. + */ +#define USBD_EP_BITPOS(ep) \ + ((NRF_USBD_EPIN_CHECK(ep) ? USBD_EPIN_BITPOS_0 : USBD_EPOUT_BITPOS_0) + NRF_USBD_EP_NR_GET(ep)) + +/** + * @brief Helper macro for creating an endpoint transfer event. + * + * @param[in] name Name of the created transfer event variable. + * @param[in] endpoint Endpoint number. + * @param[in] ep_stat Endpoint state to report. + * + * @return Initialized event constant variable. + */ +#define NRF_DRV_USBD_EP_TRANSFER_EVENT(name, endpont, ep_stat) \ + const nrf_drv_usbd_evt_t name = { \ + NRF_DRV_USBD_EVT_EPTRANSFER, \ + .data = { \ + .eptransfer = { \ + .ep = endpont, \ + .status = ep_stat \ + } \ + } \ + } + +/* Check it the bit positions values match defined DATAEPSTATUS bit positions */ +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN1) == USBD_EPDATASTATUS_EPIN1_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN2) == USBD_EPDATASTATUS_EPIN2_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN3) == USBD_EPDATASTATUS_EPIN3_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN4) == USBD_EPDATASTATUS_EPIN4_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN5) == USBD_EPDATASTATUS_EPIN5_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN6) == USBD_EPDATASTATUS_EPIN6_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPIN7) == USBD_EPDATASTATUS_EPIN7_Pos ); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT1) == USBD_EPDATASTATUS_EPOUT1_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT2) == USBD_EPDATASTATUS_EPOUT2_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT3) == USBD_EPDATASTATUS_EPOUT3_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT4) == USBD_EPDATASTATUS_EPOUT4_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT5) == USBD_EPDATASTATUS_EPOUT5_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT6) == USBD_EPDATASTATUS_EPOUT6_Pos); +STATIC_ASSERT(USBD_EP_BITPOS(NRF_DRV_USBD_EPOUT7) == USBD_EPDATASTATUS_EPOUT7_Pos); + + +/** + * @name Internal auxiliary definitions for SETUP packet + * + * Definitions used to take out the information about last SETUP packet direction + * from @c bmRequestType. + * @{ + */ +/** The position of DIR bit in bmRequestType inside SETUP packet */ +#define USBD_DRV_REQUESTTYPE_DIR_BITPOS 7 +/** The mask of DIR bit in bmRequestType inside SETUP packet */ +#define USBD_DRV_REQUESTTYPE_DIR_MASK (1U << USBD_DRV_REQUESTTYPE_DIR_BITPOS) +/** The value of DIR bit for OUT direction (Host -> Device) */ +#define USBD_DRV_REQUESTTYPE_DIR_OUT (0U << USBD_DRV_REQUESTTYPE_DIR_BITPOS) +/** The value of DIR bit for IN direction (Device -> Host) */ +#define USBD_DRV_REQUESTTYPE_DIR_IN (1U << USBD_DRV_REQUESTTYPE_DIR_BITPOS) +/** @} */ + +/** + * @brief Current driver state + */ +static nrf_drv_state_t m_drv_state = NRF_DRV_STATE_UNINITIALIZED; + +/** + * @brief Event handler for the library + * + * Event handler that would be called on events. + * + * @note Currently it cannot be null if any interrupt is activated. + */ +static nrf_drv_usbd_event_handler_t m_event_handler; + +/** + * @brief Detected state of the bus + * + * Internal state changed in interrupts handling when + * RESUME or SUSPEND event is processed. + * + * Values: + * - true - bus suspended + * - false - ongoing normal communication on the bus + * + * @note This is only the bus state and does not mean that the peripheral is in suspend state. + */ +static volatile bool m_bus_suspend; + +/** + * @brief Internal constant that contains interrupts disabled in suspend state + * + * Internal constant used in @ref nrf_drv_usbd_suspend_irq_config and @ref nrf_drv_usbd_active_irq_config + * functions. + */ +static const uint32_t m_irq_disabled_in_suspend = + NRF_USBD_INT_ENDEPIN0_MASK | + NRF_USBD_INT_EP0DATADONE_MASK | + NRF_USBD_INT_ENDEPOUT0_MASK | + NRF_USBD_INT_EP0SETUP_MASK | + NRF_USBD_INT_DATAEP_MASK; + +/** + * @brief Direction of last received Setup transfer + * + * This variable is used to redirect internal setup data event + * into selected endpoint (IN or OUT). + */ +static nrf_drv_usbd_ep_t m_last_setup_dir; + +/** + * @brief Mark endpoint readiness for DMA transfer + * + * Bits in this variable are cleared and set in interrupts. + * 1 means that endpoint is ready for DMA transfer. + * 0 means that DMA transfer cannot be performed on selected endpoint. + */ +static uint32_t m_ep_ready; + +/** + * @brief Mark endpoint with prepared data to transfer by DMA + * + * This variable can be from any place in the code (interrupt or main thread). + * It would be cleared only from USBD interrupt. + * + * Mask prepared USBD data for transmission. + * It is cleared when no more data to transmit left. + */ +static uint32_t m_ep_dma_waiting; + +/** + * @brief Current EasyDMA state + * + * Single flag, updated only inside interrupts, that marks current EasyDMA state. + * In USBD there is only one DMA channel working in background, and new transfer + * cannot be started when there is ongoing transfer on any other channel. + */ +static uint8_t m_dma_pending; + +/** + * @brief Simulated data EP status bits required for errata 104 + * + * Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE << + */ +static uint32_t m_simulated_dataepstatus; + +/** + * @brief The structure that would hold transfer configuration to every endpoint + * + * The structure that holds all the data required by the endpoint to proceed + * with LIST functionality and generate quick callback directly when data + * buffer is ready. + */ +typedef struct +{ + nrf_drv_usbd_handler_t handler; //!< Handler for current transfer, function pointer + void * p_context; //!< Context for transfer handler + size_t transfer_cnt; //!< Number of transferred bytes in the current transfer + uint16_t max_packet_size; //!< Configured endpoint size + nrf_drv_usbd_ep_status_t status; //!< NRF_SUCCESS or error code, never NRF_ERROR_BUSY - this one is calculated +}usbd_drv_ep_state_t; + +/** + * @brief The array of transfer configurations for the endpoints. + * + * The status of the transfer on each endpoint. + */ +static struct +{ + usbd_drv_ep_state_t ep_out[NRF_USBD_EPOUT_CNT]; //!< Status for OUT endpoints. + usbd_drv_ep_state_t ep_in [NRF_USBD_EPIN_CNT ]; //!< Status for IN endpoints. +}m_ep_state; + +/** + * @brief Status variables for integrated feeders. + * + * Current status for integrated feeders (IN transfers). + * Integrated feeders are used for default transfers: + * 1. Simple RAM transfer + * 2. Simple flash transfer + * 3. RAM transfer with automatic ZLP + * 4. Flash transfer with automatic ZLP + */ +nrf_drv_usbd_transfer_t m_ep_feeder_state[NRF_USBD_EPIN_CNT]; + +/** + * @brief Status variables for integrated consumers + * + * Current status for integrated consumers + * Currently one type of transfer is supported: + * 1. Transfer to RAM + * + * Transfer is finished automatically when received data block is smaller + * than the endpoint buffer or all the required data is received. + */ +nrf_drv_usbd_transfer_t m_ep_consumer_state[NRF_USBD_EPOUT_CNT]; + + +/** + * @brief Buffer used to send data directly from FLASH + * + * This is internal buffer that would be used to emulate the possibility + * to transfer data directly from FLASH. + * We do not have to care about the source of data when calling transfer functions. + * + * We do not need more buffers that one, because only one transfer can be pending + * at once. + */ +static uint32_t m_tx_buffer[CEIL_DIV( + NRF_DRV_USBD_FEEDER_BUFFER_SIZE, sizeof(uint32_t))]; + + +/* Early declaration. Documentation above definition. */ +static void usbd_dmareq_process(void); + + +/** + * @brief Change endpoint number to endpoint event code + * + * @param ep Endpoint number + * + * @return Connected endpoint event code. + * + * Marker to delete when not required anymore: >> NRF_DRV_USBD_ERRATA_ENABLE << + */ +static inline nrf_usbd_event_t nrf_drv_usbd_ep_to_endevent(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + + static const nrf_usbd_event_t epin_endev[] = + { + NRF_USBD_EVENT_ENDEPIN0, + NRF_USBD_EVENT_ENDEPIN1, + NRF_USBD_EVENT_ENDEPIN2, + NRF_USBD_EVENT_ENDEPIN3, + NRF_USBD_EVENT_ENDEPIN4, + NRF_USBD_EVENT_ENDEPIN5, + NRF_USBD_EVENT_ENDEPIN6, + NRF_USBD_EVENT_ENDEPIN7, + NRF_USBD_EVENT_ENDISOIN0 + }; + static const nrf_usbd_event_t epout_endev[] = + { + NRF_USBD_EVENT_ENDEPOUT0, + NRF_USBD_EVENT_ENDEPOUT1, + NRF_USBD_EVENT_ENDEPOUT2, + NRF_USBD_EVENT_ENDEPOUT3, + NRF_USBD_EVENT_ENDEPOUT4, + NRF_USBD_EVENT_ENDEPOUT5, + NRF_USBD_EVENT_ENDEPOUT6, + NRF_USBD_EVENT_ENDEPOUT7, + NRF_USBD_EVENT_ENDISOOUT0 + }; + + return (NRF_USBD_EPIN_CHECK(ep) ? epin_endev : epout_endev)[NRF_USBD_EP_NR_GET(ep)]; +} + + +/** + * @brief Get interrupt mask for selected endpoint + * + * @param[in] ep Endpoint number + * + * @return Interrupt mask related to the EasyDMA transfer end for the + * chosen endpoint. + */ +static inline uint32_t nrf_drv_usbd_ep_to_int(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + + static const uint8_t epin_bitpos[] = + { + USBD_INTEN_ENDEPIN0_Pos, + USBD_INTEN_ENDEPIN1_Pos, + USBD_INTEN_ENDEPIN2_Pos, + USBD_INTEN_ENDEPIN3_Pos, + USBD_INTEN_ENDEPIN4_Pos, + USBD_INTEN_ENDEPIN5_Pos, + USBD_INTEN_ENDEPIN6_Pos, + USBD_INTEN_ENDEPIN7_Pos, + USBD_INTEN_ENDISOIN_Pos + }; + static const uint8_t epout_bitpos[] = + { + USBD_INTEN_ENDEPOUT0_Pos, + USBD_INTEN_ENDEPOUT1_Pos, + USBD_INTEN_ENDEPOUT2_Pos, + USBD_INTEN_ENDEPOUT3_Pos, + USBD_INTEN_ENDEPOUT4_Pos, + USBD_INTEN_ENDEPOUT5_Pos, + USBD_INTEN_ENDEPOUT6_Pos, + USBD_INTEN_ENDEPOUT7_Pos, + USBD_INTEN_ENDISOOUT_Pos + }; + + return 1UL << (NRF_USBD_EPIN_CHECK(ep) ? epin_bitpos : epout_bitpos)[NRF_USBD_EP_NR_GET(ep)]; +} + +/** + * @name Integrated feeders and consumers + * + * Internal, default functions for transfer processing. + * @{ + */ + +/** + * @brief Integrated consumer to RAM buffer. + * + * @param p_next See @ref nrf_drv_usbd_consumer_t documentation. + * @param p_context See @ref nrf_drv_usbd_consumer_t documentation. + * @param ep_size See @ref nrf_drv_usbd_consumer_t documentation. + * @param data_size See @ref nrf_drv_usbd_consumer_t documentation. + * + * @retval true Continue transfer. + * @retval false This was the last transfer. + */ +bool nrf_drv_usbd_consumer( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size, + size_t data_size) +{ + nrf_drv_usbd_transfer_t * p_transfer = p_context; + ASSERT(ep_size >= data_size); + ASSERT((p_transfer->p_data.rx == NULL) || + nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t size = p_transfer->size; + if (size < data_size) + { + NRF_LOG_DEBUG("consumer: buffer too small: r: %u, l: %u", data_size, size); + /* Buffer size to small */ + p_next->size = 0; + p_next->p_data = p_transfer->p_data; + } + else + { + p_next->size = data_size; + p_next->p_data = p_transfer->p_data; + size -= data_size; + p_transfer->size = size; + p_transfer->p_data.ptr += data_size; + } + return (ep_size == data_size) && (size != 0); +} + +/** + * @brief Integrated feeder from RAM source. + * + * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation. + * + * @retval true Continue transfer. + * @retval false This was the last transfer. + */ +bool nrf_drv_usbd_feeder_ram( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + nrf_drv_usbd_transfer_t * p_transfer = p_context; + ASSERT(nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t tx_size = p_transfer->size; + if (tx_size > ep_size) + { + tx_size = ep_size; + } + + p_next->p_data = p_transfer->p_data; + p_next->size = tx_size; + + p_transfer->size -= tx_size; + p_transfer->p_data.ptr += tx_size; + + return (p_transfer->size != 0); +} + +/** + * @brief Integrated feeder from RAM source with ZLP. + * + * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation. + * + * @retval true Continue transfer. + * @retval false This was the last transfer. + */ +bool nrf_drv_usbd_feeder_ram_zlp( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + nrf_drv_usbd_transfer_t * p_transfer = p_context; + ASSERT(nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t tx_size = p_transfer->size; + if (tx_size > ep_size) + { + tx_size = ep_size; + } + + p_next->p_data.tx = (tx_size == 0) ? NULL : p_transfer->p_data.tx; + p_next->size = tx_size; + + p_transfer->size -= tx_size; + p_transfer->p_data.ptr += tx_size; + + return (tx_size != 0); +} + +/** + * @brief Integrated feeder from a flash source. + * + * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation. + * + * @retval true Continue transfer. + * @retval false This was the last transfer. + */ +bool nrf_drv_usbd_feeder_flash( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + nrf_drv_usbd_transfer_t * p_transfer = p_context; + ASSERT(!nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t tx_size = p_transfer->size; + void * p_buffer = nrf_drv_usbd_feeder_buffer_get(); + + if (tx_size > ep_size) + { + tx_size = ep_size; + } + + ASSERT(tx_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE); + memcpy(p_buffer, (p_transfer->p_data.tx), tx_size); + + p_next->p_data.tx = p_buffer; + p_next->size = tx_size; + + p_transfer->size -= tx_size; + p_transfer->p_data.ptr += tx_size; + + return (p_transfer->size != 0); +} + +/** + * @brief Integrated feeder from a flash source with ZLP. + * + * @param[out] p_next See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in,out] p_context See @ref nrf_drv_usbd_feeder_t documentation. + * @param[in] ep_size See @ref nrf_drv_usbd_feeder_t documentation. + * + * @retval true Continue transfer. + * @retval false This was the last transfer. + */ +bool nrf_drv_usbd_feeder_flash_zlp( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size) +{ + nrf_drv_usbd_transfer_t * p_transfer = p_context; + ASSERT(!nrf_drv_is_in_RAM((const void*)(p_transfer->p_data.ptr))); + + size_t tx_size = p_transfer->size; + void * p_buffer = nrf_drv_usbd_feeder_buffer_get(); + + if (tx_size > ep_size) + { + tx_size = ep_size; + } + + ASSERT(tx_size <= NRF_DRV_USBD_FEEDER_BUFFER_SIZE); + + if (tx_size != 0) + { + memcpy(p_buffer, (p_transfer->p_data.tx), tx_size); + p_next->p_data.tx = p_buffer; + } + else + { + p_next->p_data.tx = NULL; + } + p_next->size = tx_size; + + p_transfer->size -= tx_size; + p_transfer->p_data.ptr += tx_size; + + return (tx_size != 0); +} + +/** @} */ + +/** + * @brief Change Driver endpoint number to HAL endpoint number + * + * @param ep Driver endpoint identifier + * + * @return Endpoint identifier in HAL + * + * @sa nrf_drv_usbd_ep_from_hal + */ +static inline uint8_t ep_to_hal(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + return (uint8_t)ep; +} + +/** + * @brief Generate start task number for selected endpoint index + * + * @param ep Endpoint number + * + * @return Task for starting EasyDMA transfer on selected endpoint. + */ +static inline nrf_usbd_task_t task_start_ep(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + return (nrf_usbd_task_t)( + (NRF_USBD_EPIN_CHECK(ep) ? NRF_USBD_TASK_STARTEPIN0 : NRF_USBD_TASK_STARTEPOUT0) + + (NRF_USBD_EP_NR_GET(ep) * sizeof(uint32_t))); +} + +/** + * @brief Access selected endpoint state structure + * + * Function used to change or just read the state of selected endpoint. + * It is used for internal transmission state. + * + * @param ep Endpoint number + */ +static inline usbd_drv_ep_state_t* ep_state_access(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + return ((NRF_USBD_EPIN_CHECK(ep) ? m_ep_state.ep_in : m_ep_state.ep_out) + + NRF_USBD_EP_NR_GET(ep)); +} + +/** + * @brief Change endpoint number to bit position + * + * Bit positions are defined the same way as they are placed in DATAEPSTATUS register, + * but bits for endpoint 0 are included. + * + * @param ep Endpoint number + * + * @return Bit position related to the given endpoint number + * + * @sa bit2ep + */ +static inline uint8_t ep2bit(nrf_drv_usbd_ep_t ep) +{ + USBD_ASSERT_EP_VALID(ep); + return USBD_EP_BITPOS(ep); +} + +/** + * @brief Change bit position to endpoint number + * + * @param bitpos Bit position + * + * @return Endpoint number corresponding to given bit position. + * + * @sa ep2bit + */ +static inline nrf_drv_usbd_ep_t bit2ep(uint8_t bitpos) +{ + STATIC_ASSERT(USBD_EPOUT_BITPOS_0 > USBD_EPIN_BITPOS_0); + return (nrf_drv_usbd_ep_t)((bitpos >= USBD_EPOUT_BITPOS_0) ? + NRF_USBD_EPOUT(bitpos - USBD_EPOUT_BITPOS_0) : NRF_USBD_EPIN(bitpos)); +} + +/** + * @brief Start selected EasyDMA transmission + * + * This is internal auxiliary function. + * No checking is made if EasyDMA is ready for new transmission. + * + * @param[in] ep Number of endpoint for transmission. + * If it is OUT endpoint transmission would be directed from endpoint to RAM. + * If it is in endpoint transmission would be directed from RAM to endpoint. + */ +static inline void usbd_dma_start(nrf_drv_usbd_ep_t ep) +{ + nrf_usbd_task_trigger(task_start_ep(ep)); +} + +/** + * @brief Abort pending transfer on selected endpoint + * + * @param ep Endpoint number. + * + * @note + * This function locks interrupts that may be costly. + * It is good idea to test if the endpoint is still busy before calling this function: + * @code + (m_ep_dma_waiting & (1U << ep2bit(ep))) + * @endcode + * This function would check it again, but it makes it inside critical section. + */ +static inline void usbd_ep_abort(nrf_drv_usbd_ep_t ep) +{ + CRITICAL_REGION_ENTER(); + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + + if (NRF_USBD_EPOUT_CHECK(ep)) + { + /* Host -> Device */ + if ((~m_ep_dma_waiting) & (1U << ep2bit(ep))) + { + /* If the bit in m_ep_dma_waiting in cleared - nothing would be + * processed inside transfer processing */ + nrf_drv_usbd_transfer_out_drop(ep); + } + else + { + p_state->handler.consumer = NULL; + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + m_ep_ready &= ~(1U << ep2bit(ep)); + } + /* Aborted */ + p_state->status = NRF_USBD_EP_ABORTED; + } + else + { + if ((m_ep_dma_waiting | (~m_ep_ready)) & (1U << ep2bit(ep))) + { + /* Device -> Host */ + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + m_ep_ready |= 1U << ep2bit(ep) ; + + p_state->handler.feeder = NULL; + p_state->status = NRF_USBD_EP_ABORTED; + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_ABORTED); + m_event_handler(&evt); + } + } + CRITICAL_REGION_EXIT(); +} + +void nrf_drv_usbd_ep_abort(nrf_drv_usbd_ep_t ep) +{ + usbd_ep_abort(ep); +} + + +/** + * @brief Abort all pending endpoints + * + * Function aborts all pending endpoint transfers. + */ +static void usbd_ep_abort_all(void) +{ + uint32_t ep_waiting = m_ep_dma_waiting | (m_ep_ready & USBD_EPOUT_BIT_MASK); + while (0 != ep_waiting) + { + uint8_t bitpos = __CLZ(__RBIT(ep_waiting)); + usbd_ep_abort(bit2ep(bitpos)); + ep_waiting &= ~(1U << bitpos); + } + + m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << USBD_EPIN_BITPOS_0); +} + +/** + * @brief Force the USBD interrupt into pending state + * + * This function is used to force USBD interrupt to be processed right now. + * It makes it possible to process all EasyDMA access on one thread priority level. + */ +static inline void usbd_int_rise(void) +{ + NVIC_SetPendingIRQ(USBD_IRQn); +} + +/** + * @name USBD interrupt runtimes + * + * Interrupt runtimes that would be vectorized using @ref m_ivec_isr + * @{ + */ + +static void ev_usbreset_handler(void) +{ + m_bus_suspend = false; + m_last_setup_dir = NRF_DRV_USBD_EPOUT0; + + const nrf_drv_usbd_evt_t evt = { + .type = NRF_DRV_USBD_EVT_RESET + }; + + m_event_handler(&evt); +} + +static void ev_started_handler(void) +{ +#if NRF_DRV_USBD_STARTED_EV_ENABLE + uint32_t epstatus = nrf_usbd_epstatus_get_and_clear(); + + /* All finished endpoint have to be marked as busy */ + // #warning Check this one + // ASSERT(epstatus == ((~m_ep_ready) & epstatus)); + while (epstatus) + { + uint8_t bitpos = __CLZ(__RBIT(epstatus)); + nrf_drv_usbd_ep_t ep = bit2ep(bitpos); + epstatus &= ~(1UL << bitpos); + + UNUSED_VARIABLE(ep); + } +#endif +} + +/** + * @brief Handler for EasyDMA event without endpoint clearing. + * + * This handler would be called when EasyDMA transfer for endpoints that does not require clearing. + * All in endpoints are cleared automatically when new EasyDMA transfer is initialized. + * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler + * + * @param[in] ep Endpoint number + */ +static inline void nrf_usbd_ep0in_dma_handler(void) +{ + const nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPIN0; + NRF_LOG_DEBUG("USB event: DMA ready IN0"); + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Clear transfer information just in case */ + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else if (p_state->handler.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief Handler for EasyDMA event without endpoint clearing. + * + * This handler would be called when EasyDMA transfer for endpoints that does not require clearing. + * All in endpoints are cleared automatically when new EasyDMA transfer is initialized. + * For endpoint 0 see @ref nrf_usbd_ep0out_dma_handler + * + * @param[in] ep Endpoint number + */ +static inline void nrf_usbd_epin_dma_handler(nrf_drv_usbd_ep_t ep) +{ + + NRF_LOG_DEBUG("USB event: DMA ready IN: %x", ep); + ASSERT(NRF_USBD_EPIN_CHECK(ep)); + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + ASSERT(NRF_USBD_EP_NR_GET(ep) > 0); + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Clear transfer information just in case */ + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else if (p_state->handler.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief Handler for EasyDMA event from in isochronous endpoint + * + * @todo RK documentation + */ +static inline void nrf_usbd_epiniso_dma_handler(nrf_drv_usbd_ep_t ep) +{ + if (NRF_USBD_ISO_DEBUG) + { + NRF_LOG_DEBUG("USB event: DMA ready ISOIN: %x", ep); + } + ASSERT(NRF_USBD_EPIN_CHECK(ep)); + ASSERT(NRF_USBD_EPISO_CHECK(ep)); + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Clear transfer information just in case */ + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else if (p_state->handler.feeder == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + /* Send event to the user - for an ISO IN endpoint, the whole transfer is finished in this moment */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK); + m_event_handler(&evt); + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief Handler for EasyDMA event for OUT endpoint 0. + * + * EP0 OUT have to be cleared automatically in special way - only in the middle of the transfer. + * It cannot be cleared when required transfer is finished because it means the same that accepting the comment. + */ +static inline void nrf_usbd_ep0out_dma_handler(void) +{ + const nrf_drv_usbd_ep_t ep = NRF_DRV_USBD_EPOUT0; + NRF_LOG_DEBUG("USB event: DMA ready OUT0"); + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Clear transfer information just in case */ + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else if (p_state->handler.consumer == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK); + m_event_handler(&evt); + return; + } + else + { + /* Nothing to do */ + } + + nrf_drv_usbd_setup_data_clear(); +} + +/** + * @brief Handler for EasyDMA event from endpoinpoint that requires clearing. + * + * This handler would be called when EasyDMA transfer for OUT endpoint has been finished. + * + * @param[in] ep Endpoint number + * + */ +static inline void nrf_usbd_epout_dma_handler(nrf_drv_usbd_ep_t ep) +{ + NRF_LOG_DEBUG("USB drv: DMA ready OUT: %x", ep); + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + ASSERT(!NRF_USBD_EPISO_CHECK(ep)); + ASSERT(NRF_USBD_EP_NR_GET(ep) > 0); + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Clear transfer information just in case */ + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + } + else if (p_state->handler.consumer == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK); + m_event_handler(&evt); + } + else + { + /* Nothing to do */ + } + +#if NRF_DRV_USBD_EARLY_DMA_PROCESS + /* Speed up */ + usbd_dmareq_process(); +#endif +} + +/** + * @brief Handler for EasyDMA event from out isochronous endpoint + * + * @todo RK documentation + */ + +static inline void nrf_usbd_epoutiso_dma_handler(nrf_drv_usbd_ep_t ep) +{ + if (NRF_USBD_ISO_DEBUG) + { + NRF_LOG_DEBUG("USB drv: DMA ready ISOOUT: %x", ep); + } + ASSERT(NRF_USBD_EPISO_CHECK(ep)); + + m_dma_pending = 0; + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + if (NRF_USBD_EP_ABORTED == p_state->status) + { + /* Nothing to do - just ignore */ + } + else if (p_state->handler.consumer == NULL) + { + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << ep2bit(ep)))); + /* Send event to the user - for an OUT endpoint, the whole transfer is finished in this moment */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK); + m_event_handler(&evt); + } + else + { + /* Nothing to do */ + } +} + + +static void ev_dma_epin0_handler(void) { nrf_usbd_ep0in_dma_handler(); } +static void ev_dma_epin1_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN1 ); } +static void ev_dma_epin2_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN2 ); } +static void ev_dma_epin3_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN3 ); } +static void ev_dma_epin4_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN4 ); } +static void ev_dma_epin5_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN5 ); } +static void ev_dma_epin6_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN6 ); } +static void ev_dma_epin7_handler(void) { nrf_usbd_epin_dma_handler(NRF_DRV_USBD_EPIN7 ); } +static void ev_dma_epin8_handler(void) { nrf_usbd_epiniso_dma_handler(NRF_DRV_USBD_EPIN8 ); } + +static void ev_dma_epout0_handler(void) { nrf_usbd_ep0out_dma_handler(); } +static void ev_dma_epout1_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT1); } +static void ev_dma_epout2_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT2); } +static void ev_dma_epout3_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT3); } +static void ev_dma_epout4_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT4); } +static void ev_dma_epout5_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT5); } +static void ev_dma_epout6_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT6); } +static void ev_dma_epout7_handler(void) { nrf_usbd_epout_dma_handler(NRF_DRV_USBD_EPOUT7); } +static void ev_dma_epout8_handler(void) { nrf_usbd_epoutiso_dma_handler(NRF_DRV_USBD_EPOUT8); } + +static void ev_sof_handler(void) +{ + nrf_drv_usbd_evt_t evt = { + NRF_DRV_USBD_EVT_SOF, + .data = { .sof = { .framecnt = nrf_usbd_framecntr_get() }} + }; + + /* Process isochronous endpoints */ + m_ep_ready |= + (1U << ep2bit(NRF_DRV_USBD_EPIN8 )) | + (1U << ep2bit(NRF_DRV_USBD_EPOUT8)); + + m_event_handler(&evt); +} + +/** + * @brief React on data transfer finished + * + * Auxiliary internal function. + * @param ep Endpoint number + * @param bitpos Bit position for selected endpoint number + */ +static void usbd_ep_data_handler(nrf_drv_usbd_ep_t ep, uint8_t bitpos) +{ + NRF_LOG_DEBUG("USBD event: EndpointData: %x", ep); + /* Mark endpoint ready for next DMA access */ + m_ep_ready |= (1U << bitpos); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + /* IN endpoint (Device -> Host) */ + if (0 == (m_ep_dma_waiting & (1U << bitpos))) + { + NRF_LOG_DEBUG("USBD event: EndpointData: In finished"); + /* No more data to be send - transmission finished */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OK); + m_event_handler(&evt); + } + } + else + { + /* OUT endpoint (Host -> Device) */ + if (0 == (m_ep_dma_waiting & (1U << bitpos))) + { + NRF_LOG_DEBUG("USBD event: EndpointData: Out waiting"); + /* No buffer prepared - send event to the application */ + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_WAITING); + m_event_handler(&evt); + } + } +} + +static void ev_setup_data_handler(void) +{ + usbd_ep_data_handler(m_last_setup_dir, ep2bit(m_last_setup_dir)); +} + +static void ev_setup_handler(void) +{ + nrf_usbd_shorts_disable(NRF_USBD_SHORT_EP0DATADONE_EP0STATUS_MASK); + NRF_LOG_DEBUG("USBD event: Setup (rt:%.2x r:%.2x v:%.4x i:%.4x l:%u )", + nrf_usbd_setup_bmrequesttype_get(), + nrf_usbd_setup_brequest_get(), + nrf_usbd_setup_wvalue_get(), + nrf_usbd_setup_windex_get(), + nrf_usbd_setup_wlength_get()); + uint8_t bmRequestType = nrf_usbd_setup_bmrequesttype_get(); + + + if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U <handler.feeder) != NULL); + + if (NRF_USBD_EPIN_CHECK(ep)) + { + /* Device -> Host */ + continue_transfer = p_state->handler.feeder( + &transfer, + p_state->p_context, + p_state->max_packet_size); + + if (!continue_transfer) + { + p_state->handler.feeder = NULL; + if (ep == NRF_DRV_USBD_EPIN0) + { + /** Configure short right now - now if the last data is transferred, + * when host tries another data transfer, the endpoint will stall. */ + NRF_LOG_DEBUG("USB DMA process: Enable status short"); + nrf_usbd_shorts_enable(NRF_USBD_SHORT_EP0DATADONE_EP0STATUS_MASK); + } + } + } + else + { + /* Host -> Device */ + const size_t rx_size = nrf_drv_usbd_epout_size_get(ep); + continue_transfer = p_state->handler.consumer( + &transfer, + p_state->p_context, + p_state->max_packet_size, + rx_size); + + if (transfer.p_data.rx == NULL) + { + /* Dropping transfer - allow processing */ + ASSERT(transfer.size == 0); + } + else if (transfer.size < rx_size) + { + NRF_LOG_DEBUG("Endpoint %x overload (r: %u, e: %u)", ep, rx_size, transfer.size); + p_state->status = NRF_USBD_EP_OVERLOAD; + UNUSED_RETURN_VALUE(nrf_atomic_u32_and(&m_ep_dma_waiting, ~(1U << pos))); + NRF_DRV_USBD_EP_TRANSFER_EVENT(evt, ep, NRF_USBD_EP_OVERLOAD); + m_event_handler(&evt); + /* This endpoint will not be transmitted now, repeat the loop */ + continue; + } + else + { + /* Nothing to do - only check integrity if assertions are enabled */ + ASSERT(transfer.size == rx_size); + } + + if (!continue_transfer) + { + p_state->handler.consumer = NULL; + } + } + + m_dma_pending = 1; + m_ep_ready &= ~(1U << pos); + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG( + "USB DMA process: Starting transfer on EP: %x, size: %u", + ep, + transfer.size); + } + /* Update number of currently transferred bytes */ + p_state->transfer_cnt += transfer.size; + /* Start transfer to the endpoint buffer */ + nrf_usbd_ep_easydma_set(ep, transfer.p_data.ptr, (uint32_t)transfer.size); + + if (nrf_drv_usbd_errata_104()) + { + uint32_t cnt_end = (uint32_t)(-1); + do + { + uint32_t cnt = (uint32_t)(-1); + do + { + nrf_usbd_event_clear(NRF_USBD_EVENT_STARTED); + usbd_dma_start(ep); + nrf_drv_systick_delay_us(2); + ++cnt; + }while (!nrf_usbd_event_check(NRF_USBD_EVENT_STARTED)); + if (cnt) + { + NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" DMA restarted: %u times", cnt); + } + + nrf_drv_systick_delay_us(30); + while (0 == (0x20 & *((volatile uint32_t *)(NRF_USBD_BASE + 0x474)))) + { + nrf_drv_systick_delay_us(2); + } + nrf_drv_systick_delay_us(1); + + ++cnt_end; + } while (!nrf_usbd_event_check(nrf_drv_usbd_ep_to_endevent(ep))); + if (cnt_end) + { + NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" DMA fully restarted: %u times", cnt_end); + } + } + else + { + usbd_dma_start(ep); + } + + if (NRF_USBD_DMAREQ_PROCESS_DEBUG) + { + NRF_LOG_DEBUG("USB DMA process - finishing"); + } + /* Transfer started - exit the loop */ + break; + } + } + else + { + if (NRF_USBD_DMAREQ_PROCESS_DEBUG) + { + NRF_LOG_DEBUG("USB DMA process - EasyDMA busy"); + } + } +} +/** @} */ + +typedef void (*nrf_drv_usbd_isr_t)(void); + +/** + * @brief USBD interrupt service runtimes + * + */ +static const nrf_drv_usbd_isr_t m_isr[] = +{ + [USBD_INTEN_USBRESET_Pos ] = ev_usbreset_handler, + [USBD_INTEN_STARTED_Pos ] = ev_started_handler, + [USBD_INTEN_ENDEPIN0_Pos ] = ev_dma_epin0_handler, + [USBD_INTEN_ENDEPIN1_Pos ] = ev_dma_epin1_handler, + [USBD_INTEN_ENDEPIN2_Pos ] = ev_dma_epin2_handler, + [USBD_INTEN_ENDEPIN3_Pos ] = ev_dma_epin3_handler, + [USBD_INTEN_ENDEPIN4_Pos ] = ev_dma_epin4_handler, + [USBD_INTEN_ENDEPIN5_Pos ] = ev_dma_epin5_handler, + [USBD_INTEN_ENDEPIN6_Pos ] = ev_dma_epin6_handler, + [USBD_INTEN_ENDEPIN7_Pos ] = ev_dma_epin7_handler, + [USBD_INTEN_EP0DATADONE_Pos] = ev_setup_data_handler, + [USBD_INTEN_ENDISOIN_Pos ] = ev_dma_epin8_handler, + [USBD_INTEN_ENDEPOUT0_Pos ] = ev_dma_epout0_handler, + [USBD_INTEN_ENDEPOUT1_Pos ] = ev_dma_epout1_handler, + [USBD_INTEN_ENDEPOUT2_Pos ] = ev_dma_epout2_handler, + [USBD_INTEN_ENDEPOUT3_Pos ] = ev_dma_epout3_handler, + [USBD_INTEN_ENDEPOUT4_Pos ] = ev_dma_epout4_handler, + [USBD_INTEN_ENDEPOUT5_Pos ] = ev_dma_epout5_handler, + [USBD_INTEN_ENDEPOUT6_Pos ] = ev_dma_epout6_handler, + [USBD_INTEN_ENDEPOUT7_Pos ] = ev_dma_epout7_handler, + [USBD_INTEN_ENDISOOUT_Pos ] = ev_dma_epout8_handler, + [USBD_INTEN_SOF_Pos ] = ev_sof_handler, + [USBD_INTEN_USBEVENT_Pos ] = ev_usbevent_handler, + [USBD_INTEN_EP0SETUP_Pos ] = ev_setup_handler, + [USBD_INTEN_EPDATA_Pos ] = ev_epdata_handler, + [USBD_INTEN_ACCESSFAULT_Pos] = ev_accessfault_handler +}; + +/** + * @name Interrupt handlers + * + * @{ + */ +void USBD_IRQHandler(void) +{ + const uint32_t enabled = nrf_usbd_int_enable_get(); + uint32_t to_process = enabled; + uint32_t active = 0; + + /* Check all enabled interrupts */ + while (to_process) + { + uint8_t event_nr = __CLZ(__RBIT(to_process)); + if (nrf_usbd_event_get_and_clear((nrf_usbd_event_t)nrf_drv_bitpos_to_event(event_nr))) + { + active |= 1UL << event_nr; + } + to_process &= ~(1UL << event_nr); + } + + if (nrf_drv_usbd_errata_104()) + { + /* Event correcting */ + if ((0 == m_dma_pending) && (0 != (active & (USBD_INTEN_SOF_Msk)))) + { + uint8_t usbi, uoi, uii; + /* Testing */ + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7A9; + uii = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + if (0 != uii) + { + uii &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + } + + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AA; + uoi = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + if (0 != uoi) + { + uoi &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + } + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AB; + usbi = (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + if (0 != usbi) + { + usbi &= (uint8_t)(*((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + } + /* Processing */ + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AC; + uii &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + if (0 != uii) + { + uint8_t rb; + m_simulated_dataepstatus |= ((uint32_t)uii) << USBD_EPIN_BITPOS_0; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7A9; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = uii; + rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" uii: 0x%.2x (0x%.2x)", uii, rb); + } + + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AD; + uoi &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + if (0 != uoi) + { + uint8_t rb; + m_simulated_dataepstatus |= ((uint32_t)uoi) << USBD_EPOUT_BITPOS_0; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AA; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = uoi; + rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" uoi: 0x%.2u (0x%.2x)", uoi, rb); + } + + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AE; + usbi &= (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + if (0 != usbi) + { + uint8_t rb; + if (usbi & 0x01) + { + active |= USBD_INTEN_EP0SETUP_Msk; + } + if (usbi & 0x10) + { + active |= USBD_INTEN_USBRESET_Msk; + } + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7AB; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = usbi; + rb = (uint8_t)*((volatile uint32_t *)(NRF_USBD_BASE + 0x804)); + NRF_DRV_USBD_LOG_PROTO1_FIX_PRINTF(" usbi: 0x%.2u (0x%.2x)", usbi, rb); + } + + if (0 != (m_simulated_dataepstatus & + ~((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0)))) + { + active |= enabled & NRF_USBD_INT_DATAEP_MASK; + } + if (0 != (m_simulated_dataepstatus & + ((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0)))) + { + if (0 != (enabled & NRF_USBD_INT_EP0DATADONE_MASK)) + { + m_simulated_dataepstatus &= + ~((1U << USBD_EPOUT_BITPOS_0) | (1U << USBD_EPIN_BITPOS_0)); + active |= NRF_USBD_INT_EP0DATADONE_MASK; + } + } + } + } + + /* Process the active interrupts */ + bool setup_active = 0 != (active & NRF_USBD_INT_EP0SETUP_MASK); + active &= ~NRF_USBD_INT_EP0SETUP_MASK; + + while (active) + { + uint8_t event_nr = __CLZ(__RBIT(active)); + m_isr[event_nr](); + active &= ~(1UL << event_nr); + } + usbd_dmareq_process(); + + if (setup_active) + { + m_isr[USBD_INTEN_EP0SETUP_Pos](); + } +} + +/** @} */ +/** @} */ + +ret_code_t nrf_drv_usbd_init(nrf_drv_usbd_event_handler_t const event_handler) +{ + if (nrf_drv_usbd_errata_104()) + { + nrf_drv_systick_init(); + } + if (NULL == event_handler) + { + return NRF_ERROR_INVALID_PARAM; + } + if ( m_drv_state != NRF_DRV_STATE_UNINITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + m_event_handler = event_handler; + m_drv_state = NRF_DRV_STATE_INITIALIZED; + + uint8_t n; + for (n=0; nstatus = NRF_USBD_EP_OK; + p_state->handler.feeder = NULL; + p_state->transfer_cnt = 0; + } + for (n=0; nstatus = NRF_USBD_EP_OK; + p_state->handler.consumer = NULL; + p_state->transfer_cnt = 0; + } + + return NRF_SUCCESS; +} + +ret_code_t nrf_drv_usbd_uninit(void) +{ + if (m_drv_state != NRF_DRV_STATE_INITIALIZED) + { + return NRF_ERROR_INVALID_STATE; + } + + m_event_handler = NULL; + m_drv_state = NRF_DRV_STATE_UNINITIALIZED; + return NRF_SUCCESS; +} + +void nrf_drv_usbd_enable(void) +{ + ASSERT(m_drv_state == NRF_DRV_STATE_INITIALIZED); + + /* Prepare for READY event receiving */ + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + /* Enable the peripheral */ + nrf_usbd_enable(); + /* Waiting for peripheral to enable, this should take a few us */ + while (0 == (NRF_USBD_EVENTCAUSE_READY_MASK & nrf_usbd_eventcause_get())) + { + /* Empty loop */ + } + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + + if (nrf_drv_usbd_errata_166()) + { + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7E3; + *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0x40; + __ISB(); + __DSB(); + } + + nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); + + m_ep_ready = (((1U << NRF_USBD_EPIN_CNT) - 1U) << USBD_EPIN_BITPOS_0); + m_ep_dma_waiting = 0; + m_dma_pending = 0; + m_last_setup_dir = NRF_DRV_USBD_EPOUT0; + + m_drv_state = NRF_DRV_STATE_POWERED_ON; +} + +void nrf_drv_usbd_disable(void) +{ + ASSERT(m_drv_state != NRF_DRV_STATE_UNINITIALIZED); + + /* Stop just in case */ + nrf_drv_usbd_stop(); + + /* Disable all parts */ + nrf_usbd_int_disable(nrf_usbd_int_enable_get()); + nrf_usbd_disable(); + m_dma_pending = 0; + m_drv_state = NRF_DRV_STATE_INITIALIZED; +} + +void nrf_drv_usbd_start(bool enable_sof) +{ + ASSERT(m_drv_state == NRF_DRV_STATE_POWERED_ON); + m_bus_suspend = false; + + uint32_t ints_to_enable = + NRF_USBD_INT_USBRESET_MASK | + NRF_USBD_INT_STARTED_MASK | + NRF_USBD_INT_ENDEPIN0_MASK | + NRF_USBD_INT_EP0DATADONE_MASK | + NRF_USBD_INT_ENDEPOUT0_MASK | + NRF_USBD_INT_USBEVENT_MASK | + NRF_USBD_INT_EP0SETUP_MASK | + NRF_USBD_INT_DATAEP_MASK | + NRF_USBD_INT_ACCESSFAULT_MASK; + + if (enable_sof || nrf_drv_usbd_errata_104()) + { + ints_to_enable |= NRF_USBD_INT_SOF_MASK; + } + + /* Enable all required interrupts */ + nrf_usbd_int_enable(ints_to_enable); + + /* Enable interrupt globally */ + nrf_drv_common_irq_enable(USBD_IRQn, USBD_CONFIG_IRQ_PRIORITY); + + /* Enable pullups */ + nrf_usbd_pullup_enable(); +} + +void nrf_drv_usbd_stop(void) +{ + ASSERT(m_drv_state == NRF_DRV_STATE_POWERED_ON); + + if (nrf_drv_common_irq_enable_check(USBD_IRQn)) + { + /* Abort transfers */ + usbd_ep_abort_all(); + + /* Disable pullups */ + nrf_usbd_pullup_disable(); + + /* Disable interrupt globally */ + nrf_drv_common_irq_disable(USBD_IRQn); + + /* Disable all interrupts */ + nrf_usbd_int_disable(~0U); + } +} + +bool nrf_drv_usbd_is_initialized(void) +{ + return (m_drv_state >= NRF_DRV_STATE_INITIALIZED); +} + +bool nrf_drv_usbd_is_enabled(void) +{ + return (m_drv_state >= NRF_DRV_STATE_POWERED_ON); +} + +bool nrf_drv_usbd_is_started(void) +{ + return (nrf_drv_usbd_is_enabled() && nrf_drv_common_irq_enable_check(USBD_IRQn)); +} + +bool nrf_drv_usbd_suspend(void) +{ + bool suspended = false; + + CRITICAL_REGION_ENTER(); + if (m_bus_suspend) + { + usbd_ep_abort_all(); + + if (!(nrf_usbd_eventcause_get() & NRF_USBD_EVENTCAUSE_RESUME_MASK)) + { + nrf_usbd_lowpower_enable(); + if (nrf_usbd_eventcause_get() & NRF_USBD_EVENTCAUSE_RESUME_MASK) + { + nrf_usbd_lowpower_disable(); + } + else + { + suspended = true; + } + } + } + CRITICAL_REGION_EXIT(); + + return suspended; +} + +bool nrf_drv_usbd_wakeup_req(void) +{ + bool started = false; + + CRITICAL_REGION_ENTER(); + if (m_bus_suspend && nrf_usbd_lowpower_check()) + { + nrf_usbd_lowpower_disable(); + started = true; + } + CRITICAL_REGION_EXIT(); + + return started; +} + +bool nrf_drv_usbd_suspend_check(void) +{ + return nrf_usbd_lowpower_check(); +} + +void nrf_drv_usbd_suspend_irq_config(void) +{ + nrf_usbd_int_disable(m_irq_disabled_in_suspend); +} + +void nrf_drv_usbd_active_irq_config(void) +{ + nrf_usbd_int_enable(m_irq_disabled_in_suspend); +} + +bool nrf_drv_usbd_bus_suspend_check(void) +{ + return m_bus_suspend; +} + +void nrf_drv_usbd_ep_max_packet_size_set(nrf_drv_usbd_ep_t ep, uint16_t size) +{ + /* Only power of 2 size allowed */ + ASSERT((size != 0) && (size & (size - 1)) == 0); + /* Packet size cannot be higher than maximum buffer size */ + ASSERT( ( NRF_USBD_EPISO_CHECK(ep) && (size <= usbd_ep_iso_capacity(ep))) + || + ((!NRF_USBD_EPISO_CHECK(ep)) && (size <= NRF_DRV_USBD_EPSIZE))); + + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + p_state->max_packet_size = size; +} + +uint16_t nrf_drv_usbd_ep_max_packet_size_get(nrf_drv_usbd_ep_t ep) +{ + usbd_drv_ep_state_t const * p_state = ep_state_access(ep); + return p_state->max_packet_size; +} + +bool nrf_drv_usbd_ep_enable_check(nrf_drv_usbd_ep_t ep) +{ + return nrf_usbd_ep_enable_check(ep_to_hal(ep)); +} + +void nrf_drv_usbd_ep_enable(nrf_drv_usbd_ep_t ep) +{ + nrf_usbd_int_enable(nrf_drv_usbd_ep_to_int(ep)); + + if(nrf_usbd_ep_enable_check(ep)) + { + return; + } + nrf_usbd_ep_enable(ep_to_hal(ep)); + if ((NRF_USBD_EP_NR_GET(ep) != 0) && NRF_USBD_EPOUT_CHECK(ep) && (!NRF_USBD_EPISO_CHECK(ep))) + { + CRITICAL_REGION_ENTER(); + nrf_drv_usbd_transfer_out_drop(ep); + m_ep_dma_waiting &= ~(1U << ep2bit(ep)); + CRITICAL_REGION_EXIT(); + } +} + +void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep) +{ + usbd_ep_abort(ep); + nrf_usbd_ep_disable(ep_to_hal(ep)); + nrf_usbd_int_disable(nrf_drv_usbd_ep_to_int(ep)); +} + +void nrf_drv_usbd_ep_default_config(void) +{ + nrf_usbd_int_disable( + NRF_USBD_INT_ENDEPIN1_MASK | + NRF_USBD_INT_ENDEPIN2_MASK | + NRF_USBD_INT_ENDEPIN3_MASK | + NRF_USBD_INT_ENDEPIN4_MASK | + NRF_USBD_INT_ENDEPIN5_MASK | + NRF_USBD_INT_ENDEPIN6_MASK | + NRF_USBD_INT_ENDEPIN7_MASK | + NRF_USBD_INT_ENDISOIN0_MASK | + NRF_USBD_INT_ENDEPOUT1_MASK | + NRF_USBD_INT_ENDEPOUT2_MASK | + NRF_USBD_INT_ENDEPOUT3_MASK | + NRF_USBD_INT_ENDEPOUT4_MASK | + NRF_USBD_INT_ENDEPOUT5_MASK | + NRF_USBD_INT_ENDEPOUT6_MASK | + NRF_USBD_INT_ENDEPOUT7_MASK | + NRF_USBD_INT_ENDISOOUT0_MASK + ); + nrf_usbd_int_enable(NRF_USBD_INT_ENDEPIN0_MASK | NRF_USBD_INT_ENDEPOUT0_MASK); + nrf_usbd_ep_all_disable(); +} + +ret_code_t nrf_drv_usbd_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer) +{ + ret_code_t ret; + const uint8_t ep_bitpos = ep2bit(ep); + ASSERT(NULL != p_transfer); + + CRITICAL_REGION_ENTER(); + /* Setup data transaction can go only in one direction at a time */ + if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir)) + { + ret = NRF_ERROR_INVALID_ADDR; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: Invalid EPr\n"); + } + } + else if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos)) + { + /* IN (Device -> Host) transfer has to be transmitted out to allow new transmission */ + ret = NRF_ERROR_BUSY; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: EP is busy"); + } + } + else + { + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + /* Prepare transfer context and handler description */ + nrf_drv_usbd_transfer_t * p_context; + if (NRF_USBD_EPIN_CHECK(ep)) + { + p_context = m_ep_feeder_state + NRF_USBD_EP_NR_GET(ep); + if (nrf_drv_is_in_RAM(p_transfer->p_data.tx)) + { + /* RAM */ + if (0 == (p_transfer->flags & NRF_DRV_USBD_TRANSFER_ZLP_FLAG)) + { + p_state->handler.feeder = nrf_drv_usbd_feeder_ram; + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG( + "USB driver: Transfer called on endpoint %x, size: %u, mode: " + "RAM", + ep, + p_transfer->size); + } + } + else + { + p_state->handler.feeder = nrf_drv_usbd_feeder_ram_zlp; + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG( + "USB driver: Transfer called on endpoint %x, size: %u, mode: " + "RAM_ZLP", + ep, + p_transfer->size); + } + } + } + else + { + /* Flash */ + if (0 == (p_transfer->flags & NRF_DRV_USBD_TRANSFER_ZLP_FLAG)) + { + p_state->handler.feeder = nrf_drv_usbd_feeder_flash; + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG( + "USB driver: Transfer called on endpoint %x, size: %u, mode: " + "FLASH", + ep, + p_transfer->size); + } + } + else + { + p_state->handler.feeder = nrf_drv_usbd_feeder_flash_zlp; + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG( + "USB driver: Transfer called on endpoint %x, size: %u, mode: " + "FLASH_ZLP", + ep, + p_transfer->size); + } + } + } + } + else + { + p_context = m_ep_consumer_state + NRF_USBD_EP_NR_GET(ep); + ASSERT((p_transfer->p_data.rx == NULL) || (nrf_drv_is_in_RAM(p_transfer->p_data.rx))); + p_state->handler.consumer = nrf_drv_usbd_consumer; + } + *p_context = *p_transfer; + p_state->p_context = p_context; + + p_state->transfer_cnt = 0; + p_state->status = NRF_USBD_EP_OK; + m_ep_dma_waiting |= 1U << ep_bitpos; + ret = NRF_SUCCESS; + usbd_int_rise(); + } + CRITICAL_REGION_EXIT(); + return ret; +} + +ret_code_t nrf_drv_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler) +{ + ret_code_t ret; + const uint8_t ep_bitpos = ep2bit(ep); + ASSERT(NULL != p_handler); + + CRITICAL_REGION_ENTER(); + /* Setup data transaction can go only in one direction at a time */ + if ((NRF_USBD_EP_NR_GET(ep) == 0) && (ep != m_last_setup_dir)) + { + ret = NRF_ERROR_INVALID_ADDR; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: Invalid EP"); + } + } + else if ((m_ep_dma_waiting | ((~m_ep_ready) & USBD_EPIN_BIT_MASK)) & (1U << ep_bitpos)) + { + /* IN (Device -> Host) transfer has to be transmitted out to allow a new transmission */ + ret = NRF_ERROR_BUSY; + if (NRF_USBD_FAILED_TRANSFERS_DEBUG && (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep)))) + { + NRF_LOG_DEBUG("USB driver: Transfer failed: EP is busy");\ + } + } + else + { + /* Transfer can be configured now */ + usbd_drv_ep_state_t * p_state = ep_state_access(ep); + + p_state->transfer_cnt = 0; + p_state->handler = p_handler->handler; + p_state->p_context = p_handler->p_context; + p_state->status = NRF_USBD_EP_OK; + m_ep_dma_waiting |= 1U << ep_bitpos; + + ret = NRF_SUCCESS; + if (NRF_USBD_ISO_DEBUG || (!NRF_USBD_EPISO_CHECK(ep))) + { + NRF_LOG_DEBUG("USB driver: Transfer called on endpoint %x, mode: Handler", ep); + } + usbd_int_rise(); + } + CRITICAL_REGION_EXIT(); + return ret; +} + +void * nrf_drv_usbd_feeder_buffer_get(void) +{ + return m_tx_buffer; +} + +ret_code_t nrf_drv_usbd_ep_status_get(nrf_drv_usbd_ep_t ep, size_t * p_size) +{ + ret_code_t ret; + + usbd_drv_ep_state_t const * p_state = ep_state_access(ep); + CRITICAL_REGION_ENTER(); + *p_size = p_state->transfer_cnt; + ret = (p_state->handler.consumer == NULL) ? p_state->status : NRF_ERROR_BUSY; + CRITICAL_REGION_EXIT(); + return ret; +} + +size_t nrf_drv_usbd_epout_size_get(nrf_drv_usbd_ep_t ep) +{ + return nrf_usbd_epout_size_get(ep_to_hal(ep)); +} + +bool nrf_drv_usbd_ep_is_busy(nrf_drv_usbd_ep_t ep) +{ + return (0 != (m_ep_dma_waiting & (1UL << ep2bit(ep)))); +} + +void nrf_drv_usbd_ep_stall(nrf_drv_usbd_ep_t ep) +{ + NRF_LOG_DEBUG("USB: EP %x stalled.", ep); + nrf_usbd_ep_stall(ep_to_hal(ep)); +} + +void nrf_drv_usbd_ep_stall_clear(nrf_drv_usbd_ep_t ep) +{ + nrf_usbd_ep_unstall(ep_to_hal(ep)); +} + +bool nrf_drv_usbd_ep_stall_check(nrf_drv_usbd_ep_t ep) +{ + return nrf_usbd_ep_is_stall(ep_to_hal(ep)); +} + +void nrf_drv_usbd_ep_dtoggle_clear(nrf_drv_usbd_ep_t ep) +{ + nrf_usbd_dtoggle_set(ep, NRF_USBD_DTOGGLE_DATA0); +} + +void nrf_drv_usbd_setup_get(nrf_drv_usbd_setup_t * const p_setup) +{ + memset(p_setup, 0, sizeof(nrf_drv_usbd_setup_t)); + p_setup->bmRequestType = nrf_usbd_setup_bmrequesttype_get(); + p_setup->bmRequest = nrf_usbd_setup_brequest_get(); + p_setup->wValue = nrf_usbd_setup_wvalue_get(); + p_setup->wIndex = nrf_usbd_setup_windex_get(); + p_setup->wLength = nrf_usbd_setup_wlength_get(); +} + +void nrf_drv_usbd_setup_data_clear(void) +{ + if (nrf_drv_usbd_errata_104()) + { + /* For this fix to work properly, it must be ensured that the task is + * executed twice one after another - blocking ISR. This is however a temporary + * solution to be used only before production version of the chip. */ + uint32_t primask_copy = __get_PRIMASK(); + __disable_irq(); + nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT); + nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT); + __set_PRIMASK(primask_copy); + } + else + { + nrf_usbd_task_trigger(NRF_USBD_TASK_EP0RCVOUT); + } +} + +void nrf_drv_usbd_setup_clear(void) +{ + nrf_usbd_task_trigger(NRF_USBD_TASK_EP0STATUS); +} + +void nrf_drv_usbd_setup_stall(void) +{ + NRF_LOG_DEBUG("Setup stalled."); + nrf_usbd_task_trigger(NRF_USBD_TASK_EP0STALL); +} + +nrf_drv_usbd_ep_t nrf_drv_usbd_last_setup_dir_get(void) +{ + return m_last_setup_dir; +} + +void nrf_drv_usbd_transfer_out_drop(nrf_drv_usbd_ep_t ep) +{ + ASSERT(NRF_USBD_EPOUT_CHECK(ep)); + + if (nrf_drv_usbd_errata_sizeepout_rw()) + { + CRITICAL_REGION_ENTER(); + m_ep_ready &= ~(1U << ep2bit(ep)); + *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + (2u * NRF_USBD_EP_NR_GET(ep)); + *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0; + UNUSED_VARIABLE(((volatile uint32_t *)(NRF_USBD_BASE + 0x804))); + CRITICAL_REGION_EXIT(); + } + else + { + CRITICAL_REGION_ENTER(); + m_ep_ready &= ~(1U << ep2bit(ep)); + nrf_usbd_epout_clear(ep); + CRITICAL_REGION_EXIT(); + } +} + +#endif // USBD_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.h new file mode 100644 index 0000000000..25d7b34253 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd.h @@ -0,0 +1,947 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_USBD_H__ +#define NRF_DRV_USBD_H__ + +#include "nrf_drv_common.h" +#include "sdk_errors.h" +#include "nrf_usbd.h" +#include +#include +#include "app_util.h" +#include "nrf_drv_usbd_errata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_drv_usbd USB Device HAL and driver + * @ingroup nrf_drivers + * @brief @tagAPI52840 USB Device APIs. + * @details The USB Device HAL provides basic APIs for accessing + * the registers of the USBD. + * The USB Device driver provides APIs on a higher level. + * + * @{ + */ + +/** + * @name Possible schemes of DMA scheduling + * + * Definition of available configuration constants used by DMA scheduler + * @{ + */ + /** + * @brief Highly prioritized access + * + * Endpoint with lower number has always higher priority and its data would + * be transfered first. + * OUT endpoints ale processed before IN endpoints + */ + #define NRF_DRV_USBD_DMASCHEDULER_PRIORITIZED 0 + + /** + * @brief Round robin scheme + * + * All endpoints are processed in round-robin scheme. + * It means that when one endpoint is processed next in order would be + * the nearest with lower number. + * When no endpoints with lower number requires processing - then + * all endpoints from 0 are tested. + */ + #define NRF_DRV_USBD_DMASCHEDULER_ROUNDROBIN 1 + +/** @} */ + +/** + * @brief Number of bytes in the endpoint + * + * Constant that informs about endpoint size + */ +#define NRF_DRV_USBD_EPSIZE 64 + +/** + * @brief Number of bytes for isochronous endpoints + * + * Number of bytes for isochronous endpoints in total. + * This number would be shared between IN and OUT endpoint. + * It may be also assigned totaly to one endpoint. + * @sa nrf_usbd_isosplit_set + * @sa nrf_usbd_isosplit_get + */ +#define NRF_DRV_USBD_ISOSIZE 1024 + +/** + * @brief The size of internal feeder buffer. + * + * @sa nrf_drv_usbd_feeder_buffer_get + */ +#define NRF_DRV_USBD_FEEDER_BUFFER_SIZE NRF_DRV_USBD_EPSIZE + +/** + * @name Macros for creating endpoint identifiers + * + * Auxiliary macros to be used to create Endpoint identifier that is compatible + * with USB specification. + * @{ + */ + + /** + * @brief Create identifier for IN endpoint + * + * Simple macro to create IN endpoint identifier for given endpoint number. + * + * @param[in] n Endpoint number. + * + * @return Endpoint identifier that connects endpoint number and endpoint direction. + */ + #define NRF_DRV_USBD_EPIN(n) ((nrf_drv_usbd_ep_t)NRF_USBD_EPIN(n)) + /** + * @brief Create identifier for OUT endpoint + * + * Simple macro to create OUT endpoint identifier for given endpoint number. + * + * @param[in] n Endpoint number. + * + * @return Endpoint identifier that connects endpoint number and endpoint direction. + */ + #define NRF_DRV_USBD_EPOUT(n) ((nrf_drv_usbd_ep_t)NRF_USBD_EPOUT(n)) + +/** @} */ + +/** + * @brief Endpoint identifier + * + * Endpoint identifier used in the driver. + * This endpoint number is consistent with USB 2.0 specification. + */ +typedef enum +{ + NRF_DRV_USBD_EPOUT0 = NRF_USBD_EPOUT(0), /**< Endpoint OUT 0 */ + NRF_DRV_USBD_EPOUT1 = NRF_USBD_EPOUT(1), /**< Endpoint OUT 1 */ + NRF_DRV_USBD_EPOUT2 = NRF_USBD_EPOUT(2), /**< Endpoint OUT 2 */ + NRF_DRV_USBD_EPOUT3 = NRF_USBD_EPOUT(3), /**< Endpoint OUT 3 */ + NRF_DRV_USBD_EPOUT4 = NRF_USBD_EPOUT(4), /**< Endpoint OUT 4 */ + NRF_DRV_USBD_EPOUT5 = NRF_USBD_EPOUT(5), /**< Endpoint OUT 5 */ + NRF_DRV_USBD_EPOUT6 = NRF_USBD_EPOUT(6), /**< Endpoint OUT 6 */ + NRF_DRV_USBD_EPOUT7 = NRF_USBD_EPOUT(7), /**< Endpoint OUT 7 */ + NRF_DRV_USBD_EPOUT8 = NRF_USBD_EPOUT(8), /**< Endpoint OUT 8 */ + + NRF_DRV_USBD_EPIN0 = NRF_USBD_EPIN(0), /**< Endpoint IN 0 */ + NRF_DRV_USBD_EPIN1 = NRF_USBD_EPIN(1), /**< Endpoint IN 1 */ + NRF_DRV_USBD_EPIN2 = NRF_USBD_EPIN(2), /**< Endpoint IN 2 */ + NRF_DRV_USBD_EPIN3 = NRF_USBD_EPIN(3), /**< Endpoint IN 3 */ + NRF_DRV_USBD_EPIN4 = NRF_USBD_EPIN(4), /**< Endpoint IN 4 */ + NRF_DRV_USBD_EPIN5 = NRF_USBD_EPIN(5), /**< Endpoint IN 5 */ + NRF_DRV_USBD_EPIN6 = NRF_USBD_EPIN(6), /**< Endpoint IN 6 */ + NRF_DRV_USBD_EPIN7 = NRF_USBD_EPIN(7), /**< Endpoint IN 7 */ + NRF_DRV_USBD_EPIN8 = NRF_USBD_EPIN(8), /**< Endpoint IN 8 */ +}nrf_drv_usbd_ep_t; + +/** + * @brief Events generated by the library + * + * Enumeration of possible events that may be generated by the library. + */ +typedef enum +{ + NRF_DRV_USBD_EVT_SOF, /**< Start Of Frame event on USB bus detected */ + NRF_DRV_USBD_EVT_RESET, /**< Reset condition on USB bus detected */ + NRF_DRV_USBD_EVT_SUSPEND, /**< This device should go to suspend mode now */ + NRF_DRV_USBD_EVT_RESUME, /**< This device should resume from suspend now */ + NRF_DRV_USBD_EVT_WUREQ, /**< Wakeup request - the USBD peripheral is ready to generate WAKEUP signal after exiting low power mode. */ + NRF_DRV_USBD_EVT_SETUP, /**< Setup frame received and decoded */ + NRF_DRV_USBD_EVT_EPTRANSFER, /**< + * For Rx (OUT: Host->Device): + * 1. The packet has been received but there is no buffer prepared for transfer already. + * 2. Whole transfer has been finished + * + * For Tx (IN: Device->Host): + * The last packet from requested transfer has been transfered over USB bus and acknowledged + */ + NRF_DRV_USBD_EVT_CNT /**< Number of defined events */ +}nrf_drv_usbd_event_type_t; + +/** + * @brief Possible endpoint error codes + * + * Error codes that may be returned with @ref NRF_DRV_USBD_EVT_EPTRANSFER + */ +typedef enum +{ + NRF_USBD_EP_OK, /**< No error */ + NRF_USBD_EP_WAITING, /**< Data received, no buffer prepared already - waiting for configured transfer */ + NRF_USBD_EP_OVERLOAD, /**< Received number of bytes cannot fit given buffer + * This error would also be returned when next_transfer function has been defined + * but currently received data cannot fit completely in current buffer. + * No data split from single endpoint transmission is supported. + * + * When this error is reported - data is left inside endpoint buffer. + * Clear endpoint or prepare new buffer and read it. + */ + NRF_USBD_EP_ABORTED, /**< EP0 transfer can be aborted when new setup comes. + * Any other transfer can be aborted by USB reset or library stopping. + */ +}nrf_drv_usbd_ep_status_t; + + +/** + * @brief Event structure + * + * Structure passed to event handler + */ +typedef struct +{ + nrf_drv_usbd_event_type_t type; + union + { + struct{ + uint16_t framecnt; //!< Current value of frame counter + }sof; //!< Data aviable for @ref NRF_DRV_USBD_EVT_SOF + struct{ + nrf_drv_usbd_ep_t ep; //!< Endpoint number + }isocrc; + struct{ + nrf_drv_usbd_ep_t ep; //!< Endpoint number + nrf_drv_usbd_ep_status_t status; //!< Status for the endpoint + }eptransfer; + }data; +}nrf_drv_usbd_evt_t; + +/** + * @brief USBD event callback function type. + * + * @param[in] p_event Event information structure. + */ +typedef void (*nrf_drv_usbd_event_handler_t)(nrf_drv_usbd_evt_t const * const p_event); + +/** + * @brief Universal data pointer. + * + * Universal data pointer that can be used for any type of transfer. + */ +typedef union +{ + void const * tx; //!< Constant TX buffer pointer. + void * rx; //!< Writable RX buffer pointer. + uint32_t ptr; //!< Numeric value used internally by the library. +}nrf_drv_usbd_data_ptr_t; + +/** + * @brief Structure to be filled with information about the next transfer. + * + * This is used mainly for transfer feeders and consumers. + * It describes a single endpoint transfer and therefore the size of the buffer + * can never be higher than the endpoint size. + */ +typedef struct +{ + nrf_drv_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the library. + size_t size; //!< Size of the requested transfer. +}nrf_drv_usbd_ep_transfer_t; + +/** + * @brief Flags for the current transfer. + * + * Flags configured for the transfer that can be merged using the bitwise 'or' operator (|). + */ +typedef enum +{ + NRF_DRV_USBD_TRANSFER_ZLP_FLAG = 1U << 0, //!< Add a zero-length packet. +}nrf_drv_usbd_transfer_flags_t; + +/** + * @brief Total transfer configuration. + * + * This structure is used to configure total transfer information. + * It is used by internal built-in feeders and consumers. + */ +typedef struct +{ + nrf_drv_usbd_data_ptr_t p_data; //!< Union with available data pointers used by the library. + size_t size; //!< Total size of the requested transfer. + uint32_t flags; //!< Transfer flags. + /**< Use the @ref nrf_drv_usbd_transfer_flags_t values. */ +}nrf_drv_usbd_transfer_t; + + +/** + * @brief Auxiliary macro for declaring IN transfer description with flags. + * + * The base macro for creating transfers with any configuration option. + * + * @param name Instance name. + * @param tx_buff Buffer to transfer. + * @param tx_size Transfer size. + * @param tx_flags Flags for the transfer (see @ref nrf_drv_usbd_transfer_flags_t). + * + * @return Configured variable with total transfer description. + */ +#define NRF_DRV_USBD_TRANSFER_IN_FLAGS(name, tx_buff, tx_size, tx_flags) \ + const nrf_drv_usbd_transfer_t name = { \ + .p_data = { .tx = (tx_buff) }, \ + .size = (tx_size), \ + .flags = (tx_flags) \ + } + +/** + * @brief Helper macro for declaring IN transfer description + * + * Normal transfer mode, no ZLP would be automatically generated. + * + * @sa nrf_drv_usbd_transfer_t + * @sa NRF_DRV_USBD_TRANSFER_IN_ZLP + * + * @param name Instance name + * @param tx_buff Buffer to transfer + * @param tx_size Transfer size + * + * @return Configured variable with total transfer description + * + */ +#define NRF_DRV_USBD_TRANSFER_IN(name, tx_buff, tx_size) \ + NRF_DRV_USBD_TRANSFER_IN_FLAGS(name, tx_buff, tx_size, 0) + +/** + * @brief Helper macro for declaring IN transfer description + * + * ZLP mode - Zero Length Packet would be generated on the end of the transfer + * (always!). + * + * @sa nrf_drv_usbd_transfer_t + * @sa NRF_DRV_USBD_TRANSFER_IN + * + * @param name Instance name + * @param tx_buff Buffer to transfer + * @param tx_size Transfer size + * + * @return Configured variable with total transfer description + */ +#define NRF_DRV_USBD_TRANSFER_IN_ZLP(name, tx_buff, tx_size) \ + NRF_DRV_USBD_TRANSFER_IN_FLAGS( \ + name, \ + tx_buff, \ + tx_size, \ + NRF_DRV_USBD_TRANSFER_ZLP_FLAG) + +/** + * @brief Helper macro for declaring OUT transfer item (@ref nrf_drv_usbd_transfer_t) + * + * @param name Instance name + * @param rx_buff Buffer to transfer + * @param rx_size Transfer size + * */ +#define NRF_DRV_USBD_TRANSFER_OUT(name, rx_buff, rx_size) \ + const nrf_drv_usbd_transfer_t name = { \ + .p_data = { .rx = (rx_buff) }, \ + .size = (rx_size), \ + .flags = 0 \ + } + +/** + * @brief USBD transfer feeder. + * + * Pointer for a transfer feeder. + * Transfer feeder is a feedback function used to prepare a single + * TX (Device->Host) endpoint transfer. + * + * The transfers provided by the feeder must be simple: + * - The size of the transfer provided by this function is limited to a single endpoint buffer. + * Bigger transfers are not handled automatically in this case. + * - Flash transfers are not automatically supported- you must copy them to the RAM buffer before. + * + * @note + * This function may use @ref nrf_drv_usbd_feeder_buffer_get to gain a temporary buffer + * that can be used to prepare transfer. + * + * @param[out] p_next Structure with the data for the next transfer to be filled. + * Required only if the function returns true. + * @param[in,out] p_context Context variable configured with the transfer. + * @param[in] ep_size The endpoint size. + * + * @retval false The current transfer is the last one - you do not need to call + * the function again. + * @retval true There is more data to be prepared and when the current transfer + * finishes, the feeder function is expected to be called again. + */ +typedef bool (*nrf_drv_usbd_feeder_t)( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size); + +/** + * @brief USBD transfer consumer. + * + * Pointer for a transfer consumer. + * Transfer consumer is a feedback function used to prepare a single + * RX (Host->Device) endpoint transfer. + * + * The transfer must provide a buffer big enough to fit the whole data from the endpoint. + * Otherwise, the NRF_USBD_EP_OVERLOAD event is generated. + * + * @param[out] p_next Structure with the data for the next transfer to be filled. + * Required only if the function returns true. + * @param[in,out] p_context Context variable configured with the transfer. + * @param[in] ep_size The endpoint size. + * @param[in] data_size Number of received bytes in the endpoint buffer. + * + * @retval false Current transfer is the last one - you do not need to call + * the function again. + * @retval true There is more data to be prepared and when current transfer + * finishes, the feeder function is expected to be called again. + */ +typedef bool (*nrf_drv_usbd_consumer_t)( + nrf_drv_usbd_ep_transfer_t * p_next, + void * p_context, + size_t ep_size, + size_t data_size); + +/** + * @brief Universal transfer handler. + * + * Union with feeder and consumer function pointer. + */ +typedef union +{ + nrf_drv_usbd_feeder_t feeder; //!< Feeder function pointer. + nrf_drv_usbd_consumer_t consumer; //!< Consumer function pointer. +}nrf_drv_usbd_handler_t; + +/** + * @brief USBD transfer descriptor. + * + * Universal structure that may hold the setup for callback configuration for + * IN or OUT type of the transfer. + */ +typedef struct +{ + nrf_drv_usbd_handler_t handler; //!< Handler for the current transfer, function pointer. + void * p_context; //!< Context for the transfer handler. +}nrf_drv_usbd_handler_desc_t; + +/** + * @brief Setup packet structure + * + * Structure that contains interpreted SETUP packet. + */ +typedef struct +{ + uint8_t bmRequestType; //!< byte 0 + uint8_t bmRequest; //!< byte 1 + uint16_t wValue; //!< byte 2 + uint16_t wIndex; //!< byte 4, 5 + uint16_t wLength; //!< byte 6, 7 +}nrf_drv_usbd_setup_t; + +/** + * @brief Library initialization + * + * @param[in] event_handler Event handler provided by the user. + */ +ret_code_t nrf_drv_usbd_init(nrf_drv_usbd_event_handler_t const event_handler); + +/** + * @brief Library deinitialization + */ +ret_code_t nrf_drv_usbd_uninit(void); + +/** + * @brief Enable the USBD port + * + * After calling this function USBD peripheral would be enabled. + * The USB LDO would be enabled. + * Enabled USBD peripheral would request HFCLK. + * This function does not enable external oscillator, so if it is not enabled by other part of the + * program after enabling USBD driver HFINT would be used for the USBD peripheral. + * It is perfectly fine until USBD is started. See @ref nrf_drv_usbd_start. + * + * In normal situation this function should be called in reaction to USBDETECTED + * event from POWER peripheral. + * + * Interrupts and USB pins pull-up would stay disabled until @ref nrf_drv_usbd_start + * function is called. + */ +void nrf_drv_usbd_enable(void); + +/** + * @brief Disable the USBD port + * + * After calling this function USBD peripheral would be disabled. + * No events would be detected or processed by the library. + * Clock for the peripheral would be disconnected. + */ +void nrf_drv_usbd_disable(void); + +/** + * @brief Start USB functionality + * + * After calling this function USBD peripheral should be fully functional + * and all new incoming events / interrupts would be processed by the library. + * + * Also only after calling this function host sees new connected device. + * + * Call this function when USBD power LDO regulator is ready - on USBPWRRDY event + * from POWER peripheral. + * + * Before USBD interrupts are enabled, external HFXO is requested. + * + * @param enable_sof The flag that is used to enable SOF processing. + * If it is false, SOF interrupt is left disabled and will not be generated. + * This improves power saving if SOF is not required. + * + * @note If the isochronous endpoints are going to be used, + * it is required to enable the SOF. + * In other case any isochronous endpoint would stay busy + * after first transmission. + */ +void nrf_drv_usbd_start(bool enable_sof); + +/** + * @brief Stop USB functionality + * + * This function disables USBD pull-up and interrupts. + * + * The HFXO request is released in this function. + * + * @note + * This function can also be used to logically disconnect USB from the HOST that + * would force it to enumerate device after calling @ref nrf_drv_usbd_start. + */ +void nrf_drv_usbd_stop(void); + +/** + * @brief Check if driver is initialized + * + * @retval false Driver is not initialized + * @retval true Driver is initialized + */ +bool nrf_drv_usbd_is_initialized(void); + +/** + * @brief Check if driver is enabled + * + * @retval false Driver is disabled + * @retval true Driver is enabled + */ +bool nrf_drv_usbd_is_enabled(void); + +/** + * @brief Check if driver is started + * + * @retval false Driver is not started + * @retval true Driver is started (fully functional) + * @note The USBD peripheral interrupt state is checked + */ +bool nrf_drv_usbd_is_started(void); + +/** + * @brief Suspend USBD operation + * + * The USBD peripheral is forced to go into the low power mode. + * The function has to be called in the reaction to @ref NRF_DRV_USBD_EVT_SUSPEND event + * when the firmware is ready. + * + * After successful call of this function most of the USBD registers would be unavailable. + * + * @note Check returned value for the feedback if suspending was successful. + * + * @retval true USBD peripheral successfully suspended + * @retval false USBD peripheral was not suspended due to resume detection. + * + */ +bool nrf_drv_usbd_suspend(void); + +/** + * @brief Start wake up procedure + * + * The USBD peripheral is forced to quit the low power mode. + * After calling this function all the USBD registers would be available. + * + * The hardware starts measuring time when wake up is possible. + * This may take 0-5 ms depending on how long the SUSPEND state was kept on the USB line. + + * When NRF_DRV_USBD_EVT_WUREQ event is generated it means that Wake Up signaling has just been + * started on the USB lines. + * + * @note Do not expect only @ref NRF_DRV_USBD_EVT_WUREQ event. + * There always may appear @ref NRF_DRV_USBD_EVT_RESUME event. + * @note NRF_DRV_USBD_EVT_WUREQ event means that Remote WakeUp signal + * has just begun to be generated. + * This may take up to 20 ms for the bus to become active. + * + * @retval true WakeUp procedure started. + * @retval false No WakeUp procedure started - bus is already active. + */ +bool nrf_drv_usbd_wakeup_req(void); + +/** + * @brief Check if USBD is in SUSPEND mode + * + * @note This is the information about peripheral itself, not about the bus state. + * + * @retval true USBD peripheral is suspended + * @retval false USBD peripheral is active + */ +bool nrf_drv_usbd_suspend_check(void); + +/** + * @brief Enable only interrupts that should be processed in SUSPEND mode + * + * Auxiliary function to help with SUSPEND mode integration. + * It enables only the interrupts that can be properly processed without stable HFCLK. + * + * Normally all the interrupts are enabled. + * Use this function to suspend interrupt processing that may require stable HFCLK until the + * clock is enabled. + * + * @sa nrf_drv_usbd_active_irq_config + */ +void nrf_drv_usbd_suspend_irq_config(void); + +/** + * @brief Default active interrupt configuration + * + * Default interrupt configuration. + * Use in a pair with @ref nrf_drv_usbd_active_irq_config. + * + * @sa nrf_drv_usbd_suspend_irq_config + */ +void nrf_drv_usbd_active_irq_config(void); + +/** + * @brief Check the bus state + * + * This function checks if the bus state is suspended + * + * @note The value returned by this function changes on SUSPEND and RESUME event processing. + * + * @retval true USBD bus is suspended + * @retval false USBD bus is active + */ +bool nrf_drv_usbd_bus_suspend_check(void); + +/** + * @brief Configure packet size that should be supported by the endpoint + * + * The real endpoint buffer size is always the same. + * This value sets max packet size that would be transmitted over the endpoint. + * This is required by the library + * + * @param[in] ep Endpoint number + * @param[in] size Required maximum packet size + * + * @note Endpoint size is always set to @ref NRF_DRV_USBD_EPSIZE or @ref NRF_DRV_USBD_ISOSIZE / 2 + * when @ref nrf_drv_usbd_ep_enable function is called. + */ +void nrf_drv_usbd_ep_max_packet_size_set(nrf_drv_usbd_ep_t ep, uint16_t size); + +/** + * @brief Get configured endpoint packet size + * + * Function to get configured endpoint size on the buffer. + * + * @param[in] ep Endpoint number + * + * @return Maximum pocket size configured on selected endpoint + */ +uint16_t nrf_drv_usbd_ep_max_packet_size_get(nrf_drv_usbd_ep_t ep); + +/** + * @brief Check if the selected endpoint is enabled. + * + * @param ep Endpoint number to check. + * + * @retval true Endpoint is enabled. + * @retval false Endpoint is disabled. + */ +bool nrf_drv_usbd_ep_enable_check(nrf_drv_usbd_ep_t ep); + +/** + * @brief Enable selected endpoint + * + * This function enables endpoint itself and its interrupts. + * @param ep Endpoint number to enable + * + * @note + * Max packet size is set to endpoint default maximum value. + * + * @sa nrf_drv_usbd_ep_max_packet_size_set + */ +void nrf_drv_usbd_ep_enable(nrf_drv_usbd_ep_t ep); + +/** + * @brief Disable selected endpoint + * + * This function disables endpoint itself and its interrupts. + * @param ep Endpoint number to disable + */ +void nrf_drv_usbd_ep_disable(nrf_drv_usbd_ep_t ep); + +/** + * @brief Disable all endpoints except for EP0 + * + * Disable all endpoints that can be disabled in USB device while it is still active. + */ +void nrf_drv_usbd_ep_default_config(void); + +/** + * @brief Start sending data over endpoint + * + * Function initializes endpoint transmission. + * This is asynchronous function - it finishes immediately after configuration + * for transmission is prepared. + * + * @note Data buffer pointed by p_data have to be kept active till + * @ref NRF_DRV_USBD_EVT_EPTRANSFER event is generated. + * + * @param[in] ep Endpoint number. + * For IN endpoint sending would be initiated. + * For OUT endpoint receiving would be initiated. + * @param[in] p_transfer + * + * @retval NRF_ERROR_BUSY Selected endpoint is pending. + * @retval NRF_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0. + * @retval NRF_ERROR_FORBIDDEN Endpoint stalled. + * @retval NRF_SUCCESS Transfer queued or started. + */ +ret_code_t nrf_drv_usbd_ep_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_transfer_t const * const p_transfer); + +/** + * @brief Start sending data over the endpoint using the transfer handler function. + * + * This function initializes an endpoint transmission. + * Just before data is transmitted, the transfer handler + * is called and it prepares a data chunk. + * + * @param[in] ep Endpoint number. + * For an IN endpoint, sending is initiated. + * For an OUT endpoint, receiving is initiated. + * @param p_handler Transfer handler - feeder for IN direction and consumer for + * OUT direction. + * + * @retval NRF_ERROR_BUSY Selected endpoint is pending. + * @retval NRF_ERROR_INVALID_ADDR Unexpected transfer on EPIN0 or EPOUT0. + * @retval NRF_ERROR_FORBIDDEN Endpoint stalled. + * @retval NRF_SUCCESS Transfer queued or started. + */ +ret_code_t nrf_drv_usbd_ep_handled_transfer( + nrf_drv_usbd_ep_t ep, + nrf_drv_usbd_handler_desc_t const * const p_handler); + +/** + * @brief Get the temporary buffer to be used by the feeder. + * + * This buffer is used for TX transfers and it can be reused automatically + * when the transfer is finished. + * Use it for transfer preparation. + * + * May be used inside the feeder configured in @ref nrf_drv_usbd_ep_handled_transfer. + * + * @return Pointer to the buffer that can be used temporarily. + * + * @sa NRF_DRV_USBD_FEEDER_BUFFER_SIZE + */ +void * nrf_drv_usbd_feeder_buffer_get(void); + +/** + * @brief Get the information about last finished or current transfer + * + * Function returns the status of the last buffer set for transfer on selected endpoint. + * The status considers last buffer set by @ref nrf_drv_usbd_ep_transfer function or + * by transfer callback function. + * + * @param[in] ep Endpoint number. + * @param[out] p_size Information about the current/last transfer size. + * + * @retval NRF_SUCCESS Transfer already finished + * @retval NRF_ERROR_BUSY Ongoing transfer + * @retval NRF_ERROR_DATA_SIZE Too much of data received that cannot fit into buffer and cannot be splited into chunks. + * This may happen if buffer size is not a multiplication of endpoint buffer size. + */ +ret_code_t nrf_drv_usbd_ep_status_get(nrf_drv_usbd_ep_t ep, size_t * p_size); + +/** + * @brief Get number of received bytes + * + * Get the number of received bytes. + * The function behavior is undefined when called on IN endpoint. + * + * @param ep Endpoint number. + * + * @return Number of received bytes + */ +size_t nrf_drv_usbd_epout_size_get(nrf_drv_usbd_ep_t ep); + +/** + * @brief Check if endpoint buffer is ready or is under USB IP control + * + * Function to test if endpoint is busy. + * Endpoint that is busy cannot be accessed by MCU. + * It means that: + * - OUT (TX) endpoint: Last uploaded data is still in endpoint and is waiting + * to be received by the host. + * - IN (RX) endpoint: Endpoint is ready to receive data from the host + * and the endpoint does not have any data. + * When endpoint is not busy: + * - OUT (TX) endpoint: New data can be uploaded. + * - IN (RX) endpoint: New data can be downloaded using @ref nrf_drv_usbd_ep_transfer + * function. + */ +bool nrf_drv_usbd_ep_is_busy(nrf_drv_usbd_ep_t ep); + +/** + * @brief Stall endpoint + * + * Stall endpoit to send error information during next transfer request from + * the host. + * + * @note To stall endpoint it is safer to use @ref nrf_drv_usbd_setup_stall + * @note Stalled endpoint would not be cleared when DMA transfer finishes. + * + * @param ep Endpoint number to stall + * + */ +void nrf_drv_usbd_ep_stall(nrf_drv_usbd_ep_t ep); + +/** + * @brief Clear stall flag on endpoint + * + * This function clears endpoint that is stalled. + * @note + * If it is OUT endpoint (receiving) it would be also prepared for reception. + * It means that busy flag would be set. + * @note + * In endpoint (transmitting) would not be cleared - it gives possibility to + * write new data before transmitting. + */ +void nrf_drv_usbd_ep_stall_clear(nrf_drv_usbd_ep_t ep); + +/** + * @brief Check if endpoint is stalled + * + * This function gets stall state of selected endpoint + * + * @param ep Endpoint number to check + */ +bool nrf_drv_usbd_ep_stall_check(nrf_drv_usbd_ep_t ep); + +/** + * @brief Clear current endpoint data toggle + * + * @param ep Endpoint number to clear + */ +void nrf_drv_usbd_ep_dtoggle_clear(nrf_drv_usbd_ep_t ep); + +/** + * @brief Get parsed setup data + * + * Function fills the parsed setup data structure. + * + * @param[out] p_setup Pointer to data structure that would be filled by + * parsed data. + */ +void nrf_drv_usbd_setup_get(nrf_drv_usbd_setup_t * const p_setup); + +/** + * @brief Clear only for data transmission on setup endpoint + * + * This function may be called if any more data in control write transfer is expected. + * Clears only OUT endpoint to be able to take another OUT data token. + * It does not allow STATUS stage. + * @sa nrf_drv_usbd_setup_clear + */ +void nrf_drv_usbd_setup_data_clear(void); + +/** + * @brief Clear setup endpoint + * + * This function acknowledges setup when SETUP command was received and processed. + * It has to be called if no data respond for the SETUP command is sent. + * + * When there is any data transmission after SETUP command the data transmission + * itself would clear the endpoint. + */ +void nrf_drv_usbd_setup_clear(void); + +/** + * @brief Stall setup endpoint + * + * Mark and error on setup endpoint. + */ +void nrf_drv_usbd_setup_stall(void); + +/** +* @note +* This function locks interrupts that may be costly. +* It is good idea to test if the endpoint is still busy before calling this function: +* @code + (m_ep_dma_waiting & (1U << ep2bit(ep))) +* @endcode +* This function would check it again, but it makes it inside critical section. +*/ +void nrf_drv_usbd_ep_abort(nrf_drv_usbd_ep_t ep); + +/** + * @brief Get the information about expected transfer SETUP data direction + * + * Function returns the information about last expected transfer direction. + * + * @retval NRF_DRV_USBD_EPOUT0 Expecting OUT (Host->Device) direction or no data + * @retval NRF_DRV_USBD_EPIN0 Expecting IN (Device->Host) direction + */ +nrf_drv_usbd_ep_t nrf_drv_usbd_last_setup_dir_get(void); + +/** + * @brief Drop transfer on OUT endpoint + * + * @param[in] ep OUT endpoint ID + */ +void nrf_drv_usbd_transfer_out_drop(nrf_drv_usbd_ep_t ep); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* NRF_DRV_USBD_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd_errata.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd_errata.h new file mode 100644 index 0000000000..00371e9672 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/usbd/nrf_drv_usbd_errata.h @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_DRV_USBD_ERRATA_H__ +#define NRF_DRV_USBD_ERRATA_H__ + +#include +/** + * @defgroup nrf_drv_usbd_errata Functions to check if selected PAN is present in current chip + * @{ + * @ingroup nrf_drv_usbd + * + * Functions here are checking the presence of an error in current chip. + * The checking is done at runtime based on the microcontroller version. + * This file is subject to removal when nRF51840 prototype support is removed. + */ + +#ifndef NRF_DRV_USBD_ERRATA_ENABLE +/** + * @brief The constant that informs if errata should be enabled at all + * + * If this constant is set to 0, all the Errata bug fixes will be automatically disabled. + */ +#define NRF_DRV_USBD_ERRATA_ENABLE 1 +#endif + +/** + * @brief Internal auxiliary function to check if the program is running on NRF52840 chip + * @retval true It is NRF52480 chip + * @retval false It is other chip + */ +static inline bool nrf_drv_usbd_errata_type_52840(void) +{ + return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x08) && + (((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x0)); +} + +/** + * @brief Internal auxiliary function to check if the program is running on first sample of + * NRF52840 chip + * @retval true It is NRF52480 chip and it is first sample version + * @retval false It is other chip + */ +static inline bool nrf_drv_usbd_errata_type_52840_proto1(void) +{ + return ( nrf_drv_usbd_errata_type_52840() && + ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x00 ) && + ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) ); +} + +/** + * @brief Function to check if chip requires errata 104 + * + * Errata: USBD: EPDATA event is not always generated. + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_104(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1(); +} + +/** + * @brief Function to check if chip requires errata 154 + * + * Errata: During setup read/write transfer USBD acknowledges setup stage without SETUP task. + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_154(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1(); +} + +/** + * @brief Function to check if chip requires errata 166 + * + * Errata: ISO double buffering not functional + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_166(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && true; +} + +/** + * @brief Function to check if chip requires errata ??? + * + * Errata: SIZE.EPOUT not writable + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_sizeepout_rw(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1(); +} + +/** @} */ +#endif /* NRF_DRV_USBD_ERRATA_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.c new file mode 100644 index 0000000000..7a2f92d90d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.c @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(WDT) +#include "nrf_drv_wdt.h" +#include "nrf_drv_common.h" +#include "nrf_error.h" +#include "nrf_assert.h" +#include "nrf_wdt.h" +#include "app_util_platform.h" +#include +#include + +#define NRF_LOG_MODULE_NAME wdt + +#if WDT_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL WDT_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR WDT_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR WDT_CONFIG_DEBUG_COLOR +#else //WDT_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //WDT_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/**@brief WDT event handler. */ +static nrf_wdt_event_handler_t m_wdt_event_handler; + +/**@brief WDT state. */ +static nrf_drv_state_t m_state; + +/**@brief WDT alloc table. */ +static uint32_t m_alloc_index; + +static const nrf_drv_wdt_config_t m_default_config = NRF_DRV_WDT_DEAFULT_CONFIG; + +/**@brief WDT interrupt handler. */ +void WDT_IRQHandler(void) +{ + if (nrf_wdt_int_enable_check(NRF_WDT_INT_TIMEOUT_MASK) == true) + { + nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT); + m_wdt_event_handler(); + } +} + + +ret_code_t nrf_drv_wdt_init(nrf_drv_wdt_config_t const * p_config, + nrf_wdt_event_handler_t wdt_event_handler) +{ + ASSERT(wdt_event_handler != NULL); + ret_code_t err_code; + m_wdt_event_handler = wdt_event_handler; + + if (m_state == NRF_DRV_STATE_UNINITIALIZED) + { + m_state = NRF_DRV_STATE_INITIALIZED; + } + else + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + + nrf_wdt_behaviour_set(p_config->behaviour); + + if ((((uint64_t) p_config->reload_value * 32768) / 1000) > UINT32_MAX) // Check for overflow + { + return NRF_ERROR_INVALID_PARAM; + } + nrf_wdt_reload_value_set(((uint64_t) p_config->reload_value * 32768) / 1000); + + nrf_drv_common_irq_enable(WDT_IRQn, p_config->interrupt_priority); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +void nrf_drv_wdt_enable(void) +{ + ASSERT(m_alloc_index != 0); + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK); + nrf_wdt_task_trigger(NRF_WDT_TASK_START); + m_state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled."); +} + + +void nrf_drv_wdt_feed(void) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + for (uint32_t i = 0; i < m_alloc_index; i++) + { + nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i)); + } +} + +ret_code_t nrf_drv_wdt_channel_alloc(nrf_drv_wdt_channel_id * p_channel_id) +{ + ret_code_t result; + ASSERT(p_channel_id); + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + + CRITICAL_REGION_ENTER(); + if (m_alloc_index < NRF_WDT_CHANNEL_NUMBER) + { + *p_channel_id = (nrf_drv_wdt_channel_id)(NRF_WDT_RR0 + m_alloc_index); + m_alloc_index++; + nrf_wdt_reload_request_enable(*p_channel_id); + result = NRF_SUCCESS; + } + else + { + result = NRF_ERROR_NO_MEM; + } + CRITICAL_REGION_EXIT(); + NRF_LOG_INFO("Function: %s, error code: %s.", (uint32_t)__func__, (uint32_t)NRF_LOG_ERROR_STRING_GET(result)); + return result; +} + +void nrf_drv_wdt_channel_feed(nrf_drv_wdt_channel_id channel_id) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_wdt_reload_request_set(channel_id); +} +#endif //NRF_MODULE_ENABLED(WDT) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.h new file mode 100644 index 0000000000..4fdd1d9cbb --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/drivers_nrf/wdt/nrf_drv_wdt.h @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @addtogroup nrf_wdt WDT HAL and driver + * @ingroup nrf_drivers + * @brief Watchdog timer (WDT) APIs. + * @details The WDT HAL provides basic APIs for accessing the registers of the watchdog timer. + * The WDT driver provides APIs on a higher level. + * @defgroup nrf_drv_wdt WDT driver + * @{ + * @ingroup nrf_wdt + * + * @brief Driver for managing the watchdog timer (WDT). + */ + +#ifndef NRF_DRV_WDT_H__ +#define NRF_DRV_WDT_H__ + +#include +#include +#include "sdk_errors.h" +#include "nrf_wdt.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Struct for WDT initialization. */ +typedef struct +{ + nrf_wdt_behaviour_t behaviour; /**< WDT behaviour when CPU in sleep/halt mode. */ + uint32_t reload_value; /**< WDT reload value in ms. */ + uint8_t interrupt_priority; /**< WDT interrupt priority */ +} nrf_drv_wdt_config_t; + +/**@brief WDT event handler function type. */ +typedef void (*nrf_wdt_event_handler_t)(void); + +/**@brief WDT channel id type. */ +typedef nrf_wdt_rr_register_t nrf_drv_wdt_channel_id; + +#define NRF_DRV_WDT_DEAFULT_CONFIG \ + { \ + .behaviour = (nrf_wdt_behaviour_t)WDT_CONFIG_BEHAVIOUR, \ + .reload_value = WDT_CONFIG_RELOAD_VALUE, \ + .interrupt_priority = WDT_CONFIG_IRQ_PRIORITY, \ + } +/** + * @brief This function initializes watchdog. + * + * @param[in] p_config Initial configuration. Default configuration used if NULL. + * @param[in] wdt_event_handler specifies event handler provided by user. + * + * @note Function asserts if wdt_event_handler is NULL. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +ret_code_t nrf_drv_wdt_init(nrf_drv_wdt_config_t const * p_config, + nrf_wdt_event_handler_t wdt_event_handler); + +/** + * @brief This function allocate watchdog channel. + * + * @note This function can not be called after nrf_drv_wdt_start(void). + * + * @param[out] p_channel_id ID of granted channel. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +ret_code_t nrf_drv_wdt_channel_alloc(nrf_drv_wdt_channel_id * p_channel_id); + +/** + * @brief This function starts watchdog. + * + * @note After calling this function the watchdog is started, so the user needs to feed all allocated + * watchdog channels to avoid reset. At least one watchdog channel has to be allocated. + */ +void nrf_drv_wdt_enable(void); + +/** + * @brief This function feeds the watchdog. + * + * @details Function feeds all allocated watchdog channels. + */ +void nrf_drv_wdt_feed(void); + +/** + * @brief This function feeds the invidual watchdog channel. + * + * @param[in] channel_id ID of watchdog channel. + */ +void nrf_drv_wdt_channel_feed(nrf_drv_wdt_channel_id channel_id); + +/**@brief Function for returning a requested task address for the wdt driver module. + * + * @param[in] task One of the peripheral tasks. + * + * @retval Task address. + */ +__STATIC_INLINE uint32_t nrf_drv_wdt_ppi_task_addr(nrf_wdt_task_t task) +{ + return nrf_wdt_task_address_get(task); +} + +/**@brief Function for returning a requested event address for the wdt driver module. + * + * @param[in] event One of the peripheral events. + * + * @retval Event address + */ +__STATIC_INLINE uint32_t nrf_drv_wdt_ppi_event_addr(nrf_wdt_event_t event) +{ + return nrf_wdt_event_address_get(event); +} + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/README.md new file mode 100644 index 0000000000..0c6f23f19b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/README.md @@ -0,0 +1,51 @@ +# Folder origin + +components/libraries + +# Modifications + +Only essential folders have been copied over. + +Removed: + * block_dev/ + * bootloader/ + * bsp/ + * button/ + * cli/ + * crc16/ + * crc32/ + * crypto/ + * csense/ + * csense_drv/ + * ecc/ + * eddystone/ + * experimental_mpu/ + * experimental_ringbuf/ + * experimental_stack_guard/ + * experimental_task_manager/ + * fifo/ + * gfx/ + * gpiote/ + * hardfault/ + * hci/ + * led_softblink/ + * low_power_pwm/ + * mem_manager/ + * mutex/ + * pwm/ + * pwr_mgmt/ + * scheduler/ + * sdcard/ + * sensorsim/ + * serial/ + * sha256/ + * simple_timer/ + * slip/ + * sortlist/ + * spi_mngr/ + * svc/ + * timer/ + * twi/ + * twi_mngr/ + * uart/ + * usbd/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic.h new file mode 100644 index 0000000000..32ae3462fe --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic.h @@ -0,0 +1,495 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_atomic Atomic operations API + * @ingroup nrf_atfifo + * @{ + * + * @brief @tagAPI52 This module implements C11 stdatomic.h simplified API. + At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions). + * Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t. + */ + +#ifndef NRF_ATOMIC_H__ +#define NRF_ATOMIC_H__ + +#include "sdk_common.h" + + +#ifndef NRF_ATOMIC_USE_BUILD_IN +#if (defined(__GNUC__) && defined(WIN32)) + #define NRF_ATOMIC_USE_BUILD_IN 1 +#else + #define NRF_ATOMIC_USE_BUILD_IN 0 +#endif +#endif // NRF_ATOMIC_USE_BUILD_IN + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) +#define STREX_LDREX_PRESENT +#else +#include "app_util_platform.h" +#endif + +/** + * @brief Atomic 32 bit unsigned type + * */ +typedef volatile uint32_t nrf_atomic_u32_t; + +/** + * @brief Atomic 1 bit flag type (technically 32 bit) + * */ +typedef volatile uint32_t nrf_atomic_flag_t; + +#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT) +#include "nrf_atomic_internal.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST); + +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data = value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Stores value to an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value to store + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + __atomic_store_n(p_data, value, __ATOMIC_SEQ_CST); + return value; +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value); + + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data = value; + CRITICAL_REGION_EXIT(); + return value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data |= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical OR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand OR operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data |= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data &= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical AND operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand AND operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(and, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data &= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data ^= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Logical XOR operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand XOR operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data ^= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data += value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic ADD operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand ADD operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(add, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data += value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return Old value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return old_val; +#else + CRITICAL_REGION_ENTER(); + uint32_t old_val = *p_data; + *p_data -= value; + CRITICAL_REGION_EXIT(); + return old_val; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/** + * @brief Arithmetic SUB operation on an atomic object + * + * @param[in] p_data Atomic memory pointer + * @param[in] value Value of second operand SUB operation + * + * @return New value stored into atomic object + * */ +static inline uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value) +{ +#if NRF_ATOMIC_USE_BUILD_IN + return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST); +#elif defined(STREX_LDREX_PRESENT) + uint32_t old_val; + uint32_t new_val; + + NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value); + UNUSED_PARAMETER(old_val); + UNUSED_PARAMETER(new_val); + return new_val; +#else + CRITICAL_REGION_ENTER(); + *p_data -= value; + uint32_t new_value = *p_data; + CRITICAL_REGION_EXIT(); + return new_value; +#endif //NRF_ATOMIC_USE_BUILD_IN +} + +/**************************************************************************************************/ + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +static inline uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_or(p_data, 1); +} + +/** + * @brief Logic one bit flag set operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +static inline uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_or(p_data, 1); +} + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return Old flag value + * */ +static inline uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_fetch_and(p_data, 0); +} + +/** + * @brief Logic one bit flag clear operation on an atomic object + * + * @param[in] p_data Atomic flag memory pointer + * + * @return New flag value + * */ +static inline uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data) +{ + return nrf_atomic_u32_and(p_data, 0); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_H__ */ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_internal.h new file mode 100644 index 0000000000..ada00c6710 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_internal.h @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ATOMIC_INTERNAL_H__ +#define NRF_ATOMIC_INTERNAL_H__ + +#include "sdk_common.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @defgroup nrf_atomic_internal Atomic operations internals + * @ingroup nrf_atomic + * @{ + * + */ + +/* Only Cortex M cores > 3 support LDREX/STREX instructions*/ +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error "Unsupported core version" +#endif + +#if defined ( __CC_ARM ) +static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + /* The base standard provides for passing arguments in core registers (r0-r3) and on the stack. + * Registers r4 and r5 have to be saved on stack. Note that only even number of register push are + * allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. + * */ + push {r4, r5} + mov r4, r0 + +loop_mov + ldrex r0, [r4] + mov r5, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_mov + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_orr + ldrex r0, [r4] + orr r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_orr + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_and + ldrex r0, [r4] + and r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_and + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_eor + ldrex r0, [r4] + eor r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_eor + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_add + ldrex r0, [r4] + add r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_add + + str r5, [r2] + pop {r4, r5} + bx lr +} + +static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr, + uint32_t value, + uint32_t * p_new) +{ + push {r4, r5} + mov r4, r0 + +loop_sub + ldrex r0, [r4] + sub r5, r0, r1 + strex r3, r5, [r4] + cmp r3, #0 + bne loop_sub + + str r5, [r2] + pop {r4, r5} + bx lr +} + + +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ + old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val) + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +/** + * @brief Atomic operation generic macro + * @param[in] asm_op operation: mov, orr, and, eor, add, sub + * @param[out] old_val atomic object output (uint32_t), value before operation + * @param[out] new_val atomic object output (uint32_t), value after operation + * @param[in] value atomic operation operand + * */ +#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \ +{ \ + uint32_t str_res; \ + __ASM volatile( \ + "1: ldrex %["#old_val"], [%["#ptr"]]\n" \ + NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \ + " strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \ + " teq %[str_res], #0\n" \ + " bne.n 1b" \ + : \ + [old_val]"=&r" (old_val), \ + [new_val]"=&r" (new_val), \ + [str_res]"=&r" (str_res) \ + : \ + [ptr]"r" (ptr), \ + [value]"r" (value) \ + : "cc"); \ + UNUSED_PARAMETER(str_res); \ +} + +#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n" +#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n" + +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_INTERNAL_H__ */ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_sanity_check.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_sanity_check.h new file mode 100644 index 0000000000..f07006cf7c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic/nrf_atomic_sanity_check.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ATOMIC_SANITY_CHECK_H__ +#define NRF_ATOMIC_SANITY_CHECK_H__ + +#include "nrf_atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Quick sanity check of nrf_atomic API + * */ +static inline void nrf_atomic_sanity_check(void) +{ +#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + nrf_atomic_u32_t val; + nrf_atomic_u32_t flag; + + /*Fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store_fetch(&val, 10) == 0); + ASSERT(nrf_atomic_u32_store_fetch(&val, 0) == 10); + + val = 0; + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 16) == 0); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == (0xFFFFFFFF)); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 16)) == 0xFFFFFFFF); + ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 5)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and_fetch(&val, 0xFFFFFFFF) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16)) == 0); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 5)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16) | (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == (0)); + + val = 0; + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 0); + ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add_fetch(&val, 1 << 24) == 200); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0xFFFFFFFF) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 1000); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0xFFFFFFFF) == 800); + ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 0); + ASSERT(nrf_atomic_flag_set_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 1); + ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 0); + + /*No fetch version tests*/ + val = 0; + ASSERT(nrf_atomic_u32_store(&val, 10) == 10); + ASSERT(nrf_atomic_u32_store(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_or(&val, 1 << 16) == 1 << 16); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_or(&val, 0xFFFFFFFF) == 0xFFFFFFFF); + + val = 0xFFFFFFFF; + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 16)) == (0xFFFFFFFF & ~((1 << 16)))); + ASSERT(nrf_atomic_u32_and(&val, ~(1 << 5)) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5))))); + ASSERT(nrf_atomic_u32_and(&val, 0) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16)) == ((1 << 16))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 5)) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, 0) == ((1 << 16) | (1 << 5))); + ASSERT(nrf_atomic_u32_xor(&val, (1 << 16) | (1 << 5)) == 0); + + val = 0; + ASSERT(nrf_atomic_u32_add(&val, 100) == 100); + ASSERT(nrf_atomic_u32_add(&val, 100) == 200); + ASSERT(nrf_atomic_u32_add(&val, 1 << 24) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0) == (200 + (1 << 24))); + ASSERT(nrf_atomic_u32_add(&val, 0xFFFFFFFF) == (200 - 1 + (1 << 24))); + + val = 1000; + ASSERT(nrf_atomic_u32_sub(&val, 100) == 900); + ASSERT(nrf_atomic_u32_sub(&val, 100) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0) == 800); + ASSERT(nrf_atomic_u32_sub(&val, 0xFFFFFFFF) == 801); + + flag = 0; + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_set(&flag) == 1); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); + ASSERT(nrf_atomic_flag_clear(&flag) == 0); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATOMIC_SANITY_CHECK_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.c new file mode 100644 index 0000000000..179fbfc8de --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.c @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 +#include "app_util.h" +#include "nrf_atfifo.h" +#include "nrf_atfifo_internal.h" + + +/* Unions testing */ +STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t)); + + +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size) +{ + if (NULL == p_buf) + { + return NRF_ERROR_NULL; + } + if (0 != (buf_size % item_size)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + p_fifo->p_buf = p_buf; + p_fifo->tail.tag = 0; + p_fifo->head.tag = 0; + p_fifo->buf_size = buf_size; + p_fifo->item_size = item_size; + + return NRF_SUCCESS; +} + + +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo) +{ + bool released = nrf_atfifo_space_clear(p_fifo); + return released ? NRF_SUCCESS : NRF_ERROR_BUSY; +} + + +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible) +{ + nrf_atfifo_item_put_t context; + bool visible; + void * p_data = nrf_atfifo_item_alloc(p_fifo, &context); + if (NULL == p_data) + { + return NRF_ERROR_NO_MEM; + } + + memcpy(p_data, p_var, size); + + visible = nrf_atfifo_item_put(p_fifo, &context); + if (NULL != p_visible) + { + *p_visible = visible; + } + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail))) + { + return ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr; + } + return NULL; +} + + +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context) +{ + if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd)) + { + nrf_atfifo_wspace_close(p_fifo); + return true; + } + return false; +} + + +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released) +{ + nrf_atfifo_item_get_t context; + bool released; + void const * p_s = nrf_atfifo_item_get(p_fifo, &context); + if (NULL == p_s) + { + return NRF_ERROR_NOT_FOUND; + } + + memcpy(p_var, p_s, size); + + released = nrf_atfifo_item_free(p_fifo, &context); + if (NULL != p_released) + { + *p_released = released; + } + return NRF_SUCCESS; +} + + +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head))) + { + return ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd; + } + return NULL; +} + + +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context) +{ + if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd)) + { + nrf_atfifo_rspace_close(p_fifo); + return true; + } + return false; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.h new file mode 100644 index 0000000000..2472d458b5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo.h @@ -0,0 +1,407 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_ATFIFO_H__ +#define NRF_ATFIFO_H__ + +#include +#include "nordic_common.h" +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup nrf_atfifo Atomic FIFO + * @ingroup app_common + * + * @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without + * locking interrupts. + * + * @details There are two types of functions to prepare the FIFO writing: + * - Single function for simple access: + * @code + * if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL)) + * { + * // Error handling + * } + * @endcode + * - Function pair to limit data copying: + * @code + * struct point3d + * { + * int x, y, z; + * }point3d_t; + * nrf_atfifo_context_t context; + * point3d_t * point; + * + * if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context))) + * { + * point->x = a; + * point->y = b; + * point->z = c; + * if (nrf_atfifo_item_put(my_fifo, &context)) + * { + * // Send information to the rest of the system + * // that there is new data in the FIFO available for reading. + * } + * } + * else + * { + * // Error handling + * } + * + * @endcode + * @note + * This atomic FIFO implementation requires that the operation that is + * opened last is finished (committed/flushed) first. + * This is typical for operations performed from the interrupt runtime + * when the other operation is performed from the main thread. + * + * This implementation does not support typical multithreading operating system + * access where operations can be started and finished in totally unrelated order. + * + * @{ + */ + +/** + * @brief Read and write position structure. + * + * A structure that holds the read and write position used by the FIFO head and tail. + */ +typedef struct nrf_atfifo_postag_pos_s +{ + uint16_t wr; //!< First free space to write the data + uint16_t rd; //!< A place after the last data to read +}nrf_atfifo_postag_pos_t; + +/** + * @brief End data index tag. + * + * A tag used to mark the end of data. + * To properly realize atomic data committing, the whole variable has to be + * accessed atomically. + */ +typedef union nrf_atfifo_postag_u +{ + uint32_t tag; //!< Whole tag, used for atomic, 32-bit access + nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately +}nrf_atfifo_postag_t; + +/** + * @brief The FIFO instance. + * + * The instance of atomic FIFO. + * Used with all FIFO functions. + */ +typedef struct nrf_atfifo_s +{ + void * p_buf; //!< Pointer to the data buffer + nrf_atfifo_postag_t tail; //!< Read and write tail position tag + nrf_atfifo_postag_t head; //!< Read and write head position tag + uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size) + uint16_t item_size; //!< Size of a single FIFO item +}nrf_atfifo_t; + +/** + * @brief FIFO write operation item context. + * + * Context structure used to mark an allocated space in FIFO that is ready for put. + * All the data required to properly put allocated and written data. + */ +typedef struct nrf_atfifo_item_put_s +{ + nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write +}nrf_atfifo_item_put_t; + + +/** + * @brief FIFO read operation item context. + * + * Context structure used to mark an opened get operation to properly free an item after reading. + */ +typedef struct nrf_atfifo_rcontext_s +{ + nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read +}nrf_atfifo_item_get_t; + + +/** + * @defgroup nrf_atfifo_instmacros FIFO instance macros + * + * A group of macros helpful for FIFO instance creation and initialization. + * They may be used to create and initialize instances for most use cases. + * + * FIFO may also be created and initialized directly using + * @ref nrf_atfifo_init function. + * @{ + */ + /** + * @brief Macro for generating the name for a data buffer. + * + * The name of the data buffer that would be created by + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the buffer variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data) + + /** + * @brief Macro for generating the name for a FIFO instance. + * + * The name of the instance variable that will be created by the + * @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Name of the instance variable. + * + * @note This is auxiliary internal macro and in normal usage + * it should not be called. + */ + #define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst) + + /** + * @brief Macro for creating an instance. + * + * Creates the FIFO object variable itself. + * + * Usage example: + * @code + * NRF_ATFIFO_DEF(my_fifo, uint16_t, 12); + * NRF_ATFIFO_INIT(my_fifo); + * + * uint16_t some_val = 45; + * nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL); + * nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL); + * @endcode + * + * @param[in] fifo_id Identifier of a FIFO object. + * This identifier will be a pointer to the instance. + * It makes it possible to use this directly for the functions + * that operate on the FIFO. + * Because it is a static const object, it should be optimized by the compiler. + * @param[in] storage_type Type of data that will be stored in the FIFO. + * @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored. + * The phisical size of the buffer will be 1 element bigger. + */ + #define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \ + static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \ + static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id); \ + static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id) + + /** + * @brief Macro for initializing the FIFO that was previously declared by the macro. + * + * Use this macro to simplify FIFO initialization. + * + * @note + * This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro. + * + * @param[in] fifo_id Identifier of the FIFO object. + * + * @return Value from the @ref nrf_atfifo_init function. + */ + #define NRF_ATFIFO_INIT(fifo_id) \ + nrf_atfifo_init( \ + fifo_id, \ + NRF_ATFIFO_BUF_NAME(fifo_id), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \ + sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \ + ) + +/** @} */ + +/** + * @brief Function for initializing the FIFO. + * + * Preparing the FIFO instance to work. + * + * @param[out] p_fifo FIFO object to initialize. + * @param[in,out] p_buf FIFO buffer for storing data. + * @param[in] buf_size Total buffer size (has to be divisible by @c item_size). + * @param[in] item_size Size of a single item held inside the FIFO. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer. + * @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size. + * + * @note + * Buffer size must be able to hold one element more than the designed FIFO capacity. + * This one, empty element is used for overflow checking. + */ +ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size); + +/** + * @brief Function for clearing the FIFO. + * + * Function for clearing the FIFO. + * + * If this function is called during an opened and uncommitted write operation, + * the FIFO is cleared up to the currently ongoing commit. + * There is no possibility to cancel an ongoing commit. + * + * If this function is called during an opened and unflushed read operation, + * the read position in the head is set, but copying it into the write head position + * is left to read closing operation. + * + * This way, there is no more data to read, but the memory is released + * in the moment when it is safe. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval NRF_SUCCESS FIFO totally cleared. + * @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation. + * If it is called in the middle of writing operation, + * FIFO was cleared up to the already started and uncommitted write. + * If it is called in the middle of reading operation, + * write head was only moved. It will be copied into read tail when the reading operation + * is flushed. + */ +ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo); + +/** + * @brief Function for atomically putting data into the FIFO. + * + * It uses memcpy function inside and in most situations, it is more suitable to + * use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value + * in a FIFO. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_var Variable to copy. + * @param[in] size Size of the variable to copy. + * Can be smaller or equal to the FIFO item size. + * @param[out] p_visible See value returned by @ref nrf_atfifo_item_put. + * It may be NULL if the caller does not require the current operation status. + * + * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. + * @retval NRF_ERROR_NO_MEM If the FIFO is full. + * + * @note + * To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put + * functions pair. + */ +ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible); + +/** + * @brief Function for opening the FIFO for writing. + * + * Function called to start the FIFO write operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put. + * + * @return Pointer to the space where variable data can be stored. + * NULL if there is no space in the buffer. + */ +void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for closing the writing operation. + * + * Puts a previously allocated context into FIFO. + * This function must be called to commit an opened write operation. + * It sets all the buffers and marks the data, so that it is visible to read. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function. + * + * @retval true Data is currently ready and will be visible to read. + * @retval false The internal commit was marked, but the writing operation interrupted another writing operation. + * The data will be available to read when the interrupted operation is committed. + */ +bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context); + +/** + * @brief Function for getting a single value from the FIFO. + * + * This function gets the value from the top of the FIFO. + * The value is removed from the FIFO memory. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_var Pointer to the variable to store the data. + * @param[in] size Size of the data to be loaded. + * @param[out] p_released See the values returned by @ref nrf_atfifo_item_free. + * + * @retval NRF_SUCCESS Element was successfully copied from the FIFO memory. + * @retval NRF_ERROR_NOT_FOUND No data in the FIFO. + */ +ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released); + +/** + * @brief Function for opening the FIFO for reading. + * + * Function called to start the FIFO read operation and access the given FIFO buffer directly. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free + * + * @return Pointer to data buffer or NULL if there is no data in the FIFO. + */ +void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + +/** + * @brief Function for closing the reading operation. + * + * Function used to finish the reading operation. + * If this reading operation does not interrupt another reading operation, the head write buffer is moved. + * If this reading operation is placed in the middle of another reading, only the new read pointer is written. + * + * @param[in,out] p_fifo FIFO object. + * @param[in] p_context Context of the reading operation to be closed. + * + * @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released). + * @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released). + */ +bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ATFIFO_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo_internal.h new file mode 100644 index 0000000000..477b91ff2f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/atomic_fifo/nrf_atfifo_internal.h @@ -0,0 +1,577 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Atomic FIFO internal file + * + * This file should be included only by nrf_atfifo internally. + * Needs nrf_atfifo.h included first. + */ +#ifndef NRF_ATFIFO_H__ +#error This is internal file. Do not include this file in your program. +#endif + +#ifndef NRF_ATFIFO_INTERNAL_H__ +#define NRF_ATFIFO_INTERNAL_H__ +#include +#include "nrf.h" +#include "app_util.h" +#include "nordic_common.h" + +#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0 +#error Unsupported core version +#endif + +/* + * Make sure that rd and wr pos in a tag are aligned like expected + * Changing this would require changes inside assembly code! + */ +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0); +STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2); + +/** + * @brief Atomically reserve space for a new write. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_tail Tail position tag before new space is reserved. + * + * @retval true Space available. + * @retval false Memory full. + * + * @sa nrf_atfifo_wspace_close + */ +static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail); + +/** + * @brief Atomically mark all written data available. + * + * This function marks all data available for reading. + * This marking is done by copying tail.pos.wr into tail.pos.rd. + * + * It must be called only when closing the first write. + * It cannot be called if any write access was interrupted. + * See the code below: + * @code + * if (old_tail.pos.wr == old_tail.pos.rd) + * { + * nrf_atfifo_wspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_wspace_req + */ +static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Atomically get a part of a buffer to read data. + * + * @param[in,out] p_fifo FIFO object. + * @param[out] old_head Head position tag before the data buffer is read. + * + * @retval true Data available for reading. + * @retval false No data in the buffer. + * + * @sa nrf_atfifo_rspace_close + */ +static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head); + +/** + * @brief Atomically release all read data. + * + * This function marks all data that was read as free space, + * which is available for writing. + * This marking is done by copying head.pos.rd into head.pos.wr. + * + * It must be called only when closing the first read. + * It cannot be called when the current read access interrupted any other read access. + * See code below: + * @code + * if (old_head.pos.wr == old_head.pos.rd) + * { + * nrf_atfifo_rspace_close(my_fifo); + * return true; + * } + * return false; + * @endcode + * + * @param[in,out] p_fifo FIFO object. + * + * @sa nrf_atfifo_rspace_req + */ +static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo); + +/** + * @brief Safely clear the FIFO, internal function. + * + * This function realizes the functionality required by @ref nrf_atfifo_clear. + * + * @param[in,out] p_fifo FIFO object. + * + * @retval true All the data was released. + * @retval false All the data available for releasing was released, but there is some pending transfer. + */ +static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo); + + +/* --------------------------------------------------------------------------- + * Implementation starts here + */ + +#if defined ( __CC_ARM ) + + +__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_tail + * R2 - internal variable old_tail (saved by caller) + * R3 - internal variable new_tail (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_wspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Extract write position !!! R3 !!! */ + uxth r3, r2 + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_wspace_req_exit + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */ + pkhbt r3, r3, r2 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r4, #0 + bne nrf_atfifo_wspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_wspace_req_exit + /* Save old tail */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_wspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + /* Copy from lower byte to higher */ + pkhbt r2, r2, r2, lsl #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r1, #0 + bne nrf_atfifo_wspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - p_old_head + * R2 - internal variable old_head (saved by caller) + * R3 - internal variable new_head (saved by caller) + * R4 - internal temporary register (saved by this function) + * R5 - not used stored to keep the stack aligned to 8 bytes + * Returned value: + * R0 (bool - 32 bits) + */ + push {r4, r5} +nrf_atfifo_rspace_req_repeat + /* Load tail tag and set memory monitor !!! R2 - old tail !!! */ + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Extract read position !!! R3 !!! */ + uxth r3, r2, ror #16 + + /* Check if we have any data !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r3, r4 + ittt eq + clrexeq + moveq r0, #__cpp(false) + beq nrf_atfifo_rspace_req_exit + + /* Increment address with overload support !!! R4 used temporary !!! */ + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))] + add r3, r4 + ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))] + cmp r3, r4 + it hs + subhs r3, r3, r4 + + /* Pack everything back !!! R3 - new tail !!! */ + /* Copy lower byte from old_head, and higher byte is a value from write_pos */ + pkhbt r3, r2, r3, lsl #16 + + /* Store new value clearing memory monitor !!! R4 used temporary !!! */ + strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r4, #0 + bne nrf_atfifo_rspace_req_repeat + + /* Return true */ + mov r0, #__cpp(true) +nrf_atfifo_rspace_req_exit + /* Save old head */ + str r2, [r1] + pop {r4, r5} + bx lr +} + + +__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo + * R1 - internal temporary register + * R2 - new_tail + */ +nrf_atfifo_rspace_close_repeat + ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + /* Copy from higher byte to lower */ + pkhtb r2, r2, r2, asr #16 + + strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r1, #0 + bne nrf_atfifo_rspace_close_repeat + bx lr +} + + +__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + /* Registry usage: + * R0 - p_fifo as input, bool output after + * R1 - tail, rd pointer, new_head + * R2 - head_old, destroyed when creating new_head + * R3 - p_fifo - copy + */ + mov r3, r0 +nrf_atfifo_space_clear_repeat + /* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */ + ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))] + cmp r2, r2, ror #16 + /* Return false as default */ + mov r0, #__cpp(false) + /* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */ + itett ne + uxthne r2, r2 + orreq r1, r1, r1, lsl #16 + orrne r1, r2, r1, lsl #16 + + /* Skip header test */ + bne nrf_atfifo_space_clear_head_test_skip + + /* Load whole tail and test it !!! R2 used !!! */ + ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))] + cmp r2, r2, ror #16 + /* Return true if equal */ + it eq + moveq r0, #__cpp(true) + +nrf_atfifo_space_clear_head_test_skip + /* Store and test if success !!! R2 used temporary !!! */ + strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))] + cmp r2, #0 + bne nrf_atfifo_space_clear_repeat + bx lr +} + +#elif defined ( __ICCARM__ ) || defined ( __GNUC__ ) + +bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail) +{ + volatile bool ret; + volatile uint32_t old_tail; + uint32_t new_tail; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n" + " uxth %[new_tail], %[old_tail] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_tail], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_tail], %[temp] \n" + " it hs \n" + " subhs %[new_tail], %[new_tail], %[temp] \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n" + " cmp %[new_tail], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " pkhbt %[new_tail], %[new_tail], %[old_tail] \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_tail]"=&r"(old_tail), + [new_tail]"=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_tail->tag = old_tail; + UNUSED_VARIABLE(new_tail); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_tail; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n" + " \n" + " strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_tail] "=&r"(new_tail) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_tail); +} + + +bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head) +{ + volatile bool ret; + volatile uint32_t old_head; + uint32_t new_head; + uint32_t temp; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " uxth %[new_head], %[old_head], ror #16 \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[new_head], %[temp] \n" + " ittt eq \n" + " clrexeq \n" + " moveq %[ret], %[false_val] \n" + " beq.n 2f \n" + " \n" + " ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n" + " add %[new_head], %[temp] \n" + " ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n" + " cmp %[new_head], %[temp] \n" + " it hs \n" + " subhs %[new_head], %[new_head], %[temp] \n" + " \n" + " pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + " \n" + " mov %[ret], %[true_val] \n" + "2: \n" + : /* Output operands */ + [ret] "=r"(ret), + [temp] "=&r"(temp), + [old_head]"=&r"(old_head), + [new_head]"=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)), + [offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + p_old_head->tag = old_head; + UNUSED_VARIABLE(new_head); + UNUSED_VARIABLE(temp); + return ret; +} + + +void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo) +{ + uint32_t temp; + uint32_t new_head; + + __ASM volatile( + /* For more comments see Keil version above */ + "1: \n" + " ldrex %[new_head], [%[p_fifo], %[offset_head]] \n" + " pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n" + " \n" + " strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[temp], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [temp] "=&r"(temp), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(temp); + UNUSED_VARIABLE(new_head); +} + + +bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo) +{ + volatile bool ret; + uint32_t old_head; /* This variable is left broken after assembly code finishes */ + uint32_t new_head; + + __ASM volatile( + "1: \n" + " ldrex %[old_head], [%[p_fifo], %[offset_head]] \n" + " ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " \n" + " mov %[ret], %[false_val] \n" + " \n" + " itett ne \n" + " uxthne %[old_head], %[old_head] \n" + " orreq %[new_head], %[new_head], %[new_head], lsl #16 \n" + " orrne %[new_head], %[old_head], %[new_head], lsl #16 \n" + " \n" + " bne.n 2f \n" + " \n" + " ldr %[old_head], [%[p_fifo], %[offset_tail]] \n" + " cmp %[old_head], %[old_head], ror #16 \n" + " it eq \n" + " moveq %[ret], %[true_val] \n" + " \n" + "2: \n" + " strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n" + " cmp %[old_head], #0 \n" + " bne.n 1b \n" + : /* Output operands */ + [ret] "=&r"(ret), + [old_head] "=&r"(old_head), + [new_head] "=&r"(new_head) + : /* Input operands */ + [p_fifo] "r"(p_fifo), + [offset_head] "J"(offsetof(nrf_atfifo_t, head)), + [offset_tail] "J"(offsetof(nrf_atfifo_t, tail)), + [offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)), + [true_val] "I"(true), + [false_val] "I"(false) + : /* Clobbers */ + "cc"); + + UNUSED_VARIABLE(old_head); + UNUSED_VARIABLE(new_head); + return ret; +} + +#else +#error Unsupported compiler +#endif + +#endif /* NRF_ATFIFO_INTERNAL_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.c new file mode 100644 index 0000000000..b2eb43d091 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.c @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_BALLOC) + +#include "nrf_balloc.h" +#include "app_util_platform.h" + +#define NRF_LOG_MODULE_NAME balloc +#if NRF_BALLOC_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL NRF_BALLOC_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR NRF_BALLOC_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_BALLOC_CONFIG_DEBUG_COLOR +#else + #define NRF_LOG_LEVEL 0 +#endif // NRF_BALLOC_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define HEAD_GUARD_FILL 0xBAADF00D /**< Magic number used to mark head guard.*/ +#define TAIL_GUARD_FILL 0xBAADCAFE /**< Magic number used to mark tail guard.*/ +#define FREE_MEM_FILL 0xBAADBAAD /**< Magic number used to mark free memory.*/ + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define POOL_ID(_p_pool) _p_pool->p_name +#define POOL_MARKER "%s" +#else +#define POOL_ID(_p_pool) _p_pool +#define POOL_MARKER "0x%08X" +#endif + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Validate block memory, prepare block guards, and calculate pointer to the element. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_head Pointer to the beginning of the block. + * + * @return Pointer to the element. + */ +__STATIC_INLINE void * nrf_balloc_block_unwrap(nrf_balloc_t const * p_pool, void * p_head) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_head != NULL) && (((uint32_t)(p_head) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + uint32_t * p_element = (uint32_t *)p_head + head_words; + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + if (*ptr != FREE_MEM_FILL) + { + NRF_LOG_ERROR("Detected free memory corruption at 0x%08X (0x%08X != 0x%08X, pool: '" POOL_MARKER "')", + ptr, *ptr, FREE_MEM_FILL, POOL_ID(p_pool)); + APP_ERROR_CHECK_BOOL(false); + } + } + } + + for (uint32_t * ptr = p_head; ptr < p_element; ptr++) + { + *ptr = HEAD_GUARD_FILL; + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + *ptr = TAIL_GUARD_FILL; + } + + return p_element; +} + +/**@brief Calculate pointer to the block, validate block guards, and mark block memory as free. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Pointer to the element. + * + * @return Pointer to the beginning of the block. + */ +__STATIC_INLINE void * nrf_balloc_element_wrap(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0)); + ASSERT((p_element != NULL) && (((uint32_t)(p_element) % sizeof(uint32_t)) == 0)); + + uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags); + uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags); + + uint32_t * p_head = (uint32_t *)p_element - head_words; + uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size); + + for (uint32_t * ptr = p_head; ptr < (uint32_t *)p_element; ptr++) + { + if (*ptr != HEAD_GUARD_FILL) + { + NRF_LOG_ERROR("Detected Head Guard corruption at 0x%08X (0x%08X != 0x%08X, pool: '" POOL_MARKER "')", + ptr, *ptr, HEAD_GUARD_FILL, POOL_ID(p_pool)); + APP_ERROR_CHECK_BOOL(false); + } + } + + for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++) + { + if (*ptr != TAIL_GUARD_FILL) + { + NRF_LOG_ERROR("Detected Tail Guard corruption at 0x%08X (0x%08X != 0x%08X, pool: '" POOL_MARKER "')", + ptr, *ptr, TAIL_GUARD_FILL, POOL_ID(p_pool)); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_head; ptr < p_tail; ptr++) + { + *ptr = FREE_MEM_FILL; + } + } + + return p_head; +} + +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Convert block index to a pointer. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] idx Index of the block. + * + * @return Pointer to the beginning of the block. + */ +static void * nrf_balloc_idx2block(nrf_balloc_t const * p_pool, uint8_t idx) +{ + ASSERT(p_pool != NULL); + return (uint8_t *)(p_pool->p_memory_begin) + ((size_t)(idx) * p_pool->block_size); +} + +/**@brief Convert block pointer to index. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_block Pointer to the beginning of the block. + * + * @return Index of the block. + */ +static uint8_t nrf_balloc_block2idx(nrf_balloc_t const * p_pool, void const * p_block) +{ + ASSERT(p_pool != NULL); + return ((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) / p_pool->block_size; +} + +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool) +{ + uint8_t pool_size; + + VERIFY_PARAM_NOT_NULL(p_pool); + + ASSERT(p_pool->p_cb); + ASSERT(p_pool->p_stack_base); + ASSERT(p_pool->p_stack_limit); + ASSERT(p_pool->p_memory_begin); + ASSERT(p_pool->block_size); + + pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags)) + { + for (uint32_t * ptr = p_pool->p_memory_begin; ptr < (uint32_t *)(p_memory_end); ptr++) + { + *ptr = FREE_MEM_FILL; + } + } +#endif + + NRF_LOG_INFO("Pool '" POOL_MARKER "' initialized (size: %u x %u = %u bytes)", + POOL_ID(p_pool), + pool_size, + p_pool->block_size, + pool_size * p_pool->block_size); + + p_pool->p_cb->p_stack_pointer = p_pool->p_stack_base; + while (pool_size--) + { + *(p_pool->p_cb->p_stack_pointer)++ = pool_size; + } + + p_pool->p_cb->max_utilization = 0; + + return NRF_SUCCESS; +} + +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + + void * p_block = NULL; + + CRITICAL_REGION_ENTER(); + + if (p_pool->p_cb->p_stack_pointer > p_pool->p_stack_base) + { + // Allocate block. + p_block = nrf_balloc_idx2block(p_pool, *--(p_pool->p_cb->p_stack_pointer)); + + // Update utilization statistics. + uint8_t utilization = p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer; + if (p_pool->p_cb->max_utilization < utilization) + { + p_pool->p_cb->max_utilization = utilization; + } + } + + CRITICAL_REGION_EXIT(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + if (p_block != NULL) + { + p_block = nrf_balloc_block_unwrap(p_pool, p_block); + } +#endif + + NRF_LOG_DEBUG("nrf_balloc_alloc(pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_block); + + return p_block; +} + +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element) +{ + ASSERT(p_pool != NULL); + ASSERT(p_element != NULL) + + NRF_LOG_DEBUG("nrf_balloc_free(pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_element); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + void * p_block = nrf_balloc_element_wrap(p_pool, p_element); + + // These checks could be done outside critical region as they use only pool configuration data. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + uint8_t pool_size = p_pool->p_stack_limit - p_pool->p_stack_base; + void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size); + + // Check if the element belongs to this pool. + if ((p_block < p_pool->p_memory_begin) || (p_block >= p_memory_end)) + { + NRF_LOG_ERROR("Attempted to free element that does belong to the pool (pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_element); + APP_ERROR_CHECK_BOOL(false); + } + + // Check if the pointer is valid. + if ((((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) % p_pool->block_size) != 0) + { + NRF_LOG_ERROR("Atempted to free corrupted element address (pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_element); + APP_ERROR_CHECK_BOOL(false); + } + } +#else + void * p_block = p_element; +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + CRITICAL_REGION_ENTER(); + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + // These checks have to be done in critical region as they use p_pool->p_stack_pointer. + if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags)) + { + // Check for allocated/free ballance. + if (p_pool->p_cb->p_stack_pointer >= p_pool->p_stack_limit) + { + NRF_LOG_ERROR("Attempted to free an element while the pool is full (pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + + if (NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(p_pool->debug_flags)) + { + // Check for double free. + for (uint8_t * p_idx = p_pool->p_stack_base; p_idx < p_pool->p_cb->p_stack_pointer; p_idx++) + { + if (nrf_balloc_idx2block(p_pool, *p_idx) == p_block) + { + NRF_LOG_ERROR("Attempted to double-free an element (pool: '" POOL_MARKER "', element: 0x%08X)", + POOL_ID(p_pool), p_element); + APP_ERROR_CHECK_BOOL(false); + } + } + } +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + // Free the element. + *(p_pool->p_cb->p_stack_pointer)++ = nrf_balloc_block2idx(p_pool, p_block); + + CRITICAL_REGION_EXIT(); +} + +#endif // NRF_MODULE_ENABLED(NRF_BALLOC) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.h new file mode 100644 index 0000000000..20c2c35e3b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/balloc/nrf_balloc.h @@ -0,0 +1,309 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_balloc Block memory allocator + * @{ + * @ingroup app_common + * @brief This module handles block memory allocator features. + */ + + +#ifndef NRF_BALLOC_H__ +#define NRF_BALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdk_errors.h" +#include "sdk_config.h" +#include "app_util_platform.h" +#include "app_util.h" +/**@defgroup NRF_BALLOC_DEBUG Macros for preparing debug flags for block allocator module. + * @{ */ +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(words) (((words) & 0xFF) << 0) +#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(flags) (((flags) >> 0) & 0xFF) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(words) (((words) & 0xFF) << 8) +#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(flags) (((flags) >> 8) & 0xFF) + +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(enable) (!!(enable) << 16) +#define NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(flags) (flags & (1 << 16)) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(enable) (!!(enable) << 17) +#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(flags) (flags & (1 << 17)) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(enable) (!!(enable) << 18) +#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(flags) (flags & (1 << 18)) +/**@} */ + +/**@brief Default debug flags for @ref nrf_balloc. This is used by the @ref NRF_BALLOC_DEF macro. + * Flags can be changed in @ref sdk_config. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS \ + ( \ + NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS) | \ + NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED) | \ + NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED) | \ + NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED) \ + ) +#else + #define NRF_BALLOC_DEFAULT_DEBUG_FLAGS 0 +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +/**@brief Block memory allocator control block.*/ +typedef struct +{ + uint8_t * p_stack_pointer; //!< Current allocation stack pointer. + uint8_t max_utilization; //!< Maximum utilization of the memory pool. +} nrf_balloc_cb_t; + +/**@brief Block memory allocator pool instance. The pool is made of elements of the same size. */ +typedef struct +{ + nrf_balloc_cb_t * p_cb; //!< Pointer to the instance control block. + uint8_t * p_stack_base; //!< Base of the allocation stack. + /**< + * Stack is used to store handlers to not allocated elements. + */ + uint8_t * p_stack_limit; //!< Maximum possible value of the allocation stack pointer. + void * p_memory_begin; //!< Pointer to the start of the memory pool. + /**< + * Memory is used as a heap for blocks. + */ + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + const char * p_name; //!< Pointer to string with pool name. + uint32_t debug_flags; //!< Debugging settings. + /**< + * Debug flag should be created by @ref NRF_BALLOC_DEBUG. + */ +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + uint16_t block_size; //!< Size of the allocated block (including debug overhead). + /**< + * Single block contains user element with header and tail + * words. + */ +} nrf_balloc_t; + +/**@brief Get total memory consumed by single block (element size with overhead caused by debug + * flags). + * + * @param[in] _element_size Size of an element. + * @param[in] _debug_flags Debug flags. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ( \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(_debug_flags)) + \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(_debug_flags)) \ + ) +#else + #define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \ + ALIGN_NUM(sizeof(uint32_t), (_element_size)) +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + + +/**@brief Get element size ( excluding debugging overhead is present) + * flags). + * + * @param[in] _p_balloc Pointer to balloc instance. + */ +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (ALIGN_NUM(sizeof(uint32_t), (_p_balloc)->block_size) - \ + ((sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET((_p_balloc)->debug_flags)) + \ + (sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET((_p_balloc)->debug_flags)))) +#else +#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \ + (_p_balloc)->block_size +#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED + +#if NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) .p_name = STRINGIFY(_name), +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) .debug_flags = (_debug_flags), +#else +#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) +#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) +#endif + + +/**@brief Create a block allocator instance with custom debug flags. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + * @param[in] _debug_flags Debug flags (@ref NRF_BALLOC_DEBUG). + */ +#define NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, _debug_flags) \ + STATIC_ASSERT((_pool_size) <= UINT8_MAX); \ + static uint8_t CONCAT_2(_name, _nrf_balloc_pool_stack)[(_pool_size)]; \ + static uint32_t CONCAT_2(_name,_nrf_balloc_pool_mem) \ + [NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) * (_pool_size) / sizeof(uint32_t)]; \ + static nrf_balloc_cb_t CONCAT_2(_name,_nrf_balloc_cb); \ + static const nrf_balloc_t _name = \ + { \ + .p_cb = &CONCAT_2(_name,_nrf_balloc_cb), \ + .p_stack_base = CONCAT_2(_name,_nrf_balloc_pool_stack), \ + .p_stack_limit = CONCAT_2(_name,_nrf_balloc_pool_stack) + (_pool_size), \ + .p_memory_begin = CONCAT_2(_name,_nrf_balloc_pool_mem), \ + .block_size = NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags), \ + \ + __NRF_BALLOC_ASSIGN_POOL_NAME(_name) \ + __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) \ + } + +/**@brief Create a block allocator instance. + * + * @note This macro reserves memory for the given block allocator instance. + * + * @param[in] _name Name of the allocator. + * @param[in] _element_size Size of one element. + * @param[in] _pool_size Size of the pool. + */ +#define NRF_BALLOC_DEF(_name, _element_size, _pool_size) \ + NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, NRF_BALLOC_DEFAULT_DEBUG_FLAGS) + +/**@brief Create a block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + */ +#define NRF_BALLOC_INTERFACE_DEC(_type, _name) \ + _type * CONCAT_2(_name,_alloc)(void); \ + void CONCAT_2(_name,_free)(_type * p_element) + +/**@brief Define a custom block allocator interface. + * + * @param[in] _attr Function attribute that will be added to allocator function definition. + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_CUSTOM_DEF(_attr, _type, _name, _p_pool) \ + _attr _type * CONCAT_2(_name,_alloc)(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return (_type *)(nrf_balloc_alloc(_p_pool)); \ + } \ + \ + _attr void CONCAT_2(_name,_free)(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_pool) != NULL); \ + ASSERT((_p_pool)->block_size >= \ + NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + nrf_balloc_free((_p_pool), p_element); \ + } + +/**@brief Define block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(/* empty */, _type, _name, _p_pool) + +/**@brief Define a local block allocator interface. + * + * @param[in] _type Type which is allocated. + * @param[in] _name Name of the allocator. + * @param[in] _p_pool Pool from which data will be allocated. + */ +#define NRF_BALLOC_INTERFACE_LOCAL_DEF(_type, _name, _p_pool) \ + NRF_BALLOC_INTERFACE_CUSTOM_DEF(static, _type, _name, _p_pool) + +/**@brief Function for initializing a block memory allocator pool. + * + * @param[out] p_pool Pointer to the pool that is to be initialized. + * + * @return NRF_SUCCESS on success, otherwise error code. + */ +ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool); + +/**@brief Function for allocating an element from the pool. + * + * @note This module guarantees that the returned memory is aligned to 4. + * + * @param[in] p_pool Pointer to the memory pool from which the element will be allocated. + * + * @return Allocated element or NULL if the specified pool is empty. + */ +void * nrf_balloc_alloc(nrf_balloc_t const * p_pool); + +/**@brief Function for freeing an element back to the pool. + * + * @param[in] p_pool Pointer to the memory pool. + * @param[in] p_element Element to be freed. + */ +void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element); + +/**@brief Function for getting maximum memory pool utilization. + * + * @param[in] p_pool Pointer to the memory pool instance. + * + * @return Maximum number of elements allocated from the pool. + */ +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool) +{ + ASSERT(p_pool != NULL); + return p_pool->p_cb->max_utilization; +} +#endif //SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif // NRF_BALLOC_H__ +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log.h new file mode 100644 index 0000000000..967bc1a28a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log.h @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_log Logger module + * @{ + * @ingroup app_common + * + * @brief The nrf_log module interface. + */ + +#ifndef NRF_LOG_H_ +#define NRF_LOG_H_ + +#include "sdk_common.h" +#include "nrf_section.h" +#if NRF_MODULE_ENABLED(NRF_LOG) +#include "nrf_strerror.h" +#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code) +#else +#define NRF_LOG_ERROR_STRING_GET(code) "" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Severity level for the module. + * + * The severity level can be defined in a module to override the default. + */ +#ifndef NRF_LOG_LEVEL + #define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL +#endif + + +#include "nrf_log_internal.h" + +/** @def NRF_LOG_ERROR + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs. + */ + +/** @def NRF_LOG_WARNING + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + */ + +/** @def NRF_LOG_INFO + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + */ + +/** @def NRF_LOG_DEBUG + * @brief Macro for logging error messages. It takes a printf-like, formatted + * string with up to seven arguments. + * + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + */ + +#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__) +#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +/** + * @brief A macro for logging a formatted string without any prefix or timestamp. + */ +#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__) + +/** @def NRF_LOG_HEXDUMP_ERROR + * @brief Macro for logging raw bytes. + * @details It is compiled in only if @ref NRF_LOG_LEVEL includes error logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_WARNING + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_INFO + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +/** @def NRF_LOG_HEXDUMP_DEBUG + * @brief Macro for logging raw bytes. + * @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs. + * + * @param p_data Pointer to data. + * @param len Data length in bytes. + */ +#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) +#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) +#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) +#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) + +/** + * @brief Macro for logging hexdump without any prefix or timestamp. + */ +#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) + +/** + * @brief A macro for blocking reading from bidirectional backend used for logging. + * + * Macro call is blocking and returns when single byte is received. + */ +#define NRF_LOG_GETCHAR() NRF_LOG_INTERNAL_GETCHAR() + +/** + * @brief A macro for copying a string to internal logger buffer if logs are deferred. + * + * @param _str String. + */ +#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str) + +/** + * @brief Function for copying a string to the internal logger buffer if logs are deferred. + * + * Use this function to store a string that is volatile (for example allocated + * on stack) or that may change before the deferred logs are processed. Such string is copied + * into the internal logger buffer and is persistent until the log is processed. + * + * @note If the logs are not deferred, then this function returns the input parameter. + * + * @param p_str Pointer to the user string. + * + * @return Address to the location where the string is stored in the internal logger buffer. + */ +uint32_t nrf_log_push(char * const p_str); + +/** + * @brief Macro to be used in a formatted string to a pass float number to the log. + * + * Macro should be used in formatted string instead of the %f specifier together with + * @ref NRF_LOG_FLOAT macro. + * Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f))) + */ +#define NRF_LOG_FLOAT_MARKER "%s%d.%02d" + +/** + * @brief Macro for dissecting a float number into two numbers (integer and residuum). + */ +#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \ + (int32_t)(val), \ + (int32_t)((((val) > 0) ? (val) - (int32_t)(val) \ + : (int32_t)(val) - (val))*100) + + + +/** + * @def NRF_LOG_MODULE_REGISTER + * @brief Macro for registering an independent module. + */ +#if NRF_LOG_ENABLED + +#ifdef UNIT_TEST +#define _CONST +#define COMPILED_LOG_LEVEL 4 +#else +#define _CONST const +#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL +#endif +#define NRF_LOG_MODULE_REGISTER() \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_CONST_SECTION_NAME(NRF_LOG_MODULE_NAME), \ + _CONST nrf_log_module_const_data_t NRF_LOG_MODULE_DATA_CONST) = { \ + .p_module_name = STRINGIFY(NRF_LOG_MODULE_NAME), \ + .info_color_id = NRF_LOG_INFO_COLOR, \ + .debug_color_id = NRF_LOG_DEBUG_COLOR, \ + .compiled_lvl = COMPILED_LOG_LEVEL, \ + }; \ + NRF_SECTION_ITEM_REGISTER(NRF_LOG_DYNAMIC_SECTION_NAME(NRF_LOG_MODULE_NAME), \ + nrf_log_module_dynamic_data_t NRF_LOG_MODULE_DATA_DYNAMIC) +#else +#define NRF_LOG_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/ +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_H_ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_interface.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_interface.h new file mode 100644 index 0000000000..e5b965f44d --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_interface.h @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_BACKEND_INTERFACE_H +#define NRF_LOG_BACKEND_INTERFACE_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_interface Logger backend interface + * @{ + * @ingroup nrf_log + * @brief The nrf_log backend interface. + */ + +#include "nrf_memobj.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief nrf_log entry. + */ +typedef nrf_memobj_t nrf_log_entry_t; + +/* Forward declaration of the nrf_log_backend_t type. */ +typedef struct nrf_log_backend_s nrf_log_backend_t; + +/** + * @brief Logger backend API. + */ +typedef struct +{ + /** + * @brief @ref nrf_log_backend_put + */ + void (*put)(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_entry); + + /** + * @brief @ref nrf_log_backend_panic_set + */ + void (*panic_set)(nrf_log_backend_t const * p_backend); + + /** + * @brief @ref nrf_log_backend_flush + */ + void (*flush)(nrf_log_backend_t const * p_backend); +} nrf_log_backend_api_t; + +/** + * @brief Logger backend structure. + */ +struct nrf_log_backend_s +{ + nrf_log_backend_api_t const * p_api; //!< Pointer to interface. + nrf_log_backend_t * p_next; //!< Pointer to next backend added to the logger. + uint8_t id; //!< Backend id. + bool enabled;//!< Flag indicating backend status. +}; + +/** + * @brief Function for putting message with log entry to the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] p_msg Pointer to message with log entry. + */ +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg); + +/** + * @brief Function for reconfiguring backend to panic mode. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * p_backend); + +/** + * @brief Function for flushing backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * p_backend); + + +/** + * @brief Function for setting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @param[in] id Id. + */ +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t * p_backend, uint8_t id); + +/** + * @brief Function for getting backend id. + * + * @note It is used internally by the logger. + * + * @param[in] p_backend Pointer to the backend instance. + * @return Id. + */ +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * p_backend); + +/** + * @brief Function for enabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t * p_backend); + +/** + * @brief Function for disabling backend. + * + * @param[in] p_backend Pointer to the backend instance. + */ +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t * p_backend); + +/** + * @brief Function for checking state of the backend. + * + * @param[in] p_backend Pointer to the backend instance. + * + * @return True if backend is enabled, false otherwise. + */ +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * p_backend); + +#ifndef SUPPRESS_INLINE_IMPLEMENTATION +__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + p_backend->p_api->put(p_backend, p_msg); +} + +__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * p_backend) +{ + p_backend->p_api->panic_set(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * p_backend) +{ + p_backend->p_api->panic_set(p_backend); +} + +__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t * p_backend, uint8_t id) +{ + p_backend->id = id; +} + +__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * p_backend) +{ + return p_backend->id; +} + +__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t * p_backend) +{ + p_backend->enabled = true; +} + +__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t * p_backend) +{ + p_backend->enabled = false; +} + +__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * p_backend) +{ + return p_backend->enabled; +} + +#endif // SUPPRESS_INLINE_IMPLEMENTATION + +#ifdef __cplusplus +} +#endif + +#endif //NRF_LOG_BACKEND_INTERFACE_H + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_rtt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_rtt.h new file mode 100644 index 0000000000..66eeeb6545 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_rtt.h @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_log_backend_rtt Log RTT backend + * @{ + * @ingroup nrf_log + * @brief Log RTT backend. + */ + +#ifndef NRF_LOG_BACKEND_RTT_H +#define NRF_LOG_BACKEND_RTT_H + +#include "nrf_log_backend_interface.h" + +extern const nrf_log_backend_api_t nrf_log_backend_rtt_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_rtt_t; + +/** + * @brief RTT backend definition + * + * @param _name Name of the instance. + */ +#define NRF_LOG_BACKEND_RTT_DEF(_name) \ + static nrf_log_backend_rtt_t _name = { \ + .backend = {.p_api = &nrf_log_backend_rtt_api}, \ + } + +void nrf_log_backend_rtt_init(void); +#endif //NRF_LOG_BACKEND_RTT_H + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_uart.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_uart.h new file mode 100644 index 0000000000..4f9ce12900 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_backend_uart.h @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 nrf_log_backend_uart Log UART backend + * @{ + * @ingroup nrf_log + * @brief Log UART backend. + */ + +#ifndef NRF_LOG_BACKEND_UART_H +#define NRF_LOG_BACKEND_UART_H + +#include "nrf_log_backend_interface.h" + +extern const nrf_log_backend_api_t nrf_log_backend_uart_api; + +typedef struct { + nrf_log_backend_t backend; +} nrf_log_backend_uart_t; + +#define NRF_LOG_BACKEND_UART_DEF(name) \ + static nrf_log_backend_uart_t name = { \ + .backend = {.p_api = &nrf_log_backend_uart_api}, \ + } + +void nrf_log_backend_uart_init(void); +#endif //NRF_LOG_BACKEND_UART_H + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_ctrl.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_ctrl.h new file mode 100644 index 0000000000..0fbce415fd --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_ctrl.h @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_CTRL_H +#define NRF_LOG_CTRL_H + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_ctrl Functions for controlling nrf_log + * @{ + * @ingroup nrf_log + * @brief The nrf_log control interface. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include +#include +#include "nrf_log_ctrl_internal.h" +#include "nrf_log_backend_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + NRF_LOG_SEVERITY_NONE, + NRF_LOG_SEVERITY_ERROR, + NRF_LOG_SEVERITY_WARNING, + NRF_LOG_SEVERITY_INFO, + NRF_LOG_SEVERITY_DEBUG, +} nrf_log_severity_t; + +/** + * @brief Timestamp function prototype. + * + * @return Timestamp value. + */ +typedef uint32_t (*nrf_log_timestamp_func_t)(void); + +/**@brief Macro for initializing the logs. + * + * @note If timestamps are disabled in the configuration, then the provided pointer + * can be NULL. Otherwise, it is expected that timestamp_getter is not NULL. + * + * @param timestamp_func Function that returns the timestamp. + * + * @return NRF_SUCCESS after successful initialization, otherwise an error code. + */ +#define NRF_LOG_INIT(timestamp_func) NRF_LOG_INTERNAL_INIT(timestamp_func) + + +/**@brief Macro for processing a single log entry from a queue of deferred logs. + * + * You can call this macro from the main context or from the error handler to process + * log entries one by one. + * + * @note If logs are not deferred, this call has no use and is defined as 'false'. + * + * @retval true There are more logs to process in the buffer. + * @retval false No more logs in the buffer. + */ +#define NRF_LOG_PROCESS() NRF_LOG_INTERNAL_PROCESS() + +/** @brief Macro for processing all log entries from the buffer. + * It blocks until all buffered entries are processed by the backend. + * + * @note If logs are not deferred, this call has no use and is empty. + */ +#define NRF_LOG_FLUSH() NRF_LOG_INTERNAL_FLUSH() + +/** @brief Macro for flushing log data before reset. + * + * @note If logs are not deferred, this call has no use and is empty. + * + * @note If RTT is used, then a breakpoint is hit once flushed. + */ +#define NRF_LOG_FINAL_FLUSH() NRF_LOG_INTERNAL_FINAL_FLUSH() + +/** + * @brief Function for initializing the frontend and the default backend. + * + * @ref NRF_LOG_INIT calls this function to initialize the frontend and the backend. + * If custom backend is used, then @ref NRF_LOG_INIT should not be called. + * Instead, frontend and user backend should be verbosely initialized. + * + * @param timestamp_func Function for getting a 32-bit timestamp. + * + * @return Error status. + * + */ +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func); + +/** + * @brief Function for adding new backend interface to the logger. + * + * @param p_backend Pointer to the backend interface. + * @param severity Initial value of severity level for each module forwarded to the backend. This + * option is only applicable if @ref NRF_LOG_FILTERS_ENABLED is set. + * @return -1 if backend cannot be added or positive number (backend ID). + */ +int32_t nrf_log_backend_add(nrf_log_backend_t * p_backend, nrf_log_severity_t severity); + +/** + * @brief Function for removing backend from the logger. + * + * @param p_backend Pointer to the backend interface. + * + */ +void nrf_log_backend_remove(nrf_log_backend_t * p_backend); + +/** + * @brief Function for setting logger backends into panic mode. + * + * When this function is called all attached backends are informed about panic state of the system. + * It is up to the backend to react properly (hold or process logs in blocking mode, etc.) + */ +void nrf_log_panic(void); + +/** + * @brief Function for handling a single log entry. + * + * Use this function only if the logs are buffered. It takes a single entry from the + * buffer and attempts to process it. + * + * @retval true If there are more entries to process. + * @retval false If there are no more entries to process. + */ +bool nrf_log_frontend_dequeue(void); + +/** + * @brief Function for getting number of independent log modules registered into the logger. + * + * @return Number of registered modules. + */ +uint32_t nrf_log_module_cnt_get(void); + +/** + * @brief Function for getting module name. + * + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @return Pointer to string with module name. + */ +const char * nrf_log_module_name_get(uint32_t module_id, bool is_ordered_idx); + +/** + * @brief Function for getting coloring of specific logs. + * + * @param module_id Module ID. + * @param severity Log severity. + * + * @return ID of the color. + */ +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity); + +/** + * @brief Function for configuring filtering ofs logs in the module. + * + * Filtering of logs in modules is independent for each backend. + * + * @param backend_id Backend ID which want to chenge its configuration. + * @param module_id Module ID which logs will be reconfigured. + * @param severity New severity filter. + */ +void nrf_log_module_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t severity); + +/** + * @brief Function for getting module severity level. + * + * @param backend_id Backend ID. + * @param module_id Module ID. + * @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules. + * @param dynamic It true current filter for given backend is returned. If false then + * compiled-in level is returned (maximum available). If this parameter is + * false then backend_id parameter is not used. + * + * @return Severity. + */ +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool is_ordered_idx, + bool dynamic); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_LOG_CTRL_H + +/** + *@} + **/ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_default_backends.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_default_backends.h new file mode 100644 index 0000000000..982f3b1b5e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_default_backends.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_DEFAULT_BACKENDS_H__ +#define NRF_LOG_DEFAULT_BACKENDS_H__ + +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_default_backends Functions for initializing and adding default backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log default backends. + */ + +#include "sdk_config.h" +#include "sdk_errors.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def NRF_LOG_DEFAULT_BACKENDS_INIT + * @brief Macro for initializing default backends. + * + * Each backend enabled in configuration is initialized and added as a backend to the logger. + */ +#if NRF_LOG_ENABLED +#define NRF_LOG_DEFAULT_BACKENDS_INIT() nrf_log_default_backends_init() +#else +#define NRF_LOG_DEFAULT_BACKENDS_INIT() +#endif + +void nrf_log_default_backends_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif // NRF_LOG_DEFAULT_BACKENDS_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_str_formatter.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_str_formatter.h new file mode 100644 index 0000000000..134812d4cc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/nrf_log_str_formatter.h @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_STR_FORMATTER_H +#define NRF_LOG_STR_FORMATTER_H + +#include +#include "nrf_fprintf.h" +#include "nrf_log_ctrl.h" + +typedef struct +{ + uint32_t timestamp; + uint16_t module_id; + nrf_log_severity_t severity; + bool raw; + uint8_t use_colors; +} nrf_log_str_formatter_entry_params_t; + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx); + +#endif //NRF_LOG_STR_FORMATTER_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_rtt.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_rtt.c new file mode 100644 index 0000000000..03c32ca670 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_rtt.c @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) +#include "nrf_log_backend_rtt.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include +#include + +static uint8_t m_string_buff[NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE]; + +void nrf_log_backend_rtt_init(void) +{ + SEGGER_RTT_Init(); +} + +static void serial_tx(void const * p_context, char const * buffer, size_t len) +{ + if (len) + { + uint32_t idx = 0; + uint32_t processed; + uint32_t watchdog_counter = 10; + do + { + processed = SEGGER_RTT_WriteNoLock(0, &buffer[idx], len); + idx += processed; + len -= processed; + if (processed == 0) + { + // If RTT is not connected then ensure that logger does not block + watchdog_counter--; + if (watchdog_counter == 0) + { + break; + } + } + } while (len); + } +} +static void nrf_log_backend_rtt_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_rtt_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_rtt_panic_set(nrf_log_backend_t const * p_backend) +{ + +} + +const nrf_log_backend_api_t nrf_log_backend_rtt_api = { + .put = nrf_log_backend_rtt_put, + .flush = nrf_log_backend_rtt_flush, + .panic_set = nrf_log_backend_rtt_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.c new file mode 100644 index 0000000000..194b9a7b5b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) +#include "nrf_log_backend_serial.h" +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" + +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func) +{ + nrf_memobj_get(p_msg); + + nrf_fprintf_ctx_t fprintf_ctx = { + .p_io_buffer = (char *)p_buffer, + .io_buffer_size = length, + .io_buffer_cnt = 0, + .auto_flush = false, + .p_user_ctx = NULL, + .fwrite = tx_func + }; + + nrf_log_str_formatter_entry_params_t params; + + nrf_log_header_t header; + uint32_t memobj_offset = 0; + nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset = HEADER_SIZE*sizeof(uint32_t); + + params.timestamp = header.timestamp; + params.module_id = header.module_id; + params.use_colors = NRF_LOG_USES_COLORS; + + /*lint -save -e438*/ + if (header.base.generic.type == HEADER_TYPE_STD) + { + char const * p_log_str = (char const *)((uint32_t)header.base.std.addr); + params.severity = (nrf_log_severity_t)header.base.std.severity; + params.raw = header.base.std.raw; + uint32_t nargs = header.base.std.nargs; + uint32_t args[NRF_LOG_MAX_NUM_OF_ARGS]; + + nrf_memobj_read(p_msg, args, nargs*sizeof(uint32_t), memobj_offset); + memobj_offset += (nargs*sizeof(uint32_t)); + + nrf_log_std_entry_process(p_log_str, + args, + nargs, + ¶ms, + &fprintf_ctx); + + } + else if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t data_len = header.base.hexdump.len; + params.severity = (nrf_log_severity_t)header.base.hexdump.severity; + params.raw = header.base.hexdump.raw; + uint8_t data_buf[8]; + uint32_t chunk_len; + do + { + chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf); + nrf_memobj_read(p_msg, data_buf, chunk_len, memobj_offset); + memobj_offset += chunk_len; + data_len -= chunk_len; + + nrf_log_hexdump_entry_process(data_buf, + chunk_len, + ¶ms, + &fprintf_ctx); + } while (data_len > 0); + } + nrf_memobj_put(p_msg); + /*lint -restore*/ +} +#endif //NRF_LOG_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.h new file mode 100644 index 0000000000..583bc72945 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_serial.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_BACKEND_SERIAL_H +#define NRF_LOG_BACKEND_SERIAL_H +/**@file + * @addtogroup nrf_log Logger module + * @ingroup app_common + * + * @defgroup nrf_log_backend_serial Common part of serial backends + * @{ + * @ingroup nrf_log + * @brief The nrf_log serial backend common put function. + */ + + +#include "nrf_log_backend_interface.h" +#include "nrf_fprintf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief A function for processing logger entry with simple serial interface as output. + * + * + */ +void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg, + uint8_t * p_buffer, + uint32_t length, + nrf_fprintf_fwrite tx_func); + +#endif //NRF_LOG_BACKEND_SERIAL_H + +#ifdef __cplusplus +} +#endif + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_uart.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_uart.c new file mode 100644 index 0000000000..f81018c0da --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_backend_uart.c @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) +#include "nrf_log_backend_uart.h" +#include "nrf_log_backend_serial.h" +#include "nrf_log_internal.h" +#include "nrf_drv_uart.h" +#include "app_error.h" + +nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0); + +static uint8_t m_string_buff[NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE]; +static volatile bool m_xfer_done; +static bool m_async_mode; +static void uart_evt_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + m_xfer_done = true; +} + +static void uart_init(bool async_mode) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + config.pseltxd = NRF_LOG_BACKEND_UART_TX_PIN; + config.pselrxd = NRF_UART_PSEL_DISCONNECTED; + config.pselcts = NRF_UART_PSEL_DISCONNECTED; + config.pselrts = NRF_UART_PSEL_DISCONNECTED; + config.baudrate = (nrf_uart_baudrate_t)NRF_LOG_BACKEND_UART_BAUDRATE; + ret_code_t err_code = nrf_drv_uart_init(&m_uart, &config, async_mode ? uart_evt_handler : NULL); + APP_ERROR_CHECK(err_code); + + m_async_mode = async_mode; +} + +void nrf_log_backend_uart_init(void) +{ + bool async_mode = NRF_LOG_DEFERRED ? true : false; + uart_init(async_mode); +} + +static void serial_tx(void const * p_context, char const * p_buffer, size_t len) +{ + uint8_t len8 = (uint8_t)(len & 0x000000FF); + m_xfer_done = false; + ret_code_t err_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)p_buffer, len8); + APP_ERROR_CHECK(err_code); + /* wait for completion since buffer is reused*/ + while (m_async_mode && (m_xfer_done == false)) + { + + } + +} + +static void nrf_log_backend_uart_put(nrf_log_backend_t const * p_backend, + nrf_log_entry_t * p_msg) +{ + nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, + NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE, serial_tx); +} + +static void nrf_log_backend_uart_flush(nrf_log_backend_t const * p_backend) +{ + +} + +static void nrf_log_backend_uart_panic_set(nrf_log_backend_t const * p_backend) +{ + nrf_drv_uart_uninit(&m_uart); + + uart_init(false); +} + +const nrf_log_backend_api_t nrf_log_backend_uart_api = { + .put = nrf_log_backend_uart_put, + .flush = nrf_log_backend_uart_flush, + .panic_set = nrf_log_backend_uart_panic_set, +}; +#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_ctrl_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_ctrl_internal.h new file mode 100644 index 0000000000..fbe36cb967 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_ctrl_internal.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_CTRL_INTERNAL_H +#define NRF_LOG_CTRL_INTERNAL_H +/** + * @cond (NODOX) + * @defgroup nrf_log_ctrl_internal Auxiliary internal types declarations + * @{ + * @internal + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(NRF_LOG) + +#define NRF_LOG_INTERNAL_INIT(timestamp_func) \ + nrf_log_init(timestamp_func) + +#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue() +#define NRF_LOG_INTERNAL_FLUSH() \ + do { \ + while (NRF_LOG_INTERNAL_PROCESS()); \ + } while (0) + +#define NRF_LOG_INTERNAL_FINAL_FLUSH() \ + do { \ + nrf_log_panic(); \ + NRF_LOG_INTERNAL_FLUSH(); \ + } while (0) + + +#else // NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_INTERNAL_PROCESS() false +#define NRF_LOG_INTERNAL_FLUSH() +#define NRF_LOG_INTERNAL_INIT(timestamp_func) NRF_SUCCESS +#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \ + UNUSED_PARAMETER(default_handler); UNUSED_PARAMETER(bytes_handler) +#define NRF_LOG_INTERNAL_FINAL_FLUSH() +#endif // NRF_MODULE_ENABLED(NRF_LOG) + +/** @} + * @endcond + */ +#endif // NRF_LOG_CTRL_INTERNAL_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_default_backends.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_default_backends.c new file mode 100644 index 0000000000..039bf64590 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_default_backends.c @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) +#include "nrf_log_default_backends.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_internal.h" +#include "nrf_assert.h" + +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED +#include "nrf_log_backend_rtt.h" +NRF_LOG_BACKEND_RTT_DEF(rtt_log_backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED +#include "nrf_log_backend_uart.h" +NRF_LOG_BACKEND_UART_DEF(uart_log_backend); +#endif + +void nrf_log_default_backends_init(void) +{ + int32_t backend_id = -1; + (void)backend_id; +#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED + nrf_log_backend_rtt_init(); + backend_id = nrf_log_backend_add(&rtt_log_backend.backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&rtt_log_backend.backend); +#endif + +#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED + nrf_log_backend_uart_init(); + backend_id = nrf_log_backend_add(&uart_log_backend.backend, NRF_LOG_SEVERITY_DEBUG); + ASSERT(backend_id >= 0); + nrf_log_backend_enable(&uart_log_backend.backend); +#endif +} +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_frontend.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_frontend.c new file mode 100644 index 0000000000..459dc3e0b4 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_frontend.c @@ -0,0 +1,1146 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) +#include "app_util.h" +#include "app_util_platform.h" +#include "nrf_log.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_section.h" +#include "nrf_memobj.h" +#include "nrf_atomic.h" +#include + +STATIC_ASSERT((NRF_LOG_BUFSIZE % 4) == 0); +STATIC_ASSERT(IS_POWER_OF_TWO(NRF_LOG_BUFSIZE)); + +#define NRF_LOG_BUF_WORDS (NRF_LOG_BUFSIZE/4) + +#if NRF_LOG_BUF_WORDS < 32 +#warning "NRF_LOG_BUFSIZE too small, significant number of logs may be lost." +#endif + +NRF_MEMOBJ_POOL_DEF(mempool, NRF_LOG_MSGPOOL_ELEMENT_SIZE, NRF_LOG_MSGPOOL_ELEMENT_COUNT); + +#define NRF_LOG_BACKENDS_FULL 0xFF +#define NRF_LOG_FILTER_BITS_PER_BACKEND 3 +#define NRF_LOG_MAX_BACKENDS (32/NRF_LOG_FILTER_BITS_PER_BACKEND) +#define NRF_LOG_MAX_HEXDUMP (NRF_LOG_MSGPOOL_ELEMENT_SIZE*NRF_LOG_MSGPOOL_ELEMENT_COUNT/2) + +/** + * brief An internal control block of the logger + * + * @note Circular buffer is using never cleared indexes and a mask. It means + * that logger may break when indexes overflows. However, it is quite unlikely. + * With rate of 1000 log entries with 2 parameters per second such situation + * would happen after 12 days. + */ +typedef struct +{ + uint32_t wr_idx; // Current write index (never reset) + uint32_t rd_idx; // Current read index (never_reset) + uint32_t mask; // Size of buffer (must be power of 2) presented as mask + uint32_t buffer[NRF_LOG_BUF_WORDS]; + nrf_log_timestamp_func_t timestamp_func; // A pointer to function that returns timestamp + nrf_log_backend_t * p_backend_head; + nrf_atomic_flag_t log_skipping; + nrf_atomic_flag_t log_skipped; + bool autoflush; +} log_data_t; + +static log_data_t m_log_data; +static const char * m_overflow_info = "Overflow"; +/*lint -save -esym(526,log_const_data*) -esym(526,log_dynamic_data*)*/ +NRF_SECTION_DEF(log_dynamic_data, nrf_log_module_dynamic_data_t); +NRF_SECTION_DEF(log_const_data, nrf_log_module_const_data_t); +/*lint -restore*/ +NRF_LOG_MODULE_REGISTER(); +// Helper macros for section variables. +#define NRF_LOG_DYNAMIC_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_dynamic_data, nrf_log_module_dynamic_data_t, (i)) + +#define NRF_LOG_CONST_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_const_data, nrf_log_module_const_data_t, (i)) +#define NRF_LOG_CONST_SECTION_VARS_COUNT NRF_SECTION_ITEM_COUNT(log_const_data, nrf_log_module_const_data_t) + +#define PUSHED_HEADER_FILL(P_HDR, OFFSET, LENGTH) \ + (P_HDR)->base.pushed.type = HEADER_TYPE_PUSHED; \ + (P_HDR)->base.pushed.offset = OFFSET; \ + (P_HDR)->base.pushed.len = LENGTH + + +ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func) +{ + if (NRF_LOG_USES_TIMESTAMP && (timestamp_func == NULL)) + { + return NRF_ERROR_INVALID_PARAM; + } + + m_log_data.mask = NRF_LOG_BUF_WORDS - 1; + m_log_data.wr_idx = 0; + m_log_data.rd_idx = 0; + m_log_data.log_skipped = 0; + m_log_data.log_skipping = 0; + m_log_data.autoflush = NRF_LOG_DEFERRED ? false : true; + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.timestamp_func = timestamp_func; + } + + ret_code_t err_code = nrf_memobj_pool_init(&mempool); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + uint32_t modules_cnt = NRF_LOG_CONST_SECTION_VARS_COUNT; + uint32_t i; + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t j; + //sort modules by name + for (i = 0; i < modules_cnt; i++) + { + uint32_t idx = 0; + + for (j = 0; j < modules_cnt; j++) + { + if (i != j) + { + char const * p_name0 = NRF_LOG_CONST_SECTION_VARS_GET(i)->p_module_name; + char const * p_name1 = NRF_LOG_CONST_SECTION_VARS_GET(j)->p_module_name; + if (strncmp(p_name0, p_name1, 20) > 0) + { + idx++; + } + } + + } + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + p_module_ddata->filter = 0; + p_module_ddata->module_id = i; + p_module_ddata->order_idx = idx; + } + } + else + { + for(i = 0; i < modules_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_ddata = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + p_module_ddata->module_id = i; + } + } + + return NRF_SUCCESS; +} + +uint32_t nrf_log_module_cnt_get(void) +{ + return NRF_LOG_CONST_SECTION_VARS_COUNT; +} + +static ret_code_t module_idx_get(uint32_t * p_idx, bool ordered_idx) +{ + if (ordered_idx) + { + uint32_t module_cnt = nrf_log_module_cnt_get(); + uint32_t i; + for (i = 0; i < module_cnt; i++) + { + nrf_log_module_dynamic_data_t * p_module_data = NRF_LOG_DYNAMIC_SECTION_VARS_GET(i); + if (p_module_data->order_idx == *p_idx) + { + *p_idx = i; + return NRF_SUCCESS; + } + } + return NRF_ERROR_NOT_FOUND; + } + else + { + return NRF_SUCCESS; + } +} +const char * nrf_log_module_name_get(uint32_t module_id, bool ordered_idx) +{ + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + return p_module_data->p_module_name; + } + else + { + return NULL; + } +} + +uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity) +{ + nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id); + uint8_t color_id; + switch (severity) + { + case NRF_LOG_SEVERITY_ERROR: + color_id = NRF_LOG_ERROR_COLOR; + break; + case NRF_LOG_SEVERITY_WARNING: + color_id = NRF_LOG_WARNING_COLOR; + break; + case NRF_LOG_SEVERITY_INFO: + color_id = p_module_data->info_color_id; + break; + case NRF_LOG_SEVERITY_DEBUG: + color_id = p_module_data->debug_color_id; + break; + default: + color_id = 0; + break; + } + return color_id; +} + +static uint32_t higher_lvl_get(uint32_t lvls) +{ + uint32_t top_lvl = 0; + uint32_t tmp_lvl; + uint32_t i; + + //Find highest level enabled by backends + for (i = 0; i < (32/NRF_LOG_LEVEL_BITS); i+=NRF_LOG_LEVEL_BITS) + { + tmp_lvl = BF_GET(lvls,NRF_LOG_LEVEL_BITS, i); + if (tmp_lvl > top_lvl) + { + top_lvl = tmp_lvl; + } + } + return top_lvl; +} + +void nrf_log_module_filter_set(uint32_t backend_id, uint32_t module_id, nrf_log_severity_t severity) +{ + if (NRF_LOG_FILTERS_ENABLED) + { + nrf_log_module_dynamic_data_t * p_module_filter = NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id); + p_module_filter->filter_lvls &= ~(NRF_LOG_LEVEL_MASK << (NRF_LOG_LEVEL_BITS * backend_id)); + p_module_filter->filter_lvls |= (severity & NRF_LOG_LEVEL_MASK) << (NRF_LOG_LEVEL_BITS * backend_id); + p_module_filter->filter = higher_lvl_get(p_module_filter->filter_lvls); + } +} + +nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id, + uint32_t module_id, + bool ordered_idx, + bool dynamic) +{ + nrf_log_severity_t severity = NRF_LOG_SEVERITY_NONE; + if (NRF_LOG_FILTERS_ENABLED && dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_dynamic_data_t * p_module_filter = + NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)((p_module_filter->filter_lvls >> (NRF_LOG_LEVEL_BITS * backend_id)) & + NRF_LOG_LEVEL_MASK); + } + } + else if (!dynamic) + { + if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS) + { + nrf_log_module_const_data_t * p_module_data = + NRF_LOG_CONST_SECTION_VARS_GET(module_id); + severity = (nrf_log_severity_t)p_module_data->compiled_lvl; + } + } + return severity; +} + +/** + * @brief Skips the oldest, not pushed logs to make space for new logs. + * @details This function moves forward read index to prepare space for new logs. + */ + +static void log_skip(void) +{ + (void)nrf_atomic_flag_set(&m_log_data.log_skipped); + (void)nrf_atomic_flag_set(&m_log_data.log_skipping); + + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_log_data.mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + + // Skip any string that is pushed to the circular buffer. + while (p_header->base.generic.type == HEADER_TYPE_PUSHED) + { + rd_idx += PUSHED_HEADER_SIZE; + rd_idx += (p_header->base.pushed.len + p_header->base.pushed.offset); + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + switch (header.base.generic.type) + { + case HEADER_TYPE_HEXDUMP: + rd_idx += CEIL_DIV(header.base.hexdump.len, sizeof(uint32_t)); + break; + case HEADER_TYPE_STD: + rd_idx += header.base.std.nargs; + break; + default: + ASSERT(false); + break; + } + + uint32_t log_skipping_tmp = nrf_atomic_flag_clear_fetch(&m_log_data.log_skipping); + //update read index only if log_skip was not interrupted by another log skip + if (log_skipping_tmp) + { + m_log_data.rd_idx = rd_idx; + } +} + + +static inline void std_header_set(uint32_t severity_mid, + char const * const p_str, + uint32_t nargs, + uint32_t wr_idx, + uint32_t mask) +{ + + + //Prepare header - in reverse order to ensure that packet type is validated (set to STD as last action) + uint16_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS; + ASSERT(module_id < nrf_log_module_cnt_get()); + m_log_data.buffer[(wr_idx + 1) & mask] = module_id; + + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask]; + p_header->base.std.raw = (severity_mid & NRF_LOG_RAW) ? 1 : 0; + p_header->base.std.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.std.nargs = nargs; + p_header->base.std.addr = ((uint32_t)(p_str) & STD_ADDR_MASK); + p_header->base.std.type = HEADER_TYPE_STD; +} + +/** + * @brief Allocates chunk in a buffer for one entry and injects overflow if + * there is no room for requested entry. + * + * @param content_len Number of 32bit arguments. In case of allocating for hex dump it + * is the size of the buffer in 32bit words (ceiled). + * @param p_wr_idx Pointer to write index. + * + * @return True if successful allocation, false otherwise. + * + */ +static inline bool buf_prealloc(uint32_t content_len, uint32_t * p_wr_idx) +{ + uint32_t req_len = content_len + HEADER_SIZE; + uint32_t ovflw_tag_size = HEADER_SIZE; + bool ret = true; + CRITICAL_REGION_ENTER(); + *p_wr_idx = m_log_data.wr_idx; + uint32_t available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + uint32_t required_words = req_len + ovflw_tag_size; // room for current entry and overflow + while (required_words > available_words) + { + if (NRF_LOG_ALLOW_OVERFLOW) + { + log_skip(); + available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + } + else + { + if (available_words >= HEADER_SIZE) + { + // Overflow entry is injected + std_header_set(NRF_LOG_LEVEL_WARNING, m_overflow_info, 0, m_log_data.wr_idx, m_log_data.mask); + req_len = HEADER_SIZE; + } + else + { + // No more room for any logs. + req_len = 0; + } + ret = false; + break; + } + + } + /* Mark header as invalid.*/ + nrf_log_generic_header_t * p_header = (nrf_log_generic_header_t *)&m_log_data.buffer[m_log_data.wr_idx & m_log_data.mask]; + p_header->type = HEADER_TYPE_INVALID; + + m_log_data.wr_idx += req_len; + + CRITICAL_REGION_EXIT(); + return ret; +} + + +/** + * @brief Function for preallocating a continuous chunk of memory from circular buffer. + * + * If buffer does not fit starting from current position it will be allocated at + * the beginning of the circular buffer and offset will be returned indicating + * how much memory has been ommited at the end of the buffer. Function is + * using critical section. + * + * @param len32 Length of buffer to allocate. Given in words. + * @param p_offset Offset of the buffer. + * @param p_wr_idx Pointer to write index. + * + * @return A pointer to the allocated buffer. NULL if allocation failed. + */ +static inline uint32_t * cont_buf_prealloc(uint32_t len32, + uint32_t * p_offset, + uint32_t * p_wr_idx) +{ + uint32_t * p_buf = NULL; + + len32 += PUSHED_HEADER_SIZE; // Increment because 32bit header is needed to be stored. + + CRITICAL_REGION_ENTER(); + *p_wr_idx = m_log_data.wr_idx; + uint32_t available_words = (m_log_data.mask + 1) - + (m_log_data.wr_idx - m_log_data.rd_idx); + if (len32 <= available_words) + { + // buffer will fit as is + p_buf = &m_log_data.buffer[(m_log_data.wr_idx + 1) & m_log_data.mask]; + m_log_data.wr_idx += len32; + *p_offset = 0; + } + else if (len32 < (m_log_data.rd_idx & m_log_data.mask)) + { + // wraping to the begining of the buffer + m_log_data.wr_idx += (len32 + available_words - 1); + *p_offset = available_words - 1; + p_buf = m_log_data.buffer; + } + available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx); + // If there is no more room for even overflow tag indicate failed allocation. + if (available_words < HEADER_SIZE) + { + p_buf = NULL; + } + CRITICAL_REGION_EXIT(); + + return p_buf; +} + + +uint32_t nrf_log_push(char * const p_str) +{ + if ((m_log_data.autoflush) || (p_str == NULL)) + { + return (uint32_t)p_str; + } + + uint32_t mask = m_log_data.mask; + uint32_t slen = strlen(p_str) + 1; + uint32_t buflen = CEIL_DIV(slen, sizeof(uint32_t)); + uint32_t offset = 0; + uint32_t wr_idx; + char * p_dst_str = (char *)cont_buf_prealloc(buflen, &offset, &wr_idx); + if (p_dst_str) + { + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask]; + PUSHED_HEADER_FILL(p_header, offset, buflen); + memcpy(p_dst_str, p_str, slen); + } + return (uint32_t)p_dst_str; +} + +static inline void std_n(uint32_t severity_mid, char const * const p_str, uint32_t const * args, uint32_t nargs) +{ + uint32_t mask = m_log_data.mask; + uint32_t wr_idx; + + if (buf_prealloc(nargs, &wr_idx)) + { + // Proceed only if buffer was successfully preallocated. + + uint32_t data_idx = wr_idx + HEADER_SIZE; + uint32_t i; + for (i = 0; i < nargs; i++) + { + m_log_data.buffer[data_idx++ & mask] =args[i]; + } + std_header_set(severity_mid, p_str, nargs, wr_idx, mask); + } + if (m_log_data.autoflush) + { + NRF_LOG_FLUSH(); + } + +} + +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str) +{ + std_n(severity_mid, p_str, NULL, 0); +} + + +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0) +{ + uint32_t args[] = {val0}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1) +{ + uint32_t args[] = {val0, val1}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2) +{ + uint32_t args[] = {val0, val1, val2}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3) +{ + uint32_t args[] = {val0, val1, val2, val3}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4) +{ + uint32_t args[] = {val0, val1, val2, val3, val4}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5) +{ + uint32_t args[] = {val0, val1, val2, val3, val4, val5}; + std_n(severity_mid, p_str, args, ARRAY_SIZE(args)); +} + + +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length) +{ + uint32_t mask = m_log_data.mask; + + uint32_t wr_idx; + if (buf_prealloc(CEIL_DIV(length, sizeof(uint32_t)), &wr_idx)) + { + uint32_t header_wr_idx = wr_idx; + wr_idx += HEADER_SIZE; + + uint32_t space0 = sizeof(uint32_t) * (m_log_data.mask + 1 - (wr_idx & mask)); + if (length <= space0) + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, length); + } + else + { + memcpy(&m_log_data.buffer[wr_idx & mask], p_data, space0); + length -= space0; + memcpy(&m_log_data.buffer[0], &((uint8_t *)p_data)[space0], length); + } + + //Prepare header - in reverse order to ensure that packet type is validated (set to HEXDUMP as last action) + if (NRF_LOG_USES_TIMESTAMP) + { + m_log_data.buffer[(header_wr_idx + 2) & mask] = m_log_data.timestamp_func(); + } + + m_log_data.buffer[(header_wr_idx + 1) & mask] = severity_mid >> NRF_LOG_MODULE_ID_POS; + //Header prepare + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[header_wr_idx & mask]; + p_header->base.hexdump.raw = (severity_mid & NRF_LOG_RAW) ? 1 : 0; + p_header->base.hexdump.severity = severity_mid & NRF_LOG_LEVEL_MASK; + p_header->base.hexdump.offset = 0; + p_header->base.hexdump.len = length; + p_header->base.hexdump.type = HEADER_TYPE_HEXDUMP; + + + + } + + if (m_log_data.autoflush) + { + NRF_LOG_FLUSH(); + } +} + + +bool buffer_is_empty(void) +{ + return (m_log_data.rd_idx == m_log_data.wr_idx); +} + + +bool nrf_log_frontend_dequeue(void) +{ + if (buffer_is_empty()) + { + return false; + } + m_log_data.log_skipped = 0; + //It has to be ensured that reading rd_idx occurs after skipped flag is cleared. + __DSB(); + uint32_t rd_idx = m_log_data.rd_idx; + uint32_t mask = m_log_data.mask; + nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_log_header_t header; + nrf_memobj_t * p_msg_buf = NULL; + uint32_t memobj_offset = 0; + uint32_t severity = 0; + + // Skip any string that is pushed to the circular buffer. + while (p_header->base.generic.type == HEADER_TYPE_PUSHED) + { + rd_idx += PUSHED_HEADER_SIZE; + rd_idx += (p_header->base.pushed.len + p_header->base.pushed.offset); + p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask]; + } + + uint32_t i; + for (i = 0; i < HEADER_SIZE; i++) + { + ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask]; + } + + if (header.base.generic.type == HEADER_TYPE_HEXDUMP) + { + uint32_t orig_data_len = header.base.hexdump.len; + uint32_t data_len = MIN(header.base.hexdump.len, NRF_LOG_MAX_HEXDUMP); //limit the data + header.base.hexdump.len = data_len; + uint32_t msg_buf_size8 = sizeof(uint32_t)*HEADER_SIZE + data_len; + severity = header.base.hexdump.severity; + p_msg_buf = nrf_memobj_alloc(&mempool, msg_buf_size8); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + uint32_t space0 = sizeof(uint32_t) * (mask + 1 - (rd_idx & mask)); + if (data_len > space0) + { + uint8_t * ptr0 = space0 ? + (uint8_t *)&m_log_data.buffer[rd_idx & mask] : + (uint8_t *)&m_log_data.buffer[0]; + uint8_t len0 = space0 ? space0 : data_len; + uint8_t * ptr1 = space0 ? + (uint8_t *)&m_log_data.buffer[0] : NULL; + uint8_t len1 = space0 ? data_len - space0 : 0; + + nrf_memobj_write(p_msg_buf, ptr0, len0, memobj_offset); + memobj_offset += len0; + if (ptr1) + { + nrf_memobj_write(p_msg_buf, ptr1, len1, memobj_offset); + } + } + else + { + uint8_t * p_data = (uint8_t *)&m_log_data.buffer[rd_idx & mask]; + nrf_memobj_write(p_msg_buf, p_data, data_len, memobj_offset); + } + rd_idx += CEIL_DIV(orig_data_len, 4); + } + } + else if (header.base.generic.type == HEADER_TYPE_STD) // standard entry + { + header.base.std.nargs = MIN(header.base.std.nargs, NRF_LOG_MAX_NUM_OF_ARGS); + uint32_t msg_buf_size32 = HEADER_SIZE + header.base.std.nargs; + severity = header.base.std.severity; + + p_msg_buf = nrf_memobj_alloc(&mempool, msg_buf_size32*sizeof(uint32_t)); + + if (p_msg_buf) + { + nrf_memobj_get(p_msg_buf); + nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset); + memobj_offset += HEADER_SIZE*sizeof(uint32_t); + + for (i = 0; i < header.base.std.nargs; i++) + { + nrf_memobj_write(p_msg_buf, &m_log_data.buffer[rd_idx++ & mask], + sizeof(uint32_t), memobj_offset); + memobj_offset += sizeof(uint32_t); + } + } + } + else if (header.base.generic.type == HEADER_TYPE_INVALID && (m_log_data.log_skipped == 0)) + { + //invalid type can only occur if log entry was interrupted by log_process. It is likly final flush + // and finding invalid type means that last entry in the buffer was reached (the one that was interrupted). + // Stop processing immediately. + return false; + } + else + { + //Do nothing. In case of log overflow buffer can contain corrupted data. + } + + if (p_msg_buf) + { + nrf_log_backend_t * p_backend = m_log_data.p_backend_head; + if (NRF_LOG_ALLOW_OVERFLOW && m_log_data.log_skipped) + { + // Check if any log was skipped during log processing. Do not forward log if skipping + // occured because data may be invalid. + nrf_memobj_put(p_msg_buf); + } + else + { + while (p_backend) + { + bool entry_accepted = false; + if (nrf_log_backend_is_enabled(p_backend) == true) + { + if (NRF_LOG_FILTERS_ENABLED) + { + uint8_t backend_id = nrf_log_backend_id_get(p_backend); + uint32_t filter_lvls = NRF_LOG_DYNAMIC_SECTION_VARS_GET(header.module_id)->filter_lvls; + uint32_t backend_lvl = (filter_lvls >> (backend_id*NRF_LOG_LEVEL_BITS)) + & NRF_LOG_LEVEL_MASK; + if (backend_lvl >= severity) + { + entry_accepted = true; + } + } + else + { + (void)severity; + entry_accepted = true; + } + } + if (entry_accepted) + { + nrf_log_backend_put(p_backend, p_msg_buf); + } + p_backend = p_backend->p_next; + } + + nrf_memobj_put(p_msg_buf); + + if (NRF_LOG_ALLOW_OVERFLOW) + { + // Read index can be moved forward only if dequeueing process was not interrupt by + // skipping procedure. If NRF_LOG_ALLOW_OVERFLOW is set then in case of buffer gets full + // and new logger entry occurs, oldest entry is removed. In that case read index is + // changed and updating it here would corrupt the internal circular buffer. + CRITICAL_REGION_ENTER(); + if (m_log_data.log_skipped == 0) + { + m_log_data.rd_idx = rd_idx; + } + CRITICAL_REGION_EXIT(); + } + else + { + m_log_data.rd_idx = rd_idx; + } + } + } + + return buffer_is_empty() ? false : true; +} + +static int32_t backend_id_assign(void) +{ + int32_t candidate_id; + nrf_log_backend_t * p_backend; + bool id_available; + for (candidate_id = 0; candidate_id < NRF_LOG_MAX_BACKENDS; candidate_id++) + { + p_backend = m_log_data.p_backend_head; + id_available = true; + while (p_backend) + { + if (nrf_log_backend_id_get(p_backend) == candidate_id) + { + id_available = false; + break; + } + p_backend = p_backend->p_next; + } + if (id_available) + { + return candidate_id; + } + } + return -1; +} + +int32_t nrf_log_backend_add(nrf_log_backend_t * p_backend, nrf_log_severity_t severity) +{ + int32_t id = backend_id_assign(); + if (id == -1) + { + return id; + } + + nrf_log_backend_id_set(p_backend, id); + //add to list + if (m_log_data.p_backend_head == NULL) + { + m_log_data.p_backend_head = p_backend; + p_backend->p_next = NULL; + } + else + { + p_backend->p_next = m_log_data.p_backend_head->p_next; + m_log_data.p_backend_head->p_next = p_backend; + } + + if (NRF_LOG_FILTERS_ENABLED) + { + uint32_t i; + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + nrf_log_severity_t buildin_lvl = nrf_log_module_filter_get(id, i, false, false); + nrf_log_severity_t actual_severity = MIN(buildin_lvl, severity); + nrf_log_module_filter_set(nrf_log_backend_id_get(p_backend), i, actual_severity); + } + } + + return id; +} + +void nrf_log_backend_remove(nrf_log_backend_t * p_backend) +{ + nrf_log_backend_t * p_curr = m_log_data.p_backend_head; + nrf_log_backend_t * p_prev = NULL; + while (p_curr != p_backend) + { + p_prev = p_curr; + p_curr = p_curr->p_next; + } + + if (p_prev) + { + p_prev->p_next = p_backend->p_next; + } + else + { + m_log_data.p_backend_head = NULL; + } +} + +void nrf_log_panic(void) +{ + nrf_log_backend_t * p_backend = m_log_data.p_backend_head; + m_log_data.autoflush = true; + while (p_backend) + { + nrf_log_backend_enable(p_backend); + nrf_log_backend_panic_set(p_backend); + p_backend = p_backend->p_next; + } +} + +#if NRF_LOG_CLI_CMDS +#include "nrf_cli.h" + +static const char * m_severity_lvls[] = { + "none", + "error", + "warning", + "info", + "debug", +}; + +static const char * m_severity_lvls_sorted[] = { + "debug", + "error", + "info", + "none", + "warning", +}; + +static void log_status(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + uint32_t modules_cnt = nrf_log_module_cnt_get(); + uint32_t backend_id = p_cli->p_log_backend->backend.id; + uint32_t i; + + if (!nrf_log_backend_is_enabled(&p_cli->p_log_backend->backend)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Logs are halted!\r\n"); + } + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-24s | current | buildin \r\n", "module_name"); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "------------------------------------------\r\n"); + for (i = 0; i < modules_cnt; i++) + { + nrf_log_severity_t module_dynamic_lvl = nrf_log_module_filter_get(backend_id, i, true, true); + nrf_log_severity_t module_compiled_lvl = nrf_log_module_filter_get(backend_id, i, true, false); + nrf_log_severity_t actual_compiled_lvl = MIN(module_compiled_lvl, (nrf_log_severity_t)NRF_LOG_DEFAULT_LEVEL); + nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-24s | %-7s | %s%s\r\n", + nrf_log_module_name_get(i, true), + m_severity_lvls[module_dynamic_lvl], + m_severity_lvls[actual_compiled_lvl], + actual_compiled_lvl < module_compiled_lvl ? "*" : ""); + } +} + +static bool module_id_get(const char * p_name, uint32_t * p_id) +{ + uint32_t modules_cnt = nrf_log_module_cnt_get(); + const char * p_tmp_name; + uint32_t j; + for (j = 0; j < modules_cnt; j++) + { + p_tmp_name = nrf_log_module_name_get(j, false); + if (strncmp(p_tmp_name, p_name, 32) == 0) + { + *p_id = j; + break; + } + } + return (j != modules_cnt); +} + +static bool module_id_filter_set(uint32_t backend_id, + uint32_t module_id, + nrf_log_severity_t lvl) +{ + nrf_log_severity_t buildin_lvl = nrf_log_module_filter_get(backend_id, module_id, false, false); + if (lvl > buildin_lvl) + { + return false; + } + else + { + nrf_log_module_filter_set(backend_id, module_id, lvl); + return true; + } +} + +static void log_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + uint32_t backend_id = p_cli->p_log_backend->backend.id; + nrf_log_severity_t lvl; + uint32_t first_m_name_idx; + uint32_t i; + bool all_modules = false; + + if (argc > 0) + { + if (strncmp(argv[0], "enable", 7) == 0) + { + if (argc == 1) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad parameter count.\r\n"); + return; + } + + if (argc == 2) + { + all_modules = true; + } + + for (i = 0; i < ARRAY_SIZE(m_severity_lvls); i++) + { + if (strncmp(argv[1], m_severity_lvls[i], 10) == 0) + { + break; + } + } + + if (i == ARRAY_SIZE(m_severity_lvls)) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown severity level: %s\r\n", argv[1]); + return; + } + + lvl = (nrf_log_severity_t)i; + first_m_name_idx = 2; + + } + else if (strncmp(argv[0], "disable", 8) == 0) + { + if (argc == 1) + { + all_modules = true; + } + lvl = NRF_LOG_SEVERITY_NONE; + first_m_name_idx = 1; + } + else + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown option: %s\r\n", argv[0]); + return; + } + + if (all_modules) + { + for (i = 0; i < nrf_log_module_cnt_get(); i++) + { + if (module_id_filter_set(backend_id, i, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Level unavailable for module: %s\r\n", nrf_log_module_name_get(i, false)); + } + } + } + else + { + for (i = first_m_name_idx; i < argc; i++) + { + uint32_t module_id = 0; + if (module_id_get(argv[i], &module_id) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown module:%s\r\n", argv[i]); + } + + if (module_id_filter_set(backend_id, module_id, lvl) == false) + { + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Level unavailable for module: %s\r\n", nrf_log_module_name_get(module_id, false)); + } + } + } + } +} +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static); + +NRF_CLI_CREATE_DYNAMIC_CMD(m_module_name, module_name_get); + +static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = nrf_log_module_name_get(idx, true); +} + +static void severity_lvl_get(size_t idx, nrf_cli_static_entry_t * p_static) +{ + p_static->handler = NULL; + p_static->p_help = NULL; + p_static->p_subcmd = &m_module_name; + p_static->p_syntax = (idx < ARRAY_SIZE(m_severity_lvls_sorted)) ? + m_severity_lvls_sorted[idx] : NULL; +} + +NRF_CLI_CREATE_DYNAMIC_CMD(m_severity_lvl, severity_lvl_get); + +static void log_halt(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_log_backend_disable(&p_cli->p_log_backend->backend); +} + +static void log_go(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + nrf_log_backend_enable(&p_cli->p_log_backend->backend); +} + +NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_stat) +{ + NRF_CLI_CMD(disable, &m_module_name, + "'log disable .. ' disables logs in specified " + "modules (all if no modules specified).", + log_ctrl), + NRF_CLI_CMD(enable, &m_severity_lvl, + "'log enable ... ' enables logs up to given level in " + "specified modules (all if no modules specified).", + log_ctrl), + NRF_CLI_CMD(go, NULL, "Resume logging", log_go), + NRF_CLI_CMD(halt, NULL, "Halt logging", log_halt), + NRF_CLI_CMD(status, NULL, "Logger status", log_status), + NRF_CLI_SUBCMD_SET_END +}; + +static void log_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv) +{ + if ((argc == 1) || nrf_cli_help_requested(p_cli)) + { + nrf_cli_help_print(p_cli, NULL, 0); + return; + } + + nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "%s:%s%s\r\n", argv[0], " unknown parameter: ", argv[1]); +} + +NRF_CLI_CMD_REGISTER(log, &m_sub_log_stat, "Commands for controlling logger", log_cmd); + +#endif //NRF_LOG_CLI_CMDS + +#endif // NRF_MODULE_ENABLED(NRF_LOG) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_internal.h new file mode 100644 index 0000000000..3cf7b0600c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_internal.h @@ -0,0 +1,548 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_LOG_INTERNAL_H__ +#define NRF_LOG_INTERNAL_H__ +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_error.h" +#include "app_util.h" +#include +#include + +#ifndef NRF_LOG_ERROR_COLOR + #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_WARNING_COLOR + #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_INFO_COLOR + #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT +#endif + +#ifndef NRF_LOG_DEBUG_COLOR + #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT +#endif + + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 0 +#endif + +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +#ifndef NRF_LOG_MODULE_NAME + #define NRF_LOG_MODULE_NAME app +#endif + +#define NRF_LOG_LEVEL_ERROR 1UL +#define NRF_LOG_LEVEL_WARNING 2UL +#define NRF_LOG_LEVEL_INFO 3UL +#define NRF_LOG_LEVEL_DEBUG 4UL +#define NRF_LOG_LEVEL_INTERNAL 5UL +#define NRF_LOG_LEVEL_BITS 3 +#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1) +#define NRF_LOG_RAW_POS 4U +#define NRF_LOG_RAW (1UL << NRF_LOG_RAW_POS) +#define NRF_LOG_MODULE_ID_BITS 16 +#define NRF_LOG_MODULE_ID_POS 16 +#define NRF_LOG_LEVEL_INFO_RAW (NRF_LOG_RAW | NRF_LOG_LEVEL_INFO) + +#define NRF_LOG_MAX_NUM_OF_ARGS 6 + +/* + * For GCC sections are sorted in the group by the linker. For IAR and KEIL it is assumed that linker will sort + * dynamic and const section in the same order (but in different locations). Proper message formatting + * is based on that assumption. + */ +#if defined(__GNUC__) +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) CONCAT_2(log_dynamic_data_,_module_name) +#define NRF_LOG_CONST_SECTION_NAME(_module_name) CONCAT_2(log_const_data_,_module_name) +#else +#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) log_dynamic_data +#define NRF_LOG_CONST_SECTION_NAME(_module_name) log_const_data +#endif + +#define NRF_LOG_MODULE_DATA CONCAT_3(m_nrf_log_,NRF_LOG_MODULE_NAME,_logs_data) +#define NRF_LOG_MODULE_DATA_DYNAMIC CONCAT_2(NRF_LOG_MODULE_DATA,_dynamic) +#define NRF_LOG_MODULE_DATA_CONST CONCAT_2(NRF_LOG_MODULE_DATA,_const) + +#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED + #define NRF_LOG_FILTER NRF_LOG_MODULE_DATA_DYNAMIC.filter +#else + #undef NRF_LOG_FILTER + #define NRF_LOG_FILTER NRF_LOG_LEVEL_DEBUG +#endif + +#if NRF_LOG_ENABLED +#define NRF_LOG_MODULE_ID NRF_LOG_MODULE_DATA_DYNAMIC.module_id +#else +#define NRF_LOG_MODULE_ID 0 +#endif + + +#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) +#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ + __VA_ARGS__), type, __VA_ARGS__) +#if NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str) +#define LOG_INTERNAL_0(type, str) \ + nrf_log_frontend_std_0(type, str) +#define LOG_INTERNAL_1(type, str, arg0) \ + /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/ +#define LOG_INTERNAL_2(type, str, arg0, arg1) \ + /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1))/*lint -restore*/ +#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \ + /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/ +#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \ + /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/ +#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \ + /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/ +#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \ + /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \ + (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/ + + +#else //NRF_LOG_ENABLED +#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str) +#define LOG_INTERNAL_0(_type, _str) \ + (void)(_type); (void)(_str) +#define LOG_INTERNAL_1(_type, _str, _arg0) \ + (void)(_type); (void)(_str); (void)(_arg0) +#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1) +#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2) +#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3) +#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4) +#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \ + (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5) +#endif //NRF_LOG_ENABLED && (NRF_LOG_DEFAULT_LEVEL >= NRF_LOG_LEVEL_ERROR) + +#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS) + +#if NRF_LOG_ENABLED +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + nrf_log_frontend_hexdump((_severity), (_p_data), (_length)) +#else +#define LOG_HEXDUMP(_severity, _p_data, _length) \ + (void)(_severity); (void)(_p_data); (void)_length +#endif + +#define NRF_LOG_INTERNAL_ERROR(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \ + (NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_ERROR) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_ERROR), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \ + (NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_ERROR) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_ERROR), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_WARNING(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \ + (NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_WARNING) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_WARNING), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \ + (NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_WARNING) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_WARNING, \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_INFO(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO), __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_RAW_INFO(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO | NRF_LOG_RAW), \ + __VA_ARGS__); \ + } \ + } + +#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \ + (NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_INFO) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_INFO_RAW), \ + (p_data), (len)); \ + } \ + } + +#define NRF_LOG_INTERNAL_DEBUG(...) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \ + (NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_DEBUG) \ + { \ + LOG_INTERNAL(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_DEBUG), __VA_ARGS__); \ + } \ + } +#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \ + if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \ + (NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \ + { \ + if (NRF_LOG_FILTER >= NRF_LOG_LEVEL_DEBUG) \ + { \ + LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(NRF_LOG_LEVEL_DEBUG), \ + (p_data), (len)); \ + } \ + } + +#if NRF_MODULE_ENABLED(NRF_LOG) +#define NRF_LOG_INTERNAL_GETCHAR() nrf_log_getchar() +#else +#define NRF_LOG_INTERNAL_GETCHAR() (void) +#endif + +typedef struct +{ + uint16_t module_id; + uint16_t order_idx; + uint32_t filter; + uint32_t filter_lvls; +} nrf_log_module_dynamic_data_t; + +typedef struct +{ + const char * p_module_name; + uint8_t info_color_id; + uint8_t debug_color_id; + uint8_t compiled_lvl; +} nrf_log_module_const_data_t; + +extern nrf_log_module_dynamic_data_t NRF_LOG_MODULE_DATA_DYNAMIC; + +/** + * Set of macros for encoding and decoding header for log entries. + * There are 3 types of entries: + * 1. Standard entry (STD) + * An entry consists of header, pointer to string and values. Header contains + * severity leveland determines number of arguments and thus size of the entry. + * Since flash address space starts from 0x00000000 and is limited to kB rather + * than MB 22 bits are used to store the address (4MB). It is used that way to + * save one RAM memory. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS| P_STR | + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | ARG0 | + * |------------------------------| + * | .... | + * |------------------------------| + * | ARG(nargs-1) | + * -------------------------------- + * + * 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of + * header, optional timestamp, pointer to string and data. A header contains + * length (10bit) and offset which is updated after backend processes part of + * data. + * + * -------------------------------- + * |TYPE|SEVERITY|NARGS|OFFSET|LEN| + * |------------------------------| + * | Module_ID (optional) | + * |------------------------------| + * | TIMESTAMP (optional) | + * |------------------------------| + * | P_STR | + * |------------------------------| + * | data | + * |------------------------------| + * | data | dummy | + * -------------------------------- + * + * 3. Pushed string. If string is pushed into the logger internal buffer it is + * stored as PUSHED entry. It consists of header, unused data (optional) and + * string. Unused data is present if string does not not fit into a buffer + * without wrapping (and string cannot be wrapped). In that case header + * contains information about offset. + * + * -------------------------------- + * |TYPE| OFFSET | LEN | + * |------------------------------| + * | OFFSET | + * |------------------------------| + * end| OFFSET | + * 0|------------------------------| + * | STRING | + * |------------------------------| + * | STRING | dummy | + * -------------------------------- + */ + +#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U) +#define HEADER_TYPE_STD 1U +#define HEADER_TYPE_HEXDUMP 2U +#define HEADER_TYPE_PUSHED 0U +#define HEADER_TYPE_INVALID 3U + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t data : 29; +} nrf_log_generic_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t severity : 3; + uint32_t nargs : 4; + uint32_t addr : 22; +} nrf_log_std_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t raw : 1; + uint32_t severity : 3; + uint32_t offset : 10; + uint32_t reserved : 6; + uint32_t len : 10; +} nrf_log_hexdump_header_t; + +typedef struct +{ + uint32_t type : 2; + uint32_t reserved0 : 4; + uint32_t offset : 10; + uint32_t reserved1 : 6; + uint32_t len : 10; +} nrf_log_pushed_header_t; + +typedef struct +{ + union { + nrf_log_generic_header_t generic; + nrf_log_std_header_t std; + nrf_log_hexdump_header_t hexdump; + nrf_log_pushed_header_t pushed; + uint32_t raw; + } base; + uint32_t module_id; + uint32_t timestamp; +} nrf_log_header_t; + +#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \ + (NRF_LOG_USES_TIMESTAMP ? 0 : 1)) + +#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t)) + +//Implementation assumes that pushed header has one word. +STATIC_ASSERT(PUSHED_HEADER_SIZE == 1); +/** + * @brief A function for logging raw string. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string. + */ +void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str); + +/** + * @brief A function for logging a formatted string with one argument. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0 An argument. + */ +void nrf_log_frontend_std_1(uint32_t severity_mid, + char const * const p_str, + uint32_t val0); + +/** + * @brief A function for logging a formatted string with 2 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1 Arguments for formatting string. + */ +void nrf_log_frontend_std_2(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1); + +/** + * @brief A function for logging a formatted string with 3 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2 Arguments for formatting string. + */ +void nrf_log_frontend_std_3(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2); + +/** + * @brief A function for logging a formatted string with 4 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3 Arguments for formatting string. + */ +void nrf_log_frontend_std_4(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3); + +/** + * @brief A function for logging a formatted string with 5 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4 Arguments for formatting string. + */ +void nrf_log_frontend_std_5(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4); + +/** + * @brief A function for logging a formatted string with 6 arguments. + * + * @param severity_mid Severity. + * @param p_str A pointer to a formatted string. + * @param val0, val1, val2, val3, val4, val5 Arguments for formatting string. + */ +void nrf_log_frontend_std_6(uint32_t severity_mid, + char const * const p_str, + uint32_t val0, + uint32_t val1, + uint32_t val2, + uint32_t val3, + uint32_t val4, + uint32_t val5); + +/** + * @brief A function for logging raw data. + * + * @param severity_mid Severity. + * @param p_str A pointer to a string which is prefixing the data. + * @param p_data A pointer to data to be dumped. + * @param length Length of data (in bytes). + * + */ +void nrf_log_frontend_hexdump(uint32_t severity_mid, + const void * const p_data, + uint16_t length); + +/** + * @brief A function for reading a byte from log backend. + * + * @return Byte. + */ +uint8_t nrf_log_getchar(void); +#endif // NRF_LOG_INTERNAL_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_str_formatter.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_str_formatter.c new file mode 100644 index 0000000000..accdf224fc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_log/src/nrf_log_str_formatter.c @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_LOG) +#include "nrf_log_str_formatter.h" +#include "nrf_log_internal.h" +#include "nrf_log_ctrl.h" +#include "nrf_fprintf.h" +#include + +#define NRF_LOG_COLOR_CODE_DEFAULT "\x1B[0m" +#define NRF_LOG_COLOR_CODE_BLACK "\x1B[1;30m" +#define NRF_LOG_COLOR_CODE_RED "\x1B[1;31m" +#define NRF_LOG_COLOR_CODE_GREEN "\x1B[1;32m" +#define NRF_LOG_COLOR_CODE_YELLOW "\x1B[1;33m" +#define NRF_LOG_COLOR_CODE_BLUE "\x1B[1;34m" +#define NRF_LOG_COLOR_CODE_MAGENTA "\x1B[1;35m" +#define NRF_LOG_COLOR_CODE_CYAN "\x1B[1;36m" +#define NRF_LOG_COLOR_CODE_WHITE "\x1B[1;37m" + +static const char * severity_names[] = { + NULL, + "error", + "warning", + "info", + "debug" +}; + +static const char * m_colors[] = { + NRF_LOG_COLOR_CODE_DEFAULT, + NRF_LOG_COLOR_CODE_BLACK, + NRF_LOG_COLOR_CODE_RED, + NRF_LOG_COLOR_CODE_GREEN, + NRF_LOG_COLOR_CODE_YELLOW, + NRF_LOG_COLOR_CODE_BLUE, + NRF_LOG_COLOR_CODE_MAGENTA, + NRF_LOG_COLOR_CODE_CYAN, + NRF_LOG_COLOR_CODE_WHITE, +}; + +static void prefix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (!(p_params->raw)) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", + m_colors[nrf_log_color_id_get( p_params->module_id, p_params->severity)]); + } + + if (NRF_LOG_USES_TIMESTAMP) + { + nrf_fprintf(p_ctx, "[%08lu] ", p_params->timestamp); + } + + nrf_fprintf(p_ctx, "<%s> %s: ", + severity_names[p_params->severity], nrf_log_module_name_get(p_params->module_id, false)); + } +} + +static void postfix_process(nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx, + bool newline) +{ + if (!p_params->raw) + { + if (p_params->use_colors) + { + nrf_fprintf(p_ctx, "%s", m_colors[0]); + } + nrf_fprintf(p_ctx, "\r\n"); + } + else if (newline) + { + nrf_fprintf(p_ctx, "\r\n"); + } + nrf_fprintf_buffer_flush(p_ctx); +} + +void nrf_log_std_entry_process(char const * p_str, + uint32_t const * p_args, + uint32_t nargs, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + switch (nargs) + { + case 0: + nrf_fprintf(p_ctx, p_str); + break; + case 1: + nrf_fprintf(p_ctx, p_str, p_args[0]); + break; + case 2: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1]); + break; + case 3: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2]); + break; + case 4: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3]); + break; + case 5: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4]); + break; + case 6: + nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5]); + break; + + default: + break; + } + + postfix_process(p_params, p_ctx, false); + p_ctx->auto_flush = auto_flush; +} + +#define HEXDUMP_BYTES_IN_LINE 8 + +void nrf_log_hexdump_entry_process(uint8_t * p_data, + uint32_t data_len, + nrf_log_str_formatter_entry_params_t * p_params, + nrf_fprintf_ctx_t * p_ctx) +{ + if (data_len > HEXDUMP_BYTES_IN_LINE) + { + return; + } + bool auto_flush = p_ctx->auto_flush; + p_ctx->auto_flush = false; + + prefix_process(p_params, p_ctx); + + uint32_t i; + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + nrf_fprintf(p_ctx, " %02x", p_data[i]); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + nrf_fprintf(p_ctx, "|"); + + for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) + { + if (i < data_len) + { + char c = (char)p_data[i]; + nrf_fprintf(p_ctx, "%c", isprint((int)c) ? c :'.'); + } + else + { + nrf_fprintf(p_ctx, " "); + } + } + + postfix_process(p_params, p_ctx, true); + + p_ctx->auto_flush = auto_flush; +} +#endif //NRF_LOG_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.c new file mode 100644 index 0000000000..4d7deef085 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.c @@ -0,0 +1,231 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_memobj.h" +#include "nrf_atomic.h" +#include "nrf_assert.h" + +typedef struct memobj_elem_s memobj_elem_t; + +typedef struct +{ + memobj_elem_t * p_next; +} memobj_header_t; + +typedef struct +{ + uint8_t user_cnt; + uint8_t chunk_cnt; + uint16_t chunk_size; +} memobj_head_header_fields_t; + +typedef struct +{ + union + { + nrf_atomic_u32_t atomic_user_cnt; + memobj_head_header_fields_t fields; + } data; +} memobj_head_header_t; + +typedef struct +{ + memobj_header_t header; + memobj_head_header_t head_header; + uint8_t data[1]; +} memobj_head_t; + +STATIC_ASSERT(sizeof(memobj_header_t) == NRF_MEMOBJ_STD_HEADER_SIZE); + +struct memobj_elem_s +{ + memobj_header_t header; + uint8_t data[1]; +}; + +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool) +{ + return nrf_balloc_init((nrf_balloc_t const *)p_pool); +} + +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size) +{ + uint32_t bsize = (uint32_t)NRF_BALLOC_ELEMENT_SIZE((nrf_balloc_t const *)p_pool) - sizeof(memobj_header_t); + uint8_t num_of_chunks = (uint8_t)CEIL_DIV(size + sizeof(memobj_head_header_t), bsize); + + memobj_head_t * p_head = nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_head == NULL) + { + return NULL; + } + p_head->head_header.data.fields.user_cnt = 0; + p_head->head_header.data.fields.chunk_cnt = 1; + p_head->head_header.data.fields.chunk_size = bsize; + + memobj_header_t * p_prev = (memobj_header_t *)p_head; + memobj_header_t * p_curr; + uint32_t i; + uint32_t chunk_less1 = (uint32_t)num_of_chunks - 1; + + p_prev->p_next = (memobj_elem_t *)p_pool; + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)nrf_balloc_alloc((nrf_balloc_t const *)p_pool); + if (p_curr) + { + (p_head->head_header.data.fields.chunk_cnt)++; + p_prev->p_next = (memobj_elem_t *)p_curr; + p_curr->p_next = (memobj_elem_t *)p_pool; + p_prev = p_curr; + } + else + { + //Couldn't allocate all requested buffers + nrf_memobj_free((nrf_memobj_t *)p_head); + return NULL; + } + } + return (nrf_memobj_t *)p_head; +} + +void nrf_memobj_free(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint8_t chunk_cnt = p_head->head_header.data.fields.chunk_cnt; + uint32_t i; + memobj_header_t * p_curr = (memobj_header_t *)p_obj; + memobj_header_t * p_next; + uint32_t chunk_less1 = (uint32_t)chunk_cnt - 1; + + for (i = 0; i < chunk_less1; i++) + { + p_curr = (memobj_header_t *)p_curr->p_next; + } + nrf_balloc_t const * p_pool2 = (nrf_balloc_t const *)p_curr->p_next; + + p_curr = (memobj_header_t *)p_obj; + for (i = 0; i < chunk_cnt; i++) + { + p_next = (memobj_header_t *)p_curr->p_next; + nrf_balloc_free(p_pool2, p_curr); + p_curr = p_next; + } +} + +void nrf_memobj_get(nrf_memobj_t const * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + (void)nrf_atomic_u32_add(&p_head->head_header.data.atomic_user_cnt, 1); +} + +void nrf_memobj_put(nrf_memobj_t * p_obj) +{ + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint32_t user_cnt = nrf_atomic_u32_sub(&p_head->head_header.data.atomic_user_cnt, 1); + memobj_head_header_fields_t * p_fields = (memobj_head_header_fields_t *)&user_cnt; + if (p_fields->user_cnt == 0) + { + nrf_memobj_free(p_obj); + } +} + +static void memobj_op(nrf_memobj_t * p_obj, + void * p_data, + uint32_t len, + uint32_t offset, + bool read) +{ + + memobj_head_t * p_head = (memobj_head_t *)p_obj; + uint32_t space_in_chunk = p_head->head_header.data.fields.chunk_size; + memobj_elem_t * p_curr_chunk = (memobj_elem_t *)p_obj; + uint32_t chunk_idx = (offset + sizeof(memobj_head_header_fields_t))/space_in_chunk; + uint32_t chunk_offset = (offset + sizeof(memobj_head_header_fields_t)) % space_in_chunk; + + uint8_t chunks_expected = CEIL_DIV((offset + sizeof(memobj_head_header_fields_t) + len), + space_in_chunk); + UNUSED_VARIABLE(chunks_expected); + ASSERT(p_head->head_header.data.fields.chunk_cnt >= chunks_expected); + + while (chunk_idx > 0) + { + p_curr_chunk = p_curr_chunk->header.p_next; + chunk_idx--; + } + + uint32_t src_offset = 0; + uint32_t curr_cpy_size = space_in_chunk-chunk_offset; + curr_cpy_size = curr_cpy_size > len ? len : curr_cpy_size; + + while (len) + { + if (read) + { + memcpy(&((uint8_t *)p_data)[src_offset], &p_curr_chunk->data[chunk_offset], curr_cpy_size); + } + else + { + memcpy(&p_curr_chunk->data[chunk_offset], &((uint8_t *)p_data)[src_offset], curr_cpy_size); + } + chunk_offset = 0; + p_curr_chunk = p_curr_chunk->header.p_next; + len -= curr_cpy_size; + src_offset += curr_cpy_size; + curr_cpy_size = (space_in_chunk > len) ? len : space_in_chunk; + } +} + +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + uint32_t len, + uint32_t offset) +{ + + memobj_op(p_obj, p_data, len, offset, false); +} + +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + uint32_t len, + uint32_t offset) +{ + memobj_op(p_obj, p_data, len, offset, true); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.h new file mode 100644 index 0000000000..d3188d3bcf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_memobj/nrf_memobj.h @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_MEMOBJ_H +#define NRF_MEMOBJ_H + +/** +* @defgroup nrf_memobj Memory Object module +* @{ +* @ingroup app_common +* @brief Functions for controlling memory object +*/ +#include +#include +#include "sdk_errors.h" +#include "nrf_balloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Memory object can consist of multiple object with the same size. Each object has header and data + * part. First element in memory object is memory object head which has special header, remaining objects + * has the same header. Model of memory object is presented below. + * + * |---------------------| |---------------------| |---------------------| + * | head header (u32): | --->| std header - p_next |------->| p_memobj_pool | + * | num_of_chunks, | | |---------------------| |---------------------| + * | ref counter | | | | | | + * |---------------------| | | | | | + * | std header - p_next |-| | | .... | | + * |---------------------| | data | | data | + * | | | | | | + * | data | | | | | + * | | | | | | + * |---------------------| |---------------------| |---------------------| + * head mid_element last_element + * + * + */ +#define NRF_MEMOBJ_STD_HEADER_SIZE sizeof(uint32_t) + +/** + * @brief Macro for creating a nrf_memobj pool. + * + * Macro declares nrf_balloc object. Element in the pool contains user defined data part and + * memobj header. + */ +#define NRF_MEMOBJ_POOL_DEF(_name, _element_size, _pool_size) \ + NRF_BALLOC_DEF(_name, ((_element_size)+NRF_MEMOBJ_STD_HEADER_SIZE), (_pool_size)) + +/** + * @brief Pool of memobj. + */ +typedef nrf_balloc_t nrf_memobj_pool_t; + +/** + * @brief Memobj handle. + */ +typedef void * nrf_memobj_t; + +/** + * @brief Function for initializing the memobj pool instance. + * + * This function initializes the pool. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * + * @return NRF_SUCCESS on success, otherwise error code. + */ +ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool); + +/** + * @brief Function for allocating memobj with requested size. + * + * Fixed length elements in the pool are linked together to provide amount of memory requested by + * the user. If memory object is successfully allocated then user can use memory however it is + * fragmented into multiple object so it has to be access through the API: @ref nrf_memobj_write, + * @ref nrf_memobj_read. + * + * This function initializes the pool. + * + * @param[in] p_pool Pointer to the memobj pool instance structure. + * @param[in] size Data size of requested object. + * + * @return Pointer to memory object or NULL if requested size cannot be allocated. + */ +nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool, + size_t size); + +/** + * @brief Function for indicating that memory object is used and cannot be freed. + * + * Memory object can be shared and reused between multiple modules and this mechanism ensures that + * object is freed when no longer used by any module. Memory object has a counter which is incremented + * whenever this function is called. @ref nrf_memobj_put function decrements the counter. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_get(nrf_memobj_t const * p_obj); + + +/** + * @brief Function for indicated that memory object is no longer used by the module and can be freed + * if no other module is using it. + * + * Memory object is returned to the pool if internal counter reaches 0 after decrementing. It means + * that no other module is needing it anymore. + * + * @note Memory object holds pointer to the pool which was used to allocate it so it does not have + * to be provided explicitly to this function. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_put(nrf_memobj_t * p_obj); + + +/** + * @brief Function for forcing freeing of the memory object. + * + * @note This function should be use with caution because it can lead to undefined behavior of the + * modules since modules using the memory object are not aware that it has been freed. + * + * @param[in] p_obj Pointer to memory object. + */ +void nrf_memobj_free(nrf_memobj_t * p_obj); + +/** + * @brief Function for writing data to the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to data to be written to the memory object. + * @param[in] len Amount of data to be written to the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_write(nrf_memobj_t * p_obj, + void * p_data, + uint32_t len, + uint32_t offset); + +/** + * @brief Function for reading data from the memory object. + * + * @param[in] p_obj Pointer to memory object. + * @param[in] p_data Pointer to the destination buffer. + * @param[in] len Amount of data to be read from the memory object. + * @param[in] offset Offset. + */ +void nrf_memobj_read(nrf_memobj_t * p_obj, + void * p_data, + uint32_t len, + uint32_t offset); + +#ifdef __cplusplus +} +#endif + +#endif //NRF_MEMOBJ_H + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section.h new file mode 100644 index 0000000000..4ac2b3a4ac --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SECTION_H__ +#define NRF_SECTION_H__ + +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup section_vars Section variables + * @ingroup app_common + * @{ + * + * @brief Section variables. + */ + +//lint -save -e27 -esym(526,*) + +#if defined(__ICCARM__) +// Enable IAR language extensions +#pragma language=extended +#endif + +/**@brief Macro for obtaining the address of the beginning of a section. + * + * param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(section_name, $$Base) + +#elif defined(__GNUC__) +#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(__start_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_START_ADDR(section_name) __section_begin(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for obtaining the address of the end of a section. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_END_ADDR(section_name) __section_end(STRINGIFY(section_name)) +#endif + + +/**@brief Macro for retrieving the length of a given section, in bytes. + * + * @param[in] section_name Name of the section. + * @hideinitializer + */ +#define NRF_SECTION_LENGTH(section_name) \ + ((size_t)NRF_SECTION_END_ADDR(section_name) - \ + (size_t)NRF_SECTION_START_ADDR(section_name)) + + +/**@brief Macro for creating a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables to be registered in the section. + * + * @warning Data type must be word aligned to prevent padding. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(section_name, $$Base); \ + extern void * CONCAT_2(section_name, $$Limit) + +#elif defined(__GNUC__) +#define NRF_SECTION_DEF(section_name, data_type) \ + extern data_type * CONCAT_2(__start_, section_name); \ + extern void * CONCAT_2(__stop_, section_name) + +#elif defined(__ICCARM__) +#define NRF_SECTION_DEF(section_name, data_type) \ + _Pragma(STRINGIFY(section = STRINGIFY(section_name))); + +#endif + + +/**@brief Macro for declaring a variable and registering it in a section. + * + * @details Declares a variable and registers it in a named section. This macro ensures that the + * variable is not stripped away when using optimizations. + * + * @note The order in which variables are placed in a section is dependent on the order in + * which the linker script encounters the variables during linking. + * + * @param[in] section_name Name of the section. + * @param[in] section_var Variable to register in the given section. + * @hideinitializer + */ +#if defined(__CC_ARM) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__GNUC__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + section_var __attribute__ ((section("." STRINGIFY(section_name)))) __attribute__((used)) + +#elif defined(__ICCARM__) +#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \ + __root section_var @ STRINGIFY(section_name) +#endif + + +/**@brief Macro for retrieving a variable from a section. + * + * @warning The stored symbol can only be resolved using this macro if the + * type of the data is word aligned. The operation of acquiring + * the stored symbol relies on the size of the stored type. No + * padding can exist in the named section in between individual + * stored items or this macro will fail. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variable. + * @param[in] i Index of the variable in section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_GET(section_name, data_type, i) \ + ((data_type*)NRF_SECTION_START_ADDR(section_name) + (i)) + + +/**@brief Macro for getting the number of variables in a section. + * + * @param[in] section_name Name of the section. + * @param[in] data_type Data type of the variables in the section. + * @hideinitializer + */ +#define NRF_SECTION_ITEM_COUNT(section_name, data_type) \ + NRF_SECTION_LENGTH(section_name) / sizeof(data_type) + +/** @} */ + +//lint -restore + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.c new file mode 100644 index 0000000000..a1c827ebad --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.c @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_SECTION_ITER) + +#include "nrf_section_iter.h" + + +#if !defined(__GNUC__) +static void nrf_section_iter_item_set(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + ASSERT(p_iter->p_section != NULL); + + while (true) + { + if (p_iter->p_section == p_iter->p_set->p_last) + { + // End of the section set. + p_iter->p_item = NULL; + return; + } + + if (p_iter->p_section->p_start != p_iter->p_section->p_end) + { + // Not empty section. + p_iter->p_item = p_iter->p_section->p_start; + return; + } + + // Next section. + p_iter->p_section++; + } +} +#endif + + +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set) +{ + ASSERT(p_iter != NULL); + ASSERT(p_set != NULL); + + p_iter->p_set = p_set; + +#if defined(__GNUC__) + p_iter->p_item = p_iter->p_set->section.p_start; + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + p_iter->p_section = p_set->p_first; + nrf_section_iter_item_set(p_iter); +#endif +} + +void nrf_section_iter_next(nrf_section_iter_t * p_iter) +{ + ASSERT(p_iter != NULL); + ASSERT(p_iter->p_set != NULL); + + if (p_iter->p_item == NULL) + { + return; + } + + p_iter->p_item = (void *)((size_t)(p_iter->p_item) + p_iter->p_set->item_size); + +#if defined(__GNUC__) + if (p_iter->p_item == p_iter->p_set->section.p_end) + { + p_iter->p_item = NULL; + } +#else + ASSERT(p_iter->p_section != NULL); + // End of current section reached? + if (p_iter->p_item == p_iter->p_section->p_end) + { + p_iter->p_section++; + nrf_section_iter_item_set(p_iter); + } +#endif +} + +#endif // NRF_MODULE_ENABLED(NRF_SECTION_ITER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.h new file mode 100644 index 0000000000..104dc4b0d1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/experimental_section_vars/nrf_section_iter.h @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_SECTION_ITER_H__ +#define NRF_SECTION_ITER_H__ + +#include +#include "nrf_section.h" +#include "nrf_assert.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup nrf_section_iter Section variables iterator + * @ingroup app_common + * @{ + */ + +/**@brief Single section description structure. */ +typedef struct +{ + void * p_start; //!< Pointer to the start of section. + void * p_end; //!< Pointer to the end of section. +} nrf_section_t; + + +/**@brief Set of the sections description structure. */ +typedef struct +{ +#if defined(__GNUC__) + nrf_section_t section; //!< Description of the set of sections. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated as + * one section. + */ +#else + nrf_section_t const * p_first; //!< Pointer to the first section in the set. + nrf_section_t const * p_last; //!< Pointer to the last section in the set. +#endif + size_t item_size; //!< Size of the single item in the section. +} nrf_section_set_t; + + +/**@brief Section iterator structure. */ +typedef struct +{ + nrf_section_set_t const * p_set; //!< Pointer to the appropriate section set. +#if !defined(__GNUC__) + nrf_section_t const * p_section; //!< Pointer to the selected section. + /**< + * In case of GCC all sections in the set are sorted and + * placed in contiguous area, because they are treated + * as one section. + */ +#endif + void * p_item; //!< Pointer to the selected item in the section. +} nrf_section_iter_t; + + +/**@brief Create a set of sections. + * + * @note This macro reserves memory for the given set of sections. + * + * @details A set of sections, is an ordered collections of sections. + * + * @param[in] _name Name of the set. + * @param[in] _type Type of the elements stored in the sections. + * @param[in] _count Number of the sections in the set. This parameter is ignored in case of GCC. + * @hideinitializer + */ +#if defined(__GNUC__) + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ + \ + NRF_SECTION_DEF(_name, _type); \ + static nrf_section_set_t const _name = \ + { \ + .section = \ + { \ + .p_start = NRF_SECTION_START_ADDR(_name), \ + .p_end = NRF_SECTION_END_ADDR(_name), \ + }, \ + .item_size = sizeof(_type), \ + } + +#else + +#define NRF_SECTION_SET_DEF(_name, _type, _count) \ +/*lint -save -emacro(14, MACRO_REPEAT_FOR*) */ \ +MACRO_REPEAT_FOR(_count, NRF_SECTION_DEF_, _name, _type) \ +static nrf_section_t const CONCAT_2(_name, _array)[] = \ +{ \ + MACRO_REPEAT_FOR(_count, NRF_SECTION_SET_DEF_, _name) \ +}; \ +/*lint -restore */ \ +static nrf_section_set_t const _name = \ +{ \ + .p_first = CONCAT_2(_name, _array), \ + .p_last = CONCAT_2(_name, _array) + ARRAY_SIZE(CONCAT_2(_name, _array)), \ + .item_size = sizeof(_type), \ +} + +#ifndef DOXYGEN +#define NRF_SECTION_DEF_(_priority, _name, _type) \ +NRF_SECTION_DEF(CONCAT_2(_name, _priority), _type); + +#define NRF_SECTION_SET_DEF_(_priority, _name) \ +{ \ + .p_start = NRF_SECTION_START_ADDR(CONCAT_2(_name, _priority)), \ + .p_end = NRF_SECTION_END_ADDR(CONCAT_2(_name, _priority)), \ +}, +#endif // DOXYGEN +#endif // __GNUC__ + + +/**@brief Macro to declare a variable and register it in the section set. + * + * @note The order of the section in the set is based on the priority. The order with which + * variables are placed in a section is dependant on the order with which the linker + * encouters the variables during linking. + * + * @param[in] _name Name of the section set. + * @param[in] _priority Priority of the desired section. + * @param[in] _var The variable to register in the given section. + * @hideinitializer + */ +#define NRF_SECTION_SET_ITEM_REGISTER(_name, _priority, _var) \ + NRF_SECTION_ITEM_REGISTER(CONCAT_2(_name, _priority), _var) + + +/**@brief Function for initializing the section set iterator. + * + * @param[in] p_iter Pointer to the iterator. + * @param[in] p_set Pointer to the sections set. + */ +void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set); + + +/**@brief Function for incrementing iterator. + * + * @param[in] p_iter Pointer to the iterator. + */ +void nrf_section_iter_next(nrf_section_iter_t * p_iter); + + +/**@brief Function for getting the element pointed to by the iterator. + * + * @param[in] p_iter Pointer to the iterator. + * + * @retval Pointer to the element or NULL if iterator points end of the set. + */ +static inline void * nrf_section_iter_get(nrf_section_iter_t const * p_iter) +{ + ASSERT(p_iter); + return p_iter->p_item; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // NRF_SECTION_ITER_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.c new file mode 100644 index 0000000000..995af78fa8 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.c @@ -0,0 +1,2159 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(FDS) +#include "fds.h" +#include "fds_internal_defs.h" + +#include +#include +#include +#include "nrf_error.h" +#include "nrf_atomic.h" +#include "nrf_atfifo.h" + +#include "nrf_fstorage.h" +#if (FDS_BACKEND == NRF_FSTORAGE_SD) +#include "nrf_fstorage_sd.h" +#elif (FDS_BACKEND == NRF_FSTORAGE_NVMC) +#include "nrf_fstorage_nvmc.h" +#else +#error Invalid FDS backend. +#endif + +#if (FDS_CRC_CHECK_ON_READ) +#include "crc16.h" +#endif + + +static void fs_event_handler(nrf_fstorage_evt_t * evt); + +NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) = +{ + // The flash area boundaries are set in fds_init(). + .evt_handler = fs_event_handler, +}; + +// Internal status flags. +static struct +{ + bool volatile initialized; + nrf_atomic_flag_t initializing; +} m_flags; + +// The number of queued operations. +// Incremented by queue_start() and decremented by queue_has_next(). +static nrf_atomic_u32_t m_queued_op_cnt; + +// The number of registered users and their callback functions. +static nrf_atomic_u32_t m_users; +static fds_cb_t m_cb_table[FDS_MAX_USERS]; + +// The latest (largest) record ID written so far. +static nrf_atomic_u32_t m_latest_rec_id; + +// Queue of fds operations. +NRF_ATFIFO_DEF(m_queue, fds_op_t, FDS_OP_QUEUE_SIZE); + +// Structures used to hold informations about virtual pages. +static fds_page_t m_pages[FDS_DATA_PAGES]; +static fds_swap_page_t m_swap_page; + +// Garbage collection data. +static fds_gc_data_t m_gc; + + +static void event_send(fds_evt_t const * const p_evt) +{ + for (uint32_t user = 0; user < FDS_MAX_USERS; user++) + { + if (m_cb_table[user] != NULL) + { + m_cb_table[user](p_evt); + } + } +} + + +static void event_prepare(fds_op_t const * const p_op, fds_evt_t * const p_evt) +{ + switch (p_op->op_code) + { + case FDS_OP_INIT: + p_evt->id = FDS_EVT_INIT; + break; + + case FDS_OP_WRITE: + p_evt->id = FDS_EVT_WRITE; + p_evt->write.file_id = p_op->write.header.file_id; + p_evt->write.record_key = p_op->write.header.record_key; + p_evt->write.record_id = p_op->write.header.record_id; + p_evt->write.is_record_updated = 0; + break; + + case FDS_OP_UPDATE: + p_evt->id = FDS_EVT_UPDATE; + p_evt->write.file_id = p_op->write.header.file_id; + p_evt->write.record_key = p_op->write.header.record_key; + p_evt->write.record_id = p_op->write.header.record_id; + p_evt->write.is_record_updated = (p_op->write.step == FDS_OP_WRITE_DONE); + break; + + case FDS_OP_DEL_RECORD: + p_evt->id = FDS_EVT_DEL_RECORD; + p_evt->del.file_id = p_op->del.file_id; + p_evt->del.record_key = p_op->del.record_key; + p_evt->del.record_id = p_op->del.record_to_delete; + break; + + case FDS_OP_DEL_FILE: + p_evt->id = FDS_EVT_DEL_FILE; + p_evt->del.file_id = p_op->del.file_id; + p_evt->del.record_key = FDS_RECORD_KEY_DIRTY; + p_evt->del.record_id = 0; + break; + + case FDS_OP_GC: + p_evt->id = FDS_EVT_GC; + break; + + default: + // Should not happen. + break; + } +} + + +static bool header_has_next(fds_header_t const * p_hdr, uint32_t const * p_page_end) +{ + uint32_t const * const p_hdr32 = (uint32_t*)p_hdr; + return ( ( p_hdr32 < p_page_end) + && (*p_hdr32 != FDS_ERASED_WORD)); // Check last to be on the safe side (dereference) +} + + +// Jump to the next header. +static fds_header_t const * header_jump(fds_header_t const * const p_hdr) +{ + return (fds_header_t*)((uint32_t*)p_hdr + FDS_HEADER_SIZE + p_hdr->length_words); +} + + +static fds_header_status_t header_check(fds_header_t const * p_hdr, uint32_t const * p_page_end) +{ + if (((uint32_t*)header_jump(p_hdr) > p_page_end)) + { + // The length field would jump across the page boundary. + // FDS won't allow writing such a header, therefore it has been corrupted. + return FDS_HEADER_CORRUPT; + } + + if ( (p_hdr->file_id == FDS_FILE_ID_INVALID) + || (p_hdr->record_key == FDS_RECORD_KEY_DIRTY)) + { + return FDS_HEADER_DIRTY; + } + + return FDS_HEADER_VALID; +} + + +static bool address_is_valid(uint32_t const * const p_addr) +{ + return ((p_addr != NULL) && + (p_addr >= (uint32_t*)m_fs.start_addr) && + (p_addr <= (uint32_t*)m_fs.end_addr) && + (is_word_aligned(p_addr))); +} + + +// Reads a page tag, and determines if the page is used to store data or as swap. +static fds_page_type_t page_identify(uint32_t const * const p_page_addr) +{ + if ( (p_page_addr == NULL) // Should never happen. + || (p_page_addr[FDS_PAGE_TAG_WORD_0] != FDS_PAGE_TAG_MAGIC)) + { + return FDS_PAGE_UNDEFINED; + } + + switch (p_page_addr[FDS_PAGE_TAG_WORD_1]) + { + case FDS_PAGE_TAG_SWAP: + return FDS_PAGE_SWAP; + + case FDS_PAGE_TAG_DATA: + return FDS_PAGE_DATA; + + default: + return FDS_PAGE_UNDEFINED; + } +} + + +static bool page_is_erased(uint32_t const * const p_page_addr) +{ + for (uint32_t i = 0; i < FDS_PAGE_SIZE; i++) + { + if (*(p_page_addr + i) != FDS_ERASED_WORD) + { + return false; + } + } + + return true; +} + + +// NOTE: Must be called from within a critical section. +static bool page_has_space(uint16_t page, uint16_t length_words) +{ + length_words += m_pages[page].write_offset; + length_words += m_pages[page].words_reserved; + return (length_words < FDS_PAGE_SIZE); +} + + +// Given a pointer to a record, find the index of the page on which it is stored. +// Returns FDS_SUCCESS if the page is found, FDS_ERR_NOT_FOUND otherwise. +static ret_code_t page_from_record(uint16_t * const p_page, uint32_t const * const p_rec) +{ + ret_code_t ret = FDS_ERR_NOT_FOUND; + + CRITICAL_SECTION_ENTER(); + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if ((p_rec > m_pages[i].p_addr) && + (p_rec < m_pages[i].p_addr + FDS_PAGE_SIZE)) + { + ret = FDS_SUCCESS; + *p_page = i; + break; + } + } + CRITICAL_SECTION_EXIT(); + + return ret; +} + + +// Scan a page to determine how many words have been written to it. +// This information is used to set the page write offset during initialization. +// Additionally, this function updates the latest record ID as it proceeds. +// If an invalid record header is found, the can_gc argument is set to true. +static void page_scan(uint32_t const * p_addr, + uint16_t * const words_written, + bool * const can_gc) +{ + uint32_t const * const p_page_end = p_addr + FDS_PAGE_SIZE; + + p_addr += FDS_PAGE_TAG_SIZE; + *words_written = FDS_PAGE_TAG_SIZE; + + fds_header_t const * p_header = (fds_header_t*)p_addr; + + while (header_has_next(p_header, p_page_end)) + { + fds_header_status_t hdr = header_check(p_header, p_page_end); + + if (hdr == FDS_HEADER_VALID) + { + // Update the latest (largest) record ID. + if (p_header->record_id > m_latest_rec_id) + { + m_latest_rec_id = p_header->record_id; + } + } + else + { + if (can_gc != NULL) + { + *can_gc = true; + } + + if (hdr == FDS_HEADER_CORRUPT) + { + // It could happen that a record has a corrupt header which would set a + // wrong offset for this page. In such cases, update this value to its maximum, + // to ensure that no new records will be written to this page and to enable + // correct statistics reporting by fds_stat(). + *words_written = FDS_PAGE_SIZE; + + // We can't continue to scan this page. + return; + } + } + + *words_written += (FDS_HEADER_SIZE + p_header->length_words); + p_header = header_jump(p_header); + } +} + + +static void page_offsets_update(fds_page_t * const p_page, uint16_t length_words) +{ + p_page->write_offset += (FDS_HEADER_SIZE + length_words); + p_page->words_reserved -= (FDS_HEADER_SIZE + length_words); +} + + +// Tags a page as swap, i.e., reserved for GC. +static ret_code_t page_tag_write_swap(void) +{ + // The tag needs to be statically allocated since it is not buffered by fstorage. + static uint32_t const page_tag_swap[] = {FDS_PAGE_TAG_MAGIC, FDS_PAGE_TAG_SWAP}; + return nrf_fstorage_write(&m_fs, (uint32_t)m_swap_page.p_addr, page_tag_swap, FDS_PAGE_TAG_SIZE * sizeof(uint32_t), NULL); +} + + +// Tags a page as data, i.e, ready for storage. +static ret_code_t page_tag_write_data(uint32_t const * const p_page_addr) +{ + // The tag needs to be statically allocated since it is not buffered by fstorage. + static uint32_t const page_tag_data[] = {FDS_PAGE_TAG_MAGIC, FDS_PAGE_TAG_DATA}; + return nrf_fstorage_write(&m_fs, (uint32_t)p_page_addr, page_tag_data, FDS_PAGE_TAG_SIZE * sizeof(uint32_t), NULL); +} + + +// Reserve space on a page. +// NOTE: this function takes into the account the space required for the record header. +static ret_code_t write_space_reserve(uint16_t length_words, uint16_t * p_page) +{ + bool space_reserved = false; + uint16_t const total_len_words = length_words + FDS_HEADER_SIZE; + + if (total_len_words >= FDS_PAGE_SIZE - FDS_PAGE_TAG_SIZE) + { + return FDS_ERR_RECORD_TOO_LARGE; + } + + CRITICAL_SECTION_ENTER(); + for (uint16_t page = 0; page < FDS_DATA_PAGES; page++) + { + if ((m_pages[page].page_type == FDS_PAGE_DATA) && + (page_has_space(page, total_len_words))) + { + space_reserved = true; + *p_page = page; + + m_pages[page].words_reserved += total_len_words; + break; + } + } + CRITICAL_SECTION_EXIT(); + + return (space_reserved) ? FDS_SUCCESS : FDS_ERR_NO_SPACE_IN_FLASH; +} + + +// Undo a write_space_reserve() call. +// NOTE: Must be called within a critical section. +static void write_space_free(uint16_t length_words, uint16_t page) +{ + m_pages[page].words_reserved -= (length_words + FDS_HEADER_SIZE); +} + + +static uint32_t record_id_new(void) +{ + return nrf_atomic_u32_add(&m_latest_rec_id, 1); +} + + +// Given a page and a record, find the next valid record on that page. +// If p_record is NULL, search from the beginning of the page, +// otherwise, resume searching from p_record. +// Return true if a record is found, false otherwise. +// If no record is found, p_record is unchanged. +static bool record_find_next(uint16_t page, uint32_t const ** p_record) +{ + uint32_t const * p_page_end = (m_pages[page].p_addr + FDS_PAGE_SIZE); + + // If this is the first call on this page, start searching from its beginning. + // Otherwise, jump to the next record. + fds_header_t const * p_header = (fds_header_t*)(*p_record); + + if (p_header != NULL) + { + p_header = header_jump(p_header); + } + else + { + p_header = (fds_header_t*)(m_pages[page].p_addr + FDS_PAGE_TAG_SIZE); + } + + // Read records from the page until: + // - a valid record is found or + // - the last record on a page is found + + while (header_has_next(p_header, p_page_end)) + { + switch (header_check(p_header, p_page_end)) + { + case FDS_HEADER_VALID: + *p_record = (uint32_t*)p_header; + return true; + + case FDS_HEADER_DIRTY: + p_header = header_jump(p_header); + break; + + case FDS_HEADER_CORRUPT: + // We can't reliably jump over this record. + // There is nothing more we can do on this page. + return false; + } + } + + // No more valid records on this page. + return false; +} + + +// Find a record given its descriptor and retrive the page in which the record is stored. +// NOTE: Do not pass NULL as an argument for p_page. +static bool record_find_by_desc(fds_record_desc_t * const p_desc, uint16_t * const p_page) +{ + // If the gc_run_count field in the descriptor matches our counter, then the record has + // not been moved. If the address is valid, and the record ID matches, there is no need + // to find the record again. Only lookup the page in which the record is stored. + + if ((address_is_valid(p_desc->p_record)) && + (p_desc->gc_run_count == m_gc.run_count) && + (p_desc->record_id == ((fds_header_t*)p_desc->p_record)->record_id)) + { + return (page_from_record(p_page, p_desc->p_record) == FDS_SUCCESS); + } + + // Otherwise, find the record in flash. + for (*p_page = 0; *p_page < FDS_DATA_PAGES; (*p_page)++) + { + // Set p_record to NULL to make record_find_next() search from the beginning of the page. + uint32_t const * p_record = NULL; + + while (record_find_next(*p_page, &p_record)) + { + fds_header_t const * const p_header = (fds_header_t*)p_record; + if (p_header->record_id == p_desc->record_id) + { + p_desc->p_record = p_record; + p_desc->gc_run_count = m_gc.run_count; + return true; + } + } + } + + return false; +} + + +// Search for a record and return its descriptor. +// If p_file_id is NULL, only the record key will be used for matching. +// If p_record_key is NULL, only the file ID will be used for matching. +// If both are NULL, it will iterate through all records. +static ret_code_t record_find(uint16_t const * p_file_id, + uint16_t const * p_record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token) +{ + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_desc == NULL || p_token == NULL) + { + return FDS_ERR_NULL_ARG; + } + + // Begin (or resume) searching for a record. + for (; p_token->page < FDS_DATA_PAGES; p_token->page++) + { + if (m_pages[p_token->page].page_type != FDS_PAGE_DATA) + { + // It might be that the page is FDS_PAGE_UNDEFINED. + // Skip this page. + continue; + } + + while (record_find_next(p_token->page, &p_token->p_addr)) + { + fds_header_t const * p_header = (fds_header_t*)p_token->p_addr; + + // A valid record was found, check its header for a match. + if ((p_file_id != NULL) && + (p_header->file_id != *p_file_id)) + { + continue; + } + + if ((p_record_key != NULL) && + (p_header->record_key != *p_record_key)) + { + continue; + } + + // Record found; update the descriptor. + p_desc->record_id = p_header->record_id; + p_desc->p_record = p_token->p_addr; + p_desc->gc_run_count = m_gc.run_count; + + return FDS_SUCCESS; + } + + // We have scanned an entire page. Set the address in the token to NULL + // so that it will be updated in the next iteration. + p_token->p_addr = NULL; + } + + return FDS_ERR_NOT_FOUND; +} + + +// Retrieve statistics about dirty records on a page. +static void records_stat(uint16_t page, + uint16_t * p_valid_records, + uint16_t * p_dirty_records, + uint16_t * p_freeable_words, + bool * p_corruption) +{ + fds_header_t const * p_header = (fds_header_t*)(m_pages[page].p_addr + FDS_PAGE_TAG_SIZE); + uint32_t const * const p_page_end = (m_pages[page].p_addr + FDS_PAGE_SIZE); + + while (header_has_next(p_header, p_page_end)) + { + switch (header_check(p_header, p_page_end)) + { + case FDS_HEADER_DIRTY: + *p_dirty_records += 1; + *p_freeable_words += FDS_HEADER_SIZE + p_header->length_words; + p_header = header_jump(p_header); + break; + + case FDS_HEADER_VALID: + *p_valid_records += 1; + p_header = header_jump(p_header); + break; + + case FDS_HEADER_CORRUPT: + { + *p_dirty_records += 1; + *p_freeable_words += (p_page_end - (uint32_t*)p_header); + *p_corruption = true; + // We can't continue on this page. + return; + } + + default: + break; + } + } +} + + +// Get a buffer on the queue of operations. +static fds_op_t * queue_buf_get(nrf_atfifo_item_put_t * p_iput_ctx) +{ + fds_op_t * const p_op = (fds_op_t*) nrf_atfifo_item_alloc(m_queue, p_iput_ctx); + + memset(p_op, 0x00, sizeof(fds_op_t)); + return p_op; +} + + +// Commit a buffer to the queue of operations. +static void queue_buf_store(nrf_atfifo_item_put_t * p_iput_ctx) +{ + (void) nrf_atfifo_item_put(m_queue, p_iput_ctx); +} + + +// Load the next operation from the queue. +static fds_op_t * queue_load(nrf_atfifo_item_get_t * p_iget_ctx) +{ + return (fds_op_t*) nrf_atfifo_item_get(m_queue, p_iget_ctx); +} + + +// Free the currently loaded operation. +static void queue_free(nrf_atfifo_item_get_t * p_iget_ctx) +{ + // Free the current queue element. + (void) nrf_atfifo_item_free(m_queue, p_iget_ctx); +} + + +static bool queue_has_next(void) +{ + // Decrement the number of queued operations. + ASSERT(m_queued_op_cnt != 0); + return nrf_atomic_u32_sub(&m_queued_op_cnt, 1); +} + + +// This function is called during initialization to setup the page structure (m_pages) and +// provide additional information regarding eventual further initialization steps. +static fds_init_opts_t pages_init(void) +{ + uint32_t ret = NO_PAGES; + uint16_t page = 0; + uint16_t total_pages_available = FDS_VIRTUAL_PAGES; + bool swap_set_but_not_found = false; + + for (uint16_t i = 0; i < FDS_VIRTUAL_PAGES; i++) + { + uint32_t const * const p_page_addr = (uint32_t*)m_fs.start_addr + (i * FDS_PAGE_SIZE); + fds_page_type_t const page_type = page_identify(p_page_addr); + + switch (page_type) + { + case FDS_PAGE_UNDEFINED: + { + if (page_is_erased(p_page_addr)) + { + if (m_swap_page.p_addr != NULL) + { + // If a swap page is already set, flag the page as erased (in m_pages) + // and try to tag it as data (in flash) later on during initialization. + m_pages[page].page_type = FDS_PAGE_ERASED; + m_pages[page].p_addr = p_page_addr; + m_pages[page].write_offset = FDS_PAGE_TAG_SIZE; + + // This is a candidate for a potential new swap page, in case the + // current swap is going to be promoted to complete a GC instance. + m_gc.cur_page = page; + page++; + } + else + { + // If there is no swap page yet, use this one. + m_swap_page.p_addr = p_page_addr; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + swap_set_but_not_found = true; + } + + ret |= PAGE_ERASED; + } + else + { + // The page contains non-FDS data. + // Do not initialize or use this page. + total_pages_available--; + m_pages[page].p_addr = p_page_addr; + m_pages[page].page_type = FDS_PAGE_UNDEFINED; + page++; + } + } break; + + case FDS_PAGE_DATA: + { + m_pages[page].page_type = FDS_PAGE_DATA; + m_pages[page].p_addr = p_page_addr; + + // Scan the page to compute its write offset and determine whether or not the page + // can be garbage collected. Additionally, update the latest kwown record ID. + page_scan(p_page_addr, &m_pages[page].write_offset, &m_pages[page].can_gc); + + ret |= PAGE_DATA; + page++; + } break; + + case FDS_PAGE_SWAP: + { + if (swap_set_but_not_found) + { + m_pages[page].page_type = FDS_PAGE_ERASED; + m_pages[page].p_addr = m_swap_page.p_addr; + m_pages[page].write_offset = FDS_PAGE_TAG_SIZE; + + page++; + } + + m_swap_page.p_addr = p_page_addr; + // If the swap is promoted, this offset should be kept, otherwise, + // it should be set to FDS_PAGE_TAG_SIZE. + page_scan(p_page_addr, &m_swap_page.write_offset, NULL); + + ret |= (m_swap_page.write_offset == FDS_PAGE_TAG_SIZE) ? + PAGE_SWAP_CLEAN : PAGE_SWAP_DIRTY; + } break; + + default: + // Shouldn't happen. + break; + } + } + + if (total_pages_available < 2) + { + ret &= NO_PAGES; + } + + return (fds_init_opts_t)ret; +} + + +// Write the first part of a record header (the key and length). +static ret_code_t record_header_write_begin(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // Write the record ID next. + p_op->write.step = FDS_OP_WRITE_RECORD_ID; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_TL), + &p_op->write.header.record_key, FDS_HEADER_SIZE_TL * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? FDS_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_write_id(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // If this record has no data, write the last part of the header directly. + // Otherwise, write the record data next. + p_op->write.step = (p_op->write.p_data != NULL) ? + FDS_OP_WRITE_DATA : FDS_OP_WRITE_HEADER_FINALIZE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_ID), + &p_op->write.header.record_id, FDS_HEADER_SIZE_ID * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? FDS_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_write_finalize(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + // If this is a simple write operation, then this is the last step. + // If this is an update instead, delete the old record next. + p_op->write.step = (p_op->op_code == FDS_OP_UPDATE) ? + FDS_OP_WRITE_FLAG_DIRTY : FDS_OP_WRITE_DONE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_IC), + &p_op->write.header.file_id, FDS_HEADER_SIZE_IC * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? FDS_SUCCESS : FDS_ERR_BUSY; +} + + +static ret_code_t record_header_flag_dirty(uint32_t * const p_record, uint16_t page_to_gc) +{ + // Used to flag a record as dirty, i.e. ready for garbage collection. + // Must be statically allocated since it will be written to flash. + __ALIGN(4) static uint32_t const dirty_header = {0xFFFF0000}; + + // Flag the record as dirty. + ret_code_t ret; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)p_record, + &dirty_header, FDS_HEADER_SIZE_TL * sizeof(uint32_t), NULL); + + if (ret != NRF_SUCCESS) + { + return FDS_ERR_BUSY; + } + + m_pages[page_to_gc].can_gc = true; + + return FDS_SUCCESS; +} + + +static ret_code_t record_find_and_delete(fds_op_t * const p_op) +{ + ret_code_t ret; + uint16_t page; + fds_record_desc_t desc = {0}; + + desc.record_id = p_op->del.record_to_delete; + + if (record_find_by_desc(&desc, &page)) + { + fds_header_t const * const p_header = (fds_header_t const *)desc.p_record; + + // Copy the record key and file ID, so that they can be returned in the event. + // In case this function is run as part of an update, there is no need to copy + // the file ID and record key since they are present in the header stored + // in the queue element. + + p_op->del.file_id = p_header->file_id; + p_op->del.record_key = p_header->record_key; + + // Flag the record as dirty. + ret = record_header_flag_dirty((uint32_t*)desc.p_record, page); + } + else + { + // The record never existed, or it has already been deleted. + ret = FDS_ERR_NOT_FOUND; + } + + return ret; +} + + +// Finds a record within a file and flags it as dirty. +static ret_code_t file_find_and_delete(fds_op_t * const p_op) +{ + ret_code_t ret; + fds_record_desc_t desc; + + // This token must persist across calls. + static fds_find_token_t tok = {0}; + + // Pass NULL to ignore the record key. + ret = record_find(&p_op->del.file_id, NULL, &desc, &tok); + + if (ret == FDS_SUCCESS) + { + // A record was found: flag it as dirty. + ret = record_header_flag_dirty((uint32_t*)desc.p_record, tok.page); + } + else // FDS_ERR_NOT_FOUND + { + // No more records were found. Zero the token, so that it can be reused. + memset(&tok, 0x00, sizeof(fds_find_token_t)); + } + + return ret; +} + + +// Writes record data to flash. +static ret_code_t record_write_data(fds_op_t * const p_op, uint32_t * const p_addr) +{ + ret_code_t ret; + + p_op->write.step = FDS_OP_WRITE_HEADER_FINALIZE; + + ret = nrf_fstorage_write(&m_fs, (uint32_t)(p_addr + FDS_OFFSET_DATA), + p_op->write.p_data, p_op->write.header.length_words * sizeof(uint32_t), NULL); + + return (ret == NRF_SUCCESS) ? FDS_SUCCESS : FDS_ERR_BUSY; +} + + +#if (FDS_CRC_CHECK_ON_READ) +static bool crc_verify_success(uint16_t crc, uint16_t len_words, uint32_t const * const p_data) +{ + uint16_t computed_crc; + + // The CRC is computed on the entire record, except the CRC field itself. + // The record header is 12 bytes, out of these we have to skip bytes 6 to 8 where the + // CRC itself is stored. Then we compute the CRC for the rest of the record, from byte 8 of + // the header (where the record ID begins) to the end of the record data. + computed_crc = crc16_compute((uint8_t const *)p_data, 6, NULL); + computed_crc = crc16_compute((uint8_t const *)p_data + 8, + (FDS_HEADER_SIZE_ID + len_words) * sizeof(uint32_t), + &computed_crc); + + return (computed_crc == crc); +} +#endif + + +static void gc_init(void) +{ + m_gc.run_count++; + m_gc.cur_page = 0; + m_gc.resume = false; + + // Setup which pages to GC. Defer checking for open records and the can_gc flag, + // as other operations might change those while GC is running. + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + m_gc.do_gc_page[i] = (m_pages[i].page_type == FDS_PAGE_DATA); + } +} + + +// Obtain the next page to be garbage collected. +// Returns true if there are pages left to garbage collect, returns false otherwise. +static bool gc_page_next(uint16_t * const p_next_page) +{ + bool ret = false; + + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if (m_gc.do_gc_page[i]) + { + // Do not attempt to GC this page again. + m_gc.do_gc_page[i] = false; + + // Only GC pages with no open records and with some records which have been deleted. + if ((m_pages[i].records_open == 0) && (m_pages[i].can_gc == true)) + { + *p_next_page = i; + ret = true; + break; + } + } + } + + return ret; +} + + +static ret_code_t gc_swap_erase(void) +{ + m_gc.state = GC_DISCARD_SWAP; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + return nrf_fstorage_erase(&m_fs, (uint32_t)m_swap_page.p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); +} + + +// Erase the page being garbage collected, or erase the swap in case there are any open +// records on the page being garbage collected. +static ret_code_t gc_page_erase(void) +{ + uint32_t ret; + uint16_t const gc = m_gc.cur_page; + + if (m_pages[gc].records_open == 0) + { + m_gc.state = GC_ERASE_PAGE; + + ret = nrf_fstorage_erase(&m_fs, (uint32_t)m_pages[gc].p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); + } + else + { + // If there are open records, stop garbage collection on this page. + // Discard the swap and try to garbage collect another page. + ret = gc_swap_erase(); + } + + return ret; +} + + +// Copy the current record to swap. +static ret_code_t gc_record_copy(void) +{ + fds_header_t const * const p_header = (fds_header_t*)m_gc.p_record_src; + uint32_t const * const p_dest = m_swap_page.p_addr + m_swap_page.write_offset; + uint16_t const record_len = FDS_HEADER_SIZE + p_header->length_words; + + m_gc.state = GC_COPY_RECORD; + + // Copy the record to swap; it is guaranteed to fit in the destination page, + // so there is no need to check its size. This will either succeed or timeout. + return nrf_fstorage_write(&m_fs, (uint32_t)p_dest, m_gc.p_record_src, + record_len * sizeof(uint32_t), + NULL); +} + + +static ret_code_t gc_record_find_next(void) +{ + ret_code_t ret; + + // Find the next valid record to copy. + if (record_find_next(m_gc.cur_page, &m_gc.p_record_src)) + { + ret = gc_record_copy(); + } + else + { + // No more records left to copy on this page; swap pages. + ret = gc_page_erase(); + } + + return ret; +} + + +// Promote the swap by tagging it as a data page. +static ret_code_t gc_swap_promote(void) +{ + m_gc.state = GC_PROMOTE_SWAP; + return page_tag_write_data(m_pages[m_gc.cur_page].p_addr); +} + + +// Tag the page just garbage collected as swap. +static ret_code_t gc_tag_new_swap(void) +{ + m_gc.state = GC_TAG_NEW_SWAP; + m_gc.p_record_src = NULL; + return page_tag_write_swap(); +} + + +static ret_code_t gc_next_page(void) +{ + if (!gc_page_next(&m_gc.cur_page)) + { + // No pages left to GC; GC has terminated. Reset the state. + m_gc.state = GC_BEGIN; + m_gc.cur_page = 0; + m_gc.p_record_src = NULL; + + return FDS_OP_COMPLETED; + } + + return gc_record_find_next(); +} + + +// Update the swap page offeset after a record has been successfully copied to it. +static void gc_update_swap_offset(void) +{ + fds_header_t const * const p_header = (fds_header_t*)m_gc.p_record_src; + uint16_t const record_len = FDS_HEADER_SIZE + p_header->length_words; + + m_swap_page.write_offset += record_len; +} + + +static void gc_swap_pages(void) +{ + // The page being garbage collected will be the new swap page, + // and the current swap will be used as a data page (promoted). + uint32_t const * const p_addr = m_swap_page.p_addr; + + m_swap_page.p_addr = m_pages[m_gc.cur_page].p_addr; + m_pages[m_gc.cur_page].p_addr = p_addr; + + // Keep the offset for this page, but reset it for the swap. + m_pages[m_gc.cur_page].write_offset = m_swap_page.write_offset; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; +} + + +static void gc_state_advance(void) +{ + switch (m_gc.state) + { + case GC_BEGIN: + gc_init(); + m_gc.state = GC_NEXT_PAGE; + break; + + // A record was successfully copied. + case GC_COPY_RECORD: + gc_update_swap_offset(); + m_gc.state = GC_FIND_NEXT_RECORD; + break; + + // A page was successfully erased. Prepare to promote the swap. + case GC_ERASE_PAGE: + gc_swap_pages(); + m_gc.state = GC_PROMOTE_SWAP; + break; + + // Swap was discarded because the page being GC'ed had open records. + case GC_DISCARD_SWAP: + // Swap was successfully promoted. + case GC_PROMOTE_SWAP: + // Prepare to tag the page just GC'ed as swap. + m_gc.state = GC_TAG_NEW_SWAP; + break; + + case GC_TAG_NEW_SWAP: + m_gc.state = GC_NEXT_PAGE; + break; + + default: + // Should not happen. + break; + } +} + + +// Initialize the filesystem. +static ret_code_t init_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret = FDS_ERR_INTERNAL; + + if (prev_ret != NRF_SUCCESS) + { + // A previous operation has timed out. + m_flags.initializing = false; + return FDS_ERR_OPERATION_TIMEOUT; + } + + switch (p_op->init.step) + { + case FDS_OP_INIT_TAG_SWAP: + { + // The page write offset was determined previously by pages_init(). + p_op->init.step = FDS_OP_INIT_TAG_DATA; + ret = page_tag_write_swap(); + } break; + + case FDS_OP_INIT_TAG_DATA: + { + // Tag remaining erased pages as data. + bool write_reqd = false; + for (uint16_t i = 0; i < FDS_DATA_PAGES; i++) + { + if (m_pages[i].page_type == FDS_PAGE_ERASED) + { + m_pages[i].page_type = FDS_PAGE_DATA; + write_reqd = true; + ret = page_tag_write_data(m_pages[i].p_addr); + break; + } + } + if (!write_reqd) + { + m_flags.initialized = true; + m_flags.initializing = false; + return FDS_OP_COMPLETED; + } + } break; + + case FDS_OP_INIT_ERASE_SWAP: + { + // If the swap is going to be discarded then reset its write_offset. + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + ret = nrf_fstorage_erase(&m_fs, (uint32_t)m_swap_page.p_addr, FDS_PHY_PAGES_IN_VPAGE, NULL); + } break; + + case FDS_OP_INIT_PROMOTE_SWAP: + { + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + + // When promoting the swap, keep the write_offset set by pages_init(). + ret = page_tag_write_data(m_swap_page.p_addr); + + uint16_t const gc = m_gc.cur_page; + uint32_t const * const p_old_swap = m_swap_page.p_addr; + + // Execute the swap. + m_swap_page.p_addr = m_pages[gc].p_addr; + m_pages[gc].p_addr = p_old_swap; + + // Copy the offset from the swap to the new page. + m_pages[gc].write_offset = m_swap_page.write_offset; + m_swap_page.write_offset = FDS_PAGE_TAG_SIZE; + + m_pages[gc].page_type = FDS_PAGE_DATA; + } break; + + default: + // Should not happen. + break; + } + + if (ret != FDS_SUCCESS) + { + // fstorage queue was full. + m_flags.initializing = false; + return FDS_ERR_BUSY; + } + + return FDS_OP_EXECUTING; +} + + +// Executes write and update operations. +static ret_code_t write_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret; + uint32_t * p_write_addr; + fds_page_t * const p_page = &m_pages[p_op->write.page]; + + // This must persist across calls. + static fds_record_desc_t desc = {0}; + // When a record is updated, this variable will hold the page where the old + // copy was stored. This will be used to set the can_gc flag when the header is + // invalidated (FDS_OP_WRITE_FLAG_DIRTY). + static uint16_t page; + + if (prev_ret != NRF_SUCCESS) + { + // The previous operation has timed out, update offsets. + page_offsets_update(p_page, p_op->write.header.length_words); + return FDS_ERR_OPERATION_TIMEOUT; + } + + // Compute the address where to write data. + p_write_addr = (uint32_t*)(p_page->p_addr + p_page->write_offset); + + // Execute the current step of the operation, and set one to be executed next. + switch (p_op->write.step) + { + case FDS_OP_WRITE_FIND_RECORD: + { + // The first step of updating a record constists of locating the copy to be deleted. + // If the old copy couldn't be found for any reason then the update should fail. + // This prevents duplicates when queuing multiple updates of the same record. + desc.p_record = NULL; + desc.record_id = p_op->write.record_to_delete; + + if (!record_find_by_desc(&desc, &page)) + { + return FDS_ERR_NOT_FOUND; + } + // Setting the step is redundant since we are falling through. + } + // Fallthrough to FDS_OP_WRITE_HEADER_BEGIN. + + case FDS_OP_WRITE_HEADER_BEGIN: + ret = record_header_write_begin(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_RECORD_ID: + ret = record_header_write_id(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_DATA: + ret = record_write_data(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_HEADER_FINALIZE: + ret = record_header_write_finalize(p_op, p_write_addr); + break; + + case FDS_OP_WRITE_FLAG_DIRTY: + p_op->write.step = FDS_OP_WRITE_DONE; + ret = record_header_flag_dirty((uint32_t*)desc.p_record, page); + break; + + case FDS_OP_WRITE_DONE: + ret = FDS_OP_COMPLETED; + +#if (FDS_CRC_CHECK_ON_WRITE) + if (!crc_verify_success(p_op->write.header.crc16, + p_op->write.header.length_words, + p_write_addr)) + { + ret = FDS_ERR_CRC_CHECK_FAILED; + } +#endif + break; + + default: + ret = FDS_ERR_INTERNAL; + break; + } + + // An operation has either completed or failed. It may have failed because fstorage + // ran out of memory, or because the user tried to delete a record which did not exist. + if (ret != FDS_OP_EXECUTING) + { + // There won't be another callback for this operation, so update the page offset now. + page_offsets_update(p_page, p_op->write.header.length_words); + } + + return ret; +} + + +static ret_code_t delete_execute(uint32_t prev_ret, fds_op_t * const p_op) +{ + ret_code_t ret; + + if (prev_ret != NRF_SUCCESS) + { + return FDS_ERR_OPERATION_TIMEOUT; + } + + switch (p_op->del.step) + { + case FDS_OP_DEL_RECORD_FLAG_DIRTY: + p_op->del.step = FDS_OP_DEL_DONE; + ret = record_find_and_delete(p_op); + break; + + case FDS_OP_DEL_FILE_FLAG_DIRTY: + ret = file_find_and_delete(p_op); + if (ret == FDS_ERR_NOT_FOUND) + { + // No more records could be found. + // There won't be another callback for this operation, so return now. + ret = FDS_OP_COMPLETED; + } + break; + + case FDS_OP_DEL_DONE: + ret = FDS_OP_COMPLETED; + break; + + default: + ret = FDS_ERR_INTERNAL; + break; + } + + return ret; +} + + +static ret_code_t gc_execute(uint32_t prev_ret) +{ + ret_code_t ret; + + if (prev_ret != NRF_SUCCESS) + { + return FDS_ERR_OPERATION_TIMEOUT; + } + + if (m_gc.resume) + { + m_gc.resume = false; + } + else + { + gc_state_advance(); + } + + switch (m_gc.state) + { + case GC_NEXT_PAGE: + ret = gc_next_page(); + break; + + case GC_FIND_NEXT_RECORD: + ret = gc_record_find_next(); + break; + + case GC_COPY_RECORD: + ret = gc_record_copy(); + break; + + case GC_ERASE_PAGE: + ret = gc_page_erase(); + break; + + case GC_PROMOTE_SWAP: + ret = gc_swap_promote(); + break; + + case GC_TAG_NEW_SWAP: + ret = gc_tag_new_swap(); + break; + + default: + // Should not happen. + ret = FDS_ERR_INTERNAL; + break; + } + + // Either FDS_OP_EXECUTING, FDS_OP_COMPLETED, FDS_ERR_BUSY or FDS_ERR_INTERNAL. + return ret; +} + + +static void queue_process(ret_code_t result) +{ + static fds_op_t * m_p_cur_op; // Current fds operation. + static nrf_atfifo_item_get_t m_iget_ctx; // Queue context for the current operation. + + while (true) + { + if (m_p_cur_op == NULL) + { + // Load the next from the queue if no operation is being executed. + m_p_cur_op = queue_load(&m_iget_ctx); + } + + /* We can reach here in three ways: + * from queue_start(): something was just queued + * from the fstorage event handler: an operation is being executed + * looping: we only loop if there are operations still in the queue + * + * In all these three cases, m_p_cur_op != NULL. + */ + ASSERT(m_p_cur_op != NULL); + + switch (m_p_cur_op->op_code) + { + case FDS_OP_INIT: + result = init_execute(result, m_p_cur_op); + break; + + case FDS_OP_WRITE: + case FDS_OP_UPDATE: + result = write_execute(result, m_p_cur_op); + break; + + case FDS_OP_DEL_RECORD: + case FDS_OP_DEL_FILE: + result = delete_execute(result, m_p_cur_op); + break; + + case FDS_OP_GC: + result = gc_execute(result); + break; + + default: + result = FDS_ERR_INTERNAL; + break; + } + + if (result == FDS_OP_EXECUTING) + { + // The operation has not completed yet. Wait for the next system event. + break; + } + + // The operation has completed (either successfully or with an error). + // - send an event to the user + // - free the operation buffer + // - execute any other queued operations + + fds_evt_t evt; + memset(&evt, 0x00, sizeof(evt)); + + if (result == FDS_OP_COMPLETED) + { + evt.result = FDS_SUCCESS; + result = NRF_SUCCESS; + } + else + { + // The operation failed for one of the following reasons: + // FDS_ERR_BUSY - flash subsystem can't accept the operation + // FDS_ERR_OPERATION_TIMEOUT - flash subsystem timed out + // FDS_ERR_CRC_CHECK_FAILED - a CRC check failed + // FDS_ERR_NOT_FOUND - no record found (delete/update) + evt.result = result; + } + + event_prepare(m_p_cur_op, &evt); + event_send(&evt); + + // Zero the pointer to the current operation so that this function + // will fetch a new one from the queue next time it is run. + m_p_cur_op = NULL; + + // Free the queue element used by the current operation. + queue_free(&m_iget_ctx); + + if (!queue_has_next()) + { + // No more elements left. Nothing to do. + break; + } + } +} + + +static void queue_start(void) +{ + if (!nrf_atomic_u32_fetch_add(&m_queued_op_cnt, 1)) + { + queue_process(NRF_SUCCESS); + } +} + + +static void fs_event_handler(nrf_fstorage_evt_t * p_evt) +{ + queue_process(p_evt->result); +} + + +// Enqueues write and update operations. +static ret_code_t write_enqueue(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record, + fds_reserve_token_t const * const p_tok, + fds_op_code_t op_code) +{ + ret_code_t ret; + uint16_t page; + uint16_t crc = 0; + uint16_t length_words = 0; + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_record == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if ((p_record->file_id == FDS_FILE_ID_INVALID) || + (p_record->key == FDS_RECORD_KEY_DIRTY)) + { + return FDS_ERR_INVALID_ARG; + } + + if (!is_word_aligned(p_record->data.p_data)) + { + return FDS_ERR_UNALIGNED_ADDR; + } + + // No space was previously reserved in flash for this operation. + if (p_tok == NULL) + { + // Find a page where to write data. + length_words = p_record->data.length_words; + ret = write_space_reserve(length_words, &page); + + if (ret != FDS_SUCCESS) + { + // There is either not enough space in flash (FDS_ERR_NO_SPACE_IN_FLASH) or + // the record exceeds the size of virtual page (FDS_ERR_RECORD_TOO_LARGE). + return ret; + } + } + else + { + page = p_tok->page; + length_words = p_tok->length_words; + } + + // Get a buffer on the queue of operations. + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + CRITICAL_SECTION_ENTER(); + write_space_free(length_words, page); + CRITICAL_SECTION_EXIT(); + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + // Initialize the operation. + p_op->op_code = op_code; + p_op->write.step = FDS_OP_WRITE_HEADER_BEGIN; + p_op->write.page = page; + p_op->write.p_data = p_record->data.p_data; + p_op->write.header.record_id = record_id_new(); + p_op->write.header.file_id = p_record->file_id; + p_op->write.header.record_key = p_record->key; + p_op->write.header.length_words = length_words; + + if (op_code == FDS_OP_UPDATE) + { + p_op->write.step = FDS_OP_WRITE_FIND_RECORD; + // Save the record ID of the record to be updated. + p_op->write.record_to_delete = p_desc->record_id; + } + +#if (FDS_CRC_CHECK_ON_READ) + // First, compute the CRC for the first 6 bytes of the header which contain the + // record key, length and file ID, then, compute the CRC of the record ID (4 bytes). + crc = crc16_compute((uint8_t*)&p_op->write.header, 6, NULL); + crc = crc16_compute((uint8_t*)&p_op->write.header.record_id, 4, &crc); + + // Compute the CRC for the record data. + crc = crc16_compute((uint8_t*)p_record->data.p_data, + p_record->data.length_words * sizeof(uint32_t), &crc); +#endif + + p_op->write.header.crc16 = crc; + + queue_buf_store(&iput_ctx); + + // Initialize the record descriptor, if provided. + if (p_desc != NULL) + { + p_desc->p_record = NULL; + // Don't invoke record_id_new() again ! + p_desc->record_id = p_op->write.header.record_id; + p_desc->record_is_open = false; + p_desc->gc_run_count = m_gc.run_count; + } + + // Start processing the queue, if necessary. + queue_start(); + + return FDS_SUCCESS; +} + + +ret_code_t fds_register(fds_cb_t cb) +{ + ret_code_t ret; + + if (m_users == FDS_MAX_USERS) + { + ret = FDS_ERR_USER_LIMIT_REACHED; + } + else + { + m_cb_table[m_users] = cb; + (void) nrf_atomic_u32_add(&m_users, 1); + + ret = FDS_SUCCESS; + } + + return ret; +} + + +static uint32_t flash_end_addr(void) +{ + uint32_t const bootloader_addr = NRF_UICR->NRFFW[0]; + uint32_t const page_sz = NRF_FICR->CODEPAGESIZE; +#ifndef NRF52810_XXAA + uint32_t const code_sz = NRF_FICR->CODESIZE; +#else + // Number of flash pages, necessary to emulate the NRF52810 on NRF52832. + uint32_t const code_sz = 48; +#endif + + return (bootloader_addr != 0xFFFFFFFF) ? bootloader_addr : (code_sz * page_sz); +} + + +static void flash_bounds_set(void) +{ + uint32_t flash_size = (FDS_PHY_PAGES * FDS_PHY_PAGE_SIZE * sizeof(uint32_t)); + m_fs.end_addr = flash_end_addr(); + m_fs.start_addr = m_fs.end_addr - flash_size; +} + + +static ret_code_t flash_subsystem_init(void) +{ + flash_bounds_set(); + + #if (FDS_BACKEND == NRF_FSTORAGE_SD) + return nrf_fstorage_init(&m_fs, &nrf_fstorage_sd, NULL); + #elif (FDS_BACKEND == NRF_FSTORAGE_NVMC) + return nrf_fstorage_init(&m_fs, &nrf_fstorage_nvmc, NULL); + #else + #error Invalid FDS_BACKEND. + #endif +} + + +static void queue_init(void) +{ + (void) NRF_ATFIFO_INIT(m_queue); +} + + +ret_code_t fds_init(void) +{ + ret_code_t ret; + fds_evt_t const evt_success = + { + .id = FDS_EVT_INIT, + .result = FDS_SUCCESS, + }; + + if (m_flags.initialized) + { + // No initialization is necessary. Notify the application immediately. + event_send(&evt_success); + return FDS_SUCCESS; + } + + if (nrf_atomic_flag_set_fetch(&m_flags.initializing)) + { + // If we were already initializing, return. + return FDS_SUCCESS; + } + + // Otherwise, the flag is set and we proceed to initialization. + + ret = flash_subsystem_init(); + if (ret != NRF_SUCCESS) + { + return ret; + } + + queue_init(); + + // Initialize the page structure (m_pages), and determine which + // initialization steps are required given the current state of the filesystem. + + fds_init_opts_t init_opts = pages_init(); + + switch (init_opts) + { + case NO_PAGES: + case NO_SWAP: + return FDS_ERR_NO_PAGES; + + case ALREADY_INSTALLED: + { + // No initialization is necessary. Notify the application immediately. + m_flags.initialized = true; + m_flags.initializing = false; + event_send(&evt_success); + return FDS_SUCCESS; + } + + default: + break; + } + + // A write operation is necessary to initialize the fileystem. + + nrf_atfifo_item_put_t iput_ctx; + + fds_op_t * p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_INIT; + + switch (init_opts) + { + case FRESH_INSTALL: + case TAG_SWAP: + p_op->init.step = FDS_OP_INIT_TAG_SWAP; + break; + + case PROMOTE_SWAP: + case PROMOTE_SWAP_INST: + p_op->init.step = FDS_OP_INIT_PROMOTE_SWAP; + break; + + case DISCARD_SWAP: + p_op->init.step = FDS_OP_INIT_ERASE_SWAP; + break; + + case TAG_DATA: + case TAG_DATA_INST: + p_op->init.step = FDS_OP_INIT_TAG_DATA; + break; + + default: + // Should not happen. + break; + } + + queue_buf_store(&iput_ctx); + queue_start(); + + return FDS_SUCCESS; +} + + +ret_code_t fds_record_open(fds_record_desc_t * const p_desc, + fds_flash_record_t * const p_flash_rec) +{ + uint16_t page; + + if ((p_desc == NULL) || (p_flash_rec == NULL)) + { + return FDS_ERR_NULL_ARG; + } + + // Find the record if necessary. + if (record_find_by_desc(p_desc, &page)) + { + fds_header_t const * const p_header = (fds_header_t*)p_desc->p_record; + +#if (FDS_CRC_CHECK_ON_READ) + if (!crc_verify_success(p_header->crc16, + p_header->length_words, + p_desc->p_record)) + { + return FDS_ERR_CRC_CHECK_FAILED; + } +#endif + + (void) nrf_atomic_u32_add(&m_pages[page].records_open, 1); + + // Initialize p_flash_rec. + p_flash_rec->p_header = p_header; + p_flash_rec->p_data = (p_desc->p_record + FDS_HEADER_SIZE); + + // Set the record as open in the descriptor. + p_desc->record_is_open = true; + + return FDS_SUCCESS; + } + + // The record could not be found. + // It either never existed or it has been deleted. + return FDS_ERR_NOT_FOUND; +} + + +ret_code_t fds_record_close(fds_record_desc_t * const p_desc) +{ + ret_code_t ret; + uint16_t page; + + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if (record_find_by_desc((fds_record_desc_t*)p_desc, &page)) + { + CRITICAL_SECTION_ENTER(); + if ((m_pages[page].records_open > 0) && (p_desc->record_is_open)) + { + + m_pages[page].records_open--; + p_desc->record_is_open = false; + + ret = FDS_SUCCESS; + } + else + { + ret = FDS_ERR_NO_OPEN_RECORDS; + } + CRITICAL_SECTION_EXIT(); + } + else + { + ret = FDS_ERR_NOT_FOUND; + } + + return ret; +} + + +ret_code_t fds_reserve(fds_reserve_token_t * const p_tok, uint16_t length_words) +{ + ret_code_t ret; + uint16_t page; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + ret = write_space_reserve(length_words, &page); + + if (ret == FDS_SUCCESS) + { + p_tok->page = page; + p_tok->length_words = length_words; + } + + return ret; +} + + +ret_code_t fds_reserve_cancel(fds_reserve_token_t * const p_tok) +{ + ret_code_t ret; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + if (p_tok->page > FDS_DATA_PAGES) + { + // The page does not exist. This shouldn't happen. + return FDS_ERR_INVALID_ARG; + } + + fds_page_t const * const p_page = &m_pages[p_tok->page]; + + CRITICAL_SECTION_ENTER(); + if ((FDS_HEADER_SIZE + p_tok->length_words) <= p_page->words_reserved) + { + // Free reserved space. + write_space_free(p_tok->length_words, p_tok->page); + + // Clean the token. + p_tok->page = 0; + p_tok->length_words = 0; + ret = FDS_SUCCESS; + } + else + { + // We are trying to cancel a reservation of more words than how many are + // currently reserved on the page. Clearly, this shouldn't happen. + ret = FDS_ERR_INVALID_ARG; + } + CRITICAL_SECTION_EXIT(); + + return ret; +} + + +ret_code_t fds_record_write(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record) +{ + return write_enqueue(p_desc, p_record, NULL, FDS_OP_WRITE); +} + + +ret_code_t fds_record_write_reserved(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record, + fds_reserve_token_t const * const p_tok) +{ + // A NULL token is not allowed when writing to a reserved space. + if (p_tok == NULL) + { + return FDS_ERR_NULL_ARG; + } + + return write_enqueue(p_desc, p_record, p_tok, FDS_OP_WRITE); +} + + +ret_code_t fds_record_update(fds_record_desc_t * const p_desc, + fds_record_t const * const p_record) +{ + // A NULL descriptor is not allowed when updating a record. + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + return write_enqueue(p_desc, p_record, NULL, FDS_OP_UPDATE); +} + + +ret_code_t fds_record_delete(fds_record_desc_t * const p_desc) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_DEL_RECORD; + p_op->del.step = FDS_OP_DEL_RECORD_FLAG_DIRTY; + p_op->del.record_to_delete = p_desc->record_id; + + queue_buf_store(&iput_ctx); + queue_start(); + + return FDS_SUCCESS; +} + + +ret_code_t fds_file_delete(uint16_t file_id) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (file_id == FDS_FILE_ID_INVALID) + { + return FDS_ERR_INVALID_ARG; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_DEL_FILE; + p_op->del.step = FDS_OP_DEL_FILE_FLAG_DIRTY; + p_op->del.file_id = file_id; + + queue_buf_store(&iput_ctx); + queue_start(); + + return FDS_SUCCESS; +} + + +ret_code_t fds_gc(void) +{ + fds_op_t * p_op; + nrf_atfifo_item_put_t iput_ctx; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + p_op = queue_buf_get(&iput_ctx); + if (p_op == NULL) + { + return FDS_ERR_NO_SPACE_IN_QUEUES; + } + + p_op->op_code = FDS_OP_GC; + + queue_buf_store(&iput_ctx); + + if (m_gc.state != GC_BEGIN) + { + // Resume GC by retrying the last step. + m_gc.resume = true; + } + + queue_start(); + + return FDS_SUCCESS; +} + + +ret_code_t fds_record_iterate(fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(NULL, NULL, p_desc, p_token); +} + + +ret_code_t fds_record_find(uint16_t file_id, + uint16_t record_key, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(&file_id, &record_key, p_desc, p_token); +} + + +ret_code_t fds_record_find_by_key(uint16_t record_key, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(NULL, &record_key, p_desc, p_token); +} + + +ret_code_t fds_record_find_in_file(uint16_t file_id, + fds_record_desc_t * const p_desc, + fds_find_token_t * const p_token) +{ + return record_find(&file_id, NULL, p_desc, p_token); +} + + +ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * const p_desc, + uint32_t record_id) +{ + if (p_desc == NULL) + { + return FDS_ERR_NULL_ARG; + } + + // Zero the descriptor and set the record_id field. + memset(p_desc, 0x00, sizeof(fds_record_desc_t)); + p_desc->record_id = record_id; + + return FDS_SUCCESS; +} + + +ret_code_t fds_record_id_from_desc(fds_record_desc_t const * const p_desc, + uint32_t * const p_record_id) +{ + if ((p_desc == NULL) || (p_record_id == NULL)) + { + return FDS_ERR_NULL_ARG; + } + + *p_record_id = p_desc->record_id; + + return FDS_SUCCESS; +} + + +ret_code_t fds_stat(fds_stat_t * const p_stat) +{ + uint16_t const words_in_page = FDS_PAGE_SIZE; + // The largest number of free contiguous words on any page. + uint16_t contig_words = 0; + + if (!m_flags.initialized) + { + return FDS_ERR_NOT_INITIALIZED; + } + + if (p_stat == NULL) + { + return FDS_ERR_NULL_ARG; + } + + memset(p_stat, 0x00, sizeof(fds_stat_t)); + + p_stat->pages_available = FDS_VIRTUAL_PAGES; + + for (uint16_t page = 0; page < FDS_DATA_PAGES; page++) + { + uint16_t const words_used = m_pages[page].write_offset + m_pages[page].words_reserved; + + if (page_identify(m_pages[page].p_addr) == FDS_PAGE_UNDEFINED) + { + p_stat->pages_available--; + } + + p_stat->open_records += m_pages[page].records_open; + p_stat->words_reserved += m_pages[page].words_reserved; + p_stat->words_used += words_used; + + contig_words = (words_in_page - words_used); + if (contig_words > p_stat->largest_contig) + { + p_stat->largest_contig = contig_words; + } + + records_stat(page, + &p_stat->valid_records, + &p_stat->dirty_records, + &p_stat->freeable_words, + &p_stat->corruption); + } + + return FDS_SUCCESS; +} + +#endif //NRF_MODULE_ENABLED(FDS) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.h new file mode 100644 index 0000000000..3d5986b497 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds.h @@ -0,0 +1,700 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 FDS_H__ +#define FDS_H__ + +/** + * @defgroup fds Flash Data Storage + * @ingroup app_common + * @{ + * + * @brief Flash Data Storage (FDS). + * + * @details Flash Data Storage is a minimalistic, record-oriented file system for the on-chip + * flash. Files are stored as a collection of records of variable length. FDS supports + * synchronous read operations and asynchronous write operations (write, update, + * and delete). FDS can be used from multiple threads. + */ + +#include +#include +#include "sdk_errors.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Invalid file ID. + * + * This value must not be used as a file ID by the application. + */ +#define FDS_FILE_ID_INVALID (0xFFFF) + + +/**@brief Record key for deleted records. + * + * This key is used to flag a record as "dirty", which means that it should be removed during + * the next garbage collection. This value must not be used as a record key by the application. + */ +#define FDS_RECORD_KEY_DIRTY (0x0000) + + +/**@brief FDS return values. + */ +enum +{ + FDS_SUCCESS = NRF_SUCCESS, //!< The operation completed successfully. + FDS_ERR_OPERATION_TIMEOUT, //!< Error. The operation timed out. + FDS_ERR_NOT_INITIALIZED, //!< Error. The module has not been initialized. + FDS_ERR_UNALIGNED_ADDR, //!< Error. The input data is not aligned to a word boundary. + FDS_ERR_INVALID_ARG, //!< Error. The parameter contains invalid data. + FDS_ERR_NULL_ARG, //!< Error. The parameter is NULL. + FDS_ERR_NO_OPEN_RECORDS, //!< Error. The record is not open, so it cannot be closed. + FDS_ERR_NO_SPACE_IN_FLASH, //!< Error. There is no space in flash memory. + FDS_ERR_NO_SPACE_IN_QUEUES, //!< Error. There is no space in the internal queues. + FDS_ERR_RECORD_TOO_LARGE, //!< Error. The record exceeds the maximum allowed size. + FDS_ERR_NOT_FOUND, //!< Error. The record was not found. + FDS_ERR_NO_PAGES, //!< Error. No flash pages are available. + FDS_ERR_USER_LIMIT_REACHED, //!< Error. The maximum number of users has been reached. + FDS_ERR_CRC_CHECK_FAILED, //!< Error. The CRC check failed. + FDS_ERR_BUSY, //!< Error. The underlying flash subsystem was busy. + FDS_ERR_INTERNAL, //!< Error. An internal error occurred. +}; + + +/**@brief The record metadata as stored in flash. + * @warning Do not edit or reorder the fields in this structure. + */ +typedef struct +{ + uint16_t record_key; //!< The record key. + uint16_t length_words; //!< The length of the record data (in 4-byte words). + uint16_t file_id; //!< The ID of the file that the record belongs to. + uint16_t crc16; //!< CRC16-CCITT check value. + /* The CRC is calculated over the entire record as stored in flash, + * including the record metadata except the CRC field itself. + */ + uint32_t record_id; //!< The unique record ID (32 bits). +} fds_header_t; + + +/**@brief The record descriptor structure that is used to manipulate records. + * + * This structure is used by the FDS module. You must provide the descriptor to the module when + * you manipulate existing records. However, you should never modify it or use any of its fields. + * + * @note Never reuse the same descriptor for different records. + */ +typedef struct +{ + uint32_t record_id; //!< The unique record ID. + uint32_t const * p_record; //!< The last known location of the record in flash. + uint16_t gc_run_count; //!< Number of times garbage collection has been run. + bool record_is_open; //!< Whether the record is currently open. +} fds_record_desc_t; + + +/**@brief Structure that can be used to read the contents of a record stored in flash. + * + * This structure does not reflect the physical layout of a record in flash, but it points + * to the locations where the record header (metadata) and the record data are stored. + */ +typedef struct +{ + fds_header_t const * p_header; //!< Location of the record header in flash. + void const * p_data; //!< Location of the record data in flash. +} fds_flash_record_t; + + +/**@brief A record to be written to flash. */ +typedef struct +{ + uint16_t file_id; //!< The ID of the file that the record belongs to. + uint16_t key; //!< The record key. + struct + { + void const * p_data; + uint32_t length_words; + } data; +} fds_record_t; + + +/**@brief A token to a reserved space in flash, created by @ref fds_reserve. + * + * This token can be used to write the record in the reserved space (@ref fds_record_write_reserved) + * or to cancel the reservation (@ref fds_reserve_cancel). + */ +typedef struct +{ + uint16_t page; //!< The logical ID of the page where space was reserved. + uint16_t length_words; //!< The amount of space reserved (in 4-byte words). +} fds_reserve_token_t; + + +/**@brief A token to keep information about the progress of @ref fds_record_find, + * @ref fds_record_find_by_key, and @ref fds_record_find_in_file. + * + * @note Always zero-initialize the token before using it for the first time. + * @note Never reuse the same token to search for different records. + */ +typedef struct +{ + uint32_t const * p_addr; + uint16_t page; +} fds_find_token_t; + + +/**@brief FDS event IDs. + */ +typedef enum +{ + FDS_EVT_INIT, //!< Event for @ref fds_init. + FDS_EVT_WRITE, //!< Event for @ref fds_record_write and @ref fds_record_write_reserved. + FDS_EVT_UPDATE, //!< Event for @ref fds_record_update. + FDS_EVT_DEL_RECORD, //!< Event for @ref fds_record_delete. + FDS_EVT_DEL_FILE, //!< Event for @ref fds_file_delete. + FDS_EVT_GC //!< Event for @ref fds_gc. +} fds_evt_id_t; + + +ANON_UNIONS_ENABLE + +/**@brief An FDS event. */ +typedef struct +{ + fds_evt_id_t id; //!< The event ID. See @ref fds_evt_id_t. + ret_code_t result; //!< The result of the operation related to this event. + union + { + struct + { + uint32_t record_id; + uint16_t file_id; + uint16_t record_key; + bool is_record_updated; + } write; //!< Information for @ref FDS_EVT_WRITE and @ref FDS_EVT_UPDATE events. + struct + { + uint32_t record_id; + uint16_t file_id; + uint16_t record_key; + } del; //!< Information for @ref FDS_EVT_DEL_RECORD and @ref FDS_EVT_DEL_FILE events. + }; +} fds_evt_t; + +ANON_UNIONS_DISABLE + + +/**@brief File system statistics. */ +typedef struct +{ + uint16_t pages_available; //!< The number of pages available. + uint16_t open_records; //!< The number of open records. + uint16_t valid_records; //!< The number of valid records. + uint16_t dirty_records; //!< The number of deleted ("dirty") records. + uint16_t words_reserved; //!< The number of words reserved by @ref fds_reserve(). + + /**@brief The number of words written to flash, including those reserved for future writes. */ + uint16_t words_used; + + /**@brief The largest number of free contiguous words in the file system. + * + * This number indicates the largest record that can be stored by FDS. + * It takes into account all reservations for future writes. + */ + uint16_t largest_contig; + + /**@brief The largest number of words that can be reclaimed by garbage collection. + * + * The actual amount of space freed by garbage collection might be less than this value if + * records are open while garbage collection is run. + */ + uint16_t freeable_words; + + /**@brief Filesystem corruption has been detected. + * + * One or more corrupted records were detected. FDS will heal the filesystem automatically + * next time garbage collection is run, but some data may be lost. + * + * @note: This flag is unrelated to CRC failures. + */ + bool corruption; +} fds_stat_t; + + +/**@brief FDS event handler function prototype. + * + * @param p_evt The event. + */ +typedef void (*fds_cb_t)(fds_evt_t const * p_evt); + + +/**@brief Function for registering an FDS event handler. + * + * The maximum amount of handlers that can be registered can be configured by changing the value + * of @ref FDS_MAX_USERS in fds_config.h. + * + * @param[in] cb The event handler function. + * + * @retval FDS_SUCCESS If the event handler was registered successfully. + * @retval FDS_ERR_USER_LIMIT_REACHED If the maximum number of registered callbacks is reached. + */ +ret_code_t fds_register(fds_cb_t cb); + + +/**@brief Function for initializing the module. + * + * This function initializes the module and installs the file system (unless it is installed + * already). + * + * This function is asynchronous. Completion is reported through an event. Make sure to call + * @ref fds_register before calling @ref fds_init so that you receive the completion event. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NO_PAGES If there is no space available in flash memory to install the + * file system. + */ +ret_code_t fds_init(void); + + +/**@brief Function for writing a record to flash. + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Some modules need exclusive use of certain file IDs and record keys. + * See @ref lib_fds_functionality_keys for details. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through an event that is sent to + * the registered event handler function. + * + * @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not + * need the descriptor. + * @param[in] p_record The record to be written to flash. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_record is NULL. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * record. + */ +ret_code_t fds_record_write(fds_record_desc_t * p_desc, + fds_record_t const * p_record); + + +/**@brief Function for reserving space in flash. + * + * This function can be used to reserve space in flash memory. To write a record into the reserved + * space, use @ref fds_record_write_reserved. Alternatively, use @ref fds_reserve_cancel to cancel + * a reservation. + * + * Note that this function does not write any data to flash. + * + * @param[out] p_token A token that can be used to write a record in the reserved space or + * cancel the reservation. + * @param[in] length_words The length of the record data (in 4-byte words). + * + * @retval FDS_SUCCESS If the flash space was reserved successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record length exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * record. + */ +ret_code_t fds_reserve(fds_reserve_token_t * p_token, uint16_t length_words); + + +/**@brief Function for canceling an @ref fds_reserve operation. + * + * @param[in] p_token The token that identifies the reservation, produced by @ref fds_reserve. + * + * @retval FDS_SUCCESS If the reservation was canceled. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_INVALID_ARG If @p p_token contains invalid data. + */ +ret_code_t fds_reserve_cancel(fds_reserve_token_t * p_token); + + +/**@brief Function for writing a record to a space in flash that was reserved using + * @ref fds_reserve. + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @note + * This function behaves similarly to @ref fds_record_write, with the exception that it never + * fails with the error @ref FDS_ERR_NO_SPACE_IN_FLASH. + * + * @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not + * need the descriptor. + * @param[in] p_record The record to be written to flash. + * @param[in] p_token The token that identifies the space reserved in flash. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + */ +ret_code_t fds_record_write_reserved(fds_record_desc_t * p_desc, + fds_record_t const * p_record, + fds_reserve_token_t const * p_token); + + +/**@brief Function for deleting a record. + * + * Deleted records cannot be located using @ref fds_record_find, @ref fds_record_find_by_key, or + * @ref fds_record_find_in_file. Additionally, they can no longer be opened using + * @ref fds_record_open. + * + * Note that deleting a record does not free the space it occupies in flash memory. + * To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @param[in] p_desc The descriptor of the record that should be deleted. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If the specified record descriptor @p p_desc is NULL. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_record_delete(fds_record_desc_t * p_desc); + + +/**@brief Function for deleting all records in a file. + * + * This function deletes a file, including all its records. Deleted records cannot be located + * using @ref fds_record_find, @ref fds_record_find_by_key, or @ref fds_record_find_in_file. + * Additionally, they can no longer be opened using @ref fds_record_open. + * + * Note that deleting records does not free the space they occupy in flash memory. + * To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @param[in] file_id The ID of the file to be deleted. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_INVALID_ARG If the specified @p file_id is invalid. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_file_delete(uint16_t file_id); + + +/**@brief Function for updating a record. + * + * Updating a record first writes a new record (@p p_record) to flash and then deletes the + * old record (identified by @p p_desc). + * + * There are no restrictions on the file ID and the record key, except that the record key must be + * different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from + * @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of + * the file ID or the record key. All records with the same file ID are grouped into one file. + * If no file with the specified ID exists, it is created. There can be multiple records with the + * same record key in a file. + * + * Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and + * because it is not buffered internally, it must be kept in memory until the callback for the + * operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE + * words minus 14 bytes. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @param[in, out] p_desc The descriptor of the record to update. When the function + * returns with FDS_SUCCESS, this parameter contains the + * descriptor of the newly written record. + * @param[in] p_record The updated record to be written to flash. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid. + * @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary. + * @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record + * chunks than can be buffered. + * @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the + * updated record. + */ +ret_code_t fds_record_update(fds_record_desc_t * p_desc, + fds_record_t const * p_record); + + +/**@brief Function for iterating through all records in flash. + * + * To search for the next record, call the function again and supply the same @ref fds_find_token_t + * structure to resume searching from the last record that was found. + * + * Note that the order with which records are iterated is not defined. + * + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval FDS_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_iterate(fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for records with a given record key in a file. + * + * This function finds the first record in a file that has the given record key. To search for the + * next record with the same key in the file, call the function again and supply the same + * @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] file_id The file ID. + * @param[in] record_key The record key. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval FDS_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_find(uint16_t file_id, + uint16_t record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for records with a given record key. + * + * This function finds the first record with a given record key, independent of the file it + * belongs to. To search for the next record with the same key, call the function again and supply + * the same @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] record_key The record key. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval FDS_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no record with the given key was found. + */ +ret_code_t fds_record_find_by_key(uint16_t record_key, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for searching for any record in a file. + * + * This function finds the first record in a file, independent of its record key. + * To search for the next record in the same file, call the function again and supply the same + * @ref fds_find_token_t structure to resume searching from the last record that was found. + * + * @param[in] file_id The file ID. + * @param[out] p_desc The descriptor of the record that was found. + * @param[out] p_token A token containing information about the progress of the operation. + * + * @retval FDS_SUCCESS If a record was found. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL. + * @retval FDS_ERR_NOT_FOUND If no matching record was found. + */ +ret_code_t fds_record_find_in_file(uint16_t file_id, + fds_record_desc_t * p_desc, + fds_find_token_t * p_token); + + +/**@brief Function for opening a record for reading. + * + * This function opens a record that is stored in flash, so that it can be read. The function + * initializes an @ref fds_flash_record_t structure, which can be used to access the record data as + * well as its associated metadata. The pointers provided in the @ref fds_flash_record_t structure + * are pointers to flash memory. + * + * Opening a record with @ref fds_record_open prevents garbage collection to run on the virtual + * flash page in which record is stored, so that the contents of the memory pointed by fields in + * @ref fds_flash_record_t are guaranteed to remain unmodified as long as the record is kept open. + * + * When you are done reading a record, call @ref fds_record_close to close it. Garbage collection + * can then reclaim space on the virtual page where the record is stored. Note that you must + * provide the same descriptor for @ref fds_record_close as you did for this function. + * + * @param[in] p_desc The descriptor of the record to open. + * @param[out] p_flash_record The record, as stored in flash. + * + * @retval FDS_SUCCESS If the record was opened successfully. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_flash_record is NULL. + * @retval FDS_ERR_NOT_FOUND If the record was not found. It might have been deleted, or + * it might not have been written yet. + * @retval FDS_ERR_CRC_CHECK_FAILED If the CRC check for the record failed. + */ +ret_code_t fds_record_open(fds_record_desc_t * p_desc, + fds_flash_record_t * p_flash_record); + + +/**@brief Function for closing a record. + * + * Closing a record allows garbage collection to run on the virtual page in which the record is + * stored (if no other records remain open on that page). The descriptor passed as an argument + * must be the same as the one used to open the record using @ref fds_record_open. + * + * Note that closing a record does not invalidate its descriptor. You can still supply the + * descriptor to all functions that accept a record descriptor as a parameter. + * + * @param[in] p_desc The descriptor of the record to close. + * + * @retval FDS_SUCCESS If the record was closed successfully. + * @retval FDS_ERR_NULL_ARG If @p p_desc is NULL. + * @retval FDS_ERR_NO_OPEN_RECORDS If the record is not open. + * @retval FDS_ERR_NOT_FOUND If the record could not be found. + */ +ret_code_t fds_record_close(fds_record_desc_t * p_desc); + + +/**@brief Function for running garbage collection. + * + * Garbage collection reclaims the flash space that is occupied by records that have been deleted, + * or that failed to be completely written due to, for example, a power loss. + * + * This function is asynchronous. Completion is reported through an event that is sent to the + * registered event handler function. + * + * @retval FDS_SUCCESS If the operation was queued successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full. + */ +ret_code_t fds_gc(void); + + +/**@brief Function for obtaining a descriptor from a record ID. + * + * This function can be used to reconstruct a descriptor from a record ID, like the one that is + * passed to the callback function. + * + * @note + * This function does not check whether a record with the given record ID exists. + * If a non-existing record ID is supplied, the resulting descriptor is invalid and will cause + * other functions to fail when it is supplied as parameter. + * + * @param[out] p_desc The descriptor of the record with the given record ID. + * @param[in] record_id The record ID for which a descriptor should be returned. + * + * @retval FDS_SUCCESS If a descriptor was returned. + * @retval FDS_ERR_NULL_ARG If @p p_desc is NULL. + */ +ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * p_desc, + uint32_t record_id); + + +/**@brief Function for obtaining a record ID from a record descriptor. + * + * This function can be used to extract a record ID from a descriptor. For example, you could use + * it in the callback function to compare the record ID of an event to the record IDs of the + * records for which you have a descriptor. + * + * @warning + * This function does not check whether the record descriptor is valid. If the descriptor is not + * initialized or has been tampered with, the resulting record ID might be invalid. + * + * @param[in] p_desc The descriptor from which the record ID should be extracted. + * @param[out] p_record_id The record ID that is contained in the given descriptor. + * + * @retval FDS_SUCCESS If a record ID was returned. + * @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_record_id is NULL. + */ +ret_code_t fds_record_id_from_desc(fds_record_desc_t const * p_desc, + uint32_t * p_record_id); + + +/**@brief Function for retrieving file system statistics. + * + * This function retrieves file system statistics, such as the number of open records, the space + * that can be reclaimed by garbage collection, and others. + * + * @param[out] p_stat File system statistics. + * + * @retval FDS_SUCCESS If the statistics were returned successfully. + * @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized. + * @retval FDS_ERR_NULL_ARG If @p p_stat is NULL. + */ +ret_code_t fds_stat(fds_stat_t * p_stat); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // FDS_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds_internal_defs.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds_internal_defs.h new file mode 100644 index 0000000000..0d490cac86 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fds/fds_internal_defs.h @@ -0,0 +1,327 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 FDS_INTERNAL_DEFS_H__ +#define FDS_INTERNAL_DEFS_H__ +#include "sdk_config.h" +#include +#include + +#if defined (FDS_THREADS) + #include "nrf_soc.h" + #include "app_util_platform.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define FDS_PAGE_TAG_SIZE (2) // Page tag size, in 4-byte words. +#define FDS_PAGE_TAG_WORD_0 (0) // Offset of the first word in the page tag from the page address. +#define FDS_PAGE_TAG_WORD_1 (1) // Offset of the second word in the page tag from the page address. + +// Page tag constants +#define FDS_PAGE_TAG_MAGIC (0xDEADC0DE) +#define FDS_PAGE_TAG_SWAP (0xF11E01FF) +#define FDS_PAGE_TAG_DATA (0xF11E01FE) + +#define FDS_ERASED_WORD (0xFFFFFFFF) + +#define FDS_OFFSET_TL (0) // Offset of TL from the record base address, in 4-byte words. +#define FDS_OFFSET_IC (1) // Offset of IC from the record base address, in 4-byte words. +#define FDS_OFFSET_ID (2) // Offset of ID from the record base address, in 4-byte words. +#define FDS_OFFSET_DATA (3) // Offset of the data from the record base address, in 4-byte words. + +#define FDS_HEADER_SIZE_TL (1) // Size of the TL part of the header, in 4-byte words. +#define FDS_HEADER_SIZE_IC (1) // Size of the IC part of the header, in 4-byte words. +#define FDS_HEADER_SIZE_ID (1) // Size of the record ID in the header, in 4-byte words. +#define FDS_HEADER_SIZE (3) // Size of the whole header, in 4-byte words. + +#define FDS_OP_EXECUTING (NRF_SUCCESS) +#define FDS_OP_COMPLETED (0x1D1D) + +#define NRF_FSTORAGE_NVMC 1 +#define NRF_FSTORAGE_SD 2 + +// The size of a physical page, in 4-byte words. +#if defined(NRF51) + #define FDS_PHY_PAGE_SIZE (256) + #elif defined(NRF52_SERIES) + #define FDS_PHY_PAGE_SIZE (1024) +#endif + +// The number of physical pages to be used. This value is configured indirectly. +#define FDS_PHY_PAGES ((FDS_VIRTUAL_PAGES * FDS_VIRTUAL_PAGE_SIZE) / FDS_PHY_PAGE_SIZE) + +// The size of a virtual page, in number of physical pages. +#define FDS_PHY_PAGES_IN_VPAGE (FDS_VIRTUAL_PAGE_SIZE / FDS_PHY_PAGE_SIZE) + +// The number of pages available to store data; which is the total minus one (the swap). +#define FDS_DATA_PAGES (FDS_VIRTUAL_PAGES - 1) + + // Just a shorter name for the size, in words, of a virtual page. +#define FDS_PAGE_SIZE (FDS_VIRTUAL_PAGE_SIZE) + + +#if (FDS_VIRTUAL_PAGE_SIZE % FDS_PHY_PAGE_SIZE != 0) + #error "FDS_VIRTUAL_PAGE_SIZE must be a multiple of the size of a physical page." +#endif + +#if (FDS_VIRTUAL_PAGES < 2) + #error "FDS requires at least two virtual pages." +#endif + + +// Page types. +typedef enum +{ + FDS_PAGE_DATA, // Page is ready for storage. + FDS_PAGE_SWAP, // Page is reserved for garbage collection. + FDS_PAGE_ERASED, // Page is erased. + FDS_PAGE_UNDEFINED, // Undefined page type. +} fds_page_type_t; + + +typedef enum +{ + FDS_HEADER_VALID, // Valid header. + FDS_HEADER_DIRTY, // Header is incomplete, or record has been deleted. + FDS_HEADER_CORRUPT // Header contains corrupt information, not related to CRC. +} fds_header_status_t; + + +typedef struct +{ + fds_page_type_t page_type; // The page type. + uint32_t const * p_addr; // The address of the page. + uint16_t write_offset; // The page write offset, in 4-byte words. + uint16_t words_reserved; // The amount of words reserved. + uint32_t volatile records_open; // The number of open records. + bool can_gc; // Indicates that there are some records that have been deleted. +} fds_page_t; + + +typedef struct +{ + uint32_t const * p_addr; + uint16_t write_offset; +} fds_swap_page_t; + + +// FDS op-codes. +typedef enum +{ + FDS_OP_NONE, + FDS_OP_INIT, // Initialize the module. + FDS_OP_WRITE, // Write a record to flash. + FDS_OP_UPDATE, // Update a record. + FDS_OP_DEL_RECORD, // Delete a record. + FDS_OP_DEL_FILE, // Delete a file. + FDS_OP_GC // Run garbage collection. +} fds_op_code_t; + + +typedef enum +{ + FDS_OP_INIT_TAG_SWAP, + FDS_OP_INIT_TAG_DATA, + FDS_OP_INIT_ERASE_SWAP, + FDS_OP_INIT_PROMOTE_SWAP, +} fds_init_step_t; + + +typedef enum +{ + FDS_OP_WRITE_HEADER_BEGIN, // Write the record key and length. + FDS_OP_WRITE_HEADER_FINALIZE, // Write the file ID and CRC. + FDS_OP_WRITE_RECORD_ID, // Write the record ID. + FDS_OP_WRITE_DATA, // Write the record data. + FDS_OP_WRITE_FIND_RECORD, + FDS_OP_WRITE_FLAG_DIRTY, // Flag a record as dirty (as part of an update operation). + FDS_OP_WRITE_DONE, +} fds_write_step_t; + + +typedef enum +{ + FDS_OP_DEL_RECORD_FLAG_DIRTY, // Flag a record as dirty. + FDS_OP_DEL_FILE_FLAG_DIRTY, // Flag multiple records as dirty. + FDS_OP_DEL_DONE, +} fds_delete_step_t; + + +#if defined(__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined(__ICCARM__) + #pragma language=extended +#elif defined(__GNUC__) + // anonymous unions are enabled by default +#endif + +typedef struct +{ + fds_op_code_t op_code; // The opcode for the operation. + union + { + struct + { + fds_init_step_t step; // The current step the operation is at. + } init; + struct + { + fds_header_t header; + void const * p_data; + uint16_t page; // The page the flash space for this command was reserved. + fds_write_step_t step; // The current step the operation is at. + uint32_t record_to_delete; // The record to delete in case this is an update. + } write; + struct + { + fds_delete_step_t step; + uint16_t file_id; + uint16_t record_key; + uint32_t record_to_delete; + } del; + }; +} fds_op_t; + +#if defined(__CC_ARM) + #pragma pop +#elif defined(__ICCARM__) + // leave anonymous unions enabled +#elif defined(__GNUC__) + // anonymous unions are enabled by default +#endif + + +enum +{ + PAGE_ERASED = 0x1, // One or more erased pages found. + PAGE_DATA = 0x2, // One or more data pages found. + PAGE_SWAP_CLEAN = 0x4, // A clean (empty) swap page was found. + PAGE_SWAP_DIRTY = 0x8, // A dirty (non-empty) swap page was found. +}; + + +typedef enum +{ + // No erased pages or FDS pages found. + // This is a fatal error. + NO_PAGES, + + // The filesystem can not be garbage collected. + // This is a fatal error. + NO_SWAP = (PAGE_DATA), + + // Perform a fresh installation. + FRESH_INSTALL = (PAGE_ERASED), + + // Tag an erased page as swap. + TAG_SWAP = (PAGE_ERASED | PAGE_DATA), + + // Tag all erased pages as data. + TAG_DATA = (PAGE_ERASED | PAGE_SWAP_CLEAN), + + // Tag all remaining erased pages as data. + TAG_DATA_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_CLEAN), + + // The swap is dirty, likely because the device powered off during GC. + // Because there is also an erased page, assume that that page has been garbage collected. + // Hence, tag the swap as data (promote), an erased page as swap and remaining pages as data. + PROMOTE_SWAP = (PAGE_ERASED | PAGE_SWAP_DIRTY), + + // Tag the swap as data (promote), an erased page as swap and remaining pages as data. + PROMOTE_SWAP_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_DIRTY), + + // The swap is dirty (written) and there are no erased pages. It is likely that the device + // powered off during GC. It is safe to discard (erase) the swap, since data that was + // swapped out still lies in one of the valid pages. + DISCARD_SWAP = (PAGE_DATA | PAGE_SWAP_DIRTY), + + // Do nothing. + ALREADY_INSTALLED = (PAGE_DATA | PAGE_SWAP_CLEAN), + +} fds_init_opts_t; + + +typedef enum +{ + GC_BEGIN, // Begin GC. + GC_NEXT_PAGE, // GC a page. + GC_FIND_NEXT_RECORD, // Find a valid record to copy. + GC_COPY_RECORD, // Copy a valid record to swap. + GC_ERASE_PAGE, // Erase the page being garbage collected. + GC_DISCARD_SWAP, // Erase (discard) the swap page. + GC_PROMOTE_SWAP, // Tag the swap as valid. + GC_TAG_NEW_SWAP // Tag a freshly erased (GCed) page as swap. +} fds_gc_state_t; + + +// Holds garbage collection status and related data. +typedef struct +{ + fds_gc_state_t state; // The current GC step. + uint16_t cur_page; // The current page being garbage collected. + uint32_t const * p_record_src; // The current record being copied to swap. + uint16_t run_count; // Total number of times GC was run. + bool do_gc_page[FDS_DATA_PAGES]; // Controls which pages to garbage collect. + bool resume; // Whether or not GC should be resumed. +} fds_gc_data_t; + + +// Macros to enable and disable application interrupts. +#if defined (FDS_THREADS) + + #define CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() + #define CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() + +#else + + #define CRITICAL_SECTION_ENTER() + #define CRITICAL_SECTION_EXIT() + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // FDS_INTERNAL_DEFS_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.c new file mode 100644 index 0000000000..b0d013a6ec --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.c @@ -0,0 +1,257 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_config.h" + +#if NRF_FSTORAGE_ENABLED + +#include "nrf_fstorage.h" +#include +#include +#include "sdk_errors.h" +#include "nrf_section.h" + + +/* Create the section "fs_data". */ +NRF_SECTION_DEF(fs_data, nrf_fstorage_t); + +static bool addr_within_bounds(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len); +static bool addr_is_aligned32(uint32_t addr); + + +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param) +{ + if ((p_fs == NULL) || (p_api == NULL)) + { + return NRF_ERROR_NULL; + } + + p_fs->p_api = p_api; + + return (p_fs->p_api)->init(p_fs, p_param); +} + + +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, + void * p_param) +{ + ret_code_t rc; + + if (p_fs == NULL) + { + return NRF_ERROR_NULL; + } + + if (p_fs->p_api == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + rc = (p_fs->p_api)->uninit(p_fs, p_param); + + /* Uninitialize the API. */ + p_fs->p_api = NULL; + p_fs->p_flash_info = NULL; + + return rc; +} + + +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t src, + void * p_dest, + uint32_t len) +{ + if ((p_fs == NULL) || (p_dest == NULL)) + { + return NRF_ERROR_NULL; + } + + if (p_fs->p_api == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + if (len == 0) + { + return NRF_ERROR_INVALID_LENGTH; + } + + /* Source addres must be word-aligned. */ + if ( !addr_is_aligned32(src) + || !addr_within_bounds(p_fs, src, len)) + { + return NRF_ERROR_INVALID_ADDR; + } + + return (p_fs->p_api)->read(p_fs, src, p_dest, len); +} + + +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_context) +{ + if ((p_fs == NULL) || (p_src == NULL)) + { + return NRF_ERROR_NULL; + } + + if (p_fs->p_api == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + /* Length must be a multiple of the program unit. */ + if ((len == 0) || ((len % p_fs->p_flash_info->program_unit) != 0)) + { + return NRF_ERROR_INVALID_LENGTH; + } + + /* Source and destination addresses must be word-aligned. */ + if ( !addr_is_aligned32(dest) + || !addr_is_aligned32((uint32_t)p_src) + || !addr_within_bounds(p_fs, dest, len)) + { + return NRF_ERROR_INVALID_ADDR; + } + + return (p_fs->p_api)->write(p_fs, dest, p_src, len, p_context); +} + + +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_context) +{ + if (p_fs == NULL) + { + return NRF_ERROR_NULL; + } + + if (p_fs->p_api == NULL) + { + return NRF_ERROR_INVALID_STATE; + } + + if (len == 0) + { + return NRF_ERROR_INVALID_LENGTH; + } + + /* Address must be aligned to a page boundary. */ + if ( ((page_addr & (p_fs->p_flash_info->erase_unit - 1)) != 0) + || !addr_within_bounds(p_fs, page_addr, (len * p_fs->p_flash_info->erase_unit))) + { + return NRF_ERROR_INVALID_ADDR; + } + + return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context); +} + + +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if (p_fs == NULL) + { + return NULL; + } + + return (p_fs->p_api)->rmap(p_fs, addr); +} + + +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr) +{ + if (p_fs == NULL) + { + return NULL; + } + + return (p_fs->p_api)->wmap(p_fs, addr); +} + + +bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs) +{ + /* If a NULL instance is provided, return true if any instance is busy. + * Uninitialized instances are considered not busy. */ + if ((p_fs == NULL) || (p_fs->p_api == NULL)) + { + for (uint32_t i = 0; i < NRF_FSTORAGE_INSTANCE_CNT; i++) + { + p_fs = NRF_FSTORAGE_INSTANCE_GET(i); /* cannot be NULL. */ + if (p_fs->p_api != NULL) + { + /* p_api->is_busy() cannot be NULL. */ + if (p_fs->p_api->is_busy(p_fs)) + { + return true; + } + } + } + + return false; + } + + return p_fs->p_api->is_busy(p_fs); +} + + +static bool addr_within_bounds(nrf_fstorage_t const * p_fs, + uint32_t addr, + uint32_t len) +{ + return ((addr >= p_fs->start_addr) && + (addr + len - 1 <= p_fs->end_addr)); +} + + +static bool addr_is_aligned32(uint32_t addr) +{ + return !(addr & 0x03); +} + + +#endif // NRF_FSTORAGE_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.h new file mode 100644 index 0000000000..118753f479 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/fstorage/nrf_fstorage.h @@ -0,0 +1,340 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_FSTORAGE_H__ +#define NRF_FSTORAGE_H__ + +/** + * @file + * + * @defgroup nrf_fstorage Flash storage (fstorage) + * @ingroup app_common + * @{ + * + * @brief Flash abstraction library that provides basic read, write, and erase operations. + * + * @details The fstorage library can be implemented in different ways. Two implementations are provided: + * - The @ref nrf_fstorage_sd implements flash access through the SoftDevice. + * - The @ref nrf_fstorage_nvmc implements flash access through the non-volatile memory controller. + * + * You can select the implementation that should be used independently for each instance of fstorage. + */ + +#include +#include +#include "sdk_errors.h" +#include "nrf_section.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for defining an fstorage instance. + * + * Users of fstorage must define an instance variable by using this macro. + * Each instance is tied to an API implementation and contains information such + * as the program and erase units for the target flash peripheral. + * Instance variables are placed in the "fs_data" section of the binary. + * + * @param[in] inst A definition of an @ref nrf_fstorage_t variable. + */ +#define NRF_FSTORAGE_DEF(inst) NRF_SECTION_ITEM_REGISTER(fs_data, inst) + +/**@brief Macro for retrieving an fstorage instance. */ +#define NRF_FSTORAGE_INSTANCE_GET(i) NRF_SECTION_ITEM_GET(fs_data, nrf_fstorage_t, (i)) + +/**@brief Macro for retrieving the total number of fstorage instances. */ +#define NRF_FSTORAGE_INSTANCE_CNT NRF_SECTION_ITEM_COUNT(fs_data, nrf_fstorage_t) + + +/**@brief Event IDs. */ +typedef enum +{ + NRF_FSTORAGE_EVT_READ_RESULT, + NRF_FSTORAGE_EVT_WRITE_RESULT, //!< Event for @ref nrf_fstorage_write. + NRF_FSTORAGE_EVT_ERASE_RESULT //!< Event for @ref nrf_fstorage_erase. +} nrf_fstorage_evt_id_t; + + +/**@brief An fstorage event. */ +typedef struct +{ + nrf_fstorage_evt_id_t id; //!< The event ID. + ret_code_t result; //!< Result of the operation. + uint32_t addr; //!< Address at which the operation was performed. + uint32_t len; //!< Length of the operation. + void * p_param; //!< User-defined parameter passed to the event handler. +} nrf_fstorage_evt_t; + + +/**@brief Event handler function prototype. + * + * @param[in] p_evt The event. + */ +typedef void (*nrf_fstorage_evt_handler_t)(nrf_fstorage_evt_t * p_evt); + + +/**@brief Information about the implementation and the flash peripheral. */ +typedef struct +{ + uint32_t erase_unit; //!< Size of a flash page (in bytes). A flash page is the smallest unit that can be erased. + uint32_t program_unit; //!< Size of the smallest programmable unit (in bytes). + bool rmap; //!< The device address space is memory mapped to the MCU address space. + bool wmap; //!< The device address space is memory mapped to a writable MCU address space. +} const nrf_fstorage_info_t; + + +/* Necessary forward declaration. */ +struct nrf_fstorage_api_s; + + +/**@brief An fstorage instance. + * + * @details Use the @ref NRF_FSTORAGE_DEF macro to define an fstorage instance. + * + * An instance is tied to an API implementation and contains information about the flash device, + * such as the program and erase units as well and implementation-specific functionality. + */ +typedef struct +{ + /**@brief The API implementation used by this instance. */ + struct nrf_fstorage_api_s const * p_api; + + /**@brief Information about the implementation functionality and the flash peripheral. */ + nrf_fstorage_info_t * p_flash_info; + + /**@brief The event handler function. + * + * If set to NULL, no events will be sent. + */ + nrf_fstorage_evt_handler_t evt_handler; + + /**@brief The beginning of the flash space on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref end_addr. + * + * This field must be set manually. + */ + uint32_t start_addr; + + /**@brief The last address (exclusive) of flash on which this fstorage instance should operate. + * All flash operations must be within the address specified in + * this field and @ref start_addr. + * + * This field must be set manually. + */ + uint32_t end_addr; +} nrf_fstorage_t; + + +/**@brief Functions provided by the API implementation. */ +typedef struct nrf_fstorage_api_s +{ + /**@brief Initialize the flash peripheral. */ + ret_code_t (*init)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Uninitialize the flash peripheral. */ + ret_code_t (*uninit)(nrf_fstorage_t * p_fs, void * p_param); + /**@brief Read data from flash. */ + ret_code_t (*read)(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len); + /**@brief Write bytes to flash. */ + ret_code_t (*write)(nrf_fstorage_t const * p_fs, uint32_t dest, void const * p_src, uint32_t len, void * p_param); + /**@brief Erase flash pages. */ + ret_code_t (*erase)(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len, void * p_param); + /**@brief Map a device address to a readable address within the MCU address space. */ + uint8_t const * (*rmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Map a device address to a writable address within the MCU address space. */ + uint8_t * (*wmap)(nrf_fstorage_t const * p_fs, uint32_t addr); + /**@brief Check if there are any pending flash operations. */ + bool (*is_busy)(nrf_fstorage_t const * p_fs); +} const nrf_fstorage_api_t; + + +/**@brief Function for initializing fstorage. + * + * @param[in] p_fs The fstorage instance to initialize. + * @param[in] p_api The API implementation to use. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If initialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_api field in @p p_fs is NULL. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs, + nrf_fstorage_api_t * p_api, + void * p_param); + + +/**@brief Function for uninitializing an fstorage instance. + * + * @param[in] p_fs The fstorage instance to uninitialize. + * @param[in] p_param An optional parameter to pass to the implementation-specific API call. + * + * @retval NRF_SUCCESS If uninitialization was successful. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INTERNAL If another error occurred. + */ +ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, void * p_param); + + +/**@brief Function for reading data from flash. + * + * Copy @p len bytes from @p addr to @p p_dest. + * + * @param[in] p_fs The fstorage instance. + * @param[in] addr Address in flash where to read from. + * @param[in] p_dest Buffer where the data should be copied. + * @param[in] len Length of the data to be copied (in bytes). + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_dest is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + */ +ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs, + uint32_t addr, + void * p_dest, + uint32_t len); + + +/**@brief Function for writing data to flash. + * + * Write @p len bytes from @p p_src to @p dest. + * + * When using @ref nrf_fstorage_sd, the data is written by several calls to @ref sd_flash_write if + * the length of the data exceeds @ref NRF_FSTORAGE_SD_MAX_WRITE_SIZE bytes. + * Only one event is sent upon completion. + * + * @note The data to be written to flash must be kept in memory until the operation has + * terminated and an event is received. + * + * @param[in] p_fs The fstorage instance. + * @param[in] dest Address in flash memory where to write the data. + * @param[in] p_src Data to be written. + * @param[in] len Length of the data (in bytes). + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs or @p p_src is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or not a multiple of the program unit, + * or if it is otherwise invalid. + * @retval NRF_ERROR_INVALID_ADDR If the address @p dest is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs, + uint32_t dest, + void const * p_src, + uint32_t len, + void * p_param); + + +/**@brief Function for erasing flash pages. + * + * @details This function erases @p len pages starting from the page at address @p page_addr. + * The erase operation must be initiated on a page boundary. + * + * @param[in] p_fs The fstorage instance. + * @param[in] page_addr Address of the page to erase. + * @param[in] len Number of pages to erase. + * @param[in] p_param User-defined parameter passed to the event handler (may be NULL). + * + * @retval NRF_SUCCESS If the operation was accepted. + * @retval NRF_ERROR_NULL If @p p_fs is NULL. + * @retval NRF_ERROR_INVALID_STATE If the module is not initialized. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_INVALID_ADDR If the address @p page_addr is outside the flash memory + * boundaries specified in @p p_fs, or if it is unaligned. + * @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation. + * When using the @ref nrf_fstorage_sd, this error + * indicates that the internal queue of operations is full. + */ +ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs, + uint32_t page_addr, + uint32_t len, + void * p_param); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be dereferenced. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Map a flash address to a pointer in the MCU address space that can be written to. + * + * @param p_fs The fstorage instance. + * @param addr The address to map. + * + * @retval A pointer to the specified address, + * or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL. + */ +uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr); + + +/**@brief Function for querying the status of fstorage. + * + * @details An uninitialized instance of fstorage is treated as not busy. + * + * @param[in] p_fs The fstorage instance. Pass NULL to query all instances. + * + * @returns If @p p_fs is @c NULL, this function returns true if any fstorage instance is busy or false otherwise. + * @returns If @p p_fs is not @c NULL, this function returns true if the fstorage instance is busy or false otherwise. + */ + bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs); + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_FSTORAGE_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.c new file mode 100644 index 0000000000..62b7a8ba5a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.c @@ -0,0 +1,464 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_QUEUE) +#include "nrf_queue.h" +#include "app_util_platform.h" + +/**@brief Get next element index. + * + * @param[in] p_queue Pointer to the queue instance. + * @param[in] idx Current index. + * + * @return Next element index. + */ +__STATIC_INLINE size_t nrf_queue_next_idx(nrf_queue_t const * p_queue, size_t idx) +{ + ASSERT(p_queue != NULL); + return (idx < p_queue->size) ? (idx + 1) : 0; +} + +/**@brief Get current queue utilization. This function assumes that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Current queue utilization. + */ +__STATIC_INLINE size_t queue_utilization_get(nrf_queue_t const * p_queue) +{ + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + return (back >= front) ? (back - front) : (p_queue->size + 1 - front + back); +} + +bool nrf_queue_is_full(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + + return (nrf_queue_next_idx(p_queue, back) == front); +} + +ret_code_t nrf_queue_push(nrf_queue_t const * p_queue, void const * p_element) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_element != NULL); + + CRITICAL_REGION_ENTER(); + bool is_full = nrf_queue_is_full(p_queue); + + if (!is_full || (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW)) + { + // Get write position. + size_t write_pos = p_queue->p_cb->back; + p_queue->p_cb->back = nrf_queue_next_idx(p_queue, p_queue->p_cb->back); + if (is_full) + { + // Overwrite the oldest element. + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->front); + } + + // Write a new element. + switch (p_queue->element_size) + { + case sizeof(uint8_t): + ((uint8_t *)p_queue->p_buffer)[write_pos] = *((uint8_t *)p_element); + break; + + case sizeof(uint16_t): + ((uint16_t *)p_queue->p_buffer)[write_pos] = *((uint16_t *)p_element); + break; + + case sizeof(uint32_t): + ((uint32_t *)p_queue->p_buffer)[write_pos] = *((uint32_t *)p_element); + break; + + case sizeof(uint64_t): + ((uint64_t *)p_queue->p_buffer)[write_pos] = *((uint64_t *)p_element); + break; + + default: + memcpy((void *)((size_t)p_queue->p_buffer + write_pos * p_queue->element_size), + p_element, + p_queue->element_size); + break; + } + + // Update utilization. + size_t utilization = queue_utilization_get(p_queue); + if (p_queue->p_cb->max_utilization < utilization) + { + p_queue->p_cb->max_utilization = utilization; + } + } + else + { + status = NRF_ERROR_NO_MEM; + } + + CRITICAL_REGION_EXIT(); + + return status; +} + +ret_code_t nrf_queue_generic_pop(nrf_queue_t const * p_queue, + void * p_element, + bool just_peek) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_element != NULL); + + CRITICAL_REGION_ENTER(); + + if (!nrf_queue_is_empty(p_queue)) + { + // Get read position. + size_t read_pos = p_queue->p_cb->front; + + // Update next read position. + if (!just_peek) + { + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->front); + } + + // Read element. + switch (p_queue->element_size) + { + case sizeof(uint8_t): + *((uint8_t *)p_element) = ((uint8_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint16_t): + *((uint16_t *)p_element) = ((uint16_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint32_t): + *((uint32_t *)p_element) = ((uint32_t *)p_queue->p_buffer)[read_pos]; + break; + + case sizeof(uint64_t): + *((uint64_t *)p_element) = ((uint64_t *)p_queue->p_buffer)[read_pos]; + break; + + default: + memcpy(p_element, + (void const *)((size_t)p_queue->p_buffer + read_pos * p_queue->element_size), + p_queue->element_size); + break; + } + } + else + { + status = NRF_ERROR_NOT_FOUND; + } + + CRITICAL_REGION_EXIT(); + + return status; +} + +/**@brief Write elements to the queue. This function assumes that there is enough room in the queue + * to write the requested number of elements and that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + */ +static void queue_write(nrf_queue_t const * p_queue, void const * p_data, uint32_t element_count) +{ + size_t prev_available = nrf_queue_available_get(p_queue); + size_t continuous = p_queue->size + 1 - p_queue->p_cb->back; + void * p_write_ptr = (void *)((size_t)p_queue->p_buffer + + p_queue->p_cb->back * p_queue->element_size); + if (element_count <= continuous) + { + memcpy(p_write_ptr, + p_data, + element_count * p_queue->element_size); + + p_queue->p_cb->back = ((p_queue->p_cb->back + element_count) <= p_queue->size) + ? (p_queue->p_cb->back + element_count) + : 0; + } + else + { + size_t first_write_length = continuous * p_queue->element_size; + memcpy(p_write_ptr, + p_data, + first_write_length); + + size_t elements_left = element_count - continuous; + memcpy(p_queue->p_buffer, + (void const *)((size_t)p_data + first_write_length), + elements_left * p_queue->element_size); + + p_queue->p_cb->back = elements_left; + if (prev_available < element_count) + { + // Overwrite the oldest elements. + p_queue->p_cb->front = nrf_queue_next_idx(p_queue, p_queue->p_cb->back); + } + } + + // Update utilization. + size_t utilization = queue_utilization_get(p_queue); + if (p_queue->p_cb->max_utilization < utilization) + { + p_queue->p_cb->max_utilization = utilization; + } +} + +ret_code_t nrf_queue_write(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + ASSERT(element_count <= p_queue->size); + + if (element_count == 0) + { + return NRF_SUCCESS; + } + + CRITICAL_REGION_ENTER(); + + if ((nrf_queue_available_get(p_queue) >= element_count) + || (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW)) + { + queue_write(p_queue, p_data, element_count); + } + else + { + status = NRF_ERROR_NO_MEM; + } + + CRITICAL_REGION_EXIT(); + + return status; +} + + +size_t nrf_queue_in(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count) +{ + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + if (element_count == 0) + { + return 0; + } + + CRITICAL_REGION_ENTER(); + + if (p_queue->mode == NRF_QUEUE_MODE_OVERFLOW) + { + element_count = MIN(element_count, p_queue->size); + } + else + { + size_t available = nrf_queue_available_get(p_queue); + element_count = MIN(element_count, available); + } + + queue_write(p_queue, p_data, element_count); + + CRITICAL_REGION_EXIT(); + + return element_count; +} + +/**@brief Read elements from the queue. This function assumes that there are enough elements + * in the queue to read and that this process will not be interrupted. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + */ +static void queue_read(nrf_queue_t const * p_queue, void * p_data, uint32_t element_count) +{ + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + size_t continuous = (front <= back) ? (back - front) : (p_queue->size + 1 - front); + void const * p_read_ptr = (void const *)((size_t)p_queue->p_buffer + + front * p_queue->element_size); + + if (element_count <= continuous) + { + memcpy(p_data, + p_read_ptr, + element_count * p_queue->element_size); + + p_queue->p_cb->front = ((front + element_count) <= p_queue->size) + ? (front + element_count) + : 0; + } + else + { + size_t first_read_length = continuous * p_queue->element_size; + memcpy(p_data, + p_read_ptr, + first_read_length); + + size_t elements_left = element_count - continuous; + memcpy((void *)((size_t)p_data + first_read_length), + p_queue->p_buffer, + elements_left * p_queue->element_size); + + p_queue->p_cb->front = elements_left; + } +} + +ret_code_t nrf_queue_read(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count) +{ + ret_code_t status = NRF_SUCCESS; + + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + if (element_count == 0) + { + return NRF_SUCCESS; + } + + CRITICAL_REGION_ENTER(); + + if (element_count <= queue_utilization_get(p_queue)) + { + queue_read(p_queue, p_data, element_count); + } + else + { + status = NRF_ERROR_NOT_FOUND; + } + + CRITICAL_REGION_EXIT(); + + return status; +} + +size_t nrf_queue_out(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count) +{ + ASSERT(p_queue != NULL); + ASSERT(p_data != NULL); + + if (element_count == 0) + { + return 0; + } + + CRITICAL_REGION_ENTER(); + + size_t utilization = queue_utilization_get(p_queue); + element_count = MIN(element_count, utilization); + + queue_read(p_queue, p_data, element_count); + + CRITICAL_REGION_EXIT(); + + return element_count; +} + +void nrf_queue_reset(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + + CRITICAL_REGION_ENTER(); + + memset(p_queue->p_cb, 0, sizeof(nrf_queue_cb_t)); + + CRITICAL_REGION_EXIT(); +} + +size_t nrf_queue_utilization_get(nrf_queue_t const * p_queue) +{ + size_t utilization; + ASSERT(p_queue != NULL); + + CRITICAL_REGION_ENTER(); + + utilization = queue_utilization_get(p_queue); + + CRITICAL_REGION_EXIT(); + + return utilization; +} + +bool nrf_queue_is_empty(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + size_t front = p_queue->p_cb->front; + size_t back = p_queue->p_cb->back; + return (front == back); +} + +size_t nrf_queue_available_get(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + return p_queue->size - nrf_queue_utilization_get(p_queue); +} + +size_t nrf_queue_max_utilization_get(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + return p_queue->p_cb->max_utilization; +} + +void nrf_queue_max_utilization_reset(nrf_queue_t const * p_queue) +{ + ASSERT(p_queue != NULL); + p_queue->p_cb->max_utilization = 0; +} + + +#endif // NRF_MODULE_ENABLED(NRF_QUEUE) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.h new file mode 100644 index 0000000000..c5884f85d5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/queue/nrf_queue.h @@ -0,0 +1,406 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_queue Queue module +* @{ +* @ingroup app_common +* @brief Functions that handle the queue instances. +*/ + +#ifndef NRF_QUEUE_H__ +#define NRF_QUEUE_H__ + +#include +#include +#include +#include "nrf_assert.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "app_util_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Queue control block. */ +typedef struct +{ + volatile size_t front; //!< Queue front index. + volatile size_t back; //!< Queue back index. + size_t max_utilization; //!< Maximum utilization of the queue. +} nrf_queue_cb_t; + +/**@brief Supported queue modes. */ +typedef enum +{ + NRF_QUEUE_MODE_OVERFLOW, //!< If the queue is full, new element will overwrite the oldest. + NRF_QUEUE_MODE_NO_OVERFLOW, //!< If the queue is full, new element will not be accepted. +} nrf_queue_mode_t; + +/**@brief Instance of the queue. */ +typedef struct +{ + nrf_queue_cb_t * p_cb; //!< Pointer to the instance control block. + void * p_buffer; //!< Pointer to the memory that is used as storage. + size_t size; //!< Size of the queue. + size_t element_size; //!< Size of one element. + nrf_queue_mode_t mode; //!< Mode of the queue. +} nrf_queue_t; + +/**@brief Create a queue instance. + * + * @note This macro reserves memory for the given queue instance. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + * @param[in] _size Size of the queue. + * @param[in] _mode Mode of the queue. + */ +#define NRF_QUEUE_DEF(_type, _name, _size, _mode) \ + static _type CONCAT_2(_name, _nrf_queue_buffer[(_size) + 1]); \ + static nrf_queue_cb_t CONCAT_2(_name, _nrf_queue_cb); \ + static const nrf_queue_t _name = \ + { \ + .p_cb = &CONCAT_2(_name, _nrf_queue_cb), \ + .p_buffer = CONCAT_2(_name,_nrf_queue_buffer), \ + .size = (_size), \ + .element_size = sizeof(_type), \ + .mode = _mode, \ + } + +/**@brief Declare a queue interface. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + */ +#define NRF_QUEUE_INTERFACE_DEC(_type, _name) \ + ret_code_t _name##_push(_type const * p_element); \ + ret_code_t _name##_pop(_type * p_element); \ + ret_code_t _name##_peek(_type * p_element); \ + ret_code_t _name##_write(_type const * p_data, \ + size_t element_count); \ + ret_code_t _name##_read(_type * p_data, \ + size_t element_count); \ + size_t _name##_out(_type * p_data, \ + size_t element_count); \ + size_t _name##_in(_type const * p_data, \ + size_t element_count); \ + bool _name##_is_full(void); \ + bool _name##_is_empty(void); \ + size_t _name##_utilization_get(void); \ + size_t _name##_available_get(void); \ + size_t _name##_max_utilization_get(void); \ + void _name##_reset(void) + +/**@brief Define a queue interface. + * + * @param[in] _type Type which is stored. + * @param[in] _name Name of the queue. + * @param[in] _p_queue Queue instance. + */ +#define NRF_QUEUE_INTERFACE_DEF(_type, _name, _p_queue) \ + ret_code_t _name##_push(_type const * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_push((_p_queue), p_element); \ + } \ + ret_code_t _name##_pop(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_pop((_p_queue), p_element); \ + } \ + ret_code_t _name##_peek(_type * p_element) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_peek((_p_queue), p_element); \ + } \ + ret_code_t _name##_write(_type const * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_write((_p_queue), p_data, element_count); \ + } \ + ret_code_t _name##_read(_type * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_read((_p_queue), p_data, element_count); \ + } \ + size_t _name##_in(_type const * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_in((_p_queue), p_data, element_count); \ + } \ + size_t _name##_out(_type * p_data, \ + size_t element_count) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + ASSERT((_p_queue)->element_size == sizeof(_type)); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_out((_p_queue), p_data, element_count); \ + } \ + bool _name##_is_full(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + return nrf_queue_is_full(_p_queue); \ + GCC_PRAGMA("GCC diagnostic pop") \ + } \ + bool _name##_is_empty(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_is_empty(_p_queue); \ + } \ + size_t _name##_utilization_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_utilization_get(_p_queue); \ + } \ + size_t _name##_available_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_available_get(_p_queue); \ + } \ + size_t _name##_max_utilization_get(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + return nrf_queue_max_utilization_get(_p_queue); \ + } \ + void _name##_reset(void) \ + { \ + GCC_PRAGMA("GCC diagnostic push") \ + GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \ + ASSERT((_p_queue) != NULL); \ + GCC_PRAGMA("GCC diagnostic pop") \ + nrf_queue_reset(_p_queue); \ + } + +/**@brief Function for pushing an element to the end of queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_element Pointer to the element that will be stored in the queue. + * + * @return NRF_SUCCESS If an element has been successfully added. + * @return NRF_ERROR_NO_MEM If the queue is full (only in @ref NRF_QUEUE_MODE_NO_OVERFLOW). + */ +ret_code_t nrf_queue_push(nrf_queue_t const * p_queue, void const * p_element); + +/**@brief Generic pop implementation. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_element Pointer where the element will be copied. + * @param[out] just_peek If true, the returned element will not be removed from queue. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +ret_code_t nrf_queue_generic_pop(nrf_queue_t const * p_queue, + void * p_element, + bool just_peek); + +/**@brief Pop element from the front of the queue. + * + * @param[in] _p_queue Pointer to the nrf_queue_t instance. + * @param[out] _p_element Pointer where the element will be copied. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +#define nrf_queue_pop(_p_queue, _p_element) nrf_queue_generic_pop((_p_queue), (_p_element), false) + +/**@brief Peek element from the front of the queue. + * + * @param[in] _p_queue Pointer to the nrf_queue_t instance. + * @param[out] _p_element Pointer where the element will be copied. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND If there are no more elements in the queue. + */ +#define nrf_queue_peek(_p_queue, _p_element) nrf_queue_generic_pop((_p_queue), (_p_element), true) + +/**@brief Function for writing elements to the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + * + * @return NRF_SUCCESS If an element was written. + * @return NRF_ERROR_NO_MEM There is not enough space in the queue. No element was written. + */ +ret_code_t nrf_queue_write(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count); + +/**@brief Function for writing a portion of elements to the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[in] p_data Pointer to the buffer with elements to write. + * @param[in] element_count Number of elements to write. + * + * @return The number of added elements. + */ +size_t nrf_queue_in(nrf_queue_t const * p_queue, + void const * p_data, + size_t element_count); + +/**@brief Function for reading elements from the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + * + * @return NRF_SUCCESS If an element was returned. + * @return NRF_ERROR_NOT_FOUND There is not enough elements in the queue. + */ +ret_code_t nrf_queue_read(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count); + +/**@brief Function for reading a portion of elements from the queue. + * + * @param[in] p_queue Pointer to the nrf_queue_t instance. + * @param[out] p_data Pointer to the buffer where elements will be copied. + * @param[in] element_count Number of elements to read. + * + * @return The number of read elements. + */ +size_t nrf_queue_out(nrf_queue_t const * p_queue, + void * p_data, + size_t element_count); + +/**@brief Function for checking if the queue is full. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return True if the queue is full. + */ +bool nrf_queue_is_full(nrf_queue_t const * p_queue); + +/**@brief Function for checking if the queue is empty. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return True if the queue is empty. + */ +bool nrf_queue_is_empty(nrf_queue_t const * p_queue); + +/**@brief Function for getting the current queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Current queue utilization. + */ +size_t nrf_queue_utilization_get(nrf_queue_t const * p_queue); + +/**@brief Function for getting the size of available space. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Size of available space. + */ +size_t nrf_queue_available_get(nrf_queue_t const * p_queue); + +/**@brief Function for getting the maximal queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + * @return Maximal queue utilization. + */ +size_t nrf_queue_max_utilization_get(nrf_queue_t const * p_queue); + +/**@brief Function for resetting the maximal queue utilization. + * + * @param[in] p_queue Pointer to the queue instance. + * + */ +void nrf_queue_max_utilization_reset(nrf_queue_t const * p_queue); + +/**@brief Function for resetting the queue state. + * + * @param[in] p_queue Pointer to the queue instance. + */ +void nrf_queue_reset(nrf_queue_t const * p_queue); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_QUEUE_H__ +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.c new file mode 100644 index 0000000000..09e3fb0f20 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.c @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2011 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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(NRF_STRERROR) +#include "nrf_strerror.h" + +/** + * @brief Macro for adding an entity to the description array. + * + * Macro that helps to create a single entity in the description array. + */ +#define NRF_STRERROR_ENTITY(mnemonic) {.code = mnemonic, .name = #mnemonic} + +/** + * @brief Array entity element that describes an error. + */ +typedef struct +{ + ret_code_t code; /**< Error code. */ + char const * name; /**< Descriptive name (the same as the internal error mnemonic). */ +}nrf_strerror_desc_t; + +/** + * @brief Unknown error code. + * + * The constant string used by @ref nrf_strerror_get when the error description was not found. + */ +static char const m_unknown_str[] = "Unknown error code"; + +/** + * @brief Array with error codes. + * + * Array that describes error codes. + * + * @note It is required for this array to have error codes placed in ascending order. + * This condition is checked in automatic unit test before the release. + */ +static nrf_strerror_desc_t const nrf_strerror_array[] = +{ + NRF_STRERROR_ENTITY(NRF_SUCCESS), + NRF_STRERROR_ENTITY(NRF_ERROR_SVC_HANDLER_MISSING), + NRF_STRERROR_ENTITY(NRF_ERROR_SOFTDEVICE_NOT_ENABLED), + NRF_STRERROR_ENTITY(NRF_ERROR_INTERNAL), + NRF_STRERROR_ENTITY(NRF_ERROR_NO_MEM), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_FOUND), + NRF_STRERROR_ENTITY(NRF_ERROR_NOT_SUPPORTED), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_PARAM), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_STATE), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_LENGTH), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_FLAGS), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_DATA), + NRF_STRERROR_ENTITY(NRF_ERROR_DATA_SIZE), + NRF_STRERROR_ENTITY(NRF_ERROR_TIMEOUT), + NRF_STRERROR_ENTITY(NRF_ERROR_NULL), + NRF_STRERROR_ENTITY(NRF_ERROR_FORBIDDEN), + NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_ADDR), + NRF_STRERROR_ENTITY(NRF_ERROR_BUSY), + + /* SDK Common errors */ + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_NOT_INITIALZED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_LOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_UNLOCK_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_COND_INIT_FAILED), + NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_ALREADY_INITIALIZED), + NRF_STRERROR_ENTITY(NRF_ERROR_STORAGE_FULL), + NRF_STRERROR_ENTITY(NRF_ERROR_API_NOT_IMPLEMENTED), + NRF_STRERROR_ENTITY(NRF_ERROR_FEATURE_NOT_ENABLED), + + /* TWI error codes */ + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_OVERRUN), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_ANACK), + NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_DNACK) +}; + + +char const * nrf_strerror_get(ret_code_t code) +{ + char const * p_ret = nrf_strerror_find(code); + return (p_ret == NULL) ? m_unknown_str : p_ret; +} + +char const * nrf_strerror_find(ret_code_t code) +{ + nrf_strerror_desc_t const * p_start; + nrf_strerror_desc_t const * p_end; + p_start = nrf_strerror_array; + p_end = nrf_strerror_array + ARRAY_SIZE(nrf_strerror_array); + + while (p_start < p_end) + { + nrf_strerror_desc_t const * p_mid = p_start + ((p_end - p_start) / 2); + ret_code_t mid_c = p_mid->code; + if (mid_c > code) + { + p_end = p_mid; + } + else if (mid_c < code) + { + p_start = p_mid + 1; + } + else + { + return p_mid->name; + } + } + return NULL; +} + +#endif /* NRF_STRERROR enabled */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.h new file mode 100644 index 0000000000..f0de77d844 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/strerror/nrf_strerror.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_strerror Error code to string converter + * @ingroup app_common + * + * @brief Module for converting error code into a printable string. + * @{ + */ +#ifndef NRF_STRERROR_H__ +#define NRF_STRERROR_H__ + +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for getting a printable error string. + * + * @param code Error code to convert. + * + * @note This function cannot fail. + * For the function that may fail with error translation, see @ref nrf_strerror_find. + * + * @return Pointer to the printable string. + * If the string is not found, + * it returns a simple string that says that the error is unknown. + */ +char const * nrf_strerror_get(ret_code_t code); + +/** + * @brief Function for finding a printable error string. + * + * This function gets the error string in the same way as @ref nrf_strerror_get, + * but if the string is not found, it returns NULL. + * + * @param code Error code to convert. + * @return Pointer to the printable string. + * If the string is not found, NULL is returned. + */ +char const * nrf_strerror_find(ret_code_t code); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_STRERROR_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.c new file mode 100644 index 0000000000..e50e57d223 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.c @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +#include "nrf.h" +#include +#include "app_error.h" +#include "nordic_common.h" +#include "sdk_errors.h" +/**@brief Function for error handling, which is called when an error has occurred. + * + * @warning This handler is an example only and does not fit a final product. You need to analyze + * how your product is supposed to react in case of error. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ + +/*lint -save -e14 */ +void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +{ + error_info_t error_info = + { + .line_num = line_num, + .p_file_name = p_file_name, + .err_code = error_code, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} + +/*lint -save -e14 */ +void app_error_handler_bare(ret_code_t error_code) +{ + error_info_t error_info = + { + .line_num = 0, + .p_file_name = NULL, + .err_code = error_code, + }; + + app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info)); + + UNUSED_VARIABLE(error_info); +} + + +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info) +{ + /* static error variables - in order to prevent removal by optimizers */ + static volatile struct + { + uint32_t fault_id; + uint32_t pc; + uint32_t error_info; + assert_info_t * p_assert_info; + error_info_t * p_error_info; + ret_code_t err_code; + uint32_t line_num; + const uint8_t * p_file_name; + } m_error_data = {0}; + + // The following variable helps Keil keep the call stack visible, in addition, it can be set to + // 0 in the debugger to continue executing code after the error check. + volatile bool loop = true; + UNUSED_VARIABLE(loop); + + m_error_data.fault_id = id; + m_error_data.pc = pc; + m_error_data.error_info = info; + + switch (id) + { + case NRF_FAULT_ID_SDK_ASSERT: + m_error_data.p_assert_info = (assert_info_t *)info; + m_error_data.line_num = m_error_data.p_assert_info->line_num; + m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name; + break; + + case NRF_FAULT_ID_SDK_ERROR: + m_error_data.p_error_info = (error_info_t *)info; + m_error_data.err_code = m_error_data.p_error_info->err_code; + m_error_data.line_num = m_error_data.p_error_info->line_num; + m_error_data.p_file_name = m_error_data.p_error_info->p_file_name; + break; + } + + UNUSED_VARIABLE(m_error_data); + + // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger. + __disable_irq(); + while (loop); + + __enable_irq(); +} + +/*lint -restore */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.h new file mode 100644 index 0000000000..c8c3758660 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error.h @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler and macros for utilizing a common error handler. + */ + +#ifndef APP_ERROR_H__ +#define APP_ERROR_H__ + + +#include +#include +#include +#include "nrf.h" +#include "sdk_errors.h" +#include "nordic_common.h" +#include "app_error_weak.h" +#ifdef ANT_STACK_SUPPORT_REQD +#include "ant_error.h" +#endif // ANT_STACK_SUPPORT_REQD + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_FAULT_ID_SDK_RANGE_START 0x00004000 /**< The start of the range of error IDs defined in the SDK. */ + +/**@defgroup APP_ERROR_FAULT_IDS Fault ID types + * @{ */ +#define NRF_FAULT_ID_SDK_ERROR NRF_FAULT_ID_SDK_RANGE_START + 1 /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */ +#define NRF_FAULT_ID_SDK_ASSERT NRF_FAULT_ID_SDK_RANGE_START + 2 /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */ +/**@} */ + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR. + */ +typedef struct +{ + uint16_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ + uint32_t err_code; /**< The error code representing the error that occurred. */ +} error_info_t; + +/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT. + */ +typedef struct +{ + uint16_t line_num; /**< The line number where the error occurred. */ + uint8_t const * p_file_name; /**< The file in which the error occurred. */ +} assert_info_t; + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + * @param[in] line_num Line number where the handler is called. + * @param[in] p_file_name Pointer to the file name. + */ +void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name); + +/**@brief Function for error handling, which is called when an error has occurred. + * + * @param[in] error_code Error code supplied to the handler. + */ +void app_error_handler_bare(ret_code_t error_code); + +/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. Refer to each fault + * identifier for details. + */ +void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info); + + +/**@brief Macro for calling error handler function. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#ifdef DEBUG +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \ + } while (0) +#else +#define APP_ERROR_HANDLER(ERR_CODE) \ + do \ + { \ + app_error_handler_bare((ERR_CODE)); \ + } while (0) +#endif +/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS. + * + * @param[in] ERR_CODE Error code supplied to the error handler. + */ +#define APP_ERROR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != NRF_SUCCESS) \ + { \ + APP_ERROR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +/**@brief Macro for calling error handler function if supplied boolean value is false. + * + * @param[in] BOOLEAN_VALUE Boolean value to be evaluated. + */ +#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \ + do \ + { \ + const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \ + if (!LOCAL_BOOLEAN_VALUE) \ + { \ + APP_ERROR_HANDLER(0); \ + } \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.c new file mode 100644 index 0000000000..f00b36f716 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.c @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "app_error.h" + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_strerror.h" + +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#endif + +/*lint -save -e14 */ + +/** + * Function is implemented as weak so that it can be overwritten by custom application error handler + * when needed. + */ +__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) +{ + NRF_LOG_FINAL_FLUSH(); + +#ifndef DEBUG + NRF_LOG_ERROR("Fatal error"); +#else + switch (id) + { +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT + case NRF_FAULT_ID_SD_ASSERT: + NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); + break; + case NRF_FAULT_ID_APP_MEMACC: + NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); + break; +#endif + case NRF_FAULT_ID_SDK_ASSERT: + { + assert_info_t * p_info = (assert_info_t *)info; + NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", + p_info->p_file_name, + p_info->line_num); + break; + } + case NRF_FAULT_ID_SDK_ERROR: + { + error_info_t * p_info = (error_info_t *)info; + NRF_LOG_ERROR("ERROR %u [%s] at %s:%u", + p_info->err_code, + nrf_strerror_get(p_info->err_code), + p_info->p_file_name, + p_info->line_num); + break; + } + default: + NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); + break; + } +#endif + + NRF_BREAKPOINT_COND; + // On assert, the system can only recover with a reset. + +#ifndef DEBUG + NRF_LOG_WARNING("System reset"); + NVIC_SystemReset(); +#else + app_error_save_and_stop(id, pc, info); +#endif // DEBUG +} + +/*lint -restore */ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.h new file mode 100644 index 0000000000..fa49dc3f01 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_error_weak.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2016 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 APP_ERROR_WEAK_H__ +#define APP_ERROR_WEAK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * + * @defgroup app_error Common application error handler + * @{ + * @ingroup app_common + * + * @brief Common application error handler. + */ + +/**@brief Callback function for errors, asserts, and faults. + * + * @details This function is called every time an error is raised in app_error, nrf_assert, or + * in the SoftDevice. Information about the error can be found in the @p info + * parameter. + * + * See also @ref nrf_fault_handler_t for more details. + * + * @note The function is implemented as weak so that it can be redefined by a custom error + * handler when needed. + * + * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. + * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if + * unavailable. + * @param[in] info Optional additional information regarding the fault. The value of the @p id + * parameter dictates how to interpret this parameter. Refer to the documentation + * for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for + * details about interpreting @p info. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info); + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif // APP_ERROR_WEAK_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util.h new file mode 100644 index 0000000000..a8ffba29fe --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util.h @@ -0,0 +1,1082 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_H__ +#define APP_UTIL_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//lint -save -e27 -e10 -e19 +#if defined ( __CC_ARM ) && !defined (__LINT__) +extern char STACK$$Base; +extern char STACK$$Length; +#define STACK_BASE &STACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&STACK$$Length)) +#elif defined ( __ICCARM__ ) +extern char CSTACK$$Base; +extern char CSTACK$$Length; +#define STACK_BASE &CSTACK$$Base +#define STACK_TOP ((void*)((uint32_t)STACK_BASE + (uint32_t)&CSTACK$$Length)) +#elif defined ( __GNUC__ ) +extern uint32_t __StackTop; +extern uint32_t __StackLimit; +#define STACK_BASE &__StackLimit +#define STACK_TOP &__StackTop +#endif +//lint -restore + +enum +{ + UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ + UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ + UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ +}; + + +/*Segger embedded studio originally has offsetof macro which cannot be used in macros (like STATIC_ASSERT). + This redefinition is to allow using that. */ +#if defined(__SES_ARM) && defined(__GNUC__) +#undef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#endif + +/**@brief Implementation specific macro for delayed macro expansion used in string concatenation +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs + + +/**@brief Macro used to concatenate string using delayed macro expansion +* +* @note This macro will delay concatenation until the expressions have been resolved +* +* @param[in] lhs Left hand side in concatenation +* @param[in] rhs Right hand side in concatenation +*/ +#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) + + +#ifndef __LINT__ + +#ifdef __GNUC__ +#define STATIC_ASSERT_SIMPLE(EXPR) _Static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG) +#endif + +#ifdef __CC_ARM +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(EXPR)])] +#endif + +#ifdef __ICCARM__ +#define STATIC_ASSERT_SIMPLE(EXPR) static_assert(EXPR, "unspecified message") +#define STATIC_ASSERT_MSG(EXPR, MSG) static_assert(EXPR, MSG) +#endif + +#else // __LINT__ + +#define STATIC_ASSERT_SIMPLE(EXPR) extern char (*_ignore(void)) +#define STATIC_ASSERT_MSG(EXPR, MSG) extern char (*_ignore(void)) + +#endif + + +#define _SELECT_ASSERT_FUNC(x, EXPR, MSG, ASSERT_MACRO, ...) ASSERT_MACRO + +/** + * @brief Static (i.e. compile time) assert macro. + * + * @note The output of STATIC_ASSERT can be different across compilers. + * + * Usage: + * STATIC_ASSERT(expression); + * STATIC_ASSERT(expression, message); + * + * @hideinitializer + */ +//lint -save -esym(???, STATIC_ASSERT) +#define STATIC_ASSERT(...) \ + _SELECT_ASSERT_FUNC(x, ##__VA_ARGS__, \ + STATIC_ASSERT_MSG(__VA_ARGS__), \ + STATIC_ASSERT_SIMPLE(__VA_ARGS__)) +//lint -restore + + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_IMPL( \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + + +/**@brief Macro to get the number of arguments in a call variadic macro call + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +/**@brief Implementation details for NUM_VAR_ARGS */ +#define NUM_VA_ARGS_LESS_1_IMPL( \ + _ignored, \ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, N, ...) N + +/**@brief Macro to get the number of arguments in a call variadic macro call. + * First argument is not counted. + * + * param[in] ... List of arguments + * + * @retval Number of variadic arguments in the argument list + */ +#define NUM_VA_ARGS_LESS_1(...) NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) + + +/**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ +typedef uint8_t uint16_le_t[2]; + +/**@brief Type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ +typedef uint8_t uint32_le_t[4]; + +/**@brief Byte array type. */ +typedef struct +{ + uint16_t size; /**< Number of array entries. */ + uint8_t * p_data; /**< Pointer to array entries. */ +} uint8_array_t; + + +/**@brief Macro for performing rounded integer division (as opposed to truncating the result). + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Rounded (integer) result of dividing A by B. + */ +#define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) + + +/**@brief Macro for checking if an integer is a power of two. + * + * @param[in] A Number to be tested. + * + * @return true if value is power of two. + * @return false if value not power of two. + */ +#define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) + + +/**@brief Macro for converting milliseconds to ticks. + * + * @param[in] TIME Number of milliseconds to convert. + * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. + */ +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) + + +/**@brief Macro for performing integer division, making sure the result is rounded up. + * + * @details One typical use for this is to compute the number of objects with size B is needed to + * hold A number of bytes. + * + * @param[in] A Numerator. + * @param[in] B Denominator. + * + * @return Integer result of dividing A by B, rounded up. + */ +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + + +/**@brief Macro for creating a buffer aligned to 4 bytes. + * + * @param[in] NAME Name of the buffor. + * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). + */ +#define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] + + +/**@brief Macro for calculating the number of words that are needed to hold a number of bytes. + * + * @details Adds 3 and divides by 4. + * + * @param[in] n_bytes The number of bytes. + * + * @return The number of words that @p n_bytes take up (rounded up). + */ +#define BYTES_TO_WORDS(n_bytes) (((n_bytes) + 3) >> 2) + + +/**@brief The number of bytes in a word. + */ +#define BYTES_PER_WORD (4) + + +/**@brief Macro for increasing a number to the nearest (larger) multiple of another number. + * + * @param[in] alignment The number to align to. + * @param[in] number The number to align (increase). + * + * @return The aligned (increased) @p number. + */ +#define ALIGN_NUM(alignment, number) ((number - 1) + alignment - ((number - 1) % alignment)) + +/**@brief Macro for getting first of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_1(a1, a2) a1 + +/**@brief Macro for getting second of 2 parameters. + * + * @param[in] a1 First parameter. + * @param[in] a2 Second parameter. + */ +#define GET_ARG_2(a1, a2) a2 + + +/**@brief Container of macro (borrowed from Linux kernel). + * + * This macro returns parent structure address basing on child member address. + * + * @param ptr Address of child type. + * @param type Type of parent structure. + * @param member Name of child field in parent structure. + * + * @return Parent structure address. + * */ +#define CONTAINER_OF(ptr, type, member) \ + (type *)((char *)ptr - offsetof(type, member)) + + +/** + * @brief Define Bit-field mask + * + * Macro that defined the mask with selected number of bits set, starting from + * provided bit number. + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + */ +#define BF_MASK(bcnt, boff) ( ((1U << (bcnt)) - 1U) << (boff) ) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value + * + * @param[in] val Value from witch selected bit-field would be extracted + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return Value of the selected bits + */ +#define BF_GET(val, bcnt, boff) ( ( (val) & BF_MASK((bcnt), (boff)) ) >> (boff) ) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field + * + * @param[in] val Value to set on bit-field + * @param[in] bcnt Number of bits for bit-field + * @param[in] boff Offset of bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_VAL(val, bcnt, boff) ( (((uint32_t)(val)) << (boff)) & BF_MASK(bcnt, boff) ) + +/** + * @name Configuration of complex bit-field + * + * @sa BF_CX + * @{ + */ +/** @brief Position of bit count in complex bit-field value */ +#define BF_CX_BCNT_POS 0U +/** @brief Mask of bit count in complex bit-field value */ +#define BF_CX_BCNT_MASK (0xffU << BF_CX_BCNT_POS) +/** @brief Position of bit position in complex bit-field value */ +#define BF_CX_BOFF_POS 8U +/** @brief Mask of bit position in complex bit-field value */ +#define BF_CX_BOFF_MASK (0xffU << BF_CX_BOFF_POS) +/** @} */ + +/** + * @brief Define complex bit-field + * + * Complex bit-field would contain its position and size in one number. + * @sa BF_CX_MASK + * @sa BF_CX_POS + * @sa BF_CX_GET + * + * @param[in] bcnt Number of bits in the bit-field + * @param[in] boff Lowest bit number + * + * @return The single number that describes the bit-field completely. + */ +#define BF_CX(bcnt, boff) ( ((((uint32_t)(bcnt)) << BF_CX_BCNT_POS) & BF_CX_BCNT_MASK) | ((((uint32_t)(boff)) << BF_CX_BOFF_POS) & BF_CX_BOFF_MASK) ) + +/** + * @brief Get number of bits in bit-field + * + * @sa BF_CX + * + * @param bf_cx Complex bit-field + * + * @return Number of bits in given bit-field + */ +#define BF_CX_BCNT(bf_cx) ( ((bf_cx) & BF_CX_BCNT_MASK) >> BF_CX_BCNT_POS ) + +/** + * @brief Get lowest bit number in the field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Lowest bit number in given bit-field + */ +#define BF_CX_BOFF(bf_cx) ( ((bf_cx) & BF_CX_BOFF_MASK) >> BF_CX_BOFF_POS ) + +/** + * @brief Get bit mask of the selected field + * + * @sa BF_CX + * + * @param[in] bf_cx Complex bit-field + * + * @return Mask of given bit-field + */ +#define BF_CX_MASK(bf_cx) BF_MASK(BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Get bit-field + * + * Macro that extracts selected bit-field from provided value. + * Bit-field is given as a complex value. + * + * @sa BF_CX + * @sa BF_GET + * + * @param[in] val Value from witch selected bit-field would be extracted + * @param[in] bf_cx Complex bit-field + * + * @return Value of the selected bits. + */ +#define BF_CX_GET(val, bf_cx) BF_GET(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Create bit-field value + * + * Value is masked and shifted to match given bit-field. + * + * @param[in] val Value to set on bit-field + * @param[in] bf_cx Complex bit-field + * + * @return Value positioned of given bit-field. + */ +#define BF_CX_VAL(val, bf_cx) BF_VAL(val, BF_CX_BCNT(bf_cx), BF_CX_BOFF(bf_cx)) + +/** + * @brief Extracting data from the brackets + * + * This macro get rid of brackets around the argument. + * It can be used to pass multiple arguments in logical one argument to a macro. + * Call it with arguments inside brackets: + * @code + * #define ARGUMENTS (a, b, c) + * BRACKET_EXTRACT(ARGUMENTS) + * @endcode + * It would produce: + * @code + * a, b, c + * @endcode + * + * @param a Argument with anything inside brackets + * @return Anything that appears inside the brackets of the argument + * + * @note + * The argument of the macro have to be inside brackets. + * In other case the compilation would fail. + */ +#define BRACKET_EXTRACT(a) BRACKET_EXTRACT_(a) +#define BRACKET_EXTRACT_(a) BRACKET_EXTRACT__ a +#define BRACKET_EXTRACT__(...) __VA_ARGS__ + + +/** + * @brief Check if number of parameters is more than 1 + * + * @param ... Arguments to count + * + * @return 0 If argument count is <= 1 + * @return 1 If argument count is > 1 + * + * @sa NUM_VA_ARGS + * @sa NUM_IS_MORE_THAN_1 + */ +#define NUM_VA_ARGS_IS_MORE_THAN_1(...) NUM_IS_MORE_THAN_1(NUM_VA_ARGS(__VA_ARGS__)) + +/** + * @brief Check if given numeric value is bigger than 1 + * + * This macro accepts numeric value, that may be the result of argument expansion. + * This numeric value is then converted to 0 if it is lover than 1 or to 1 if + * its value is higher than 1. + * The generated result can be used to glue it into other macro mnemonic name. + * + * @param N Numeric value to check + * + * @return 0 If argument is <= 1 + * @return 1 If argument is > 1 + * + * @note Any existing definition of a form NUM_IS_MORE_THAN_1_PROBE_[N] can + * broke the result of this macro + */ +#define NUM_IS_MORE_THAN_1(N) NUM_IS_MORE_THAN_1_(N) +#define NUM_IS_MORE_THAN_1_(N) NUM_IS_MORE_THAN_1_PROBE_(NUM_IS_MORE_THAN_1_PROBE_ ## N, 1) +#define NUM_IS_MORE_THAN_1_PROBE_(...) GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__)) +#define NUM_IS_MORE_THAN_1_PROBE_0 ~, 0 +#define NUM_IS_MORE_THAN_1_PROBE_1 ~, 0 + +/** + * @brief Get the first argument + * + * @param ... Arguments to select + * + * @return First argument or empty if no arguments are provided + */ +#define GET_VA_ARG_1(...) GET_VA_ARG_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_VA_ARG_1_(a1, ...) a1 + +/** + * @brief Get all the arguments but the first one + * + * @param ... Arguments to select + * + * @return All arguments after the first one or empty if less than 2 arguments are provided + */ +#define GET_ARGS_AFTER_1(...) GET_ARGS_AFTER_1_(__VA_ARGS__, ) // Make sure that also for 1 argument it works +#define GET_ARGS_AFTER_1_(a1, ...) __VA_ARGS__ + +/** + * @brief Size of a field in declared structure + * + * Macro that returns the size of the structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. It can be even field inside field (field.somethingelse.and_another). + * + * @return Size of the field + */ +#define FIELD_SIZE(struct_type, field) sizeof(((struct struct_type*)NULL)->field) + +/** + * @brief Number of elements in field array in declared structure + * + * Macro that returns number of elementy in structure field. + * @param struct_type Variable type to get the field size from + * @param field Field name to analyze. + * + * @return Number of elements in field array + * + * @sa FIELD_SIZE + */ +#define FIELD_ARRAY_SIZE(struct_type, field) (FIELD_SIZE(struct_type, field) / FIELD_SIZE(struct_type, field[0])) + +/** + * @brief Mapping macro + * + * Macro that process all arguments using given macro + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) +#define MACRO_MAP_(...) MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total + +/** + * @brief Mapping macro, recursive version + * + * Can be used in @ref MACRO_MAP macro + */ +#define MACRO_MAP_REC(...) MACRO_MAP_REC_(__VA_ARGS__) +#define MACRO_MAP_REC_(...) MACRO_MAP_REC_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) // To make sure it works also for 2 arguments in total +/** + * @brief Mapping N arguments macro + * + * Macro similar to @ref MACRO_MAP but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) +#define MACRO_MAP_N_(N, ...) CONCAT_2(MACRO_MAP_, N)(__VA_ARGS__, ) + +/** + * @brief Mapping N arguments macro, recursive version + * + * Can be used in @ref MACRO_MAP_N macro + */ +#define MACRO_MAP_REC_N(N, ...) MACRO_MAP_REC_N_(N, __VA_ARGS__) +#define MACRO_MAP_REC_N_(N, ...) CONCAT_2(MACRO_MAP_REC_, N)(__VA_ARGS__, ) + +#define MACRO_MAP_0( ...) +#define MACRO_MAP_1( macro, a, ...) macro(a) +#define MACRO_MAP_2( macro, a, ...) macro(a) MACRO_MAP_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_3( macro, a, ...) macro(a) MACRO_MAP_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_4( macro, a, ...) macro(a) MACRO_MAP_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_5( macro, a, ...) macro(a) MACRO_MAP_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_6( macro, a, ...) macro(a) MACRO_MAP_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_7( macro, a, ...) macro(a) MACRO_MAP_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_8( macro, a, ...) macro(a) MACRO_MAP_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_9( macro, a, ...) macro(a) MACRO_MAP_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_10(macro, a, ...) macro(a) MACRO_MAP_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_11(macro, a, ...) macro(a) MACRO_MAP_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_12(macro, a, ...) macro(a) MACRO_MAP_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_13(macro, a, ...) macro(a) MACRO_MAP_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_14(macro, a, ...) macro(a) MACRO_MAP_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_15(macro, a, ...) macro(a) MACRO_MAP_14(macro, __VA_ARGS__, ) + +#define MACRO_MAP_REC_0( ...) +#define MACRO_MAP_REC_1( macro, a, ...) macro(a) +#define MACRO_MAP_REC_2( macro, a, ...) macro(a) MACRO_MAP_REC_1 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_3( macro, a, ...) macro(a) MACRO_MAP_REC_2 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_4( macro, a, ...) macro(a) MACRO_MAP_REC_3 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_5( macro, a, ...) macro(a) MACRO_MAP_REC_4 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_6( macro, a, ...) macro(a) MACRO_MAP_REC_5 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_7( macro, a, ...) macro(a) MACRO_MAP_REC_6 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_8( macro, a, ...) macro(a) MACRO_MAP_REC_7 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_9( macro, a, ...) macro(a) MACRO_MAP_REC_8 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_10(macro, a, ...) macro(a) MACRO_MAP_REC_9 (macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_11(macro, a, ...) macro(a) MACRO_MAP_REC_10(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_12(macro, a, ...) macro(a) MACRO_MAP_REC_11(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_13(macro, a, ...) macro(a) MACRO_MAP_REC_12(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_14(macro, a, ...) macro(a) MACRO_MAP_REC_13(macro, __VA_ARGS__, ) +#define MACRO_MAP_REC_15(macro, a, ...) macro(a) MACRO_MAP_REC_14(macro, __VA_ARGS__, ) + +/** + * @brief Mapping macro with current index + * + * Basically macro similar to @ref MACRO_MAP, but the processing function would get an argument + * and current argument index (beginning from 0). + * + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR(...) MACRO_MAP_FOR_(__VA_ARGS__) +#define MACRO_MAP_FOR_N_LIST 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +#define MACRO_MAP_FOR_(...) MACRO_MAP_FOR_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with current index + * + * Macro is similar to @ref MACRO_MAP_FOR but maps exact number of arguments. + * If there is more arguments given, the rest would be ignored. + * + * @param N Number of arguments to map + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index) + * + * @return Selected number of arguments processed by given macro + */ +#define MACRO_MAP_FOR_N(N, ...) MACRO_MAP_FOR_N_(N, __VA_ARGS__) +#define MACRO_MAP_FOR_N_(N, ...) CONCAT_2(MACRO_MAP_FOR_, N)((MACRO_MAP_FOR_N_LIST), __VA_ARGS__, ) + +#define MACRO_MAP_FOR_0( n_list, ...) +#define MACRO_MAP_FOR_1( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) +#define MACRO_MAP_FOR_2( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_3( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_4( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_5( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_6( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_7( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_8( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_9( n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_10(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_11(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_12(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_13(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_14(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_15(n_list, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list))) MACRO_MAP_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__, ) + + +/** + * @brief Mapping macro with current index and parameter + * + * Version of @ref MACRO_MAP_FOR that passes also the same parameter to all macros. + * + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM(param, ...) MACRO_MAP_FOR_PARAM_(param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_(param, ...) MACRO_MAP_FOR_PARAM_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), param, __VA_ARGS__) + +/** + * @brief Mapping N arguments macro with with current index and parameter + * + * @param N Number of arguments to map + * @param param Parameter that would be passed to each macro call during mapping. + * @param ... Macro name to be used for argument processing followed by arguments to process. + * Macro should have following form: MACRO(argument, index, param) + * + * @return All arguments processed by given macro + */ +#define MACRO_MAP_FOR_PARAM_N(N, param, ...) MACRO_MAP_FOR_PARAM_N_(N, param, __VA_ARGS__) +#define MACRO_MAP_FOR_PARAM_N_(N, param, ...) CONCAT_2(MACRO_MAP_FOR_PARAM_, N)((MACRO_MAP_FOR_N_LIST), param, __VA_ARGS__, ) + + +#define MACRO_MAP_FOR_PARAM_0( n_list, param, ...) +#define MACRO_MAP_FOR_PARAM_1( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) +#define MACRO_MAP_FOR_PARAM_2( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_1 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_3( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_2 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_4( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_3 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_5( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_4 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_6( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_5 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_7( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_6 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_8( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_7 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_9( n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_8 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_10(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_9 ((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_11(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_12(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_13(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_14(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) +#define MACRO_MAP_FOR_PARAM_15(n_list, param, macro, a, ...) macro(a, GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), param) MACRO_MAP_FOR_PARAM_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), param, macro, __VA_ARGS__, ) + + +/** + * @brief Repeating macro. + * + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT(count, macro, ...) MACRO_REPEAT_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_(count, macro, ...) CONCAT_2(MACRO_REPEAT_, count)(macro, __VA_ARGS__) + +#define MACRO_REPEAT_0(macro, ...) +#define MACRO_REPEAT_1(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_0(macro, __VA_ARGS__) +#define MACRO_REPEAT_2(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_1(macro, __VA_ARGS__) +#define MACRO_REPEAT_3(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_2(macro, __VA_ARGS__) +#define MACRO_REPEAT_4(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_3(macro, __VA_ARGS__) +#define MACRO_REPEAT_5(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_4(macro, __VA_ARGS__) +#define MACRO_REPEAT_6(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_5(macro, __VA_ARGS__) +#define MACRO_REPEAT_7(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_6(macro, __VA_ARGS__) +#define MACRO_REPEAT_8(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_7(macro, __VA_ARGS__) +#define MACRO_REPEAT_9(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_8(macro, __VA_ARGS__) +#define MACRO_REPEAT_10(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_9(macro, __VA_ARGS__) +#define MACRO_REPEAT_11(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_10(macro, __VA_ARGS__) +#define MACRO_REPEAT_12(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_11(macro, __VA_ARGS__) +#define MACRO_REPEAT_13(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_12(macro, __VA_ARGS__) +#define MACRO_REPEAT_14(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_13(macro, __VA_ARGS__) +#define MACRO_REPEAT_15(macro, ...) macro(__VA_ARGS__) MACRO_REPEAT_14(macro, __VA_ARGS__) + + +/** + * @brief Repeating macro with current index. + * + * Macro similar to @ref MACRO_REPEAT but the processing function gets the arguments + * and the current argument index (beginning from 0). + + * @param count Count of repeats. + * @param macro Macro must have the following form: MACRO(index, arguments). + * @param ... Arguments passed to the macro. + * + * @return All arguments processed by the given macro. + */ +#define MACRO_REPEAT_FOR(count, macro, ...) MACRO_REPEAT_FOR_(count, macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_(count, macro, ...) CONCAT_2(MACRO_REPEAT_FOR_, count)((MACRO_MAP_FOR_N_LIST), macro, __VA_ARGS__) + +#define MACRO_REPEAT_FOR_0(n_list, macro, ...) +#define MACRO_REPEAT_FOR_1(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_0((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_2(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_1((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_3(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_2((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_4(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_3((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_5(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_4((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_6(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_5((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_7(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_6((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_8(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_7((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_9(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_8((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_10(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_9((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_11(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_10((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_12(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_11((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_13(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_12((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_14(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_13((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) +#define MACRO_REPEAT_FOR_15(n_list, macro, ...) macro(GET_VA_ARG_1(BRACKET_EXTRACT(n_list)), __VA_ARGS__) MACRO_REPEAT_FOR_14((GET_ARGS_AFTER_1(BRACKET_EXTRACT(n_list))), macro, __VA_ARGS__) + +/**@brief Adding curly brace to the macro parameter. + * + * Useful in array of structures initialization. + * + * @param p Parameter to put into the curly brace. */ +#define PARAM_CBRACE(p) { p }, + + +/**@brief Function for changing the value unit. + * + * @param[in] value Value to be rescaled. + * @param[in] old_unit_reversal Reversal of the incoming unit. + * @param[in] new_unit_reversal Reversal of the desired unit. + * + * @return Number of bytes written. + */ +static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) +{ + return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); +} + +/**@brief Function for encoding a uint16 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +/**@brief Function for encoding a three-byte value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + return 3; +} + +/**@brief Function for encoding a uint32 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + +/**@brief Function for encoding a uint48 value. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint48_encode(uint64_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((value & 0x0000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((value & 0x00000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((value & 0x000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((value & 0x0000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((value & 0x00FF00000000) >> 32); + p_encoded_data[5] = (uint8_t) ((value & 0xFF0000000000) >> 40); + return 6; +} + +/**@brief Function for decoding a uint16 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); +} + +/**@brief Function for decoding a uint16 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint16_t uint16_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint16_t)((uint8_t *)p_encoded_data)[0]) << 8 ) | + (((uint16_t)((uint8_t *)p_encoded_data)[1])) ); +} + +/**@brief Function for decoding a three-byte value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value (uint32_t). + */ +static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); +} + +/**@brief Function for decoding a uint32 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); +} + +/**@brief Function for decoding a uint32 value in big-endian format. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. + */ +static __INLINE uint32_t uint32_big_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 24) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 0) ); +} + +/** + * @brief Function for encoding an uint16 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint16_big_encode(uint16_t value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) (value >> 8); + p_encoded_data[1] = (uint8_t) (value & 0xFF); + + return sizeof(uint16_t); +} + +/**@brief Function for encoding a uint32 value in big-endian format. + * + * @param[in] value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data will be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t uint32_big_encode(uint32_t value, uint8_t * p_encoded_data) +{ + *(uint32_t *)p_encoded_data = __REV(value); + return sizeof(uint32_t); +} + +/**@brief Function for decoding a uint48 value. + * + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * + * @return Decoded value. (uint64_t) + */ +static __INLINE uint64_t uint48_decode(const uint8_t * p_encoded_data) +{ + return ( (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24) | + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32) | + (((uint64_t)((uint8_t *)p_encoded_data)[5]) << 40 )); +} + +/** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. + * + * @details The calculation is based on a linearized version of the battery's discharge + * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and + * is considered to be the lower boundary. + * + * The discharge curve for CR2032 is non-linear. In this model it is split into + * 4 linear sections: + * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) + * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) + * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) + * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) + * + * These numbers are by no means accurate. Temperature and + * load in the actual application is not accounted for! + * + * @param[in] mvolts The voltage in mV + * + * @return Battery level in percent. +*/ +static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) + { + battery_level = 100; + } + else if (mvolts > 2900) + { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } + else if (mvolts > 2740) + { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } + else if (mvolts > 2440) + { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } + else if (mvolts > 2100) + { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } + else + { + battery_level = 0; + } + + return battery_level; +} + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +static __INLINE bool is_word_aligned(void const* p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + +/** + * @brief Function for checking if provided address is located in stack space. + * + * @param[in] ptr Pointer to be checked. + * + * @return true if address is in stack space, false otherwise. + */ +static __INLINE bool is_address_from_stack(void * ptr) +{ + if (((uint32_t)ptr >= (uint32_t)STACK_BASE) && + ((uint32_t)ptr < (uint32_t)STACK_TOP) ) + { + return true; + } + else + { + return false; + } +} + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_bds.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_bds.h new file mode 100644 index 0000000000..e88069322f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_bds.h @@ -0,0 +1,449 @@ +/** + * Copyright (c) 2012 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 app_util Utility Functions and Definitions + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications. + */ + +#ifndef APP_UTIL_BDS_H__ +#define APP_UTIL_BDS_H__ + +#include +#include +#include +#include "compiler_abstraction.h" +#include "app_util.h" +#include "ble_srv_common.h" +#include "nordic_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t nibble_t; +typedef uint32_t uint24_t; +typedef uint64_t uint40_t; + +/**@brief IEEE 11073-20601 Regulatory Certification Data List Structure */ +typedef struct +{ + uint8_t * p_list; /**< Pointer the byte array containing the encoded opaque structure based on IEEE 11073-20601 specification. */ + uint8_t list_len; /**< Length of the byte array. */ +} regcertdatalist_t; + +/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */ +typedef struct +{ + int8_t exponent; /**< Base 10 exponent, should be using only 4 bits */ + int16_t mantissa; /**< Mantissa, should be using only 12 bits */ +} sfloat_t; + +/**@brief Date and Time structure. */ +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hours; + uint8_t minutes; + uint8_t seconds; +} ble_date_time_t; + + +/**@brief Function for encoding a uint16 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint16_encode(const uint16_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0xFF00) >> 8); + return sizeof(uint16_t); +} + +static __INLINE uint8_t bds_int16_encode(const int16_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t tmp = *p_value; + return bds_uint16_encode(&tmp, p_encoded_data); +} + +/**@brief Function for encoding a uint24 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint24_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + return (3); +} + + +/**@brief Function for encoding a uint32 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint32_encode(const uint32_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0xFF000000) >> 24); + return sizeof(uint32_t); +} + + +/**@brief Function for encoding a uint40 value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_uint40_encode(const uint64_t * p_value, uint8_t * p_encoded_data) +{ + p_encoded_data[0] = (uint8_t) ((*p_value & 0x00000000000000FF) >> 0); + p_encoded_data[1] = (uint8_t) ((*p_value & 0x000000000000FF00) >> 8); + p_encoded_data[2] = (uint8_t) ((*p_value & 0x0000000000FF0000) >> 16); + p_encoded_data[3] = (uint8_t) ((*p_value & 0x00000000FF000000) >> 24); + p_encoded_data[4] = (uint8_t) ((*p_value & 0x000000FF00000000) >> 32); + return 5; +} + +/**@brief Function for encoding a sfloat value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + * + * @return Number of bytes written. + */ +static __INLINE uint8_t bds_sfloat_encode(const sfloat_t * p_value, uint8_t * p_encoded_data) +{ + uint16_t encoded_val; + + encoded_val = ((p_value->exponent << 12) & 0xF000) | + ((p_value->mantissa << 0) & 0x0FFF); + + return(bds_uint16_encode(&encoded_val, p_encoded_data)); +} + + +/**@brief Function for encoding a uint8_array value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + */ +static __INLINE uint8_t bds_uint8_array_encode(const uint8_array_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_data, p_value->size); + return p_value->size; +} + + +/**@brief Function for encoding a utf8_str value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_encode(const ble_srv_utf8_str_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_str, p_value->length); + return p_value->length; +} + +/**@brief Function for encoding a regcertdatalist value. + * + * @param[in] p_value Value to be encoded. + * @param[out] p_encoded_data Buffer where the encoded data is to be written. + + */ +static __INLINE uint8_t bds_regcertdatalist_encode(const regcertdatalist_t * p_value, + uint8_t * p_encoded_data) +{ + memcpy(p_encoded_data, p_value->p_list, p_value->list_len); + return p_value->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] p_date_time pointer to the date_time structure to encode. + * @param[in] p_encoded_data pointer to the encoded data + * @return length of the encoded field. + */ +static __INLINE uint8_t bds_ble_date_time_encode(const ble_date_time_t * p_date_time, + uint8_t * p_encoded_data) +{ + uint8_t len = bds_uint16_encode(&p_date_time->year, &p_encoded_data[0]); + + p_encoded_data[len++] = p_date_time->month; + p_encoded_data[len++] = p_date_time->day; + p_encoded_data[len++] = p_date_time->hours; + p_encoded_data[len++] = p_date_time->minutes; + p_encoded_data[len++] = p_date_time->seconds; + + return len; +} + + +/**@brief Function for decoding a uint16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint16_t)((uint8_t *)p_encoded_data)[0])) | + (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 ); + return (sizeof(uint16_t)); +} + + +/**@brief Function for decoding a int16 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_int16_decode(const uint8_t len, + const uint8_t * p_encoded_data, + int16_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + uint16_t tmp = 0; + uint8_t retval = bds_uint16_decode(len, p_encoded_data, &tmp); + *p_decoded_val = (int16_t)tmp; + return retval; +} + + +/**@brief Function for decoding a uint24 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint24_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16); + return (3); +} + + +/**@brief Function for decoding a uint32 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint32_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint32_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 ); + return (sizeof(uint32_t)); +} + + +/**@brief Function for decoding a uint40 value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint40_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint64_t * p_decoded_val) +{ + UNUSED_VARIABLE(len); + *p_decoded_val = (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) | + (((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) | + (((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) | + (((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24 )| + (((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 ); + return (40); +} + + +/**@brief Function for decoding a sfloat value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + + */ +static __INLINE uint8_t bds_sfloat_decode(const uint8_t len, + const uint8_t * p_encoded_data, + sfloat_t * p_decoded_val) +{ + + p_decoded_val->exponent = 0; + bds_uint16_decode(len, p_encoded_data, (uint16_t*)&p_decoded_val->mantissa); + p_decoded_val->exponent = (uint8_t)((p_decoded_val->mantissa & 0xF000) >> 12); + p_decoded_val->mantissa &= 0x0FFF; + return len; +} + + +/**@brief Function for decoding a uint8_array value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_uint8_array_decode(const uint8_t len, + const uint8_t * p_encoded_data, + uint8_array_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_data, p_encoded_data, len); + p_decoded_val->size = len; + return p_decoded_val->size; +} + + +/**@brief Function for decoding a utf8_str value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_srv_utf8_str_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_srv_utf8_str_t * p_decoded_val) +{ + p_decoded_val->p_str = (uint8_t*)p_encoded_data; + p_decoded_val->length = len; + return p_decoded_val->length; +} + + +/**@brief Function for decoding a regcertdatalist value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_decoded_val pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_regcertdatalist_decode(const uint8_t len, + const uint8_t * p_encoded_data, + regcertdatalist_t * p_decoded_val) +{ + memcpy(p_decoded_val->p_list, p_encoded_data, len); + p_decoded_val->list_len = len; + return p_decoded_val->list_len; +} + + +/**@brief Function for decoding a date_time value. + * + * @param[in] len length of the field to be decoded. + * @param[in] p_encoded_data Buffer where the encoded data is stored. + * @param[in] p_date_time pointer to the decoded value + * + * @return length of the decoded field. + */ +static __INLINE uint8_t bds_ble_date_time_decode(const uint8_t len, + const uint8_t * p_encoded_data, + ble_date_time_t * p_date_time) +{ + UNUSED_VARIABLE(len); + uint8_t pos = bds_uint16_decode(len, &p_encoded_data[0], &p_date_time->year); + p_date_time->month = p_encoded_data[pos++]; + p_date_time->day = p_encoded_data[pos++]; + p_date_time->hours = p_encoded_data[pos++]; + p_date_time->minutes = p_encoded_data[pos++]; + p_date_time->seconds = p_encoded_data[pos++]; + + return pos; +} + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_BDS_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.c new file mode 100644 index 0000000000..740d42233b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.c @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "app_util_platform.h" + +#ifdef SOFTDEVICE_PRESENT +/* Global nvic state instance, required by nrf_nvic.h */ +nrf_nvic_state_t nrf_nvic_state; +#endif + +static uint32_t m_in_critical_region = 0; + +void app_util_disable_irq(void) +{ + __disable_irq(); + m_in_critical_region++; +} + +void app_util_enable_irq(void) +{ + m_in_critical_region--; + if (m_in_critical_region == 0) + { + __enable_irq(); + } +} + +void app_util_critical_region_enter(uint8_t *p_nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_enter(p_nested); +#else + app_util_disable_irq(); +#endif +} + +void app_util_critical_region_exit(uint8_t nested) +{ +#if __CORTEX_M == (0x04U) + ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get()) +#endif + +#if defined(SOFTDEVICE_PRESENT) + /* return value can be safely ignored */ + (void) sd_nvic_critical_region_exit(nested); +#else + app_util_enable_irq(); +#endif +} + + +uint8_t privilege_level_get(void) +{ +#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__) + /* the Cortex-M0 has no concept of privilege */ + return APP_LEVEL_PRIVILEGED; +#elif __CORTEX_M == (0x04U) + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (0 == isr_vector_num) + { + /* Thread Mode, check nPRIV */ + int32_t control = __get_CONTROL(); + return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED; + } + else + { + /* Handler Mode, always privileged */ + return APP_LEVEL_PRIVILEGED; + } +#endif +} + + +uint8_t current_int_priority_get(void) +{ + uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ; + if (isr_vector_num > 0) + { + int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); + return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); + } + else + { + return APP_IRQ_PRIORITY_THREAD; + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.h new file mode 100644 index 0000000000..141c3394bc --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/app_util_platform.h @@ -0,0 +1,262 @@ +/** + * Copyright (c) 2014 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 app_util_platform Utility Functions and Definitions (Platform) + * @{ + * @ingroup app_common + * + * @brief Various types and definitions available to all applications when using SoftDevice. + */ + +#ifndef APP_UTIL_PLATFORM_H__ +#define APP_UTIL_PLATFORM_H__ + +#include +#include "compiler_abstraction.h" +#include "nrf.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#include "nrf_nvic.h" +#endif +#include "nrf_assert.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __CORTEX_M == (0x00U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_APP_HIGH 1 +#define _PRIO_APP_MID 1 +#define _PRIO_SD_LOW 2 +#define _PRIO_APP_LOW 3 +#define _PRIO_APP_LOWEST 3 +#define _PRIO_THREAD 4 +#elif __CORTEX_M == (0x04U) +#define _PRIO_SD_HIGH 0 +#define _PRIO_SD_MID 1 +#define _PRIO_APP_HIGH 2 +#define _PRIO_APP_MID 3 +#define _PRIO_SD_LOW 4 +#define _PRIO_SD_LOWEST 5 +#define _PRIO_APP_LOW 6 +#define _PRIO_APP_LOWEST 7 +#define _PRIO_THREAD 15 +#else + #error "No platform defined" +#endif + + +//lint -save -e113 -e452 +/**@brief The interrupt priorities available to the application while the SoftDevice is active. */ +typedef enum +{ +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH, +#else + APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH, +#endif + APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH, +#ifndef SOFTDEVICE_PRESENT + APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW, +#else + APP_IRQ_PRIORITY_MID = _PRIO_APP_MID, +#endif + APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW, + APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST, + APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< "Interrupt level" when running in Thread Mode. */ +} app_irq_priority_t; +//lint -restore + + +/*@brief The privilege levels available to applications in Thread Mode */ +typedef enum +{ + APP_LEVEL_UNPRIVILEGED, + APP_LEVEL_PRIVILEGED +} app_level_t; + +/**@cond NO_DOXYGEN */ +#define EXTERNAL_INT_VECTOR_OFFSET 16 +/**@endcond */ + +/**@brief Macro for setting a breakpoint. + */ +#if defined(__GNUC__) +#define NRF_BREAKPOINT __builtin_trap() +#else +#define NRF_BREAKPOINT __BKPT(0) +#endif + +/** @brief Macro for setting a breakpoint. + * + * If it is possible to detect debugger presence then it is set only in that case. + * + */ +#if __CORTEX_M == 0x04 +#define NRF_BREAKPOINT_COND do { \ + /* C_DEBUGEN == 1 -> Debugger Connected */ \ + if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ + { \ + /* Generate breakpoint if debugger is connected */ \ + NRF_BREAKPOINT; \ + } \ + }while (0) +#else +#define NRF_BREAKPOINT_COND NRF_BREAKPOINT +#endif // __CORTEX_M == 0x04 + +#if defined ( __CC_ARM ) +#define PACKED(TYPE) __packed TYPE +#define PACKED_STRUCT PACKED(struct) +#elif defined ( __GNUC__ ) +#define PACKED __attribute__((packed)) +#define PACKED_STRUCT struct PACKED +#elif defined (__ICCARM__) +#define PACKED_STRUCT __packed struct +#endif + +void app_util_critical_region_enter (uint8_t *p_nested); +void app_util_critical_region_exit (uint8_t nested); + +/**@brief Macro for entering a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_ENTER() \ + { \ + uint8_t __CR_NESTED = 0; \ + app_util_critical_region_enter(&__CR_NESTED); +#else +#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL) +#endif + +/**@brief Macro for leaving a critical region. + * + * @note Due to implementation details, there must exist one and only one call to + * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located + * in the same scope. + */ +#ifdef SOFTDEVICE_PRESENT +#define CRITICAL_REGION_EXIT() \ + app_util_critical_region_exit(__CR_NESTED); \ + } +#else +#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0) +#endif + +/* Workaround for Keil 4 */ +#ifndef IPSR_ISR_Msk +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ +#endif + + + +/**@brief Macro to enable anonymous unions from a certain point in the code. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_ENABLE _Pragma("push") \ + _Pragma("anon_unions") +#elif defined(__ICCARM__) + #define ANON_UNIONS_ENABLE _Pragma("language=extended") +#else + #define ANON_UNIONS_ENABLE + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro to disable anonymous unions from a certain point in the code. + * @note Call only after first calling @ref ANON_UNIONS_ENABLE. + */ +#if defined(__CC_ARM) + #define ANON_UNIONS_DISABLE _Pragma("pop") +#elif defined(__ICCARM__) + #define ANON_UNIONS_DISABLE + // for IAR leave anonymous unions enabled +#else + #define ANON_UNIONS_DISABLE + // No action will be taken. + // For GCC anonymous unions are enabled by default. +#endif + +/**@brief Macro for adding pragma directive only for GCC. + */ +#ifdef __GNUC__ +#define GCC_PRAGMA(v) _Pragma(v) +#else +#define GCC_PRAGMA(v) +#endif + +/* Workaround for Keil 4 */ +#ifndef CONTROL_nPRIV_Msk +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ +#endif + +/**@brief Function for finding the current interrupt level. + * + * @return Current interrupt level. + * @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level. + * @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level. + * @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode. + */ +uint8_t current_int_priority_get(void); + + +/**@brief Function for finding out the current privilege level. + * + * @return Current privilege level. + * @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level. + * @retval APP_LEVEL_PRIVILEGED We are running in privileged level. + */ +uint8_t privilege_level_get(void); + + +#ifdef __cplusplus +} +#endif + +#endif // APP_UTIL_PLATFORM_H__ + +/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nordic_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nordic_common.h new file mode 100644 index 0000000000..e7f63b1290 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nordic_common.h @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2008 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Common defines and macros for firmware developed by Nordic Semiconductor. + */ + +#ifndef NORDIC_COMMON_H__ +#define NORDIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Check if selected module is enabled + * + * This is save function for driver enable checking. + * Correct from Lint point of view (not using default of undefined value). + * + * Usage: + * @code + #if NRF_MODULE_ENABLED(UART) + ... + #endif + * @endcode + * + * @param module The module name. + * + * @retval 1 The macro _ENABLE is defined and is non-zero. + * @retval 0 The macro _ENABLE is not defined or it equals zero. + * + * @note + * This macro intentionally does not implement second expansion level. + * The name of the module to be checked has to be given directly as a parameter. + * And given parameter would be connected with @c _ENABLED postfix directly + * without evaluating its value. + */ +//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator" +#define NRF_MODULE_ENABLED(module) \ + ((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0) + +/** The upper 8 bits of a 32 bit value */ +//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value" +#define MSB_32(a) (((a) & 0xFF000000) >> 24) +/** The lower 8 bits (of a 32 bit value) */ +#define LSB_32(a) ((a) & 0x000000FF) + +/** The upper 8 bits of a 16 bit value */ +//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value" +#define MSB_16(a) (((a) & 0xFF00) >> 8) +/** The lower 8 bits (of a 16 bit value) */ +#define LSB_16(a) ((a) & 0x00FF) + +/** Leaves the minimum of the two 32-bit arguments */ +/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/** Leaves the maximum of the two 32-bit arguments */ +/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +/**@brief Concatenates two parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * + * @return Two parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_3 + */ +#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2) +/** Auxiliary macro used by @ref CONCAT_2 */ +#define CONCAT_2_(p1, p2) p1##p2 + +/**@brief Concatenates three parameters. + * + * It realizes two level expansion to make it sure that all the parameters + * are actually expanded before gluing them together. + * + * @param p1 First parameter to concatenating + * @param p2 Second parameter to concatenating + * @param p3 Third parameter to concatenating + * + * @return Three parameters glued together. + * They have to create correct C mnemonic in other case + * preprocessor error would be generated. + * + * @sa CONCAT_2 + */ +#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3) +/** Auxiliary macro used by @ref CONCAT_3 */ +#define CONCAT_3_(p1, p2, p3) p1##p2##p3 + +#define STRINGIFY_(val) #val +/** Converts a macro argument into a character constant. + */ +#define STRINGIFY(val) STRINGIFY_(val) + +/** Counts number of elements inside the array + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/**@brief Set a bit in the uint32 word. + * + * @param[in] W Word whose bit is being set. + * @param[in] B Bit number in the word to be set. + */ +#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B))) + + +/**@brief Clears a bit in the uint32 word. + * + * @param[in] W Word whose bit is to be cleared. + * @param[in] B Bit number in the word to be cleared. + */ +#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B)))) + + +/**@brief Checks if a bit is set. + * + * @param[in] W Word whose bit is to be checked. + * @param[in] B Bit number in the word to be checked. + * + * @retval 1 if bit is set. + * @retval 0 if bit is not set. + */ +#define IS_SET(W, B) (((W) >> (B)) & 1) + +#define BIT_0 0x01 /**< The value of bit 0 */ +#define BIT_1 0x02 /**< The value of bit 1 */ +#define BIT_2 0x04 /**< The value of bit 2 */ +#define BIT_3 0x08 /**< The value of bit 3 */ +#define BIT_4 0x10 /**< The value of bit 4 */ +#define BIT_5 0x20 /**< The value of bit 5 */ +#define BIT_6 0x40 /**< The value of bit 6 */ +#define BIT_7 0x80 /**< The value of bit 7 */ +#define BIT_8 0x0100 /**< The value of bit 8 */ +#define BIT_9 0x0200 /**< The value of bit 9 */ +#define BIT_10 0x0400 /**< The value of bit 10 */ +#define BIT_11 0x0800 /**< The value of bit 11 */ +#define BIT_12 0x1000 /**< The value of bit 12 */ +#define BIT_13 0x2000 /**< The value of bit 13 */ +#define BIT_14 0x4000 /**< The value of bit 14 */ +#define BIT_15 0x8000 /**< The value of bit 15 */ +#define BIT_16 0x00010000 /**< The value of bit 16 */ +#define BIT_17 0x00020000 /**< The value of bit 17 */ +#define BIT_18 0x00040000 /**< The value of bit 18 */ +#define BIT_19 0x00080000 /**< The value of bit 19 */ +#define BIT_20 0x00100000 /**< The value of bit 20 */ +#define BIT_21 0x00200000 /**< The value of bit 21 */ +#define BIT_22 0x00400000 /**< The value of bit 22 */ +#define BIT_23 0x00800000 /**< The value of bit 23 */ +#define BIT_24 0x01000000 /**< The value of bit 24 */ +#define BIT_25 0x02000000 /**< The value of bit 25 */ +#define BIT_26 0x04000000 /**< The value of bit 26 */ +#define BIT_27 0x08000000 /**< The value of bit 27 */ +#define BIT_28 0x10000000 /**< The value of bit 28 */ +#define BIT_29 0x20000000 /**< The value of bit 29 */ +#define BIT_30 0x40000000 /**< The value of bit 30 */ +#define BIT_31 0x80000000 /**< The value of bit 31 */ + +#define UNUSED_VARIABLE(X) ((void)(X)) +#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X) +#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X) + +#ifdef __cplusplus +} +#endif + +#endif // NORDIC_COMMON_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.c new file mode 100644 index 0000000000..6255ba920c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.c @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2006 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_assert.h" +#include "app_error.h" +#include "nordic_common.h" + +__WEAK void assert_nrf_callback(uint16_t line_num, const uint8_t * file_name) +{ + assert_info_t assert_info = + { + .line_num = line_num, + .p_file_name = file_name, + }; + app_error_fault_handler(NRF_FAULT_ID_SDK_ASSERT, 0, (uint32_t)(&assert_info)); + + UNUSED_VARIABLE(assert_info); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.h new file mode 100644 index 0000000000..2ec647c87b --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_assert.h @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2006 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Utilities for verifying program logic + */ + +#ifndef NRF_ASSERT_H_ +#define NRF_ASSERT_H_ + +#include +#include "nrf.h" +#include "app_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for handling assertions. + * + * + * @note + * This function is called when an assertion has triggered. + * + * @note + * This function is deprecated and will be removed in future releases. + * Use app_error_fault_handler instead. + * + * + * @post + * All hardware is put into an idle non-emitting state (in particular the radio is highly + * important to switch off since the radio might be in a state that makes it send + * packets continiously while a typical final infinit ASSERT loop is executing). + * + * + * @param line_num The line number where the assertion is called + * @param file_name Pointer to the file name + */ +//lint -save -esym(14, assert_nrf_callback) +void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name); +//lint -restore + +#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)) +#define NRF_ASSERT_PRESENT 1 +#else +#define NRF_ASSERT_PRESENT 0 +#endif + +//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER) + +/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ +/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ + +/** @brief Function for checking intended for production code. + * + * Check passes if "expr" evaluates to true. */ + +#ifdef _lint +#define ASSERT(expr) \ +if (expr) \ +{ \ +} \ +else \ +{ \ + while (1); \ +} +#else //_lint +#define ASSERT(expr) \ +if (NRF_ASSERT_PRESENT) \ +{ \ + if (expr) \ + { \ + } \ + else \ + { \ + assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ + } \ +} + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_ASSERT_H_ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_bitmask.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_bitmask.h new file mode 100644 index 0000000000..72f531f1a7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/nrf_bitmask.h @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2006 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_BITMASK_H +#define NRF_BITMASK_H + +#include "compiler_abstraction.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8) +#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007) + +/** + * Function for checking if bit in the multi-byte bit mask is set. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + * + * @return 0 if bit is not set, positive value otherwise. + */ +__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask) +{ + uint8_t const * p_mask8 = (uint8_t const *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + return (1 << bit) & p_mask8[byte_idx]; +} + +/** + * Function for setting a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] |= (1 << bit); +} + +/** + * Function for clearing a bit in the multi-byte bit mask. + * + * @param bit Bit index. + * @param p_mask A pointer to mask with bit fields. + */ +__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask) +{ + uint8_t * p_mask8 = (uint8_t *)p_mask; + uint32_t byte_idx = BITMASK_BYTE_GET(bit); + bit = BITMASK_RELBIT_GET(bit); + p_mask8[byte_idx] &= ~(1 << bit); +} + +/** + * Function for performing bitwise OR operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i]; + } +} + +/** + * Function for performing bitwise AND operation on two multi-byte bit masks. + * + * @param p_mask1 A pointer to the first bit mask. + * @param p_mask2 A pointer to the second bit mask. + * @param p_mask_out A pointer to the output bit mask. + * @param length Length of output mask in bytes. + */ +__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1, + void const * p_mask2, + void * p_out_mask, + uint32_t length) +{ + uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1; + uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2; + uint8_t * p_mask8_out = (uint8_t *)p_out_mask; + uint32_t i; + for (i = 0; i < length; i++) + { + p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i]; + } +} + +#ifdef __cplusplus +} +#endif + +#endif //NRF_BITMASK_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_common.h new file mode 100644 index 0000000000..54ef51c4f1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_common.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** @cond */ +/**@file + * + * @ingroup experimental_api + * @defgroup sdk_common SDK Common Header + * @brief All common headers needed for SDK examples will be included here so that application + * developer does not have to include headers on him/herself. + * @{ + */ + +#ifndef SDK_COMMON_H__ +#define SDK_COMMON_H__ + +#include +#include +#include +#include "sdk_config.h" +#include "nordic_common.h" +#include "compiler_abstraction.h" +#include "sdk_os.h" +#include "sdk_errors.h" +#include "app_util.h" +#include "sdk_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_COMMON_H__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_errors.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_errors.h new file mode 100644 index 0000000000..96920fc617 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_errors.h @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 sdk_error SDK Error codes + * @{ + * @ingroup app_common + * @{ + * @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for + * identifying the module where the error occurred while the least least significant LSB + * are used to provide the cause or nature of error. Each module is assigned a 16-bit + * unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit + * LSB range is with module id as the MSB in the 32-bit error code is reserved for the + * module. As an example, if 0x8800 identifies a certain SDK module, all values from + * 0x88000000 - 0x8800FFFF are reserved for this module. + * It should be noted that common error reasons have been assigned values to make it + * possible to decode error reason easily. As an example, lets module uninitialized has + * been assigned an error code 0x000A0. Then, if application encounters an error code + * 0xZZZZ00A0, it knows that it accessing a certain module without initializing it. + * Apart from this, each module is allowed to define error codes that are not covered by + * the common ones, however, these values are defined in a range that does not conflict + * with common error values. For module, specific error however, it is possible that the + * same error value is used by two different modules to indicated errors of very different + * nature. If error is already defined by the NRF common error codes, these are reused. + * A range is reserved for application as well, it can use this range for defining + * application specific errors. + * + * @note Success code, NRF_SUCCESS, does not include any module identifier. + + */ + +#ifndef SDK_ERRORS_H__ +#define SDK_ERRORS_H__ + +#include +#include "nrf_error.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup sdk_err_base Base defined for SDK Modules + * @{ + */ +#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */ +#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */ +/** @} */ + +/** + * @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred. + * @{ + */ +#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) +#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) +#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) +#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) +/** @} */ + + +/** + * @defgroup sdk_iot_errors Codes reserved as identification for IoT errors. + * @{ + */ +#define NRF_ERROR_IOT_ERR_BASE_START (0xA000) +#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF) +/** @} */ + + +/** + * @defgroup sdk_common_errors Codes reserved as identification for common errors. + * @{ + */ +#define NRF_ERROR_MODULE_NOT_INITIALZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) +#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) +#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) +#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) +#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) +#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) +#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) +#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) +#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) +/** @} */ + + +/** + * @defgroup drv_specific_errors Error / status codes specific to drivers. + * @{ + */ +#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000) +#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001) +#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002) +/** @} */ + + +/** + * @defgroup ble_ipsp_errors IPSP codes + * @brief Error and status codes specific to IPSP. + * @{ + */ +#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000) +#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001) +#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002) +#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003) +/* @} */ + + +/** + * @brief API Result. + * + * @details Indicates success or failure of an API procedure. In case of failure, a comprehensive + * error code indicating cause or reason for failure is provided. + * + * Though called an API result, it could used in Asynchronous notifications callback along + * with asynchronous callback as event result. This mechanism is employed when an event + * marks the end of procedure initiated using API. API result, in this case, will only be + * an indicative of whether the procedure has been requested successfully. + */ +typedef uint32_t ret_code_t; + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_ERRORS_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_macros.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_macros.h new file mode 100644 index 0000000000..01dcdf5d4c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_macros.h @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 sdk_common_macros SDK Common Header + * @ingroup app_common + * @brief Macros for parameter checking and similar tasks + * @{ + */ + +#ifndef SDK_MACROS_H__ +#define SDK_MACROS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * err_code if the statement is not true. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is false. + */ +#define VERIFY_TRUE(statement, err_code) \ +do \ +{ \ + if (!(statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be true. It will cause the exterior function to return + * if the statement is not true. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), ) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * err_code if the statement is not false. + * + * @param[in] statement Statement to test. + * @param[in] err_code Error value to return if test was invalid. + * + * @retval nothing, but will cause the exterior function to return @p err_code if @p statement + * is true. + */ +#define VERIFY_FALSE(statement, err_code) \ +do \ +{ \ + if ((statement)) \ + { \ + return err_code; \ + } \ +} while (0) + + +/**@brief Macro for verifying statement to be false. It will cause the exterior function to return + * if the statement is not false. + * + * @param[in] statement Statement to test. + */ +#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), ) + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return err_code if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_SUCCESS() +#else +#define VERIFY_SUCCESS(err_code) VERIFY_TRUE((err_code) == NRF_SUCCESS, (err_code)) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior + * function to return if the err_code is not @ref NRF_SUCCESS. + * + * @param[in] err_code The error code to check. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_SUCCESS_VOID() +#else +#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return @ref NRF_ERROR_INVALID_STATE if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_MODULE_INITIALIZED() +#else +#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED + * should be true if the module is initialized, false if not. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_MODULE_INITIALIZED_VOID() +#else +#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED)) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_PARAM_NOT_NULL() +#else +#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL) +#endif /* DISABLE_PARAM_CHECK */ + + +/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to + * return if not. + * + * @param[in] param The variable to check if is NULL. + */ +#ifdef DISABLE_PARAM_CHECK +#define VERIFY_PARAM_NOT_NULL_VOID() +#else +#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL)) +#endif /* DISABLE_PARAM_CHECK */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_MACROS_H__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.c new file mode 100644 index 0000000000..1a99ac382f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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_mapped_flags.h" +#include +#include +#include +#include "compiler_abstraction.h" + + +// Test whether the flag collection type is large enough to hold all the flags. If this fails, +// reduce SDK_MAPPED_FLAGS_N_KEYS or increase the size of sdk_mapped_flags_t. +STATIC_ASSERT((sizeof(sdk_mapped_flags_t) * SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE) >= SDK_MAPPED_FLAGS_N_KEYS); + + +/**@brief Function for setting the state of a flag to true. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_set_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags |= (1U << index); +} + + +/**@brief Function for setting the state of a flag to false. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to modify. + * @param[in] index The index of the flag to modify. + */ +static __INLINE void sdk_mapped_flags_clear_by_index(sdk_mapped_flags_t * p_flags, uint16_t index) +{ + *p_flags &= ~(1U << index); +} + + +/**@brief Function for getting the state of a flag. + * + * @note This function does not check whether the index is valid. + * + * @param[in] p_flags The collection of flags to read. + * @param[in] index The index of the flag to get. + */ +static __INLINE bool sdk_mapped_flags_get_by_index(sdk_mapped_flags_t flags, uint16_t index) +{ + return ((flags & (1 << index)) != 0); +} + + + +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags) +{ + for (uint16_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + return i; + } + } + return SDK_MAPPED_FLAGS_INVALID_INDEX; +} + + +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value) +{ + sdk_mapped_flags_bulk_update_by_key(p_keys, p_flags, 1, key, value); +} + + +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value) +{ + if ((p_keys != NULL) && (p_flags != NULL) && (n_flag_collections > 0)) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + for (uint32_t j = 0; j < n_flag_collections; j++) + { + if (value) + { + sdk_mapped_flags_set_by_index(&p_flags[j], i); + } + else + { + sdk_mapped_flags_clear_by_index(&p_flags[j], i); + } + } + return; + } + } + } +} + + +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + if (p_index != NULL) + { + *p_index = i; + } + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + if (p_index != NULL) + { + *p_index = SDK_MAPPED_FLAGS_N_KEYS; + } + return false; +} + + +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key) +{ + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (p_keys[i] == key) + { + return sdk_mapped_flags_get_by_index(flags, i); + } + } + } + return false; +} + + +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags) +{ + sdk_mapped_flags_key_list_t key_list; + key_list.len = 0; + + if (p_keys != NULL) + { + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + key_list.flag_keys[key_list.len++] = p_keys[i]; + } + } + } + + return key_list; +} + + +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags) +{ + uint32_t n_flags_set = 0; + + for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++) + { + if (sdk_mapped_flags_get_by_index(flags, i)) + { + n_flags_set += 1; + } + } + return n_flags_set; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.h new file mode 100644 index 0000000000..1f9033909a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_mapped_flags.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 SDK_MAPPED_FLAGS_H__ +#define SDK_MAPPED_FLAGS_H__ + +#include +#include +#include "app_util.h" +#include "compiler_abstraction.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @defgroup sdk_mapped_flags Mapped flags + * @ingroup app_common + * @{ + * @brief Module for writing and reading flags that are associated + * with keys. + * + * @details The flags are represented as bits in a bitmap called a flag collection. The keys + * are uint16_t. Each flag collection contains all flags of the same type, one flag for + * each key. + * + * The mapped flags module does not keep the flag states, nor the list of keys. These are + * provided in the API calls. A key's index in the key list determines which bit in the + * flag collection is associated with it. This module does not ever edit the key list, and + * does not edit flags except in function calls that take the flag collection as a pointer. + * + */ + +#define SDK_MAPPED_FLAGS_N_KEYS 32 /**< The number of keys to keep flags for. This is also the number of flags in a flag collection. If changing this value, you might also need change the width of the sdk_mapped_flags_t type. */ +#define SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE 8 /**< The number of flags that fit in one byte. */ +#define SDK_MAPPED_FLAGS_INVALID_INDEX 0xFFFF /**< A flag index guaranteed to be invalid. */ + +typedef uint32_t sdk_mapped_flags_t; /**< The bitmap to hold flags. Each flag is one bit, and each bit represents the flag state associated with one key. */ + + +/**@brief Type used to present a subset of the registered keys. + */ +typedef struct +{ + uint32_t len; /**< The length of the list. */ + uint16_t flag_keys[SDK_MAPPED_FLAGS_N_KEYS]; /**< The list of keys. */ +} sdk_mapped_flags_key_list_t; + + +/**@brief Function for getting the first index at which the flag is true in the provided + * collection. + * + * @param[in] flags The flag collection to search for a flag set to true. + * + * @return The first index that has its flag set to true. If none were found, the + * function returns @ref SDK_MAPPED_FLAGS_INVALID_INDEX. + */ +uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags); + + +/**@brief Function for updating the state of a flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collection to modify. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint16_t key, + bool value); + + +/**@brief Function for updating the state of the same flag in multiple flag collections. + * + * @details The key and value are the same for all flag collections in the p_flags array. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[out] p_flags The flag collections to modify. + * @param[out] n_flag_collections The number of flag collections in p_flags. + * @param[in] key The key to modify the flag of. + * @param[in] value The state to set the flag to. + */ +void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys, + sdk_mapped_flags_t * p_flags, + uint32_t n_flag_collections, + uint16_t key, + bool value); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to read from. + * @param[in] key The key to get the flag for. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key); + + +/**@brief Function for getting the state of a specific flag. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection from which to read. + * @param[in] key The key for which to get the flag. + * @param[out] p_index If not NULL, the index of the key. + * + * @return The state of the flag. + */ +bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys, + sdk_mapped_flags_t flags, + uint16_t key, + uint8_t * p_index); + + +/**@brief Function for getting a list of all keys that have a specific flag set to true. + * + * @param[in] p_keys The list of associated keys (assumed to have a length of + * @ref SDK_MAPPED_FLAGS_N_KEYS). + * @param[in] flags The flag collection to search. + * + * @return The list of keys. + */ +sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys, + sdk_mapped_flags_t flags); + + +/**@brief Function for getting the number of keys that have a specific flag set to true. + * + * @param[in] flags The flag collection to search. + * + * @return The number of keys. + */ +uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags); + + +/**@brief Function for querying whether any flags in the collection are set. + * + * @param[in] flags The flag collection to query. + * + * @retval true If one or more flags are set to true. + * @retval false Otherwise. + */ +static __INLINE bool sdk_mapped_flags_any_set(sdk_mapped_flags_t flags) +{ + return (flags != 0); +} + + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SDK_MAPPED_FLAGS_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_os.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_os.h new file mode 100644 index 0000000000..c1660070b9 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_os.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2013 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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. + * + */ +/** @cond */ +/**@file + * + * @defgroup sdk_os SDK OS Abstraction + * @ingroup experimental_api + * @details In order to made SDK modules independent of use of an embedded OS, and permit + * application with varied task architecture, SDK abstracts the OS specific + * elements here in order to make all other modules agnostic to the OS or task + * architecture. + * @{ + */ + +#ifndef SDK_OS_H__ +#define SDK_OS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDK_MUTEX_DEFINE(X) +#define SDK_MUTEX_INIT(X) +#define SDK_MUTEX_LOCK(X) +#define SDK_MUTEX_UNLOCK(X) + +/** + * @defgroup os_data_type Data types. + */ + +/** @} */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif // SDK_OS_H__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_resources.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_resources.h new file mode 100644 index 0000000000..91d2af1294 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/libraries/util/sdk_resources.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2015 - 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 form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 + * @brief Definition file for resource usage by SoftDevice, ESB and Gazell. + */ + +#ifndef APP_RESOURCES_H__ +#define APP_RESOURCES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SOFTDEVICE_PRESENT + #include "nrf_sd_def.h" +#else + #define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */ + #define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */ + #define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */ + #define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */ + #define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */ +#endif + +#ifdef GAZELL_PRESENT + #include "nrf_gzll_resources.h" +#else + #define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */ + #define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */ + #define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */ +#endif + +#ifdef ESB_PRESENT + #include "nrf_esb_resources.h" +#else + #define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */ + #define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */ + #define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */ +#endif + +#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED) +#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED) +#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED) +#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED) + +#ifdef __cplusplus +} +#endif + +#endif // APP_RESOURCES_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/analogin_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/analogin_api.c new file mode 100644 index 0000000000..4d2d8aba0e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/analogin_api.c @@ -0,0 +1,148 @@ +/* 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 DEVICE_ANALOGIN +#include "hal/analogin_api.h" + +#include "pinmap.h" +#include "PeripheralPins.h" + +#include "nrf_drv_saadc.h" + +#define ADC_12BIT_RANGE 0x0FFF +#define ADC_16BIT_RANGE 0xFFFF + +/* Unused event handler but driver requires one. */ +static void analog_in_event_handler(nrf_drv_saadc_evt_t const *p_event) +{ + (void) p_event; +} + +/* Interrupt handler implemented in nrf_drv_saadc.c. */ +void SAADC_IRQHandler(void); + +/** Initialize the analogin peripheral + * + * Configures the pin used by analogin. + * @param obj The analogin object to initialize + * @param pin The analogin pin name + */ +void analogin_init(analogin_t *obj, PinName pin) +{ + MBED_ASSERT(obj); + + /* Only initialize SAADC on first pin. */ + static bool first_init = true; + + if (first_init) { + + first_init = false; + + /* Use configuration from sdk_config.h. + * Default is: + * - 12 bit. + * - No oversampling. + * - Priority 7 (lowest). + * - No low power mode. + */ + nrf_drv_saadc_config_t adc_config = { + .resolution = (nrf_saadc_resolution_t)SAADC_CONFIG_RESOLUTION, + .oversample = (nrf_saadc_oversample_t)SAADC_CONFIG_OVERSAMPLE, + .interrupt_priority = SAADC_CONFIG_IRQ_PRIORITY, + .low_power_mode = SAADC_CONFIG_LP_MODE + }; + + ret_code_t result = nrf_drv_saadc_init(&adc_config, analog_in_event_handler); + MBED_ASSERT(result == NRF_SUCCESS); + + /* Register interrupt handler in vector table. */ + NVIC_SetVector(SAADC_IRQn, (uint32_t)SAADC_IRQHandler); + } + + /* Use pinmap function to get associated channel. */ + uint32_t channel = pinmap_function(pin, PinMap_ADC); + MBED_ASSERT(channel != (uint32_t) NC); + + /* Account for an off-by-one in Channel definition and Input definition. */ + nrf_saadc_input_t input = channel + 1; + + /* Configure channel and pin: + * - the 1/4 gain and VDD/4 makes the reference voltage VDD. + */ + nrf_saadc_channel_config_t channel_config = { + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, + .gain = NRF_SAADC_GAIN1_4, + .reference = NRF_SAADC_REFERENCE_VDD4, + .acq_time = NRF_SAADC_ACQTIME_10US, + .mode = NRF_SAADC_MODE_SINGLE_ENDED, + .burst = NRF_SAADC_BURST_DISABLED, + .pin_p = input, + .pin_n = NRF_SAADC_INPUT_DISABLED + }; + + ret_code_t result = nrf_drv_saadc_channel_init(channel, &channel_config); + MBED_ASSERT(result == NRF_SUCCESS); + + /* Store channel in ADC object. */ + obj->channel = channel; +} + + +/** Read the input voltage, represented as a float in the range [0.0, 1.0] + * + * @param obj The analogin object + * @return A floating value representing the current input voltage + */ +uint16_t analogin_read_u16(analogin_t *obj) +{ + MBED_ASSERT(obj); + + /* Default return value is 0. */ + uint16_t retval = 0; + + /* Read single channel, blocking. */ + nrf_saadc_value_t value = { 0 }; + ret_code_t result = nrf_drv_saadc_sample_convert(obj->channel, &value); + + /* nrf_saadc_value_t is a signed integer. Only take the absolute value. */ + if ((result == NRF_SUCCESS) && (value > 0)) { + + /* Normalize 12 bit ADC value to 16 bit Mbed ADC range. */ + uint32_t normalized = value; + retval = (normalized * ADC_16BIT_RANGE) / ADC_12BIT_RANGE; + } + + return retval; +} + +/** Read the value from analogin pin, represented as an unsigned 16bit value + * + * @param obj The analogin object + * @return An unsigned 16bit value representing the current input voltage + */ +float analogin_read(analogin_t *obj) +{ + MBED_ASSERT(obj); + + /* Read 16 bit ADC value (using Mbed API) and convert to [0;1] range float. */ + uint16_t value = analogin_read_u16(obj); + float result = ((float) value / (float) ADC_16BIT_RANGE); + + return result; +} + +#endif // DEVICE_ANALOGIN diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.h new file mode 100644 index 0000000000..2ebe70ecf7 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.h @@ -0,0 +1,61 @@ +/* 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 US_TICKER_SW_IRQ_MASK 0x1 +#define LP_TICKER_SW_IRQ_MASK 0x2 + +#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; +extern uint8_t volatile m_common_sw_irq_flag; + +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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/critical_section_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/critical_section_api.c new file mode 100644 index 0000000000..599709f7e2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/critical_section_api.c @@ -0,0 +1,43 @@ +/* + * 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 "hal/critical_section_api.h" +#include "nrf_nvic.h" + +#include + +static uint8_t outside_critical_region = 1; + +void hal_critical_section_enter() +{ + /* expect 1 or N calls but only lock on the first one */ + if (outside_critical_region) { + sd_nvic_critical_region_enter(&outside_critical_region); + } +} + +void hal_critical_section_exit() +{ + /* unlock on first call */ + outside_critical_region = 1; + sd_nvic_critical_region_exit(0); +} + +bool hal_in_critical_section(void) +{ + return !outside_critical_region; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/flash_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/flash_api.c new file mode 100644 index 0000000000..ea8f400048 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/flash_api.c @@ -0,0 +1,214 @@ +/* + * 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. + * + */ + +#if DEVICE_FLASH + +#include "hal/flash_api.h" +#include "hal/lp_ticker_api.h" + +#include "nrf_fstorage.h" + +#if defined(SOFTDEVICE_PRESENT) +#include "nrf_fstorage_sd.h" +#else +#include "nrf_fstorage_nvmc.h" +#endif + +#include + +#define PAGE_ERASE_TIMEOUT_US (200 * 1000) // Max. value from datasheet: 89.7 ms +#define WORD_SIZE_IN_BYTES 4 + +NRF_FSTORAGE_DEF(static nrf_fstorage_t nordic_fstorage) = { 0 }; + +int32_t flash_init(flash_t *obj) +{ + (void)(obj); + + ret_code_t result = NRF_SUCCESS; + + /* Only initialize once. */ + static bool do_init = true; + + if (do_init) { + do_init = false; + + /* Set instance to cover the whole flash. */ + nordic_fstorage.p_flash_info = NULL; + nordic_fstorage.evt_handler = NULL; + nordic_fstorage.start_addr = 0; + nordic_fstorage.end_addr = NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE; + + /* Initialize either SoftDevice API or NVMC API. + * SoftDevice API should work both when the SoftDevice is enabled or disabled. + * NVMC API is used when the SoftDevice is not present. + */ +#if defined(SOFTDEVICE_PRESENT) + result = nrf_fstorage_init(&nordic_fstorage, &nrf_fstorage_sd, NULL); +#else + result = nrf_fstorage_init(&nordic_fstorage, &nrf_fstorage_nvmc, NULL); +#endif + + /* Initialize low power ticker for timeouts. */ + lp_ticker_init(); + } + + /* Convert Nordic SDK error code to mbed HAL. */ + return (result == NRF_SUCCESS) ? 0 : -1; +} + +int32_t flash_free(flash_t *obj) +{ + (void)(obj); + + return 0; +} + +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + (void)(obj); + + ret_code_t result = NRF_ERROR_NO_MEM; + + /* Setup stop watch for timeout. */ + uint32_t start_us = lp_ticker_read(); + uint32_t now_us = start_us; + + /* Retry if flash is busy until timeout is reached. */ + while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && + (result == NRF_ERROR_NO_MEM)) { + + /* Map mbed HAL call to Nordic fstorage call. */ + result = nrf_fstorage_erase(&nordic_fstorage, address, 1, NULL); + + /* Read timeout timer. */ + now_us = lp_ticker_read(); + } + + /* Convert Nordic SDK error code to mbed HAL. */ + return (result == NRF_SUCCESS) ? 0 : -1; +} + +int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) +{ + (void)(obj); + + /* Check that data pointer is not NULL. */ + ret_code_t result = NRF_ERROR_NULL; + + if (data) { + + /* nrf_fstorage_write only accepts word aligned input buffers. + * Cast data pointer to word pointer and read word into temporary word variable + * which should be word aligned. This should be safe on Cortex-m4 which is able + * to load unaligned data. + */ + const uint32_t *data_word = (const uint32_t *) data; + + /* Loop through input buffer 4 bytes at a time. */ + for (size_t index = 0; index < (size / WORD_SIZE_IN_BYTES); index++) { + + /* Load 4 bytes into temporary variable. */ + uint32_t word = data_word[index]; + + /* Setup stop watch for timeout. */ + uint32_t start_us = lp_ticker_read(); + uint32_t now_us = start_us; + + /* Retry if flash is busy until timeout is reached. */ + do { + /* Write one word at a time. */ + result = nrf_fstorage_write(&nordic_fstorage, + address + (WORD_SIZE_IN_BYTES * index), + &word, + WORD_SIZE_IN_BYTES, + NULL); + + /* Read timeout timer. */ + now_us = lp_ticker_read(); + + /* Loop if queue is full or until time runs out. */ + } while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && + (result == NRF_ERROR_NO_MEM)); + + /* Break loop if write command wasn't accepted. */ + if (result != NRF_SUCCESS) { + break; + } + } + } + + /* Convert Nordic SDK error code to mbed HAL. */ + return (result == NRF_SUCCESS) ? 0 : -1; +} + +uint32_t flash_get_size(const flash_t *obj) +{ + (void)(obj); + + return nordic_fstorage.end_addr - nordic_fstorage.start_addr; + ; +} + +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +{ + (void)(obj); + + /* Check if passed address is in flash area. Note end_addr is outside valid range. */ + if ((address >= nordic_fstorage.start_addr) && (address < nordic_fstorage.end_addr)) { + return nordic_fstorage.p_flash_info->erase_unit; + } + + /* Return invalid size if request is outisde flash area. */ + return MBED_FLASH_INVALID_SIZE; +} + +uint32_t flash_get_page_size(const flash_t *obj) +{ + (void)(obj); + + /* Return minimum writeable page size. */ + return WORD_SIZE_IN_BYTES; +} + +uint32_t flash_get_start_address(const flash_t *obj) +{ + return 0; +} + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_api.c new file mode 100644 index 0000000000..9e12311e8e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_api.c @@ -0,0 +1,265 @@ +/* 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; + 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; +} + +#ifdef TARGET_SDK11 +// implement polyfill of gpio hal for the nRF5 SDK v11 +__STATIC_INLINE uint32_t nrf_gpio_pin_out_read(uint32_t pin) +{ + return (NRF_GPIO->OUTSET & (1UL << (pin))); +} +#endif + +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)1UL << 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_gpio_cfg_input(pin,cfg.pull); + } + } + else { + // Configure as output. + nrf_drv_gpiote_out_config_t cfg = GPIOTE_CONFIG_OUT_SIMPLE(nrf_gpio_pin_out_read(pin)); + nrf_drv_gpiote_out_init(pin, &cfg); + } + m_gpio_initialized |= ((gpio_mask_t)1UL << pin); + } + else { + m_gpio_initialized &= ~((gpio_mask_t)1UL << 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); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_object.h b/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_object.h new file mode 100644 index 0000000000..f7b621a9ed --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/gpio_object.h @@ -0,0 +1,48 @@ +/* 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/i2c_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/i2c_api.c new file mode 100644 index 0000000000..c4e646c9de --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/i2c_api.c @@ -0,0 +1,952 @@ +/* + * 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. + * + */ + +#if DEVICE_I2C + +/* I2C + * + * This HAL implementation uses the nrf_drv_twi.h API primarily but switches to TWI for the + * low-level HAL functions. These calls can't be implemented with the TWIM due to the + * different API. + * + * Known limitations: + * * The TWI/TWIM only supports 7-bit addresses. + * * The TWI API doesn't allow reading 1 byte. At least 2 bytes will be read. + */ + +#include "i2c_api.h" +#include "lp_ticker_api.h" + +#include "object_owners.h" +#include "pinmap_ex.h" + +#include "nrf_drv_twi.h" +#include "nrf_drv_common.h" +#include "app_util_platform.h" + +#if 0 +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +#define DEFAULT_TIMEOUT_US (1000) // timeout for waiting for address NACK +#define MAXIMUM_TIMEOUT_US (10000) // timeout for waiting for RX +#define I2C_READ_BIT 0x01 // read bit + +/* Keep track of what mode the peripheral is in. On NRF52, Driver mode can use TWIM. */ +typedef enum { + NORDIC_I2C_MODE_NONE, + NORDIC_I2C_MODE_TWI, + NORDIC_I2C_MODE_DRIVER +} nordic_nrf5_mode_t; + +/* In simple mode, the Start signal is sent on the first write call due to hardware limitations. */ +typedef enum { + NORDIC_TWI_STATE_IDLE, + NORDIC_TWI_STATE_START, + NORDIC_TWI_STATE_BUSY +} nordic_nrf5_twi_state_t; + +/* Forward declaration. These functions are implemented in the driver but not + * set up in the NVIC due to it being relocated. + */ +void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void); +void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void); + +/** Initialize the I2C peripheral. It sets the default parameters for I2C + * peripheral, and configures its specifieds pins. + * + * @param obj The I2C object + * @param sda The sda pin + * @param scl The scl pin + */ +void i2c_init(i2c_t *obj, PinName sda, PinName scl) +{ + DEBUG_PRINTF("i2c_init: %p %d %d\r\n", obj, sda, scl); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + /* Get instance from pin configuration. */ + int instance = pin_instance_i2c(sda, scl); + MBED_ASSERT(instance < ENABLED_TWI_COUNT); + + /* Initialize i2c_t object */ + config->instance = instance; + config->sda = sda; + config->scl = scl; + config->frequency = NRF_TWI_FREQ_100K; + config->state = NORDIC_TWI_STATE_IDLE; + config->mode = NORDIC_I2C_MODE_NONE; + +#if DEVICE_I2C_ASYNCH + config->handler = 0; + config->event = 0; + config->mask = 0; +#endif + + /* Force reconfiguration */ + config->update = true; + + static bool first_init = true; + + if (first_init) { + first_init = false; + /* Initialize low power ticker. Used for timeouts. */ + lp_ticker_init(); + + /* Register interrupt handlers in driver with the NVIC. */ + NVIC_SetVector(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, (uint32_t) SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler); + NVIC_SetVector(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, (uint32_t) SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler); + } +} + +/** Configure the I2C frequency + * + * @param obj The I2C object + * @param hz Frequency in Hz + */ +void i2c_frequency(i2c_t *obj, int hz) +{ + DEBUG_PRINTF("i2c_frequency: %p %d\r\n", obj, hz); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + /* Round down to nearest valid frequency. */ + nrf_twi_frequency_t new_frequency; + + if (hz < 250000) { + new_frequency = NRF_TWI_FREQ_100K; + } else if (hz < 400000) { + new_frequency = NRF_TWI_FREQ_250K; + } else { + new_frequency = NRF_TWI_FREQ_400K; + } + + /* Only store frequency in object. Configuration happens at the beginning of each transaction. */ + config->frequency = new_frequency; + config->update = true; +} + + +/*** + * _____ _ _ _________ _______ + * / ____(_) | | |__ __\ \ / /_ _| + * | (___ _ _ __ ___ _ __ | | ___ | | \ \ /\ / / | | + * \___ \| | '_ ` _ \| '_ \| |/ _ \ | | \ \/ \/ / | | + * ____) | | | | | | | |_) | | __/ | | \ /\ / _| |_ + * |_____/|_|_| |_| |_| .__/|_|\___| |_| \/ \/ |_____| + * | | + * |_| + */ + +/*****************************************************************************/ +/* Simple API implementation using TWI */ +/*****************************************************************************/ + +/* Global array for easy register selection for each instance. */ +static NRF_TWI_Type * nordic_nrf5_twi_register[2] = { NRF_TWI0, NRF_TWI1 }; + +/** + * @brief Reconfigure TWI register. + * + * If the peripheral is enabled, it will be disabled first. All + * registers are cleared to their default values unless replaced + * by new configuration. + * + * If the object is the owner, the mode hasn't changed, and the + * force change flag is false, all settings are kept unchanged. + * + * @param obj The object + */ +void i2c_configure_twi_instance(i2c_t *obj) +{ +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + + /* Get pointer to object of the current owner of the peripheral. */ + void *current_owner = object_owner_spi2c_get(instance); + + /* Check if reconfiguration is actually necessary. */ + if ((obj != current_owner) || (config->mode != NORDIC_I2C_MODE_TWI) || config->update) { + + DEBUG_PRINTF("i2c_configure_twi_instance: %p %p\r\n", obj, current_owner); + + /* Claim ownership of peripheral. */ + object_owner_spi2c_set(instance, obj); + + /* Set current mode. */ + config->mode = NORDIC_I2C_MODE_TWI; + + /* Disable peripheral if it is currently enabled. */ + if (nordic_nrf5_twi_register[instance]->ENABLE) { + nrf_twi_disable(nordic_nrf5_twi_register[instance]); + } + + /* Force resource release. This is necessary because mbed drivers don't + * deinitialize on object destruction. + */ + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *) nordic_nrf5_twi_register[instance])); + nrf_drv_common_per_res_release(nordic_nrf5_twi_register[instance]); + + /* Reset shorts register. */ + nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], 0); + + /* Disable all TWI interrupts. */ + nrf_twi_int_disable(nordic_nrf5_twi_register[instance], + NRF_TWI_INT_STOPPED_MASK | + NRF_TWI_INT_RXDREADY_MASK | + NRF_TWI_INT_TXDSENT_MASK | + NRF_TWI_INT_ERROR_MASK | + NRF_TWI_INT_BB_MASK | + NRF_TWI_INT_SUSPENDED_MASK); + + /* Clear error register. */ + nrf_twi_errorsrc_get_and_clear(nordic_nrf5_twi_register[instance]); + + /* Clear all previous events. */ + nrf_twi_event_clear(nordic_nrf5_twi_register[instance], + NRF_TWI_EVENT_STOPPED | + NRF_TWI_EVENT_RXDREADY | + NRF_TWI_EVENT_TXDSENT | + NRF_TWI_EVENT_ERROR | + NRF_TWI_EVENT_BB | + NRF_TWI_EVENT_SUSPENDED); + + /* Configure SDA and SCL pins. */ + nrf_twi_pins_set(nordic_nrf5_twi_register[instance], + config->scl, + config->sda); + + /* Set frequency. */ + nrf_twi_frequency_set(nordic_nrf5_twi_register[instance], + config->frequency); + + /* Enable TWI peripheral with new settings. */ + nrf_twi_enable(nordic_nrf5_twi_register[instance]); + } +} + +/** Send START command + * + * @param obj The I2C object + */ +int i2c_start(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_start: %p\r\n", obj); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + /* Change state but defer actual signaling until the first byte (the address) + is transmitted. This is due to hardware limitations. + */ + config->state = NORDIC_TWI_STATE_START; + + return 0; +} + +/** Write one byte + * + * @param obj The I2C object + * @param data Byte to be written + * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. + */ +int i2c_byte_write(i2c_t *obj, int data) +{ + DEBUG_PRINTF("i2c_byte_write: %p %d\r\n", obj, data); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + int result = 1; // default to ACK + + /* Check if this is the first byte to be transferred. If it is, then send start signal and address. */ + if (config->state == NORDIC_TWI_STATE_START) { + config->state = NORDIC_TWI_STATE_BUSY; + + /* Beginning of new transaction, configure peripheral if necessary. */ + i2c_configure_twi_instance(obj); + + /* Set I2C device address. NOTE: due to hardware limitations only 7-bit addresses are supported. */ + nrf_twi_address_set(nordic_nrf5_twi_register[instance], data >> 1); + + /* If read bit is set, trigger read task otherwise trigger write task. */ + if (data & I2C_READ_BIT) { + /* For timing reasons, reading bytes requires shorts to suspend peripheral after each byte. */ + nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], NRF_TWI_SHORT_BB_SUSPEND_MASK); + nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_STARTRX); + } else { + /* Reset shorts register. */ + nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], 0); + nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_STARTTX); + } + + /* Setup stop watch for timeout. */ + uint32_t start_us = lp_ticker_read(); + uint32_t now_us = start_us; + + /* Block until timeout or an address error has been detected. */ + while (((now_us - start_us) < DEFAULT_TIMEOUT_US) && + !(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_ERROR))) { + now_us = lp_ticker_read(); + } + + /* Check error register and update return value if an address NACK was detected. */ + uint32_t error = nrf_twi_errorsrc_get_and_clear(nordic_nrf5_twi_register[instance]); + + if (error & NRF_TWI_ERROR_ADDRESS_NACK) { + result = 0; // set NACK + } + } else { + + /* Normal write. Send next byte after clearing event flag. */ + nrf_twi_event_clear(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_TXDSENT); + nrf_twi_txd_set(nordic_nrf5_twi_register[instance], data); + + /* Setup stop watch for timeout. */ + uint32_t start_us = lp_ticker_read(); + uint32_t now_us = start_us; + + /* Block until timeout or the byte has been sent. */ + while (((now_us - start_us) < MAXIMUM_TIMEOUT_US) && + !(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_TXDSENT))) { + now_us = lp_ticker_read(); + } + + /* Check the error code to see if the byte was acknowledged. */ + uint32_t error = nrf_twi_errorsrc_get_and_clear(nordic_nrf5_twi_register[instance]); + + if (error & NRF_TWI_ERROR_DATA_NACK) { + result = 0; // set NACK + } else if (now_us - start_us >= MAXIMUM_TIMEOUT_US) { + result = 2; // set timeout + } + } + + return result; +} + +/** Read one byte + * + * @param obj The I2C object + * @param last Acknoledge + * @return The read byte + */ +int i2c_byte_read(i2c_t *obj, int last) +{ + DEBUG_PRINTF("i2c_byte_read: %p %d\r\n", obj, last); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + int retval = I2C_ERROR_NO_SLAVE; + + uint32_t start_us = 0; + uint32_t now_us = 0; + + /* Due to hardware limitations, the stop condition must triggered through a short before + * reading the last byte. + */ + if (last) { + nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], NRF_TWI_SHORT_BB_STOP_MASK); + + /* Transaction will be complete after this call, reset state. */ + config->state = NORDIC_TWI_STATE_IDLE; + } + + /* Due to the way events are generated, if a byte is available it should be read directly + * but without resuming reading. Otherwise the TWI will read one byte too many. + */ + if (nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_RXDREADY)) { + retval = nrf_twi_rxd_get(nordic_nrf5_twi_register[instance]); + nrf_twi_event_clear(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_RXDREADY); + } else { + + /* No data available, resume reception. */ + nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_RESUME); + + /* Setup timeout */ + start_us = lp_ticker_read(); + now_us = start_us; + + /* Block until timeout or data ready event has been signaled. */ + while (((now_us - start_us) < MAXIMUM_TIMEOUT_US) && + !(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_RXDREADY))) { + now_us = lp_ticker_read(); + } + + /* Retrieve data from buffer. */ + if ((now_us - start_us) < MAXIMUM_TIMEOUT_US) { + retval = nrf_twi_rxd_get(nordic_nrf5_twi_register[instance]); + nrf_twi_event_clear(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_RXDREADY); + } + } + + return retval; +} + +/** Send STOP command + * + * @param obj The I2C object + */ +int i2c_stop(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_stop: %p\r\n", obj); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + + /* Set explicit stop signal. */ + nrf_twi_event_clear(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_STOPPED); + nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_STOP); + + /* Block until stop signal has been generated. */ + uint32_t start_us = lp_ticker_read(); + uint32_t now_us = start_us; + + while (((now_us - start_us) < MAXIMUM_TIMEOUT_US) && + !(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_STOPPED))) { + now_us = lp_ticker_read(); + } + + /* Reset state. */ + config->state = NORDIC_TWI_STATE_IDLE; + + return 0; +} + +/** Reset I2C peripheral. TODO: The action here. Most of the implementation sends stop() + * + * @param obj The I2C object + */ +void i2c_reset(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_reset: %p\r\n", obj); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + /* Force reconfiguration to reset peripheral completely. */ + config->update = true; + i2c_configure_twi_instance(obj); +} + + + +/*** + * _____ _ _________ _______ + * | __ \ (_) |__ __\ \ / /_ _| + * | | | |_ __ ___ _____ _ __ | | \ \ /\ / / | | + * | | | | '__| \ \ / / _ \ '__| | | \ \/ \/ / | | + * | |__| | | | |\ V / __/ | | | \ /\ / _| |_ + * |_____/|_| |_| \_/ \___|_| |_| \/ \/ |_____| + * + * + */ + +/* Global array holding driver configuration for easy access. */ +static const nrf_drv_twi_t nordic_nrf5_instance[2] = { NRF_DRV_TWI_INSTANCE(0), NRF_DRV_TWI_INSTANCE(1) }; + +/* Forward declare interrupt handler. */ +#if DEVICE_I2C_ASYNCH +static void nordic_nrf5_twi_event_handler(nrf_drv_twi_evt_t const *p_event, void *p_context); +#endif + +/** + * @brief Reconfigure driver. + * + * If the peripheral is enabled, it will be disabled first. All + * registers are cleared to their default values unless replaced + * by new configuration. + * + * If the object is the owner, the mode hasn't changed, and the + * force change flag is false, all settings are kept unchanged. + * + * @param obj The object + * @param[in] force_change Set to true to force a reconfiguration. + */ +static void i2c_configure_driver_instance(i2c_t *obj) +{ +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + + /* Get pointer to object of the current owner of the peripheral. */ + void *current_owner = object_owner_spi2c_get(instance); + + /* Check if reconfiguration is actually necessary. */ + if ((obj != current_owner) || (config->mode != NORDIC_I2C_MODE_DRIVER) || config->update) { + + DEBUG_PRINTF("i2c_configure_driver_instance: %p %p\r\n", obj, current_owner); + + /* Claim ownership of peripheral. */ + object_owner_spi2c_set(instance, obj); + + /* Set current mode. */ + config->mode = NORDIC_I2C_MODE_DRIVER; + + /* If the peripheral is already running, then disable it and use the driver API to uninitialize it.*/ + if (nordic_nrf5_instance[instance].reg.p_twi->ENABLE) { + nrf_drv_twi_disable(&nordic_nrf5_instance[instance]); + nrf_drv_twi_uninit(&nordic_nrf5_instance[instance]); + } + + /* Force resource release. This is necessary because mbed drivers don't + * deinitialize on object destruction. + */ + nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *) nordic_nrf5_twi_register[instance])); + nrf_drv_common_per_res_release(nordic_nrf5_twi_register[instance]); + + /* Configure driver with new settings. */ + nrf_drv_twi_config_t twi_config = { + .scl = config->scl, + .sda = config->sda, + .frequency = config->frequency, + .interrupt_priority = APP_IRQ_PRIORITY_LOWEST, + .clear_bus_init = false, + .hold_bus_uninit = false + }; + +#if DEVICE_I2C_ASYNCH + /* Set callback handler in asynchronous mode. */ + if (config->handler) { + + /* Initialze driver in non-blocking mode. */ + nrf_drv_twi_init(&nordic_nrf5_instance[instance], + &twi_config, + nordic_nrf5_twi_event_handler, + obj); + } else { + + /* Initialze driver in blocking mode. */ + nrf_drv_twi_init(&nordic_nrf5_instance[instance], + &twi_config, + NULL, + NULL); + } +#else + /* Initialze driver in blocking mode. */ + nrf_drv_twi_init(&nordic_nrf5_instance[instance], + &twi_config, + NULL, + NULL); +#endif + + /* Enable peripheral. */ + nrf_drv_twi_enable(&nordic_nrf5_instance[instance]); + } +} + +/** Blocking reading data + * + * @param obj The I2C object + * @param address 7-bit address (last bit is 1) + * @param data The buffer for receiving + * @param length Number of bytes to read + * @param stop Stop to be generated after the transfer is done + * @return Number of read bytes + */ +int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) +{ + DEBUG_PRINTF("i2c_read: %p %d %p %d %d\r\n", obj, address, data, length, stop); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + int result = I2C_ERROR_NO_SLAVE; + + /* Force peripheral configuration to avoid timing errors. */ + config->update = true; + i2c_configure_driver_instance(obj); + + /* Initialize transaction. */ + ret_code_t retval = nrf_drv_twi_rx(&nordic_nrf5_instance[instance], + address >> 1, + (uint8_t *) data, + length); + + /* Set return value on success. */ + if (retval == NRF_SUCCESS) { + result = length; + } + + DEBUG_PRINTF("result: %lu %d\r\n", retval, result); + + return result; +} + +/** Blocking sending data + * + * @param obj The I2C object + * @param address 7-bit address (last bit is 0) + * @param data The buffer for sending + * @param length Number of bytes to write + * @param stop Stop to be generated after the transfer is done + * @return + * zero or non-zero - Number of written bytes + * negative - I2C_ERROR_XXX status + */ +int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) +{ + DEBUG_PRINTF("i2c_write: %p %d %p %d %d\r\n", obj, address, data, length, stop); + +#if DEVICE_I2C_ASYNCH + struct i2c_s *config = &obj->i2c; +#else + struct i2c_s *config = obj; +#endif + + int instance = config->instance; + int result = I2C_ERROR_NO_SLAVE; + + /* Force peripheral configuration to avoid timing errors. */ + config->update = true; + i2c_configure_driver_instance(obj); + + /* Initialize transaction. */ + ret_code_t retval = nrf_drv_twi_tx(&nordic_nrf5_instance[instance], + address >> 1, + (const uint8_t *) data, + length, + !stop); + + /* Set return value on success. */ + if (retval == NRF_SUCCESS) { + result = length; + } + + DEBUG_PRINTF("result: %lu %d\r\n", retval, result); + + return result; +} + + +#if DEVICE_I2C_ASYNCH + +/*** + * _____ _____ + * /\ /\ | __ \_ _| + * / \ ___ _ _ _ __ ___ / \ | |__) || | + * / /\ \ / __| | | | '_ \ / __| / /\ \ | ___/ | | + * / ____ \\__ \ |_| | | | | (__ / ____ \| | _| |_ + * /_/ \_\___/\__, |_| |_|\___| /_/ \_\_| |_____| + * __/ | + * |___/ + */ + +/* Callback function for driver calls. This is called from ISR context. */ +static void nordic_nrf5_twi_event_handler(nrf_drv_twi_evt_t const *p_event, void *p_context) +{ + // Only safe to use with mbed-printf. + //DEBUG_PRINTF("nordic_nrf5_twi_event_handler: %d %p\r\n", p_event->type, p_context); + + i2c_t *obj = (i2c_t *) p_context; + struct i2c_s *config = &obj->i2c; + + /* Translate event type from NRF driver values to mbed HAL values. */ + switch (p_event->type) + { + /* Transfer completed event. */ + case NRF_DRV_TWI_EVT_DONE: + config->event = I2C_EVENT_TRANSFER_COMPLETE; + break; + + /* Error event: NACK received after sending the address. */ + case NRF_DRV_TWI_EVT_ADDRESS_NACK: + config->event = I2C_EVENT_ERROR_NO_SLAVE; + break; + + /* Error event: NACK received after sending a data byte. */ + case NRF_DRV_TWI_EVT_DATA_NACK: + config->event = I2C_EVENT_TRANSFER_EARLY_NACK; + break; + + default: + config->event = I2C_EVENT_ERROR; + break; + } + + /* If event matches event mask and event handler is set, signal event. */ + if ((config->event & config->mask) && config->handler) { + + /* Cast handler to function pointer. */ + void (*callback)(void) = (void (*)(void)) config->handler; + + /* Reset handler and force reconfiguration. */ + config->handler = 0; + config->update = true; + + /* Signal callback handler. */ + callback(); + } +} + +/** Start I2C asynchronous transfer + * + * @param obj The I2C object + * @param tx The transmit buffer + * @param tx_length The number of bytes to transmit + * @param rx The receive buffer + * @param rx_length The number of bytes to receive + * @param address The address to be set - 7bit or 9bit + * @param stop If true, stop will be generated after the transfer is done + * @param handler The I2C IRQ handler to be set + * @param event Event mask for the transfer. See \ref hal_I2CEvents + * @param hint DMA hint usage + */ +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 mask, + DMAUsage hint) +{ + DEBUG_PRINTF("i2c_transfer_asynch\r\n"); + + /* TWI only supports 7 bit addresses. */ + MBED_ASSERT(address < 0xFF); + + struct i2c_s *config = &obj->i2c; + int instance = config->instance; + + /* Save event handler and event mask in global variables so they can be called from interrupt handler. */ + config->handler = handler; + config->mask = mask; + + /* Clear event flag. */ + config->event = 0; + + /* Configure peripheral. */ + config->update = true; + i2c_configure_driver_instance(obj); + + /* Configure TWI transfer. */ + const nrf_drv_twi_xfer_desc_t twi_config = NRF_DRV_TWI_XFER_DESC_TXRX(address >> 1, + (uint8_t*) tx, + tx_length, + rx, + rx_length); + + uint32_t flags = (stop) ? 0 : NRF_DRV_TWI_FLAG_TX_NO_STOP; + + /* Initiate TWI transfer using NRF driver. */ + ret_code_t result = nrf_drv_twi_xfer(&nordic_nrf5_instance[instance], + &twi_config, + flags); + + /* Signal error if event mask matches and event handler is set. */ + if ((result != NRF_SUCCESS) && (mask & I2C_EVENT_ERROR) && handler) { + + /* Store event value so it can be read back. */ + config->event = I2C_EVENT_ERROR; + + /* Cast handler to function pointer. */ + void (*callback)(void) = (void (*)(void)) handler; + + /* Reset handler and force reconfiguration. */ + config->handler = 0; + config->update = true; + + /* Signal callback handler. */ + callback(); + } +} + +/** The asynchronous IRQ handler + * + * @param obj The I2C object which holds the transfer information + * @return Event flags if a transfer termination condition was met, otherwise return 0. + */ +uint32_t i2c_irq_handler_asynch(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_irq_handler_asynch\r\n"); + + /* Return latest event. */ + return obj->i2c.event; +} + +/** Attempts to determine if the I2C peripheral is already in use + * + * @param obj The I2C object + * @return Non-zero if the I2C module is active or zero if it is not + */ +uint8_t i2c_active(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_active\r\n"); + + /* Query NRF driver if transaction is in progress. */ + return nrf_drv_twi_is_busy(&nordic_nrf5_instance[obj->i2c.instance]); +} + +/** Abort asynchronous transfer + * + * This function does not perform any check - that should happen in upper layers. + * @param obj The I2C object + */ +void i2c_abort_asynch(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_abort_asynch\r\n"); + + /* Reconfiguration will disable and enable the TWI module. */ + obj->i2c.update = true; + i2c_configure_driver_instance(obj); +} + +#endif // DEVICE_I2C_ASYNCH + +#if DEVICE_I2CSLAVE +#warning DEVICE_I2CSLAVE + +/*** + * _____ ___ _____ _____ _ + * |_ _|__ \ / ____| / ____| | + * | | ) | | | (___ | | __ ___ _____ + * | | / /| | \___ \| |/ _` \ \ / / _ \ + * _| |_ / /_| |____ ____) | | (_| |\ V / __/ + * |_____|____|\_____| |_____/|_|\__,_| \_/ \___| + * + * + */ + +/** Configure I2C as slave or master. + * @param obj The I2C object + * @param enable_slave Enable i2c hardware so you can receive events with ::i2c_slave_receive + * @return non-zero if a value is available + */ +void i2c_slave_mode(i2c_t *obj, int enable_slave) +{ + DEBUG_PRINTF("i2c_slave_mode\r\n"); +} + +/** Check to see if the I2C slave has been addressed. + * @param obj The I2C object + * @return The status - 1 - read addresses, 2 - write to all slaves, + * 3 write addressed, 0 - the slave has not been addressed + */ +int i2c_slave_receive(i2c_t *obj) +{ + DEBUG_PRINTF("i2c_slave_receive\r\n"); + + return 0; +} + +/** Configure I2C as slave or master. + * @param obj The I2C object + * @param data The buffer for receiving + * @param length Number of bytes to read + * @return non-zero if a value is available + */ +int i2c_slave_read(i2c_t *obj, char *data, int length) +{ + DEBUG_PRINTF("i2c_slave_read\r\n"); + + return 0; +} + +/** Configure I2C as slave or master. + * @param obj The I2C object + * @param data The buffer for sending + * @param length Number of bytes to write + * @return non-zero if a value is available + */ +int i2c_slave_write(i2c_t *obj, const char *data, int length) +{ + DEBUG_PRINTF("i2c_slave_write\r\n"); + + return 0; +} + +/** Configure I2C address. + * @param obj The I2C object + * @param idx Currently not used + * @param address The address to be set + * @param mask Currently not used + */ +void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) +{ + DEBUG_PRINTF("i2c_slave_address\r\n"); +} + +#endif // DEVICE_I2CSLAVE + +#endif // DEVICE_I2C diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/irq_handlers_hw.h b/targets/TARGET_NORDIC/TARGET_NRF5x/irq_handlers_hw.h new file mode 100644 index 0000000000..7eba37ad99 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/irq_handlers_hw.h @@ -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__ + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/itm_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/itm_api.c new file mode 100644 index 0000000000..593ef6b6f9 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/itm_api.c @@ -0,0 +1,44 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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(DEVICE_ITM) + +#include "hal/itm_api.h" + +#include "nrf.h" +#include "nrf5x_lf_clk_helper.h" + +/* SWO frequency: 4000 kHz */ +void itm_init(void) +{ + /* Enable SWO trace functionality */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos; + + /* set SWO clock speed to 4 MHz */ + NRF_CLOCK->TRACECONFIG = (NRF_CLOCK->TRACECONFIG & ~CLOCK_TRACECONFIG_TRACEPORTSPEED_Msk) | + (CLOCK_TRACECONFIG_TRACEPORTSPEED_4MHz << CLOCK_TRACECONFIG_TRACEPORTSPEED_Pos); + + /* set SWO pin */ + NRF_P0->PIN_CNF[18] = (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); + + /* set prescaler */ + TPI->ACPR = 0; +} + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/lp_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/lp_ticker.c new file mode 100644 index 0000000000..def44835e2 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/lp_ticker.c @@ -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. + */ +#include "lp_ticker_api.h" + +#if DEVICE_LOWPOWERTIMER + +#include "common_rtc.h" +#include "mbed_critical.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_fire_interrupt(void) +{ + core_util_critical_section_enter(); + m_common_sw_irq_flag |= LP_TICKER_SW_IRQ_MASK; + NVIC_SetPendingIRQ(RTC1_IRQn); + core_util_critical_section_exit(); +} + +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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/mbed_lib.json new file mode 100644 index 0000000000..d8b12f59b5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/mbed_lib.json @@ -0,0 +1,199 @@ +{ + "name": "nordic", + "config": { + "uart_timeout_us": { + "help": "Idle time in micro seconds between characters before buffer is flushed.", + "value": 2000 + }, + "uart_0_fifo_size": { + "help": "UART0 FIFO buffer. FIFO buffer is filled from DMA buffer.", + "value": 32 + }, + "uart_1_fifo_size": { + "help": "UART1 FIFO buffer. FIFO buffer is filled from DMA buffer.", + "value": 32 + }, + "uart_dma_size": { + "help": "UART DMA buffer. 2 buffers per instance. DMA buffer is filled by UARTE", + "value": 8 + } + }, + "target_overrides": { + "DELTA_DFBM_NQ620": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ], + "target.lf_clock_src": "NRF_LF_SRC_RC", + "target.lf_clock_rc_calib_timer_interval": 16, + "target.lf_clock_rc_calib_mode_config": 0 + }, + "MTB_LAIRD_BL652": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ], + "target.lf_clock_src": "NRF_LF_SRC_RC", + "target.console-uart-flow-control": "RTSCTS" + }, + "MTB_UBLOX_NINA_B1": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ] + }, + "NRF52_DK": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ], + "target.console-uart-flow-control": "RTSCTS" + }, + "RBLAB_BLENANO2": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ] + }, + "UBLOX_EVA_NINA": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ] + }, + "UBLOX_EVK_NINA_B1": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ], + "target.console-uart-flow-control": "RTSCTS" + }, + "VBLUNO52": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_PAN_12", + "NRF52_PAN_15", + "NRF52_PAN_20", + "NRF52_PAN_30", + "NRF52_PAN_31", + "NRF52_PAN_36", + "NRF52_PAN_51", + "NRF52_PAN_53", + "NRF52_PAN_54", + "NRF52_PAN_55", + "NRF52_PAN_58", + "NRF52_PAN_62", + "NRF52_PAN_63", + "NRF52_PAN_64" + ], + "target.console-uart-flow-control": "RTSCTS" + }, + "NRF52840_DK": { + "target.macros_add": [ + "CONFIG_GPIO_AS_PINRESET", + "SWI_DISABLE0", + "NRF52_ERRATA_20" + ], + "target.console-uart-flow-control": "RTSCTS" + } + } +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/nrf5x_lf_clk_helper.h b/targets/TARGET_NORDIC/TARGET_NRF5x/nrf5x_lf_clk_helper.h new file mode 100644 index 0000000000..08744be767 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/nrf5x_lf_clk_helper.h @@ -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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.c b/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.c new file mode 100644 index 0000000000..2f3bc3779a --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.c @@ -0,0 +1,57 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 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 "object_owners.h" + +#include "nrf.h" +#include "nrf_peripherals.h" + +#include + +#define SPI2C_INSTANCES SPI_COUNT + +static void * nordic_spi2c_owners[SPI2C_INSTANCES] = { NULL, NULL, NULL }; + +/** + * Brief Set instance owner for the SPI/I2C peripheral. + * + * Parameter instance The instance. + * Parameter object The object. + */ +void object_owner_spi2c_set(int instance, void *object) +{ + if (instance < SPI2C_INSTANCES) { + nordic_spi2c_owners[instance] = object; + } +} + +/** + * Brief Get instance owner for the SPI/I2C peripheral. + * + * Parameter instance The instance. + * + * Return Pointer to the object owning the instance. + */ +void * object_owner_spi2c_get(int instance) +{ + void *object = (void *) 0xFFFFFFFF; + + if (instance < SPI2C_INSTANCES) { + object = nordic_spi2c_owners[instance]; + } + + return object; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.h b/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.h new file mode 100644 index 0000000000..0751362fa3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/object_owners.h @@ -0,0 +1,45 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 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 OBJECT_OWNERS_H +#define OBJECT_OWNERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set instance owner for the SPI/I2C peripheral. + * + * @param[in] instance The instance. + * @param object The object. + */ +void object_owner_spi2c_set(int instance, void *object); + +/** + * @brief Get instance owner for the SPI/I2C peripheral. + * + * @param[in] instance The instance. + * + * @return Pointer to the object owning the instance. + */ +void * object_owner_spi2c_get(int instance); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/objects.h b/targets/TARGET_NORDIC/TARGET_NRF5x/objects.h new file mode 100644 index 0000000000..760674b3ce --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/objects.h @@ -0,0 +1,147 @@ +/* + * 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" +#include "nrf_drv_spi.h" +#include "nrf_twi.h" + +#include "nrf_pwm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nrf_uart.h" + +struct serial_s { + int instance; + uint32_t tx; + uint32_t rx; + uint32_t cts; + uint32_t rts; + nrf_uart_hwfc_t hwfc; + nrf_uart_parity_t parity; + nrf_uart_baudrate_t baudrate; + uint32_t context; + uint32_t handler; + uint32_t mask; + uint32_t event; + bool update; +#if DEVICE_SERIAL_ASYNCH + bool rx_asynch; + uint32_t tx_handler; + uint32_t tx_mask; + uint32_t tx_event; + uint32_t rx_handler; + uint32_t rx_mask; + uint32_t rx_event; +#endif +}; + +struct spi_s { + int instance; + PinName cs; + nrf_drv_spi_config_t config; + bool update; + +#if DEVICE_SPI_ASYNCH + uint32_t handler; + uint32_t mask; + uint32_t event; +#endif +}; + +struct port_s { + PortName port; + uint32_t mask; +}; + +struct pwmout_s { + int instance; + PinName pin; + nrf_pwm_values_common_t pulse; + uint16_t period; + float percent; + nrf_pwm_sequence_t sequence; +}; + +struct i2c_s { + int instance; + PinName sda; + PinName scl; + nrf_twi_frequency_t frequency; + int state; + int mode; + bool update; + +#if DEVICE_I2C_ASYNCH + uint32_t handler; + uint32_t mask; + uint32_t event; +#endif +}; + +struct analogin_s { + uint8_t channel; +}; + +struct gpio_irq_s { + uint32_t ch; +}; + +struct flash_s { + uint32_t placeholder; +}; + +struct trng_s { + uint32_t placeholder; +}; + +#include "gpio_object.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap.c b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap.c new file mode 100644 index 0000000000..f723a5837e --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap.c @@ -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. + */ +#include "mbed_assert.h" +#include "mbed_error.h" +#include "pinmap.h" +#include "nrf_gpio.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; + +#ifdef TARGET_SDK11 + NRF_GPIO_Type * reg = NRF_GPIO; +#else + NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number); +#endif + reg->PIN_CNF[pin_number] &= ~GPIO_PIN_CNF_PULL_Msk; + reg->PIN_CNF[pin_number] |= (mode << GPIO_PIN_CNF_PULL_Pos); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.c b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.c new file mode 100644 index 0000000000..bae8185331 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.c @@ -0,0 +1,481 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 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 "pinmap_ex.h" + +#include "mbed_toolchain.h" +#include "nrf.h" +#include "nrf_peripherals.h" + +#include + +#if 0 +#define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0) +#else +#define DEBUG_PRINTF(...) {} +#endif + +/* Define number of instances */ +#define NORDIC_TWI_COUNT TWI_COUNT +#define NORDIC_SPI_COUNT SPI_COUNT +#define NORDIC_PWM_COUNT PWM_COUNT +#define NORDIC_UART_COUNT UARTE_COUNT + +/* Define which instance to return when there are no free instances left. + * The Mbed HAL API doesn't provide a way for signaling initialization errors + * so we return the default value. Any instance conflicts must be handled + * by the driver implementation. + */ +#define DEFAULT_I2C_INSTANCE 0 // SPI counts down, choose instance furthest away +#define DEFAULT_SPI_INSTANCE (NORDIC_SPI_COUNT - 1) // I2C counts up, choose instance furthers away +#define DEFAULT_PWM_INSTANCE (NORDIC_PWM_COUNT - 1) +#define DEFAULT_UART_INSTANCE (NORDIC_UART_COUNT - 1) + + +/*** + * _____ _____ _____ ___ _____ + * / ____| __ \_ _|__ \ / ____| + * | (___ | |__) || | ) | | + * \___ \| ___/ | | / /| | + * ____) | | _| |_ / /_| |____ + * |_____/|_| |_____|____|\_____| + * + * + */ + +/* Internal data structure shared between SPI and I2C to keep track of allocated + * instances. The data structure is shared to reflect the hardware sharing. + */ +typedef struct { + PinName locaction0; + PinName locaction1; + PinName locaction2; +} spi2c_t; + +static spi2c_t nordic_internal_spi2c[3] = { + {NC, NC, NC}, + {NC, NC, NC}, + {NC, NC, NC}, +}; + +/** + * Brief Find hardware instance for the provided I2C pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * Parameter sda sda pin. + * Parameter scl scl pin. + * + * Return Hardware instance associated with provided pins. + */ +int pin_instance_i2c(PinName sda, PinName scl) +{ + int instance = NC; + + /* Search pin map for pre-allocated instance */ + for (size_t index = 0; + !((PinMap_I2C[index].sda == NC) && + (PinMap_I2C[index].scl == NC)); + index++) { + + /* Compare pins to entry. */ + if ((PinMap_I2C[index].sda == sda) && + (PinMap_I2C[index].scl == scl)) { + + DEBUG_PRINTF("found: %d %d %d\r\n", sda, scl, PinMap_I2C[index].instance); + + /* Instance found, save result. */ + instance = PinMap_I2C[index].instance; + + /* Lock out entry in map to prevent SPI from grabbing it. */ + nordic_internal_spi2c[instance].locaction0 = sda; + nordic_internal_spi2c[instance].locaction1 = scl; + nordic_internal_spi2c[instance].locaction2 = NC; + break; + } + } + + /* No instance was found in static map. */ + if (instance == NC) { + + /* Search dynamic map for entry. */ + for (size_t index = 0; index < NORDIC_TWI_COUNT; index++) { + + /* Pins match previous dynamic allocation, return instance. */ + if ((nordic_internal_spi2c[index].locaction0 == sda) && + (nordic_internal_spi2c[index].locaction1 == scl) && + (nordic_internal_spi2c[index].locaction2 == NC)) { + + instance = index; + break; + } + } + } + + /* No instance was found in dynamic map. */ + if (instance == NC) { + + /* Search dynamic map for empty slot. */ + for (size_t index = 0; index < NORDIC_TWI_COUNT; index++) { + + /* Empty slot found, reserve slot by storing pins. */ + if ((nordic_internal_spi2c[index].locaction0 == NC) && + (nordic_internal_spi2c[index].locaction1 == NC) && + (nordic_internal_spi2c[index].locaction2 == NC)) { + + nordic_internal_spi2c[index].locaction0 = sda; + nordic_internal_spi2c[index].locaction1 = scl; + + instance = index; + break; + } + } + } + +#if defined(DEFAULT_I2C_INSTANCE) + /* Exhausted all options. Return default value. */ + if (instance == NC) { + instance = DEFAULT_I2C_INSTANCE; + } +#endif + + DEBUG_PRINTF("I2C: %d %d %d\r\n", sda, scl, instance); + + return instance; +} + +/** + * Brief Find hardware instance for the provided SPI pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * Parameter mosi mosi pin. + * Parameter miso miso pin. + * Parameter clk clk pin. + * + * Return Hardware instance associated with provided pins. + */ +int pin_instance_spi(PinName mosi, PinName miso, PinName clk) +{ + int instance = NC; + + /* Search pin map for pre-allocated instance */ + for (size_t index = 0; + !((PinMap_SPI[index].mosi == NC) && + (PinMap_SPI[index].miso == NC) && + (PinMap_SPI[index].clk == NC)); + index++) { + + DEBUG_PRINTF("search: %d %d %d\r\n", PinMap_SPI[index].mosi, PinMap_SPI[index].miso, PinMap_SPI[index].clk); + + /* Compare pins to entry. */ + if ((PinMap_SPI[index].mosi == mosi) && + (PinMap_SPI[index].miso == miso) && + (PinMap_SPI[index].clk == clk)) { + + DEBUG_PRINTF("found: %d %d %d %d\r\n", mosi, miso, clk, PinMap_SPI[index].instance); + + /* Foung instance, save result. */ + instance = PinMap_SPI[index].instance; + + /* Lock out entry in map to prevent I2C from grabbing it. */ + nordic_internal_spi2c[instance].locaction0 = mosi; + nordic_internal_spi2c[instance].locaction1 = miso; + nordic_internal_spi2c[instance].locaction2 = clk; + break; + } + } + + /* No instance was found in static map. */ + if (instance == NC) { + + /* Search dynamic map for entry. */ + for (int index = NORDIC_SPI_COUNT - 1; index > -1; index--) { + if ((nordic_internal_spi2c[index].locaction0 == mosi) && + (nordic_internal_spi2c[index].locaction1 == miso) && + (nordic_internal_spi2c[index].locaction2 == clk)) { + + instance = index; + break; + } + } + } + + /* No instance was found in dynamic map. */ + if (instance == NC) { + + /* Search dynamic map for empty slot. */ + for (int index = NORDIC_SPI_COUNT - 1; index > -1; index--) { + + /* Empty slot found, reserve slot by storing pins. */ + if ((nordic_internal_spi2c[index].locaction0 == NC) && + (nordic_internal_spi2c[index].locaction1 == NC) && + (nordic_internal_spi2c[index].locaction2 == NC)) { + + nordic_internal_spi2c[index].locaction0 = mosi; + nordic_internal_spi2c[index].locaction1 = miso; + nordic_internal_spi2c[index].locaction2 = clk; + + instance = index; + break; + } + } + } + +#if defined(DEFAULT_SPI_INSTANCE) + /* Exhausted all options. Return default value. */ + if (instance == NC) { + instance = DEFAULT_SPI_INSTANCE; + } +#endif + + DEBUG_PRINTF("SPI: %d %d %d %d\r\n", mosi, miso, clk, instance); + + return instance; +} + + +/*** + * _______ ____ __ + * | __ \ \ / / \/ | + * | |__) \ \ /\ / /| \ / | + * | ___/ \ \/ \/ / | |\/| | + * | | \ /\ / | | | | + * |_| \/ \/ |_| |_| + * + * + */ + +/* Internal data structure to keep track of allocated instances. + */ +static PinName nordic_internal_pwm[NORDIC_PWM_COUNT] = { + NC, + NC, + NC, +#if (NORDIC_PWM_COUNT == 4) + NC, +#endif +}; + +/** + * Brief Find hardware instance for the provided PWM pin. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * Parameter pwm pwm pin. + * + * Return Hardware instance associated with provided pins. + */ +int pin_instance_pwm(PinName pwm) +{ + int instance = NC; + + /* Search pin map for pre-allocated instance */ + for (size_t index = 0; (PinMap_PWM[index].pwm != NC); index++) { + + /* Compare pins to entry. */ + if (PinMap_PWM[index].pwm == pwm) { + + DEBUG_PRINTF("found: %d %d\r\n", pwm, PinMap_PWM[index].instance); + + /* Instance found, save result. */ + instance = PinMap_PWM[index].instance; + + /* Lock out entry in map. */ + nordic_internal_pwm[instance] = pwm; + break; + } + } + + /* No instance was found in static map. */ + if (instance == NC) { + + /* Search dynamic map for entry. */ + for (size_t index = 0; index < NORDIC_PWM_COUNT; index++) { + + /* Pins match previous dynamic allocation, return instance. */ + if (nordic_internal_pwm[index] == pwm) { + + instance = index; + break; + } + } + } + + /* No instance was found in dynamic map. */ + if (instance == NC) { + + /* Search dynamic map for empty slot. */ + for (size_t index = 0; index < NORDIC_PWM_COUNT; index++) { + + /* Empty slot found, reserve slot by storing pins. */ + if (nordic_internal_pwm[index] == NC) { + + nordic_internal_pwm[index] = pwm; + + instance = index; + break; + } + } + } + +#if defined(DEFAULT_PWM_INSTANCE) + /* Exhausted all options. Return default value. */ + if (instance == NC) { + instance = DEFAULT_PWM_INSTANCE; + } +#endif + + DEBUG_PRINTF("PWM: %d %d\r\n", pwm, instance); + + return instance; +} + + +/*** + * _ _ _____ _______ + * | | | | /\ | __ \__ __| + * | | | | / \ | |__) | | | + * | | | |/ /\ \ | _ / | | + * | |__| / ____ \| | \ \ | | + * \____/_/ \_\_| \_\ |_| + * + * + */ + +/* Internal data structure to keep track of allocated instances. + */ +typedef struct { + PinName tx; + PinName rx; +} uart_t; + +static uart_t nordic_internal_uart[NORDIC_UART_COUNT] = { + { NC, NC }, +#if (NORDIC_UART_COUNT == 2) + { NC, NC } +#endif +}; + +/** + * Brief Find hardware instance for the provided UART pin. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * Parameter tx tx pin. + * Parameter rx rx pin. + * + * Return Hardware instance associated with provided pins. + */ +int pin_instance_uart(PinName tx, PinName rx) +{ + int instance = NC; + + /* Search pin map for pre-allocated instance */ + for (size_t index = 0; ((PinMap_UART[index].tx != NC) && (PinMap_UART[index].rx != NC)); index++) { + + /* Compare pins to entry. */ + if ((PinMap_UART[index].tx == tx) && (PinMap_UART[index].rx == rx)) { + + DEBUG_PRINTF("found: %d %d %d\r\n", tx, rx, PinMap_UART[index].instance); + + /* Instance found, save result. */ + instance = PinMap_UART[index].instance; + + /* Lock out entry in map. */ + nordic_internal_uart[instance].tx = tx; + nordic_internal_uart[instance].rx = rx; + break; + } + } + + /* No instance was found in static map. */ + if (instance == NC) { + + /* Search dynamic map for entry. */ + for (size_t index = 0; index < NORDIC_UART_COUNT; index++) { + + /* Pins match previous dynamic allocation, return instance. */ + if ((nordic_internal_uart[index].tx == tx) && (nordic_internal_uart[index].rx == rx)) { + + instance = index; + break; + } + } + } + + /* No instance was found in dynamic map. */ + if (instance == NC) { + + /* Search dynamic map for empty slot. */ + for (size_t index = 0; index < NORDIC_UART_COUNT; index++) { + + /* Empty slot found, reserve slot by storing pins. */ + if ((nordic_internal_uart[index].tx == NC) && (nordic_internal_uart[index].rx == NC)) { + + nordic_internal_uart[index].tx = tx; + nordic_internal_uart[index].rx = rx; + + instance = index; + break; + } + } + } + +#if defined(DEFAULT_UART_INSTANCE) + /* Exhausted all options. Return default value. */ + if (instance == NC) { + instance = DEFAULT_UART_INSTANCE; + } +#endif + + DEBUG_PRINTF("UART: %d %d %d\r\n", tx, rx, instance); + + return instance; +} + diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.h b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.h new file mode 100644 index 0000000000..5738248a3c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/pinmap_ex.h @@ -0,0 +1,146 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 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 PINMAP_EX_H +#define PINMAP_EX_H + +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Data structure for pre-allocated I2C instances. */ +typedef struct { + PinName sda; + PinName scl; + int instance; +} PinMapI2C; + +extern const PinMapI2C PinMap_I2C[]; + +/* Data structure for pre-allocated SPI instances. */ +typedef struct { + PinName mosi; + PinName miso; + PinName clk; + int instance; +} PinMapSPI; + +extern const PinMapSPI PinMap_SPI[]; + +/* Data structure for pre-allocated PWM instances. */ +typedef struct { + PinName pwm; + int instance; +} PinMapPWM; + +extern const PinMapPWM PinMap_PWM[]; + +/* Data structure for pre-allocated UART instances. */ +typedef struct { + PinName tx; + PinName rx; + int instance; +} PinMapUART; + +extern const PinMapUART PinMap_UART[]; + +/** + * @brief Find hardware instance for the provided I2C pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * @param[in] sda sda pin. + * @param[in] scl scl pin. + * + * @return Hardware instance associated with provided pins. + */ +int pin_instance_i2c(PinName sda, PinName scl); + +/** + * @brief Find hardware instance for the provided SPI pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * @param[in] mosi mosi pin. + * @param[in] miso miso pin. + * @param[in] clk clk pin. + * + * @return Hardware instance associated with provided pins. + */ +int pin_instance_spi(PinName mosi, PinName miso, PinName clk); + +/** + * @brief Find hardware instance for the provided PWM pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * @param[in] pwm pwm pin. + * + * @return Hardware instance associated with provided pins. + */ +int pin_instance_pwm(PinName pwm); + +/** + * @brief Find hardware instance for the provided UART pins. + * + * The function will search the PeripheralPin map for a pre-allocated + * assignment. If none is found the allocation map will be searched + * to see if the same pins have been assigned an instance before. + * + * If no assignement is found and there is an empty slot left in the + * map, the pins are stored in the map and the hardware instance is + * returned. + * + * If no free instances are available, the default instance is returned. + * + * @param[in] tx tx pin. + * @param[in] rx rx pin. + * + * @return Hardware instance associated with provided pins. + */ +int pin_instance_uart(PinName tx, PinName rx); + +#ifdef __cplusplus +} +#endif + +#endif // PINMAP_EX_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/port_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/port_api.c new file mode 100644 index 0000000000..e8c57184a5 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/port_api.c @@ -0,0 +1,134 @@ +/* + * 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" + +#if defined(TARGET_MCU_NRF51822) || defined(TARGET_MCU_NRF52832) + #define GPIO_REG_LIST {NRF_GPIO} +#endif + +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(m_gpio_pin_count[0])) + + +PinName port_pin(PortName port, int pin_n) +{ +#if defined(TARGET_MCU_NRF51822) || defined(TARGET_MCU_NRF52832) + return (PinName)pin_n; +#else + return (PinName)NRF_GPIO_PIN_MAP(port, pin_n); +#endif +} + +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<31; 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); +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/pwmout_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/pwmout_api.c new file mode 100644 index 0000000000..57dd7a28af --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/pwmout_api.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2018 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. + * + */ + +#if DEVICE_PWMOUT + +#include "hal/pwmout_api.h" + +#include "pinmap_ex.h" +#include "nrf_drv_pwm.h" + +#if 0 +#define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0) +#else +#define DEBUG_PRINTF(...) {} +#endif + +/* 0x7FFF is the max of COUNTERTOP pulse for the PWM peripherial of the nRF52. */ +#define MAX_PWM_COUNTERTOP (0x7FFF) + +/* The PWM is driven by a 1 MHz clock to fit the 1 us resolution expected by the API. */ +#define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP) +#define MAX_PWM_PERIOD_MS (MAX_PWM_PERIOD_US / 1000) +#define MAX_PWM_PERIOD_S ((float) MAX_PWM_PERIOD_US / 1000000.0f) + +/* Allocate PWM instances. */ +static nrf_drv_pwm_t nordic_nrf5_pwm_instance[] = { +#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 +#if PWM3_ENABLED + NRF_DRV_PWM_INSTANCE(3), +#endif +}; + +/* Helper function for (re)initializing the PWM instance. + */ +static void nordic_pwm_init(pwmout_t *obj) +{ + MBED_ASSERT(obj); + + /* Default configuration: + * 1 pin per instance, otherwise they would share base count. + * 1 MHz clock source to match the 1 us resolution. + */ + nrf_drv_pwm_config_t config = { + .output_pins = { + obj->pin, + NRF_DRV_PWM_PIN_NOT_USED, + NRF_DRV_PWM_PIN_NOT_USED, + NRF_DRV_PWM_PIN_NOT_USED, + }, + .irq_priority = PWM_DEFAULT_CONFIG_IRQ_PRIORITY, + .base_clock = NRF_PWM_CLK_1MHz, + .count_mode = NRF_PWM_MODE_UP, + .top_value = obj->period, + .load_mode = NRF_PWM_LOAD_COMMON, + .step_mode = NRF_PWM_STEP_AUTO, + }; + + /* Make sure PWM instance is not running before making changes. */ + nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]); + + /* Initialize instance with new configuration. */ + ret_code_t result = nrf_drv_pwm_init(&nordic_nrf5_pwm_instance[obj->instance], + &config, + NULL); + + MBED_ASSERT(result == NRF_SUCCESS); +} + +/* Helper function for reinitializing the PWM instance and setting the duty-cycle. */ +static void nordic_pwm_restart(pwmout_t *obj) +{ + MBED_ASSERT(obj); + + /* (Re)initialize PWM instance. */ + nordic_pwm_init(obj); + + /* Set duty-cycle from object. */ + ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance], + &obj->sequence, + 1, + NRF_DRV_PWM_FLAG_LOOP); + + MBED_ASSERT(result == NRF_SUCCESS); +} + +/** Initialize the pwm out peripheral and configure the pin + * + * Parameter obj The pwmout object to initialize + * Parameter pin The pwmout pin to initialize + */ +void pwmout_init(pwmout_t *obj, PinName pin) +{ + DEBUG_PRINTF("pwmout_init: %d\r\n", pin); + + MBED_ASSERT(obj); + + /* Get hardware instance from pinmap. */ + int instance = pin_instance_pwm(pin); + + MBED_ASSERT(instance < (int)(sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t))); + + /* Populate PWM object with default values. */ + obj->instance = instance; + obj->pin = pin; + obj->pulse = 0; + obj->period = MAX_PWM_COUNTERTOP; + obj->percent = 0; + obj->sequence.values.p_common = &obj->pulse; + obj->sequence.length = NRF_PWM_VALUES_LENGTH(obj->pulse); + obj->sequence.repeats = 0; + obj->sequence.end_delay = 0; + + /* Initialize PWM instance. */ + nordic_pwm_init(obj); +} + +/** Deinitialize the pwmout object + * + * Parameter obj The pwmout object + */ +void pwmout_free(pwmout_t *obj) +{ + DEBUG_PRINTF("pwmout_free\r\n"); + + MBED_ASSERT(obj); + + /* Uninitialize PWM instance. */ + nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]); +} + +/** Set the output duty-cycle in range <0.0f, 1.0f> + * + * pulse 0.0f represents 0 percentage, 1.0f represents 100 percent. + * Parameter obj The pwmout object + * Parameter percent The floating-point percentage number + */ +void pwmout_write(pwmout_t *obj, float percent) +{ + DEBUG_PRINTF("pwmout_write: %f\r\n", percent); + + /* Find counts based on period. */ + uint16_t pulse = obj->period * percent; + + /* Ensure we don't overcount. */ + obj->pulse = (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse; + + /* Store actual percentage passed as parameter to avoid floating point rounding errors. */ + obj->percent = percent; + + /* Set new duty-cycle. */ + ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance], + &obj->sequence, + 1, + NRF_DRV_PWM_FLAG_LOOP); + + MBED_ASSERT(result == NRF_SUCCESS); +} + +/** Read the current float-point output duty-cycle + * + * Parameter obj The pwmout object + * Return A floating-point output duty-cycle + */ +float pwmout_read(pwmout_t *obj) +{ + DEBUG_PRINTF("pwmout_read: %f\r\n", obj->percent); + + /* Return percentage stored in object instead of calculating the value. + * This prevents floating point rounding errors. + */ + return obj->percent; +} + +/** Set the PWM period specified in seconds, keeping the duty cycle the same + * + * Periods smaller than microseconds (the lowest resolution) are set to zero. + * Parameter obj The pwmout object + * Parameter seconds The floating-point seconds period + */ +void pwmout_period(pwmout_t *obj, float period) +{ + DEBUG_PRINTF("pwmout_period: %f\r\n", period); + + /* Cap period if too large. */ + if (period > MAX_PWM_PERIOD_S) { + period = MAX_PWM_PERIOD_S; + } + + /* Set new period. */ + pwmout_period_us(obj, period * 1000000); +} + +/** Set the PWM period specified in miliseconds, keeping the duty cycle the same + * + * Parameter obj The pwmout object + * Parameter ms The milisecond period + */ +void pwmout_period_ms(pwmout_t *obj, int period) +{ + DEBUG_PRINTF("pwmout_period_ms: %d\r\n", period); + + /* Cap period if too large. */ + if (period > MAX_PWM_PERIOD_MS) { + period = MAX_PWM_PERIOD_MS; + } + + /* Set new period. */ + pwmout_period_us(obj, period * 1000); +} + +/** Set the PWM period specified in microseconds, keeping the duty cycle the same + * + * Parameter obj The pwmout object + * Parameter us The microsecond period + */ +void pwmout_period_us(pwmout_t *obj, int period) +{ + DEBUG_PRINTF("pwmout_period_us: %d\r\n", period); + + /* Cap period if too large. */ + if (period > MAX_PWM_PERIOD_US) { + period = MAX_PWM_PERIOD_US; + } + + /* Scale new count based on stored duty-cycle and new period. */ + uint32_t pulse = (period * obj->pulse) / obj->period; + + /* Store new values in object. */ + obj->pulse = pulse; + obj->period = period; + obj->percent = (float) pulse / (float) period; + + /* Restart instance with new values. */ + nordic_pwm_restart(obj); +} + +/** Set the PWM pulsewidth specified in seconds, keeping the period the same. + * + * Parameter obj The pwmout object + * Parameter seconds The floating-point pulsewidth in seconds + */ +void pwmout_pulsewidth(pwmout_t *obj, float pulse) +{ + DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse); + + /* Cap pulsewidth to period before setting it. */ + if ((pulse * 1000000) > (float) obj->pulse) { + obj->pulse = obj->period; + pwmout_pulsewidth_us(obj, obj->pulse); + } else { + pwmout_pulsewidth_us(obj, pulse * 1000000); + } +} + +/** Set the PWM pulsewidth specified in miliseconds, keeping the period the same. + * + * Parameter obj The pwmout object + * Parameter ms The floating-point pulsewidth in miliseconds + */ +void pwmout_pulsewidth_ms(pwmout_t *obj, int pulse) +{ + DEBUG_PRINTF("pwmout_pulsewidth_ms: %d\r\n", ms); + + /* Cap pulsewidth to period before setting it. */ + if ((pulse * 1000) > (int) obj->period) { + obj->pulse = obj->period; + pwmout_pulsewidth_us(obj, obj->pulse); + } else { + pwmout_pulsewidth_us(obj, pulse * 1000); + } +} + +/** Set the PWM pulsewidth specified in microseconds, keeping the period the same. + * + * Parameter obj The pwmout object + * Parameter us The floating-point pulsewidth in microseconds + */ +void pwmout_pulsewidth_us(pwmout_t *obj, int pulse) +{ + DEBUG_PRINTF("pwmout_pulsewidth_us: %d\r\n", pulse); + + /* Cap pulsewidth to period. */ + if (pulse > obj->period) { + pulse = obj->period; + } + + /* Store new values in object. */ + obj->pulse = pulse; + obj->percent = (float) pulse / (float) obj->period; + + /* Restart instance with new values. */ + nordic_pwm_restart(obj); +} + +#endif // DEVICE_PWMOUT diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/reloc_vector_table.c b/targets/TARGET_NORDIC/TARGET_NRF5x/reloc_vector_table.c new file mode 100644 index 0000000000..f1c82798d3 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/reloc_vector_table.c @@ -0,0 +1,82 @@ +/* + * 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" + +#if defined(SOFTDEVICE_PRESENT) +#include "nrf_sdm.h" +#endif + +#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + __attribute__ ((section(".bss.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]; + } + +#if defined(SOFTDEVICE_PRESENT) + sd_softdevice_vector_table_base_set((uint32_t) nrf_dispatch_vector); +#else + SCB->VTOR = (uint32_t) nrf_dispatch_vector; +#endif +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/rtc_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/rtc_api.c new file mode 100644 index 0000000000..cc4d0f118f --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/rtc_api.c @@ -0,0 +1,92 @@ +/* + * 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 diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/serial_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/serial_api.c new file mode 100644 index 0000000000..f5770e2638 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/serial_api.c @@ -0,0 +1,1836 @@ +/* + * 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. + * + */ + +#if DEVICE_SERIAL + +#include "hal/serial_api.h" + +#include "nrf_uarte.h" +#include "nrf_drv_uart.h" +#include "nrf_drv_common.h" +#include "nrf_atfifo.h" +#include "app_util_platform.h" +#include "nrf_rtc.h" +#include "pinmap_ex.h" + +#include "platform/mbed_critical.h" + +#if UART0_ENABLED == 0 +#error UART0 is disabled. DEVICE_SERIAL must also be disabled to continue. +#endif + + +/*** + * _____ __ _ _ _ + * / ____| / _(_) | | (_) + * | | ___ _ __ | |_ _ __ _ _ _ _ __ __ _| |_ _ ___ _ __ + * | | / _ \| '_ \| _| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \ + * | |___| (_) | | | | | | | (_| | |_| | | | (_| | |_| | (_) | | | | + * \_____\___/|_| |_|_| |_|\__, |\__,_|_| \__,_|\__|_|\___/|_| |_| + * __/ | + * |___/ + */ + +/** + * Idle timeout between characters before DMA buffer is flushed. + */ +#ifndef MBED_CONF_NORDIC_UART_TIMEOUT_US +#define MBED_CONF_NORDIC_UART_TIMEOUT_US 2000 +#endif + +/** + * Default FIFO buffer size for UARTE0. + */ +#ifndef MBED_CONF_NORDIC_UART_0_FIFO_SIZE +#define MBED_CONF_NORDIC_UART_0_FIFO_SIZE 32 +#endif + +/** + * Default FIFO buffer size for UARTE1. + */ +#ifndef MBED_CONF_NORDIC_UART_1_FIFO_SIZE +#define MBED_CONF_NORDIC_UART_1_FIFO_SIZE 32 +#endif + +/** + * Default DMA buffer size. Each instance has two DMA buffers. + */ +#ifndef MBED_CONF_NORDIC_UART_DMA_SIZE +#define MBED_CONF_NORDIC_UART_DMA_SIZE 8 +#else +#if MBED_CONF_NORDIC_UART_DMA_SIZE < 5 +#error MBED_CONF_NORDIC_UART_DMA_SIZE must be at least 5 bytes +#endif +#if MBED_CONF_NORDIC_UART_DMA_SIZE > 255 +#error MBED_CONF_NORDIC_UART_DMA_SIZE must be less than 256 bytes +#endif +#endif + +/** + * Internal short names. + */ +#define IDLE_TIMEOUT_US MBED_CONF_NORDIC_UART_TIMEOUT_US +#define UART0_FIFO_BUFFER_SIZE MBED_CONF_NORDIC_UART_0_FIFO_SIZE +#define UART1_FIFO_BUFFER_SIZE MBED_CONF_NORDIC_UART_1_FIFO_SIZE +#define DMA_BUFFER_SIZE MBED_CONF_NORDIC_UART_DMA_SIZE +#define NUMBER_OF_BANKS 2 + +/** + * Default timer delay for callbacks. + */ +#define CALLBACK_DELAY_US 100 + +/** + * Use RTC2 for idle timeouts and deferred callbacks. + * Each channel is dedicated to one particular task. + */ +#define UARTE0_RTC_TIMEOUT_CHANNEL 0 +#define UARTE0_RTC_CALLBACK_CHANNEL 1 +#define UARTE1_RTC_TIMEOUT_CHANNEL 2 +#define UARTE1_RTC_CALLBACK_CHANNEL 3 + +/** + * RTC frequency. + */ +#define RTC_FREQUENCY 32768 + + +/*** + * _______ _ __ + * |__ __| | | / _| + * | |_ _ _ __ ___ __| | ___| |_ ___ + * | | | | | '_ \ / _ \/ _` |/ _ \ _/ __| + * | | |_| | |_) | __/ (_| | __/ | \__ \ + * |_|\__, | .__/ \___|\__,_|\___|_| |___/ + * __/ | | + * |___/|_| + */ + +/** + * Missing event typedefs. + */ +typedef enum +{ + NRF_UARTE_EVENT_RXDRDY = offsetof(NRF_UARTE_Type, EVENTS_RXDRDY), + NRF_UARTE_EVENT_TXDRDY = offsetof(NRF_UARTE_Type, EVENTS_TXDRDY), +} nrf_uarte_event_extra_t; + +/** + * Missing interrupt masks. + */ +typedef enum +{ + NRF_UARTE_INT_RXDRDY_MASK = UARTE_INTENSET_RXDRDY_Msk, + NRF_UARTE_INT_TXDRDY_MASK = UARTE_INTENSET_TXDRDY_Msk, +} nrf_uarte_int_mask_extra_t; + +/** + * Internal struct for storing each UARTE instance's state: + * + * owner: pointer to serial object currently using instance. + * buffer: buffers assigned to EasyDMA. + * rxdrdy_counter: count received characters for idle detection. + * endrx_counter: count filled DMA buffers for idle detection. + * tx_data: 1 byte Tx buffer for blocking putc. + * tx_in_progress: mutex for atomic Tx. + * rx_in_progress: mutex for atomic Rx when using async API. + * tx_asynch: set synch or asynch mode for Tx. + * rx_asynch: set synch or asynch mode for Rx. + * ticker_is_running: flag for enabling/disabling idle timer. + * callback_posted: flag for posting only one callback. + * active_bank: flag for buffer swapping. + * fifo: pointer to the FIFO buffer. + */ +typedef struct { + struct serial_s *owner; + uint8_t buffer[NUMBER_OF_BANKS][DMA_BUFFER_SIZE]; + uint32_t rxdrdy_counter; + uint32_t endrx_counter; + uint32_t usage_counter; + uint8_t tx_data; + volatile uint8_t tx_in_progress; + volatile uint8_t rx_in_progress; + bool tx_asynch; + bool rx_asynch; + bool ticker_is_running; + bool callback_posted; + uint8_t active_bank; + nrf_atfifo_t *fifo; +} nordic_uart_state_t; + +/** + * Turn Mbed HAL IRQ flags into maskable bit masks. + */ +typedef enum { + NORDIC_TX_IRQ = (1 << 0), + NORDIC_RX_IRQ = (1 << 1), +} nordic_irq_t; + + +/*** + * _____ _ _ _ __ __ _ _ _ + * / ____| | | | | | \ \ / / (_) | | | | + * | | __| | ___ | |__ __ _| | \ \ / /_ _ _ __ _ __ _| |__ | | ___ ___ + * | | |_ | |/ _ \| '_ \ / _` | | \ \/ / _` | '__| |/ _` | '_ \| |/ _ \/ __| + * | |__| | | (_) | |_) | (_| | | \ / (_| | | | | (_| | |_) | | __/\__ \ + * \_____|_|\___/|_.__/ \__,_|_| \/ \__,_|_| |_|\__,_|_.__/|_|\___||___/ + * + * + */ + +/** + * UARTE state. One for each instance. + */ +static nordic_uart_state_t nordic_nrf5_uart_state[UART_ENABLED_COUNT] = { 0 }; + +/** + * Array with UARTE register pointers for easy access. + */ +static NRF_UARTE_Type *nordic_nrf5_uart_register[UART_ENABLED_COUNT] = { + NRF_UARTE0, +#if UART1_ENABLED + NRF_UARTE1, +#endif +}; + +/** + * @brief Create atomic fifo using macro. Macro defines static arrays + * for buffer and internal state. + */ +NRF_ATFIFO_DEF(nordic_nrf5_uart_fifo_0, uint8_t, UART0_FIFO_BUFFER_SIZE); + +#if UART1_ENABLED +NRF_ATFIFO_DEF(nordic_nrf5_uart_fifo_1, uint8_t, UART1_FIFO_BUFFER_SIZE); +#endif + +/** + * Global variables expected by mbed_retarget.cpp for STDOUT. + */ +int stdio_uart_inited = 0; +serial_t stdio_uart = { 0 }; + + +/*** + * _____ _ _______ _ + * / ____| | | |__ __(_) + * | | _ _ ___| |_ ___ _ __ ___ | | _ _ __ ___ ___ _ __ + * | | | | | / __| __/ _ \| '_ ` _ \ | | | | '_ ` _ \ / _ \ '__| + * | |___| |_| \__ \ || (_) | | | | | | | | | | | | | | | __/ | + * \_____\__,_|___/\__\___/|_| |_| |_| |_| |_|_| |_| |_|\___|_| + * + * + */ + +/** + * @brief Set timout for a particular channel in RTC2. + * + * @param[in] timeout The timeout + * @param[in] channel The channel + */ +static void nordic_custom_ticker_set(uint32_t timeout, int channel) +{ + /** + * Add timeout to current time and set as compare value for channel. + */ + uint32_t now = nrf_rtc_counter_get(NRF_RTC2); + uint32_t ticksout = (timeout * RTC_FREQUENCY) / (1000 * 1000); + nrf_rtc_cc_set(NRF_RTC2, channel, ticksout + now); + + /** + * Enable interrupt for channel. + */ + uint32_t mask = nrf_rtc_int_get(NRF_RTC2); + nrf_rtc_int_enable(NRF_RTC2, mask | RTC_CHANNEL_INT_MASK(channel)); +} + +/** + * @brief Set idle timeout for particular instance. + * This function translates instance number to RTC channel. + * + * @param[in] instance The instance + */ +static void nordic_custom_ticker_set_timeout(int instance) +{ + if (instance == 0) { + + nordic_custom_ticker_set(IDLE_TIMEOUT_US, UARTE0_RTC_TIMEOUT_CHANNEL); + } + else if (instance == 1) { + + nordic_custom_ticker_set(IDLE_TIMEOUT_US, UARTE1_RTC_TIMEOUT_CHANNEL); + } +} + +/** + * @brief Schedule callback for particular instance. + * This function translates instance number to RTC channel. + * + * @param[in] instance The instance + */ +static void nordic_custom_ticker_set_callback(int instance) +{ + if (instance == 0) { + + nordic_custom_ticker_set(CALLBACK_DELAY_US, UARTE0_RTC_CALLBACK_CHANNEL); + } + else if (instance == 1) { + + nordic_custom_ticker_set(CALLBACK_DELAY_US, UARTE1_RTC_CALLBACK_CHANNEL); + } +} + + +/*** + * _______ _ _ _ _ _ + * |__ __(_) | | | | | | | + * | | _ _ __ ___ ___ _ __ | |__| | __ _ _ __ __| | | ___ _ __ + * | | | | '_ ` _ \ / _ \ '__| | __ |/ _` | '_ \ / _` | |/ _ \ '__| + * | | | | | | | | | __/ | | | | | (_| | | | | (_| | | __/ | + * |_| |_|_| |_| |_|\___|_| |_| |_|\__,_|_| |_|\__,_|_|\___|_| + * + * + */ + +/** + * @brief Interrupt handler for idle timeouts. + * This function fans out interrupts from ISR and + * translates channel to instance. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_timeout_handler(uint32_t instance) +{ + /** + * Check if any characters have been received or buffers been flushed + * since the last idle timeout. + */ + if ((nordic_nrf5_uart_state[instance].rxdrdy_counter > 0) || + (nordic_nrf5_uart_state[instance].endrx_counter > 0)) { + + /* Activity detected, reset timeout. */ + nordic_custom_ticker_set_timeout(instance); + + } else { + + /* No activity detected, no timeout set. */ + nordic_nrf5_uart_state[instance].ticker_is_running = false; + + /** + * Stop Rx, this triggers a buffer swap and copies data from + * DMA buffer to FIFO buffer. + */ + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STOPRX); + } + + /* reset activity counters. */ + nordic_nrf5_uart_state[instance].rxdrdy_counter = 0; + nordic_nrf5_uart_state[instance].endrx_counter = 0; +} + +/** + * @brief Interrupt handler for scheduled callbacks. + * This function fans out interrupts from ISR and + * translates channel to instance. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_callback_handler(uint32_t instance) +{ + /* Flag that no callback is posted. */ + nordic_nrf5_uart_state[instance].callback_posted = false; + + /* Check if callback handler is set and if event mask match. */ + uart_irq_handler callback = (uart_irq_handler) nordic_nrf5_uart_state[instance].owner->handler; + uint32_t mask = nordic_nrf5_uart_state[instance].owner->mask; + + if (callback && (mask & NORDIC_RX_IRQ)) { + + /* Invoke callback function. */ + uint32_t context = nordic_nrf5_uart_state[instance].owner->context; + callback(context, RxIrq); + } +} + +/** + * @brief RTC2 ISR. Used for timeouts and scheduled callbacks. + */ +static void nordic_nrf5_rtc2_handler(void) +{ + /* Channel 0 */ + if (nrf_rtc_event_pending(NRF_RTC2, NRF_RTC_EVENT_COMPARE_0)) { + + /* Clear event and disable interrupt for channel. */ + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_0); + + uint32_t mask = nrf_rtc_int_get(NRF_RTC2); + nrf_rtc_int_enable(NRF_RTC2, mask & ~NRF_RTC_INT_COMPARE0_MASK); + + /* Call timeout handler with instance ID. */ + nordic_nrf5_uart_timeout_handler(0); + } + + /* Channel 1 */ + if (nrf_rtc_event_pending(NRF_RTC2, NRF_RTC_EVENT_COMPARE_1)) { + + /* Clear event and disable interrupt for channel. */ + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_1); + + uint32_t mask = nrf_rtc_int_get(NRF_RTC2); + nrf_rtc_int_enable(NRF_RTC2, mask & ~NRF_RTC_INT_COMPARE1_MASK); + + /* Call callback handler with instance ID. */ + nordic_nrf5_uart_callback_handler(0); + } + +#if UART1_ENABLED + /* Channel 2 */ + if (nrf_rtc_event_pending(NRF_RTC2, NRF_RTC_EVENT_COMPARE_2)) { + + /* Clear event and disable interrupt for channel. */ + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_2); + + uint32_t mask = nrf_rtc_int_get(NRF_RTC2); + nrf_rtc_int_enable(NRF_RTC2, mask & ~NRF_RTC_INT_COMPARE2_MASK); + + /* Call timeout handler with instance ID. */ + nordic_nrf5_uart_timeout_handler(1); + } + + /* Channel 3 */ + if (nrf_rtc_event_pending(NRF_RTC2, NRF_RTC_EVENT_COMPARE_3)) { + + /* Clear event and disable interrupt for channel. */ + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_3); + + uint32_t mask = nrf_rtc_int_get(NRF_RTC2); + nrf_rtc_int_enable(NRF_RTC2, mask & ~NRF_RTC_INT_COMPARE3_MASK); + + /* Call callback handler with instance ID. */ + nordic_nrf5_uart_callback_handler(1); + } +#endif + +} + + +/*** + * _ _ _____ _______ ______ _ _ _ _ _ + * | | | | /\ | __ \__ __| | ____| | | | | | | | | | + * | | | | / \ | |__) | | | | |____ _____ _ __ | |_ | |__| | __ _ _ __ __| | | ___ _ __ + * | | | |/ /\ \ | _ / | | | __\ \ / / _ \ '_ \| __| | __ |/ _` | '_ \ / _` | |/ _ \ '__| + * | |__| / ____ \| | \ \ | | | |___\ V / __/ | | | |_ | | | | (_| | | | | (_| | | __/ | + * \____/_/ \_\_| \_\ |_| |______\_/ \___|_| |_|\__| |_| |_|\__,_|_| |_|\__,_|_|\___|_| + * + * + */ + +/** + * @brief Event handler for when Rx buffer is full or buffer swap has been + * triggered by idle task. + * + * Copy data from DMA buffer to FIFO buffer. + * Post callback if not already posted. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_endrx(int instance) +{ + /* Increment idle counter. */ + core_util_atomic_incr_u32(&nordic_nrf5_uart_state[instance].endrx_counter, 1); + + /* Read out active bank flag and swap DMA buffers. */ + uint8_t active_bank = nordic_nrf5_uart_state[instance].active_bank; + nordic_nrf5_uart_state[instance].active_bank = active_bank ^ 0x01; + + /* Get number of bytes in DMA buffer. */ + uint32_t available = nrf_uarte_rx_amount_get(nordic_nrf5_uart_register[instance]); + + if (available > 0) { + + /* Copy data from DMA buffer to FIFO buffer. */ + for (size_t index = 0; index < available; index++) { + + /* Atomic FIFO can be used safely without disabling interrutps. */ + nrf_atfifo_item_put_t fifo_context; + + /* Get pointer to available space. */ + uint8_t *byte = (uint8_t *) nrf_atfifo_item_alloc(nordic_nrf5_uart_state[instance].fifo, &fifo_context); + + if (byte != NULL) { + + /* Copy 1 byte from DMA buffer and commit to FIFO buffer. */ + *byte = nordic_nrf5_uart_state[instance].buffer[active_bank][index]; + nrf_atfifo_item_put(nordic_nrf5_uart_state[instance].fifo, &fifo_context); + + } else { + + /* Buffer overflow. */ + break; + } + } + + /* Schedule callback to signal data is available if not already posted. */ + if (nordic_nrf5_uart_state[instance].callback_posted == false) { + + nordic_nrf5_uart_state[instance].callback_posted = true; + nordic_custom_ticker_set_callback(instance); + } + } +} + +/** + * @brief Event handler for when DMA has been armed with Rx buffer. + * + * Arm Rx buffer with second buffer for optimal reception. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_rxstarted(int instance) +{ + uint8_t next_bank = nordic_nrf5_uart_state[instance].active_bank ^ 0x01; + + nrf_uarte_rx_buffer_set(nordic_nrf5_uart_register[instance], nordic_nrf5_uart_state[instance].buffer[next_bank], DMA_BUFFER_SIZE); +} + +/** + * @brief Event handler for when a character has been received in DMA buffer. + * + * Increment idle counter and set idle timeout if not already set. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_rxdrdy(int instance) +{ + /* Increment idle counter. */ + core_util_atomic_incr_u32(&nordic_nrf5_uart_state[instance].rxdrdy_counter, 1); + + /* Set idle timeout if not already set. */ + if (nordic_nrf5_uart_state[instance].ticker_is_running == false) { + + nordic_nrf5_uart_state[instance].ticker_is_running = true; + + nordic_custom_ticker_set_timeout(instance); + } +} + +/** + * @brief Event handler for when the Tx buffer has been transmitted. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_endtx(int instance) +{ + /* Check if callback handler and Tx event mask is set. */ + uart_irq_handler callback = (uart_irq_handler) nordic_nrf5_uart_state[instance].owner->handler; + uint32_t mask = nordic_nrf5_uart_state[instance].owner->mask; + + if (callback && (mask & NORDIC_TX_IRQ)) { + + /* Invoke callback function. */ + uint32_t context = nordic_nrf5_uart_state[instance].owner->context; + callback(context, TxIrq); + } +} + +#if DEVICE_SERIAL_ASYNCH +/** + * @brief Asynchronous event handler for when Rx DMA buffer is full. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_endrx_asynch(int instance) +{ + /* Set Rx done and reset Rx mode to be not asynchronous. */ + nordic_nrf5_uart_state[instance].rx_in_progress = 0; + nordic_nrf5_uart_state[instance].rx_asynch = false; + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) nordic_nrf5_uart_state[instance].owner->rx_handler; + uint32_t mask = nordic_nrf5_uart_state[instance].owner->rx_mask; + + /* Signal error if event mask matches and event handler is set. */ + if (callback && (mask & SERIAL_EVENT_RX_COMPLETE)) { + + /* Store event value so it can be read back. */ + nordic_nrf5_uart_state[instance].owner->rx_event = SERIAL_EVENT_RX_COMPLETE; + + /* Signal callback handler. */ + callback(); + } +} + +/** + * @brief Asynchronous event handler for when Tx DMA buffer has been sent. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler_endtx_asynch(int instance) +{ + /* Disable ENDTX interrupt. */ + nordic_nrf5_uart_register[instance]->INTEN &= ~NRF_UARTE_INT_ENDTX_MASK; + + /* Clear ENDTX event. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX); + + /* Set Tx done and reset Tx mode to be not asynchronous. */ + nordic_nrf5_uart_state[instance].tx_in_progress = 0; + nordic_nrf5_uart_state[instance].tx_asynch = false; + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) nordic_nrf5_uart_state[instance].owner->tx_handler; + uint32_t mask = nordic_nrf5_uart_state[instance].owner->tx_mask; + + /* Signal error if event mask matches and event handler is set. */ + if (callback && (mask & SERIAL_EVENT_TX_COMPLETE)) { + + /* Store event value so it can be read back. */ + nordic_nrf5_uart_state[instance].owner->tx_event = SERIAL_EVENT_TX_COMPLETE; + + /* Signal callback handler. */ + callback(); + } +} +#endif + +/** + * @brief UARTE event handler. + * + * Collect signals from UARTE0 and UARTE1 ISR and translate to instance. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_event_handler(int instance) +{ + /* DMA buffer is full or has been swapped out by idle timeout. */ + if (nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDRX)) + { + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDRX); + +#if DEVICE_SERIAL_ASYNCH + /* Call appropriate event handler based on current mode. */ + if (nordic_nrf5_uart_state[instance].rx_asynch) { + + nordic_nrf5_uart_event_handler_endrx_asynch(instance); + } else +#endif + { + nordic_nrf5_uart_event_handler_endrx(instance); + } + } + + /* Rx DMA buffer has been armed. */ + if (nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXSTARTED)) + { + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXSTARTED); + + nordic_nrf5_uart_event_handler_rxstarted(instance); + } + + /* Single character has been put in DMA buffer. */ + if (nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXDRDY)) + { + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXDRDY); + + nordic_nrf5_uart_event_handler_rxdrdy(instance); + } + + /* Tx single character has been sent. */ + if (nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXDRDY)) { + + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXDRDY); + + /* In non-async transfers this will generate and interrupt if callback and mask is set. */ + if (!nordic_nrf5_uart_state[instance].tx_asynch) { + + nordic_nrf5_uart_event_handler_endtx(instance); + } + } + + /* Tx DMA buffer has been sent. */ + if (nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX)) + { +#if DEVICE_SERIAL_ASYNCH + /* Call async event handler in async mode. */ + if (nordic_nrf5_uart_state[instance].tx_asynch) { + + nordic_nrf5_uart_event_handler_endtx_asynch(instance); + } +#endif + } +} + +/** + * @brief UARTE0 ISR. + */ +static void nordic_nrf5_uart0_handler(void) +{ + /* Call event handler with instance ID. */ + nordic_nrf5_uart_event_handler(0); +} + +#if UART1_ENABLED +/** + * @brief UARTE1 ISR. + */ +static void nordic_nrf5_uart1_handler(void) +{ + /* Call event handler with instance ID. */ + nordic_nrf5_uart_event_handler(1); +} +#endif + + +/*** + * _____ __ _ _ _ + * / ____| / _(_) | | (_) + * | | ___ _ __ | |_ _ __ _ _ _ _ __ __ _| |_ _ ___ _ __ + * | | / _ \| '_ \| _| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \ + * | |___| (_) | | | | | | | (_| | |_| | | | (_| | |_| | (_) | | | | + * \_____\___/|_| |_|_| |_|\__, |\__,_|_| \__,_|\__|_|\___/|_| |_| + * __/ | + * |___/ + */ + +/** + * @brief Enable UARTE interrupts. + * + * Translates instance to UARTE register. + * Set IRQ priority to highest to avoid Rx overflow. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_irq_enable(int instance) +{ + if (instance == 0) { + + nrf_drv_common_irq_enable(UARTE0_UART0_IRQn, APP_IRQ_PRIORITY_HIGHEST); + } + +#if UART1_ENABLED + else if (instance == 1) { + + nrf_drv_common_irq_enable(UARTE1_IRQn, APP_IRQ_PRIORITY_HIGHEST); + } +#endif +} + +/** + * @brief Configure UARTE based on serial object settings. + * + * Common for both Rx and Tx. + * + * @param obj The object + */ +static void nordic_nrf5_uart_configure_object(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Configure Tx and Rx pins. */ + nrf_gpio_pin_set(uart_object->tx); + nrf_gpio_cfg_output(uart_object->tx); + nrf_gpio_cfg_input(uart_object->rx, NRF_GPIO_PIN_NOPULL); + + nrf_uarte_txrx_pins_set(nordic_nrf5_uart_register[uart_object->instance], + uart_object->tx, + uart_object->rx); + + /* Set hardware flow control pins. */ + if (uart_object->hwfc == NRF_UART_HWFC_ENABLED) { + + /* Check if pin is set before configuring it. */ + if (uart_object->rts != NRF_UART_PSEL_DISCONNECTED) { + + nrf_gpio_cfg_output(uart_object->rts); + } + + /* Check if pin is set before configuring it. */ + if (uart_object->cts != NRF_UART_PSEL_DISCONNECTED) { + + nrf_gpio_cfg_input(uart_object->cts, NRF_GPIO_PIN_NOPULL); + } + + nrf_uarte_hwfc_pins_set(nordic_nrf5_uart_register[uart_object->instance], + uart_object->rts, + uart_object->cts); + } + + /* Enable flow control and parity. */ + nrf_uarte_configure(nordic_nrf5_uart_register[uart_object->instance], + uart_object->parity, + uart_object->hwfc); + + /* Set baudrate. */ + nrf_uarte_baudrate_set(nordic_nrf5_uart_register[uart_object->instance], + uart_object->baudrate); +} + +/** + * @brief Setup non-asynchronous reception. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_configure_rx(int instance) +{ + /* Disable interrupts during confiration. */ + nordic_nrf5_uart_register[instance]->INTEN &= ~(NRF_UARTE_INT_RXSTARTED_MASK | + NRF_UARTE_INT_ENDRX_MASK | + NRF_UARTE_INT_RXDRDY_MASK); + + /* Clear FIFO buffer. */ + nrf_atfifo_clear(nordic_nrf5_uart_state[instance].fifo); + + /* Clear Rx related events. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDRX); + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXDRDY); + + /* Enable shortcut between buffer full and begin reception on next buffer armed. */ + nrf_uarte_shorts_enable(nordic_nrf5_uart_register[instance], NRF_UARTE_SHORT_ENDRX_STARTRX); + + /* Reset bank flag. */ + nordic_nrf5_uart_state[instance].active_bank = 0; + + /* Arm first DMA buffer. */ + nrf_uarte_rx_buffer_set(nordic_nrf5_uart_register[instance], + nordic_nrf5_uart_state[instance].buffer[0], + DMA_BUFFER_SIZE); + + /* Set non-asynchronous mode. */ + nordic_nrf5_uart_state[instance].rx_asynch = false; + + /* Enable interrupts again. */ + nordic_nrf5_uart_register[instance]->INTEN |= (NRF_UARTE_INT_RXSTARTED_MASK | + NRF_UARTE_INT_ENDRX_MASK | + NRF_UARTE_INT_RXDRDY_MASK); +} + +#if DEVICE_SERIAL_ASYNCH +/** + * @brief Setup asynchronous reception. + * + * @param[in] instance The instance + */ +static void nordic_nrf5_uart_configure_rx_asynch(int instance) +{ + /* Disable Rx related interrupts. */ + nordic_nrf5_uart_register[instance]->INTEN &= ~(NRF_UARTE_INT_RXSTARTED_MASK | + NRF_UARTE_INT_ENDRX_MASK | + NRF_UARTE_INT_RXDRDY_MASK); + + /* Clear Rx related events. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDRX); + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_RXDRDY); + + /* Disable shortcut. Next Rx buffer must be manually started. */ + nrf_uarte_shorts_disable(nordic_nrf5_uart_register[instance], NRF_UARTE_SHORT_ENDRX_STARTRX); + + /* Set asynchronous mode. */ + nordic_nrf5_uart_state[instance].rx_asynch = true; + + /* Enable Rx interrupt. */ + nordic_nrf5_uart_register[instance]->INTEN |= NRF_UARTE_INT_ENDRX_MASK; +} +#endif + +/** + * @brief Main configuration function. + * + * @param obj The serial object + */ +static void nordic_nrf5_serial_configure(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Get object instance. */ + int instance = uart_object->instance; + + /* Only configure if instance owner has changed or an update is forced. */ + if ((uart_object != nordic_nrf5_uart_state[instance].owner) || (uart_object->update)) { + + /* Configure common setting. */ + nordic_nrf5_uart_configure_object(obj); + + /* Set new owner. */ + nordic_nrf5_uart_state[instance].owner = uart_object; + uart_object->update = false; + +#if DEVICE_SERIAL_ASYNCH + /* Set asynchronous mode. */ + if (uart_object->rx_asynch == true) { + + nordic_nrf5_uart_configure_rx_asynch(instance); + } else +#endif + { + /* Set non-asynchronous mode. */ + nordic_nrf5_uart_configure_rx(instance); + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STARTRX); + } + } +#if DEVICE_SERIAL_ASYNCH + /* Owner hasn't changed but mode has. Reconfigure. */ + else if ((uart_object->rx_asynch == false) && (nordic_nrf5_uart_state[instance].rx_asynch == true)) { + + nordic_nrf5_uart_configure_rx(instance); + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STARTRX); + + /* Owner hasn't changed but mode has. Reconfigure. */ + } else if ((uart_object->rx_asynch == true) && (nordic_nrf5_uart_state[instance].rx_asynch == false)) { + + nordic_nrf5_uart_configure_rx_asynch(instance); + } +#endif +} + +/*** + * __ __ _ _ _ _ _ _____ _____ + * | \/ | | | | | | | | /\ | | /\ | __ \_ _| + * | \ / | |__ ___ __| | | |__| | / \ | | / \ | |__) || | + * | |\/| | '_ \ / _ \/ _` | | __ | / /\ \ | | / /\ \ | ___/ | | + * | | | | |_) | __/ (_| | | | | |/ ____ \| |____ / ____ \| | _| |_ + * |_| |_|_.__/ \___|\__,_| |_| |_/_/ \_\______| /_/ \_\_| |_____| + * + * + */ + +/** Initialize the serial peripheral. It sets the default parameters for serial + * peripheral, and configures its specifieds pins. + * + * Param obj The serial object + * Param tx The TX pin name + * Param rx The RX pin name + */ +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Only initialize on first call. */ + static bool first_init = true; + if (first_init) { + first_init = false; + + /* Register RTC2 ISR. */ + NVIC_SetVector(RTC2_IRQn, (uint32_t) nordic_nrf5_rtc2_handler); + + /* Clear RTC2 channel events. */ + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_0); + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_1); + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_2); + nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_3); + + /* Enable interrupts for all four RTC2 channels. */ + nrf_rtc_event_enable(NRF_RTC2, + NRF_RTC_INT_COMPARE0_MASK | + NRF_RTC_INT_COMPARE1_MASK | + NRF_RTC_INT_COMPARE2_MASK | + NRF_RTC_INT_COMPARE3_MASK); + + /* Enable RTC2 IRQ. Priority is set to lowest so that the UARTE ISR can interrupt it. */ + nrf_drv_common_irq_enable(RTC2_IRQn, APP_IRQ_PRIORITY_LOWEST); + + /* Start RTC2. According to the datasheet the added power consumption is neglible so + * the RTC2 will run forever. + */ + nrf_rtc_task_trigger(NRF_RTC2, NRF_RTC_TASK_START); + + /* Initialize FIFO buffer for UARTE0. */ + NRF_ATFIFO_INIT(nordic_nrf5_uart_fifo_0); + nordic_nrf5_uart_state[0].fifo = nordic_nrf5_uart_fifo_0; + + /* Initialize owner to NULL. */ + nordic_nrf5_uart_state[0].owner = NULL; + + /* Enable interrupts for UARTE0. */ + NVIC_SetVector(UARTE0_UART0_IRQn, (uint32_t) nordic_nrf5_uart0_handler); + nordic_nrf5_uart_irq_enable(0); + +#if UART1_ENABLED + /* Initialize FIFO buffer for UARTE1. */ + NRF_ATFIFO_INIT(nordic_nrf5_uart_fifo_1); + nordic_nrf5_uart_state[1].fifo = nordic_nrf5_uart_fifo_1; + + /* Initialize owner to NULL. */ + nordic_nrf5_uart_state[1].owner = NULL; + + /* Enable interrupts for UARTE1. */ + NVIC_SetVector(UARTE1_IRQn, (uint32_t) nordic_nrf5_uart1_handler); + nordic_nrf5_uart_irq_enable(1); +#endif + } + + /* Get instance ID based on provided pins. */ + int instance = pin_instance_uart(tx, rx); + + uart_object->instance = instance; + + /* Increment usage counter for this instance. */ + nordic_nrf5_uart_state[instance].usage_counter++; + + /* Enable instance on first usage. */ + if (nordic_nrf5_uart_state[instance].usage_counter == 1) { + + nrf_uarte_enable(nordic_nrf5_uart_register[instance]); + } + + /* Store pins in serial object. */ + if (tx == NC) { + + uart_object->tx = NRF_UART_PSEL_DISCONNECTED; + } else { + + uart_object->tx = tx; + } + + if (rx == NC) { + + uart_object->rx = NRF_UART_PSEL_DISCONNECTED; + } else { + + uart_object->rx = rx; + } + + /* Set default parity and baud rate. */ + uart_object->parity = NRF_UART_PARITY_EXCLUDED; + uart_object->baudrate = NRF_UART_BAUDRATE_9600; + uart_object->cts = NRF_UART_PSEL_DISCONNECTED; + uart_object->rts = NRF_UART_PSEL_DISCONNECTED; + uart_object->hwfc = NRF_UART_HWFC_DISABLED; + + /* The STDIO object is stored in this file. Set the flag once initialized. */ + if (obj == &stdio_uart) { + stdio_uart_inited = 1; + } + + /* Initializing the serial object does not make it the owner of an instance. + * Only when the serial object is being used will the object take ownership + * over the instance. + */ + uart_object->update = true; + uart_object->handler = 0; +} + +/** Release the serial peripheral, not currently invoked. It requires further + * resource management. + * + * Param obj The serial object + */ +void serial_free(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + int instance = uart_object->instance; + + /* Only consider disabling UARTE if number of users is not zero. */ + if (nordic_nrf5_uart_state[instance].usage_counter > 0) { + + /* Decrement usage counter for this instance. */ + nordic_nrf5_uart_state[instance].usage_counter--; + + /* Disable instance when not in use. */ + if (nordic_nrf5_uart_state[instance].usage_counter == 0) { + + nrf_uarte_disable(nordic_nrf5_uart_register[instance]); + } + } +} + +/** Configure the baud rate + * + * Param obj The serial object + * Param baudrate The baud rate to be configured + */ +void serial_baud(serial_t *obj, int baudrate) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + nrf_uart_baudrate_t new_rate = NRF_UART_BAUDRATE_9600; + + /* Round down to nearest supported baud rate. */ + if (baudrate < 2400) { + new_rate = NRF_UARTE_BAUDRATE_1200; + } else if (baudrate < 4800) { + new_rate = NRF_UARTE_BAUDRATE_2400; + } else if (baudrate < 9600) { + new_rate = NRF_UARTE_BAUDRATE_4800; + } else if (baudrate < 14400) { + new_rate = NRF_UARTE_BAUDRATE_9600; + } else if (baudrate < 19200) { + new_rate = NRF_UARTE_BAUDRATE_14400; + } else if (baudrate < 28800) { + new_rate = NRF_UARTE_BAUDRATE_19200; + } else if (baudrate < 38400) { + new_rate = NRF_UARTE_BAUDRATE_28800; + } else if (baudrate < 57600) { + new_rate = NRF_UARTE_BAUDRATE_38400; + } else if (baudrate < 76800) { + new_rate = NRF_UARTE_BAUDRATE_57600; + } else if (baudrate < 115200) { + new_rate = NRF_UARTE_BAUDRATE_76800; + } else if (baudrate < 230400) { + new_rate = NRF_UARTE_BAUDRATE_115200; + } else if (baudrate < 250000) { + new_rate = NRF_UARTE_BAUDRATE_230400; + } else if (baudrate < 460800) { + new_rate = NRF_UARTE_BAUDRATE_250000; + } else if (baudrate < 921600) { + new_rate = NRF_UARTE_BAUDRATE_460800; + } else if (baudrate < 1000000) { + new_rate = NRF_UARTE_BAUDRATE_921600; + } else { + new_rate = NRF_UARTE_BAUDRATE_1000000; + } + + /* Force reconfiguration next time serial object is owner if baud rate has changed. */ + if (uart_object->baudrate != new_rate) { + + uart_object->baudrate = new_rate; + uart_object->update = true; + } +} + +/** Configure the format. Set the number of bits, parity and the number of stop bits + * + * Param obj The serial object + * Param data_bits The number of data bits + * Param parity The parity + * Param stop_bits The number of stop bits + */ +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) +{ + MBED_ASSERT(obj); + + /** + * Only 8-bit mode, None/Even parity, and 1 stop bit supported by hardware. + */ + MBED_ASSERT(data_bits == 8); + MBED_ASSERT((parity == ParityNone) || (parity == ParityEven)); + MBED_ASSERT(stop_bits == 1); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /** + * Only force change if parity has changed. + */ + if ((uart_object->parity != NRF_UART_PARITY_EXCLUDED) && (parity == ParityNone)) { + + uart_object->parity = NRF_UART_PARITY_EXCLUDED; + uart_object->update = true; + + } else if ((uart_object->parity != NRF_UART_PARITY_INCLUDED) && (parity == ParityEven)) { + + uart_object->parity = NRF_UART_PARITY_INCLUDED; + uart_object->update = true; + } +} + +/** Configure the serial for the flow control. It sets flow control in the hardware + * if a serial peripheral supports it, otherwise software emulation is used. + * + * Param obj The serial object + * Param type The type of the flow control. Look at the available FlowControl types. + * Param rxflow The TX pin name + * Param txflow The RX pin name + */ +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /** + * Convert Mbed pin names to Nordic pin names. + */ + uart_object->cts = ((txflow == NC) || (type == FlowControlRTS)) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t) txflow; + uart_object->rts = ((rxflow == NC) || (type == FlowControlCTS)) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t) rxflow; + uart_object->hwfc = (type == FlowControlNone) ? NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED; + + /* Force reconfiguration next time object is owner. */ + uart_object->update = true; +} + +/** Clear the serial peripheral + * + * Param obj The serial object + */ +void serial_clear(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /** + * Reconfigure UART. + */ + uart_object->update = true; + nordic_nrf5_uart_configure_object(obj); +} + +/** Set the break + * + * Param obj The serial object + */ +void serial_break_set(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Set Tx pin low. */ + nrf_gpio_pin_clear(uart_object->tx); +} + +/** Clear the break + * + * Param obj The serial object + */ +void serial_break_clear(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Set Tx pin high (default). */ + nrf_gpio_pin_set(uart_object->tx); +} + +/** Configure the TX pin for UART function. + * + * Param tx The pin name used for TX + */ +void serial_pinout_tx(PinName tx) +{ + /** + * Legacy API. Not used by Mbed. + */ + MBED_ASSERT(0); +} + +/*** + * _____ _ _ _____ _____ + * / ____(_) | | /\ | __ \_ _| + * | (___ _ _ __ ___ _ __ | | ___ / \ | |__) || | + * \___ \| | '_ ` _ \| '_ \| |/ _ \ / /\ \ | ___/ | | + * ____) | | | | | | | |_) | | __/ / ____ \| | _| |_ + * |_____/|_|_| |_| |_| .__/|_|\___| /_/ \_\_| |_____| + * | | + * |_| + */ + +/** The serial interrupt handler registration + * + * Param obj The serial object + * Param handler The interrupt handler which will be invoked when the interrupt fires + * Param id The SerialBase object + */ +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Store handler and ID in serial object. */ + uart_object->handler = (uint32_t) handler; + uart_object->context = id; +} + +/** Configure serial interrupt. This function is used for word-approach + * + * Param obj The serial object + * Param irq The serial IRQ type (RX or TX) + * Param enable Set to non-zero to enable events, or zero to disable them + */ +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + /* Convert Mbed type to Nordic IRQ mask. */ + uint32_t type = (irq == TxIrq) ? NORDIC_TX_IRQ : NORDIC_RX_IRQ; + + /* Enable/disable interrupt bit mask. */ + if (enable) { + + uart_object->mask |= type; + + } else { + + uart_object->mask &= ~type; + } + + /* Enable TXDRDY event. */ + if ((type == NORDIC_TX_IRQ) && enable) { + + /* Clear Tx ready event and enable Tx ready interrupts. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[uart_object->instance], NRF_UARTE_EVENT_TXDRDY); + nordic_nrf5_uart_register[uart_object->instance]->INTEN |= NRF_UARTE_INT_TXDRDY_MASK; + + /* Disable TXDRDY event. */ + } else if ((type == NORDIC_TX_IRQ) && !enable) { + + /* Disable Tx ready interrupts and clear Tx ready event. */ + nordic_nrf5_uart_register[uart_object->instance]->INTEN &= ~NRF_UARTE_INT_TXDRDY_MASK; + nrf_uarte_event_clear(nordic_nrf5_uart_register[uart_object->instance], NRF_UARTE_EVENT_TXDRDY); + } +} + +/** Get character. This is a blocking call, waiting for a character + * + * Param obj The serial object + */ +int serial_getc(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; + uart_object->rx_asynch = false; +#else + struct serial_s *uart_object = obj; +#endif + + int instance = uart_object->instance; + + /* Take ownership and configure UART if necessary. */ + nordic_nrf5_serial_configure(obj); + + /** + * Use head and tail pointer in FIFO to determine whether there is data available. + */ + nrf_atfifo_t *fifo = nordic_nrf5_uart_state[instance].fifo; + + volatile uint16_t *head = &fifo->head.pos.rd; + volatile uint16_t *tail = &fifo->tail.pos.rd; + + /* serial_getc is a blocking call. */ + while (*head == *tail); + + /* Get 1 byte from FIFO buffer. The buffer is atomic + * and doesn't need to be protected in a critical section. + */ + nrf_atfifo_item_get_t context; + uint8_t *byte = (uint8_t *) nrf_atfifo_item_get(fifo, &context); + nrf_atfifo_item_free(fifo, &context); + + return *byte; +} + +/** Send a character. This is a blocking call, waiting for a peripheral to be available + * for writing + * + * Param obj The serial object + * Param c The character to be sent + */ +void serial_putc(serial_t *obj, int character) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + int instance = uart_object->instance; + + /** + * tx_in_progress acts like a mutex to ensure only one transmission can be active at a time. + * The flag is modified using the atomic compare-and-set function. + */ + bool mutex = false; + + do { + uint8_t expected = 0; + uint8_t desired = 1; + + mutex = core_util_atomic_cas_u8((uint8_t *) &nordic_nrf5_uart_state[instance].tx_in_progress, &expected, desired); + } while (mutex == false); + + /* Take ownership and configure UART if necessary. */ + nordic_nrf5_serial_configure(obj); + + /** + * The UARTE module can generate two different Tx events: TXDRDY when each character has + * been transmitted and ENDTX when the entire buffer has been sent. + * + * For the blocking serial_putc, TXDRDY interrupts are enabled and only used for the + * single character TX IRQ callback handler. The ENDTX event does not generate an interrupt + * but is caught using a busy-wait loop. Once ENDTX has been generated we disable TXDRDY + * interrupts again. + */ + + /* Arm Tx DMA buffer. */ + nordic_nrf5_uart_state[instance].tx_data = character; + nrf_uarte_tx_buffer_set(nordic_nrf5_uart_register[instance], + &nordic_nrf5_uart_state[instance].tx_data, + 1); + + /* Clear TXDRDY event and enable TXDRDY interrupts. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXDRDY); + nordic_nrf5_uart_register[instance]->INTEN |= NRF_UARTE_INT_TXDRDY_MASK; + + /* Clear ENDTX event. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX); + + /* Trigger DMA transfer. */ + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STARTTX); + + /* Busy-wait until the ENDTX event occurs. */ + while (!nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX)); + + /* Disable TXDRDY event again. */ + nordic_nrf5_uart_register[instance]->INTEN &= ~NRF_UARTE_INT_TXDRDY_MASK; + + /* Release mutex. As the owner this call is safe. */ + nordic_nrf5_uart_state[instance].tx_in_progress = 0; +} + +/** Check if the serial peripheral is readable + * + * Param obj The serial object + * Return Non-zero value if a character can be read, 0 if nothing to read + */ +int serial_readable(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; + uart_object->rx_asynch = false; +#else + struct serial_s *uart_object = obj; +#endif + + int instance = uart_object->instance; + + /* Take ownership and configure UART if necessary. */ + nordic_nrf5_serial_configure(obj); + + /** + * Use head and tail pointer in FIFO to determine whether there is data available. + */ + nrf_atfifo_t *fifo = nordic_nrf5_uart_state[instance].fifo; + + return (fifo->head.pos.rd != fifo->tail.pos.rd); +} + +/** Check if the serial peripheral is writable + * + * Param obj The serial object + * Return Non-zero value if a character can be written, 0 otherwise. + */ +int serial_writable(serial_t *obj) +{ + MBED_ASSERT(obj); + +#if DEVICE_SERIAL_ASYNCH + struct serial_s *uart_object = &obj->serial; +#else + struct serial_s *uart_object = obj; +#endif + + int instance = uart_object->instance; + + return (nordic_nrf5_uart_state[instance].tx_in_progress == 0); +} + +/*** + * _ _____ _____ + * /\ | | /\ | __ \_ _| + * / \ ___ _ _ _ __ ___| |__ _ __ ___ _ __ ___ _ _ ___ / \ | |__) || | + * / /\ \ / __| | | | '_ \ / __| '_ \| '__/ _ \| '_ \ / _ \| | | / __| / /\ \ | ___/ | | + * / ____ \\__ \ |_| | | | | (__| | | | | | (_) | | | | (_) | |_| \__ \ / ____ \| | _| |_ + * /_/ \_\___/\__, |_| |_|\___|_| |_|_| \___/|_| |_|\___/ \__,_|___/ /_/ \_\_| |_____| + * __/ | + * |___/ + */ + +#if DEVICE_SERIAL_ASYNCH + +/** Begin asynchronous TX transfer. The used buffer is specified in the serial object, + * tx_buff + * + * Param obj The serial object + * Param tx The transmit buffer + * Param tx_length The number of bytes to transmit + * Param tx_width Deprecated argument + * Param handler The serial handler + * Param event The logical OR of events to be registered + * Param hint A suggestion for how to use DMA with this transfer + * Return Returns number of data transfered, otherwise returns 0 + */ +int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t mask, DMAUsage hint) +{ + MBED_ASSERT(obj); + MBED_ASSERT(tx_width == 8); + MBED_ASSERT(tx_length < 256); + + int instance = obj->serial.instance; + + /** + * tx_in_progress acts like a mutex to ensure only one transmission can be active at a time. + * The flag is modified using the atomic compare-and-set function. + */ + bool mutex = false; + + do { + uint8_t expected = 0; + uint8_t desired = 1; + + mutex = core_util_atomic_cas_u8((uint8_t *) &nordic_nrf5_uart_state[instance].tx_in_progress, &expected, desired); + } while (mutex == false); + + /* State variables. */ + int result = 0; + bool valid = false; + + /** + * EasyDMA can only access RAM. Check if provided buffer is in RAM or flash. + * If the buffer is in flash, check if the FIFO buffer is large enough to store + * the Tx data. + */ + if (instance == 0) { + + if (nrf_drv_is_in_RAM(tx) || (tx_length <= UART0_FIFO_BUFFER_SIZE)) { + valid = true; + } + } +#if UART1_ENABLED + else { + if (nrf_drv_is_in_RAM(tx) || (tx_length <= UART1_FIFO_BUFFER_SIZE)) { + valid = true; + } + } +#endif + + if (valid) { + + /* Setup buffers for transfer. */ + uint8_t *buffer = NULL; + + /* Tx buffer is in RAM. */ + if (nrf_drv_is_in_RAM(tx)) { + + buffer = (uint8_t *) tx; + } else { + + /** + * Tx buffer is in flash. Copy Tx buffer to FIFO buffer. + * NOTE: this prevents simultaneous Rx using non-asynchronous API. + */ + const uint8_t *pointer = (const uint8_t *) tx; + + for (size_t index = 0; index < tx_length; index++) { + nordic_nrf5_uart_fifo_0_data[index] = pointer[index]; + } + + buffer = (uint8_t *) nordic_nrf5_uart_fifo_0_data; + } + + /* Store callback handler, mask and reset event value. */ + obj->serial.tx_handler = handler; + obj->serial.tx_mask = mask; + obj->serial.tx_event = 0; + + /* Enable asynchronous mode and configure UART. */ + nordic_nrf5_uart_state[instance].tx_asynch = true; + nordic_nrf5_serial_configure(obj); + + /** + * The UARTE module can generate two different Tx events: TXDRDY when each + * character has been transmitted and ENDTX when the entire buffer has been sent. + * + * For the async serial_tx_async, TXDRDY interrupts are disabled completely. ENDTX + * interrupts are enabled and used to signal the completion of the async transfer. + * + * The ENDTX interrupt is diabled immediately after it is fired in the ISR. + */ + + /* Clear Tx event and enable Tx interrupts. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX); + nordic_nrf5_uart_register[instance]->INTEN |= NRF_UARTE_INT_ENDTX_MASK; + + /* Set Tx DMA buffer. */ + nrf_uarte_tx_buffer_set(nordic_nrf5_uart_register[obj->serial.instance], + buffer, + tx_length); + + /* Trigger DMA transfer. */ + nrf_uarte_task_trigger(nordic_nrf5_uart_register[obj->serial.instance], + NRF_UARTE_TASK_STARTTX); + + /* Setup complete, return length as sign of success. */ + result = tx_length; + + } else { + + /* Signal error if event mask matches and event handler is set. */ + if ((mask & SERIAL_EVENT_ERROR) && handler) { + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) handler; + + /* Store event value so it can be read back. */ + obj->serial.event = SERIAL_EVENT_ERROR; + + /* Signal callback handler. */ + callback(); + } + } + + return result; +} + +/** Begin asynchronous RX transfer (enable interrupt for data collecting) + * The used buffer is specified in the serial object - rx_buff + * + * Param obj The serial object + * Param rx The receive buffer + * Param rx_length The number of bytes to receive + * Param rx_width Deprecated argument + * Param handler The serial handler + * Param event The logical OR of events to be registered + * Param handler The serial handler + * Param char_match A character in range 0-254 to be matched + * Param hint A suggestion for how to use DMA with this transfer + */ +void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t mask, uint8_t char_match, DMAUsage hint) +{ + MBED_ASSERT(obj); + MBED_ASSERT(rx_width == 8); + MBED_ASSERT(rx_length < 256); + MBED_ASSERT(char_match == SERIAL_RESERVED_CHAR_MATCH); + + int instance = obj->serial.instance; + + /** + * rx_in_progress acts like a mutex to ensure only one asynchronous reception can be active at a time. + * The flag is modified using the atomic compare-and-set function. + */ + bool mutex = false; + + do { + uint8_t expected = 0; + uint8_t desired = 1; + + mutex = core_util_atomic_cas_u8((uint8_t *) &nordic_nrf5_uart_state[instance].rx_in_progress, &expected, desired); + } while (mutex == false); + + /* Store callback handler, mask and reset event value. */ + obj->serial.rx_handler = handler; + obj->serial.rx_mask = mask; + obj->serial.rx_event = 0; + + /* Enable asynchronous mode and configure UART. */ + obj->serial.rx_asynch = true; + nordic_nrf5_serial_configure(obj); + + /* Set Rx DMA buffer. */ + nrf_uarte_rx_buffer_set(nordic_nrf5_uart_register[instance], + (uint8_t *) rx, + rx_length); + + /* Enable reception. */ + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STARTRX); + +} + +/** Attempts to determine if the serial peripheral is already in use for TX + * + * Param obj The serial object + * Return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_tx_active(serial_t *obj) +{ + MBED_ASSERT(obj); + + return nordic_nrf5_uart_state[obj->serial.instance].tx_asynch; +} + +/** Attempts to determine if the serial peripheral is already in use for RX + * + * Param obj The serial object + * Return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_rx_active(serial_t *obj) +{ + MBED_ASSERT(obj); + + return nordic_nrf5_uart_state[obj->serial.instance].rx_asynch; +} + +/** The asynchronous TX and RX handler. + * + * Param obj The serial object + * Return Returns event flags if an RX transfer termination condition was met; otherwise returns 0 + */ +int serial_irq_handler_asynch(serial_t *obj) +{ + MBED_ASSERT(obj); + + return (obj->serial.tx_event | obj->serial.rx_event); +} + +/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and + * flushes the TX hardware buffer if TX FIFO is used + * + * Param obj The serial object + */ +void serial_tx_abort_asynch(serial_t *obj) +{ + MBED_ASSERT(obj); + + /* Transmission might be in progress. Disable interrupts to prevent ISR from firing. */ + core_util_critical_section_enter(); + + int instance = obj->serial.instance; + + /* Disable ENDTX interrupts. */ + nordic_nrf5_uart_register[instance]->INTEN &= ~NRF_UARTE_INT_ENDTX_MASK; + + /* Clear ENDTX event. */ + nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_ENDTX); + + /* Reset Tx flags. */ + nordic_nrf5_uart_state[instance].tx_in_progress = 0; + nordic_nrf5_uart_state[instance].tx_asynch = false; + + /* Force reconfiguration. */ + obj->serial.update = true; + nordic_nrf5_serial_configure(obj); + + /* Trigger STOP task. */ + nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], + NRF_UARTE_TASK_STOPTX); + + /* Enable interrupts again. */ + core_util_critical_section_exit(); +} + +/** Abort the ongoing RX transaction. It disables the enabled interrupt for RX and + * flushes the RX hardware buffer if RX FIFO is used + * + * Param obj The serial object + */ +void serial_rx_abort_asynch(serial_t *obj) +{ + MBED_ASSERT(obj); + + /* Transmission might be in progress. Disable interrupts to prevent ISR from firing. */ + core_util_critical_section_enter(); + + /* Reset Rx flags. */ + nordic_nrf5_uart_state[obj->serial.instance].rx_in_progress = 0; + nordic_nrf5_uart_state[obj->serial.instance].rx_asynch = false; + obj->serial.rx_asynch = false; + + /* Force reconfiguration. */ + obj->serial.update = true; + nordic_nrf5_serial_configure(obj); + + /* Enable interrupts again. */ + core_util_critical_section_exit(); +} + +#endif // DEVICE_SERIAL_ASYNCH + +#endif // DEVICE_SERIAL diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5x/sleep.c new file mode 100644 index 0000000000..f7ec7911a6 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/sleep.c @@ -0,0 +1,88 @@ +/* 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 "sleep_api.h" +#include "cmsis.h" +#include "mbed_interface.h" +#include "nrf_soc.h" + +#if defined(SOFTDEVICE_PRESENT) +#include "nrf_sdh.h" +#define NRF_HAL_SLEEP_SD_IS_ENABLED() nrf_sdh_is_enabled() +#else +#define NRF_HAL_SLEEP_SD_IS_ENABLED() 0 +#endif + +// Mask of reserved bits of the register ICSR in the System Control Block peripheral +// In this case, bits which are equal to 0 are the bits reserved in this register +#define SCB_ICSR_RESERVED_BITS_MASK 0x9E43F03F + +#define FPU_EXCEPTION_MASK 0x0000009F + +void hal_sleep(void) +{ + // ensure debug is disconnected if semihost is enabled.... + + // Trigger an event when an interrupt is pending. This allows to wake up + // the processor from disabled interrupts. + SCB->SCR |= SCB_SCR_SEVONPEND_Msk; + +#if defined(NRF52) || defined(NRF52840_XXAA) + /* Clear exceptions and PendingIRQ from the FPU unit */ + __set_FPSCR(__get_FPSCR() & ~(FPU_EXCEPTION_MASK)); + (void) __get_FPSCR(); + NVIC_ClearPendingIRQ(FPU_IRQn); +#endif + + // If the SoftDevice is enabled, its API must be used to go to sleep. + if (NRF_HAL_SLEEP_SD_IS_ENABLED()) { +#if defined(SOFTDEVICE_PRESENT) + sd_power_mode_set(NRF_POWER_MODE_LOWPWR); + sd_app_evt_wait(); +#endif + } else { + NRF_POWER->TASKS_LOWPWR = 1; + + // Note: it is not sufficient to just use WFE here, since the internal + // event register may be already set from an event that occurred in the + // past (like an SVC call to the SoftDevice) and in such case WFE will + // just clear the register and continue execution. + // Therefore, the strategy here is to first clear the event register + // by using SEV/WFE pair, and then execute WFE again, unless there is + // a pending interrupt. + + // Set an event and wake up whatsoever, this will clear the event + // register from all previous events set (SVC call included) + __SEV(); + __WFE(); + + // Test if there is an interrupt pending (mask reserved regions) + if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { + // Ok, there is an interrut pending, no need to go to sleep + return; + } else { + // next event will wakeup the CPU + // If an interrupt occured between the test of SCB->ICSR and this + // instruction, WFE will just not put the CPU to sleep + __WFE(); + } + } +} + +void hal_deepsleep(void) +{ + hal_sleep(); + // NRF_POWER->SYSTEMOFF=1; +} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/spi_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/spi_api.c new file mode 100644 index 0000000000..2dffd0d294 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/spi_api.c @@ -0,0 +1,729 @@ +/* + * 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. + * + */ + +#if DEVICE_SPI + +#include "hal/spi_api.h" + +#include "object_owners.h" +#include "pinmap_ex.h" + +#include "nrf_drv_spi.h" + +/* Pre-allocate instances and share them globally. */ +static const nrf_drv_spi_t nordic_nrf5_spi_instance[3] = { + NRF_DRV_SPI_INSTANCE(0), + NRF_DRV_SPI_INSTANCE(1), + NRF_DRV_SPI_INSTANCE(2) +}; + +/* Forware declare interrupt handler. */ +#if DEVICE_SPI_ASYNCH +static void nordic_nrf5_spi_event_handler(nrf_drv_spi_evt_t const *p_event, void *p_context); +#endif + +/* Forward declaration. These functions are implemented in the driver but not + * set up in the NVIC due to it being relocated. + */ +void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void); +void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void); +void SPIM2_SPIS2_SPI2_IRQHandler(void); + +/** + * Brief Reconfigure peripheral. + * + * If the peripheral has changed ownership clear old configuration and + * re-initialize the peripheral with the new settings. + * + * Parameter obj The object + * Parameter handler Optional callback handler. + * Parameter force_change Force change regardless of ownership. + */ +static void spi_configure_driver_instance(spi_t *obj) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + int instance = spi_inst->instance; + + /* Get pointer to object of the current owner of the peripheral. */ + void *current_owner = object_owner_spi2c_get(instance); + + /* Check if reconfiguration is actually necessary. */ + if ((obj != current_owner) || spi_inst->update) { + + /* Update applied, reset flag. */ + spi_inst->update = false; + + /* clean up and initialize peripheral. */ + nrf_drv_spi_uninit(&nordic_nrf5_spi_instance[instance]); + +#if DEVICE_SPI_ASYNCH + /* Set callback handler in asynchronous mode. */ + if (spi_inst->handler) { + nrf_drv_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), nordic_nrf5_spi_event_handler, obj); + } else { + nrf_drv_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), NULL, NULL); + } +#else + /* Set callback handler to NULL in synchronous mode. */ + nrf_drv_spi_init(&nordic_nrf5_spi_instance[instance], &(spi_inst->config), NULL, NULL); +#endif + /* Claim ownership of peripheral. */ + object_owner_spi2c_set(instance, obj); + } +} + +/** Initialize the SPI peripheral + * + * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral + * Parameter obj The SPI object to initialize + * Parameter mosi The pin to use for MOSI + * Parameter miso The pin to use for MISO + * Parameter sclk The pin to use for SCLK + * Parameter ssel The pin to use for SSEL + */ +void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + /* Get instance based on requested pins. */ + spi_inst->instance = pin_instance_spi(mosi, miso, sclk); + MBED_ASSERT(spi_inst->instance < ENABLED_SPI_COUNT); + + /* Store chip select separately for manual enabling. */ + spi_inst->cs = ssel; + + /* Store pins except chip select. */ + spi_inst->config.sck_pin = sclk; + spi_inst->config.mosi_pin = mosi; + spi_inst->config.miso_pin = miso; + spi_inst->config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; + + /* Use the default config. */ + spi_inst->config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY; + spi_inst->config.orc = SPI_FILL_CHAR; + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_1M; + spi_inst->config.mode = NRF_DRV_SPI_MODE_0; + spi_inst->config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST; + +#if DEVICE_SPI_ASYNCH + /* Set default values for asynchronous variables. */ + spi_inst->handler = 0; + spi_inst->mask = 0; + spi_inst->event = 0; +#endif + + /* Configuration has changed, set flag to force update. */ + spi_inst->update = true; + + /* Configure GPIO pin if chip select has been set. */ + if (ssel != NC) { + nrf_gpio_pin_set(ssel); + nrf_gpio_cfg_output(ssel); + } + + static bool first_init = true; + + if (first_init) { + first_init = false; + + /* Register interrupt handlers in driver with the NVIC. */ + NVIC_SetVector(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, (uint32_t) SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler); + NVIC_SetVector(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, (uint32_t) SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler); + NVIC_SetVector(SPIM2_SPIS2_SPI2_IRQn, (uint32_t) SPIM2_SPIS2_SPI2_IRQHandler); + } +} + +/** Release a SPI object + * + * TODO: spi_free is currently unimplemented + * This will require reference counting at the C++ level to be safe + * + * Return the pins owned by the SPI object to their reset state + * Disable the SPI peripheral + * Disable the SPI clock + * Parameter obj The SPI object to deinitialize + */ +void spi_free(spi_t *obj) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + int instance = spi_inst->instance; + + /* Use driver uninit to free instance. */ + nrf_drv_spi_uninit(&nordic_nrf5_spi_instance[instance]); +} + +/** Configure the SPI format + * + * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode. + * The default bit order is MSB. + * Parameter obj The SPI object to configure + * Parameter bits The number of bits per frame + * Parameter mode The SPI mode (clock polarity, phase, and shift direction) + * Parameter slave Zero for master mode or non-zero for slave mode + */ +void spi_format(spi_t *obj, int bits, int mode, int slave) +{ + /* SPI module only supports 8 bit transfers. */ + MBED_ASSERT(bits == 8); + /* SPI module doesn't support Mbed HAL Slave API. */ + MBED_ASSERT(slave == 0); + +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + /* Convert Mbed HAL mode to Nordic mode. */ + if(mode == 0) { + spi_inst->config.mode = NRF_DRV_SPI_MODE_0; + } else if(mode == 1) { + spi_inst->config.mode = NRF_DRV_SPI_MODE_1; + } else if(mode == 2) { + spi_inst->config.mode = NRF_DRV_SPI_MODE_2; + } else if(mode == 3) { + spi_inst->config.mode = NRF_DRV_SPI_MODE_3; + } + + /* Configuration has changed, set flag to force application. */ + spi_inst->update = true; +} + +/** Set the SPI baud rate + * + * Actual frequency may differ from the desired frequency due to available dividers and bus clock + * Configures the SPI peripheral's baud rate + * Parameter obj The SPI object to configure + * Parameter hz The baud rate in Hz + */ +void spi_frequency(spi_t *obj, int hz) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + /* Convert frequency to Nordic enum type. */ + if (hz < 250000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_125K; + } else if (hz < 500000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_250K; + } else if (hz < 1000000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_500K; + } else if (hz < 2000000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_1M; + } else if (hz < 4000000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_2M; + } else if (hz < 8000000) { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_4M; + } else { + spi_inst->config.frequency = NRF_DRV_SPI_FREQ_8M; + } + + /* Configuration has changed, set flag to force application. */ + spi_inst->update = true; +} + +/** Write a byte out in master mode and receive a value + * + * Parameter obj The SPI peripheral to use for sending + * Parameter value The value to send + * Return Returns the value received during send + */ +int spi_master_write(spi_t *obj, int value) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + int instance = spi_inst->instance; + + /* Manually clear chip select pin if defined. */ + if (spi_inst->cs != NC) { + nrf_gpio_pin_clear(spi_inst->cs); + } + + /* Local variables used in transfer. */ + const uint8_t tx_buff = (uint8_t) value; + uint8_t rx_buff; + + /* Configure peripheral if necessary. */ + spi_configure_driver_instance(obj); + + /* Transfer 1 byte. */ + nrf_drv_spi_transfer(&nordic_nrf5_spi_instance[instance], &tx_buff, 1, &rx_buff, 1); + + /* Manually set chip select pin if defined. */ + if (spi_inst->cs != NC) { + nrf_gpio_pin_set(spi_inst->cs); + } + + return rx_buff; +} + +/** Write a block out in master mode and receive a value + * + * The total number of bytes sent and recieved will be the maximum of + * tx_length and rx_length. The bytes written will be padded with the + * value 0xff. + * + * Parameter obj The SPI peripheral to use for sending + * Parameter tx_buffer Pointer to the byte-array of data to write to the device + * Parameter tx_length Number of bytes to write, may be zero + * Parameter rx_buffer Pointer to the byte-array of data to read from the device + * Parameter rx_length Number of bytes to read, may be zero + * Parameter write_fill Default data transmitted while performing a read + * @returns + * The number of bytes written and read from the device. This is + * maximum of tx_length and rx_length. + */ +int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + int instance = spi_inst->instance; + + /* Check if overflow character has changed. */ + if (spi_inst->config.orc != write_fill) { + + /* Store new overflow character and force reconfiguration. */ + spi_inst->update = true; + spi_inst->config.orc = write_fill; + } + + /* Configure peripheral if necessary. */ + spi_configure_driver_instance(obj); + + /* Manually clear chip select pin if defined. */ + if (spi_inst->cs != NC) { + nrf_gpio_pin_clear(spi_inst->cs); + } + + /* The Nordic SPI driver is only able to transfer 255 bytes at a time. + * The following code will write/read the data 255 bytes at a time and + * ensure that asymmetrical transfers are handled properly. + */ + int tx_offset = 0; + int rx_offset = 0; + + ret_code_t result = NRF_SUCCESS; + + /* Loop until all data is sent and received. */ + while (((tx_length > 0) || (rx_length > 0)) && (result == NRF_SUCCESS)) { + + /* Check if tx_length is larger than 255 and if so, limit to 255. */ + int tx_actual_length = (tx_length > 255) ? 255 : tx_length; + + /* Set tx buffer pointer. Set to NULL if no data is going to be transmitted. */ + const uint8_t * tx_actual_buffer = (tx_actual_length > 0) ? + (const uint8_t *)(tx_buffer + tx_offset) : + NULL; + + /* Check if rx_length is larger than 255 and if so, limit to 255. */ + int rx_actual_length = (rx_length > 255) ? 255 : rx_length; + + /* Set rx buffer pointer. Set to NULL if no data is going to be received. */ + uint8_t * rx_actual_buffer = (rx_actual_length > 0) ? + (uint8_t *)(rx_buffer + rx_offset) : + NULL; + + /* Blocking transfer. */ + result = nrf_drv_spi_transfer(&nordic_nrf5_spi_instance[instance], + tx_actual_buffer, + tx_actual_length, + rx_actual_buffer, + rx_actual_length); + + /* Update loop variables. */ + tx_length -= tx_actual_length; + tx_offset += tx_actual_length; + + rx_length -= rx_actual_length; + rx_offset += rx_actual_length; + } + + /* Manually set chip select pin if defined. */ + if (spi_inst->cs != NC) { + nrf_gpio_pin_set(spi_inst->cs); + } + + return (rx_offset < tx_offset) ? tx_offset : rx_offset; +} + +/** Checks if the specified SPI peripheral is in use + * + * Parameter obj The SPI peripheral to check + * Return non-zero if the peripheral is currently transmitting + */ +int spi_busy(spi_t *obj) +{ + /* Legacy API call. Always return zero. */ + return 0; +} + +/** Get the module number + * + * Parameter obj The SPI peripheral to check + * Return The module number + */ +uint8_t spi_get_module(spi_t *obj) +{ +#if DEVICE_SPI_ASYNCH + struct spi_s *spi_inst = &obj->spi; +#else + struct spi_s *spi_inst = obj; +#endif + + return spi_inst->instance; +} + +#if DEVICE_SPISLAVE + +/** Check if a value is available to read + * + * Parameter obj The SPI peripheral to check + * Return non-zero if a value is available + */ +int spi_slave_receive(spi_t *obj) +{ + return 0; +} + +/** Get a received value out of the SPI receive buffer in slave mode + * + * Blocks until a value is available + * Parameter obj The SPI peripheral to read + * Return The value received + */ +int spi_slave_read(spi_t *obj) +{ + return 0; +} + +/** Write a value to the SPI peripheral in slave mode + * + * Blocks until the SPI peripheral can be written to + * Parameter obj The SPI peripheral to write + * Parameter value The value to write + */ +void spi_slave_write(spi_t *obj, int value) +{ + return; +} + +#endif + +#if DEVICE_SPI_ASYNCH + +/*** + * _____ _____ + * /\ /\ | __ \_ _| + * / \ ___ _ _ _ __ ___ / \ | |__) || | + * / /\ \ / __| | | | '_ \ / __| / /\ \ | ___/ | | + * / ____ \\__ \ |_| | | | | (__ / ____ \| | _| |_ + * /_/ \_\___/\__, |_| |_|\___| /_/ \_\_| |_____| + * __/ | + * |___/ + */ + +static ret_code_t spi_master_transfer_async_continue(spi_t *obj) +{ + /* Remaining data to be transferred. */ + size_t tx_length = obj->tx_buff.length - obj->tx_buff.pos; + size_t rx_length = obj->rx_buff.length - obj->rx_buff.pos; + + /* Cap TX length to 255 bytes. */ + if (tx_length > 255) { + tx_length = 255; + } + + /* Cap RX length to 255 bytes. */ + if (rx_length > 255) { + rx_length = 255; + } + + ret_code_t result = nrf_drv_spi_transfer(&nordic_nrf5_spi_instance[obj->spi.instance], + ((const uint8_t *)(obj->tx_buff.buffer) + obj->tx_buff.pos), + tx_length, + ((uint8_t *)(obj->rx_buff.buffer) + obj->rx_buff.pos), + rx_length); + + return result; +} + +/* Callback function for driver calls. This is called from ISR context. */ +static void nordic_nrf5_spi_event_handler(nrf_drv_spi_evt_t const *p_event, void *p_context) +{ + // Only safe to use with mbed-printf. + //DEBUG_PRINTF("nordic_nrf5_twi_event_handler: %d %p\r\n", p_event->type, p_context); + + bool signal_complete = false; + bool signal_error = false; + + spi_t *obj = (spi_t *) p_context; + struct spi_s *spi_inst = &obj->spi; + + if (p_event->type == NRF_DRV_SPI_EVENT_DONE) { + + /* Update buffers with new positions. */ + obj->tx_buff.pos += p_event->data.done.tx_length; + obj->rx_buff.pos += p_event->data.done.rx_length; + + /* Setup a new transfer if more data is pending. */ + if ((obj->tx_buff.pos < obj->tx_buff.length) || (obj->rx_buff.pos < obj->tx_buff.length)) { + + /* Initiate SPI transfer. */ + ret_code_t result = spi_master_transfer_async_continue(obj); + + /* Abort if transfer wasn't accepted. */ + if (result != NRF_SUCCESS) { + + /* Signal callback handler that transfer failed. */ + signal_error = true; + } + + } else { + + /* Signal callback handler that transfer is complete. */ + signal_complete = true; + } + } else { + + /* Unexpected event, signal callback handler that transfer failed. */ + signal_error = true; + } + + /* Transfer complete, signal success if mask is set.*/ + if (signal_complete) { + + /* Signal success if event mask matches and event handler is set. */ + if ((spi_inst->mask & SPI_EVENT_COMPLETE) && spi_inst->handler) { + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) spi_inst->handler; + + /* Reset object. */ + spi_inst->handler = 0; + spi_inst->update = true; + + /* Store event value so it can be read back. */ + spi_inst->event = SPI_EVENT_COMPLETE; + + /* Signal callback handler. */ + callback(); + } + + /* Transfer failed, signal error if mask is set. */ + } else if (signal_error) { + + /* Signal error if event mask matches and event handler is set. */ + if ((spi_inst->mask & SPI_EVENT_ERROR) && spi_inst->handler) { + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) spi_inst->handler; + + /* Reset object. */ + spi_inst->handler = 0; + spi_inst->update = true; + + /* Store event value so it can be read back. */ + spi_inst->event = SPI_EVENT_ERROR; + + /* Signal callback handler. */ + callback(); + } + } + + /* Transfer completed one way or another. Set chip select manually if defined. */ + if (signal_complete || signal_error) { + + if (spi_inst->cs != NC) { + nrf_gpio_pin_set(spi_inst->cs); + } + } +} + +/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff + * + * Parameter obj The SPI object that holds the transfer information + * Parameter tx The transmit buffer + * Parameter tx_length The number of bytes to transmit + * Parameter rx The receive buffer + * Parameter rx_length The number of bytes to receive + * Parameter bit_width The bit width of buffer words + * Parameter event The logical OR of events to be registered + * Parameter handler SPI interrupt handler + * Parameter hint A suggestion for how to use DMA with this transfer + */ +void spi_master_transfer(spi_t *obj, + const void *tx, + size_t tx_length, + void *rx, + size_t rx_length, + uint8_t bit_width, + uint32_t handler, + uint32_t mask, + DMAUsage hint) +{ + /* SPI peripheral only supports 8 bit transfers. */ + MBED_ASSERT(bit_width == 8); + + /* Setup buffers for transfer. */ + struct buffer_s *buffer_pointer; + + buffer_pointer = &obj->tx_buff; + buffer_pointer->buffer = (void*) tx; + buffer_pointer->length = tx_length; + buffer_pointer->pos = 0; + buffer_pointer->width = 8; + + buffer_pointer = &obj->rx_buff; + buffer_pointer->buffer = rx; + buffer_pointer->length = rx_length; + buffer_pointer->pos = 0; + buffer_pointer->width = 8; + + /* Save event handler and event mask so they can be called from interrupt handler. */ + struct spi_s *spi_inst = &obj->spi; + spi_inst->handler = handler; + spi_inst->mask = mask; + + /* Clear event flag. */ + spi_inst->event = 0; + + /* Force reconfiguration. */ + spi_inst->update = true; + + /* Configure peripheral if necessary. */ + spi_configure_driver_instance(obj); + + /* Manually clear chip select pin if defined. */ + if (spi_inst->cs != NC) { + nrf_gpio_pin_clear(spi_inst->cs); + } + + /* Initiate SPI transfer. */ + ret_code_t result = spi_master_transfer_async_continue(obj); + + /* Signal error if event mask matches and event handler is set. */ + if ((result != NRF_SUCCESS) && (mask & SPI_EVENT_ERROR) && handler) { + + /* Cast handler to callback function pointer. */ + void (*callback)(void) = (void (*)(void)) handler; + + /* Reset object. */ + spi_inst->handler = 0; + spi_inst->update = true; + + /* Store event value so it can be read back. */ + spi_inst->event = SPI_EVENT_ERROR; + + /* Signal callback handler. */ + callback(); + } +} + +/** The asynchronous IRQ handler + * + * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination + * conditions, such as buffer overflows or transfer complete. + * Parameter obj The SPI object that holds the transfer information + * Return Event flags if a transfer termination condition was met; otherwise 0. + */ +uint32_t spi_irq_handler_asynch(spi_t *obj) +{ + /* Return latest event. */ + return obj->spi.event; +} + +/** Attempts to determine if the SPI peripheral is already in use + * + * If a temporary DMA channel has been allocated, peripheral is in use. + * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA + * channel were allocated. + * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check + * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if + * there are any bytes in the FIFOs. + * Parameter obj The SPI object to check for activity + * Return Non-zero if the SPI port is active or zero if it is not. + */ +uint8_t spi_active(spi_t *obj) +{ + /* Callback handler is non-zero when a transfer is in progress. */ + return (obj->spi.handler != 0); +} + +/** Abort an SPI transfer + * + * Parameter obj The SPI peripheral to stop + */ +void spi_abort_asynch(spi_t *obj) +{ + int instance = obj->spi.instance; + + /* Abort transfer. */ + nrf_drv_spi_abort(&nordic_nrf5_spi_instance[instance]); + + /* Force reconfiguration. */ + object_owner_spi2c_set(instance, NULL); +} + +#endif // DEVICE_SPI_ASYNCH + +#endif // DEVICE_SPI diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/trng_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/trng_api.c new file mode 100644 index 0000000000..747ac6aabf --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/trng_api.c @@ -0,0 +1,123 @@ +/* + * 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. + * + */ + +#if defined(DEVICE_TRNG) + +#include "hal/trng_api.h" +#include "hal/critical_section_api.h" + +#include "nrf_drv_rng.h" + +/* Keep track of instantiated FlashIAP objects. */ +static int nordic_trng_counter = 0; + +void trng_init(trng_t *obj) +{ + MBED_ASSERT(obj); + + /* Increment global counter. */ + nordic_trng_counter++; + + /* Initialize TRNG on first object only. */ + if (nordic_trng_counter == 1) { + nrf_drv_rng_init(NULL); + } +} + +void trng_free(trng_t *obj) +{ + MBED_ASSERT(obj); + + /* Decrement global counter. */ + nordic_trng_counter--; + + /* Deinitialize TRNG when all objects have been freed. */ + if (nordic_trng_counter == 0) { + nrf_drv_rng_uninit(); + } +} + +/* Get random data from NRF5x TRNG peripheral. + * + * This implementation returns num of random bytes in range <1, length>. + * For parameters description see trng_api.h file. + */ +int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) +{ + MBED_ASSERT(obj); + MBED_ASSERT(output); + MBED_ASSERT(output_length); + + int result = 0; + + /* Return immediately if requested length is zero. */ + if (length != 0) { + + /* Query how many bytes are available. */ + uint8_t bytes_available; + nrf_drv_rng_bytes_available(&bytes_available); + + /* If no bytes are cached, block until at least 1 byte is available. */ + if (bytes_available == 0) { + nrf_drv_rng_block_rand(output, 1); + *output_length = 1; + } else { + + /* Get up to the requested number of bytes. */ + if (bytes_available > length) { + bytes_available = length; + } + + ret_code_t result = nrf_drv_rng_rand(output, bytes_available); + + /* Set output length with available bytes. */ + if (result == NRF_SUCCESS) { + *output_length = bytes_available; + } else { + *output_length = 0; + } + } + + /* Set return value based on how many bytes were read. */ + result = (*output_length == 0) ? -1 : 0; + } + + return result; +} + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/us_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/us_ticker.c new file mode 100644 index 0000000000..a939606297 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/us_ticker.c @@ -0,0 +1,334 @@ +/* + * 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 "us_ticker_api.h" +#include "common_rtc.h" +#include "app_util.h" +#include "nrf_drv_common.h" +#include "lp_ticker_api.h" +#include "mbed_critical.h" + +#if defined(NRF52_ERRATA_20) +#if defined(SOFTDEVICE_PRESENT) +#include "nrf_sdh.h" +#define NRF_HAL_US_TICKER_SD_IS_ENABLED() nrf_sdh_is_enabled() +#else +#define NRF_HAL_US_TICKER_SD_IS_ENABLED() 0 +#endif +#endif + +//------------------------------------------------------------------------------ +// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). +// +#include "app_util_platform.h" + +bool m_common_rtc_enabled = false; +uint32_t volatile m_common_rtc_overflows = 0; + +// lp/us ticker fire interrupt flag for IRQ handler +volatile uint8_t m_common_sw_irq_flag = 0; + +__STATIC_INLINE void rtc_ovf_event_check(void) +{ + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + // Don't disable this event. It shall occur periodically. + + ++m_common_rtc_overflows; + } +} + +#if defined(TARGET_MCU_NRF51822) +void common_rtc_irq_handler(void) +#else +void COMMON_RTC_IRQ_HANDLER(void) +#endif +{ + + rtc_ovf_event_check(); + + if ((m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) || nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) { + us_ticker_irq_handler(); + } + +#if DEVICE_LOWPOWERTIMER + if (m_common_sw_irq_flag & LP_TICKER_SW_IRQ_MASK) { + m_common_sw_irq_flag &= ~LP_TICKER_SW_IRQ_MASK; + lp_ticker_irq_handler(); + } + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT)) { + + lp_ticker_irq_handler(); + } +#endif +} + +// Function for fix errata 20: RTC Register values are invalid +__STATIC_INLINE void errata_20(void) +{ +#if defined(NRF52_ERRATA_20) + if (!NRF_HAL_US_TICKER_SD_IS_ENABLED()) + { + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) + { + } + } + NRF_RTC1->TASKS_STOP = 0; +#endif +} + +void RTC1_IRQHandler(void); + +void common_rtc_init(void) +{ + if (m_common_rtc_enabled) { + return; + } + + errata_20(); + + NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + + // RTC is driven by the low frequency (32.768 kHz) clock, a proper request + // must be made to have it running. + // Currently this clock is started in 'SystemInit' (see "system_nrf51.c" + // or "system_nrf52.c", respectively). + + nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); +#if defined(TARGET_MCU_NRF51822) + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); +#endif +#if DEVICE_LOWPOWERTIMER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); +#endif + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + + // Interrupts on all related events are enabled permanently. Particular + // events will be enabled or disabled as needed (such approach is more + // energy efficient). + nrf_rtc_int_enable(COMMON_RTC_INSTANCE, +#if DEVICE_LOWPOWERTIMER + LP_TICKER_INT_MASK | +#endif + US_TICKER_INT_MASK | + NRF_RTC_INT_OVERFLOW_MASK); + + // This event is enabled permanently, since overflow indications are needed + // continuously. + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + // All other relevant events are initially disabled. + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, +#if defined(TARGET_MCU_NRF51822) + OS_TICK_INT_MASK | +#endif +#if DEVICE_LOWPOWERTIMER + LP_TICKER_INT_MASK | +#endif + US_TICKER_INT_MASK); + + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), +#ifdef NRF51 + APP_IRQ_PRIORITY_LOW +#elif defined(NRF52) || defined(NRF52840_XXAA) + APP_IRQ_PRIORITY_LOWEST +#endif + ); + + nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); + + m_common_rtc_enabled = true; +} + +__STATIC_INLINE void rtc_ovf_event_safe_check(void) +{ + core_util_critical_section_enter(); + + rtc_ovf_event_check(); + + core_util_critical_section_exit(); +} + + +uint32_t common_rtc_32bit_ticks_get(void) +{ + uint32_t ticks; + uint32_t prev_overflows; + + do { + prev_overflows = m_common_rtc_overflows; + + ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); + // The counter used for time measurements is less than 32 bit wide, + // so its value is complemented with the number of registered overflows + // of the counter. + ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS); + + // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler) + // m_common_rtc_overflows might been updated in this call. + rtc_ovf_event_safe_check(); + + // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler. + } while (m_common_rtc_overflows != prev_overflows); + + return ticks; +} + +uint64_t common_rtc_64bit_us_get(void) +{ + uint32_t ticks = common_rtc_32bit_ticks_get(); + // [ticks -> microseconds] + return ROUNDED_DIV(((uint64_t)ticks) * 1000000, RTC_INPUT_FREQ); +} + +void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel, + uint32_t int_mask) +{ + // The internal counter is clocked with a frequency that cannot be easily + // multiplied to 1 MHz, therefore besides the translation of values + // (microsecond <-> ticks) a special care of overflows handling must be + // taken. Here the 32-bit timestamp value is complemented with information + // about current the system up time of (ticks + number of overflows of tick + // counter on upper bits, converted to microseconds), and such 64-bit value + // is then translated to counter ticks. Finally, the lower 24 bits of thus + // calculated value is written to the counter compare register to prepare + // the interrupt generation. + uint64_t current_time64 = common_rtc_64bit_us_get(); + // [add upper 32 bits from the current time to the timestamp value] + uint64_t timestamp64 = us_timestamp + + (current_time64 & ~(uint64_t)0xFFFFFFFF); + // [if the original timestamp value happens to be after the 32 bit counter + // of microsends overflows, correct the upper 32 bits accordingly] + if (us_timestamp < (uint32_t)(current_time64 & 0xFFFFFFFF)) { + timestamp64 += ((uint64_t)1 << 32); + } + // [microseconds -> ticks, always round the result up to avoid too early + // interrupt generation] + uint32_t compare_value = + (uint32_t)CEIL_DIV((timestamp64) * RTC_INPUT_FREQ, 1000000); + + + core_util_critical_section_enter(); + // The COMPARE event occurs when the value in compare register is N and + // the counter value changes from N-1 to N. Therefore, the minimal safe + // difference between the compare value to be set and the current counter + // value is 2 ticks. This guarantees that the compare trigger is properly + // setup before the compare condition occurs. + uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2; + if ((int)(compare_value - closest_safe_compare) <= 0) { + compare_value = closest_safe_compare; + } + + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, RTC_WRAP(compare_value)); + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, int_mask); + + core_util_critical_section_exit(); +} +//------------------------------------------------------------------------------ + + +void us_ticker_init(void) +{ + common_rtc_init(); +} + +uint32_t us_ticker_read() +{ + us_ticker_init(); + return (uint32_t)common_rtc_64bit_us_get(); +} + +void us_ticker_set_interrupt(timestamp_t timestamp) +{ + common_rtc_set_interrupt(timestamp, + US_TICKER_CC_CHANNEL, US_TICKER_INT_MASK); +} + +void us_ticker_fire_interrupt(void) +{ + core_util_critical_section_enter(); + m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK; + NVIC_SetPendingIRQ(RTC1_IRQn); + core_util_critical_section_exit(); +} + +void us_ticker_disable_interrupt(void) +{ + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); +} + +void us_ticker_clear_interrupt(void) +{ + m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK; + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); +} + + +// Since there is no SysTick on NRF51, the RTC1 channel 1 is used as an +// alternative source of RTOS ticks. +#if defined(TARGET_MCU_NRF51822) + +#include "mbed_toolchain.h" + + +#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) + +#ifndef RTC1_CONFIG_FREQUENCY + #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] +#endif + + + +void COMMON_RTC_IRQ_HANDLER(void) +{ + if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { + common_rtc_irq_handler(); + } +} + +IRQn_Type mbed_get_m0_tick_irqn() +{ + return SWI3_IRQn; +} + + +#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/targets.json b/targets/targets.json index 1ca1773e81..d1bfca5823 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -2441,11 +2441,8 @@ }, "RBLAB_BLENANO2": { "supported_form_factors": ["ARDUINO"], - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "release_versions": ["2", "5"], - "overrides": {"uart_hwfc": 0}, + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "NRF51822_Y5_MBUG": { @@ -3494,179 +3491,172 @@ "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE"], "device_name": "nRF51822_xxAC" }, - "MCU_NRF52": { + "MCU_NRF52832": { "inherits": ["Target"], "core": "Cortex-M4F", - "macros": ["NRF52", "TARGET_NRF52832", "BLE_STACK_SUPPORT_REQD", "SOFTDEVICE_PRESENT", "S132", "CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", "MBED_TICKLESS"], - "device_has": ["STCLK_OFF_DURING_SLEEP", "ITM", "TRNG"], - "extra_labels": ["NORDIC", "MCU_NRF52", "MCU_NRF52832", "NRF5", "SDK11", "NRF52_COMMON"], + "macros": [ + "BOARD_PCA10040", + "NRF52", + "TARGET_NRF52832", + "CMSIS_VECTAB_VIRTUAL", + "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", + "MBED_TICKLESS" + ], + "device_has": [ + "ANALOGIN", + "FLASH", + "I2C", + "I2C_ASYNCH", + "INTERRUPTIN", + "ITM", + "LOWPOWERTIMER", + "PORTIN", + "PORTINOUT", + "PORTOUT", + "PWMOUT", + "RTC", + "SERIAL", + "SERIAL_ASYNCH", + "SERIAL_FC", + "SLEEP", + "SPI", + "SPI_ASYNCH", + "STCLK_OFF_DURING_SLEEP", + "TRNG" + ], + "extra_labels": [ + "NORDIC", + "NRF5x", + "NRF52", + "SDK_14_2", + "SOFTDEVICE_COMMON", + "SOFTDEVICE_S132" + ], + "config": { + "lf_clock_src": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC", + "help": "Select Low Frequency clock source. Options: NRF_LF_SRC_XTAL, NRF_LF_SRC_SYNTH, and NRF_LF_SRC_RC", + "value": "NRF_LF_SRC_XTAL" + }, + "lf_clock_rc_calib_timer_interval": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL", + "value": 16 + }, + "lf_clock_rc_calib_mode_config": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG", + "value": 0 + } + }, "OUTPUT_EXT": "hex", "is_disk_virtual": true, "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "public": false, "detect_code": ["1101"], "program_cycle_s": 6, - "MERGE_SOFT_DEVICE": true, - "EXPECTED_SOFTDEVICES_WITH_OFFSETS": [ - { - "boot": "", - "name": "s132_nrf52_2.0.0_softdevice.hex", - "offset": 114688 - } - ], - "post_binary_hook": { - "function": "MCU_NRF51Code.binary_hook", - "toolchains": ["ARM_STD", "GCC_ARM", "IAR"] - }, - "MERGE_BOOTLOADER": false, - "features": ["BLE"], - "config": { - "lf_clock_src": { - "value": "NRF_LF_SRC_XTAL", - "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC" - }, - "uart_hwfc": { - "help": "Value: 1 for enable, 0 for disable", - "value": 1, - "macro_name": "MBED_CONF_NORDIC_UART_HWFC" - } - } + "bootloader_supported": true }, "NRF52_DK": { "supported_form_factors": ["ARDUINO"], - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "FLASH"], - "release_versions": ["2", "5"], + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "UBLOX_EVA_NINA": { - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "release_versions": ["2", "5"], - "overrides": {"uart_hwfc": 0}, + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "UBLOX_EVK_NINA_B1": { "supported_form_factors": ["ARDUINO"], - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "release_versions": ["2", "5"], + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "MTB_UBLOX_NINA_B1": { - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "extra_labels_add": ["MTB_UBLOX_NINA_B1"], + "inherits": ["MCU_NRF52832"], "release_versions": ["5"], - "device_name": "nRF52832_xxAA", - "bootloader_supported": true, - "overrides": { - "uart_hwfc": 0 - }, - "config": { - "usb_tx": { - "help": "Value p6", - "value": "p6" - }, - "usb_rx": { - "help": "Value p5", - "value": "p5" - } - } + "device_name": "nRF52832_xxAA" }, "MTB_LAIRD_BL652": { - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "extra_labels_add": ["MTB_LAIRD_BL652"], + "inherits": ["MCU_NRF52832"], "release_versions": ["5"], - "device_name": "nRF52832_xxAA", - "bootloader_supported": true, - "config": { - "usb_tx": { - "help": "Value SIO_06", - "value": "SIO_6" - }, - "usb_rx": { - "help": "Value SIO_08", - "value": "SIO_8" - } - }, - "overrides": { - "lf_clock_src": "NRF_LF_SRC_RC", - "uart_hwfc": 0 - } + "device_name": "nRF52832_xxAA" }, "DELTA_DFBM_NQ620": { "supported_form_factors": ["ARDUINO"], - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "release_versions": ["2", "5"], - "overrides": {"lf_clock_src": "NRF_LF_SRC_RC"}, - "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": 0, - "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG" - } - }, + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "MCU_NRF52840": { "inherits": ["Target"], "core": "Cortex-M4F", - "macros": ["TARGET_NRF52840", "BLE_STACK_SUPPORT_REQD", "SOFTDEVICE_PRESENT", "S140", "NRF_SD_BLE_API_VERSION=5", "NRF52840_XXAA", "NRF_DFU_SETTINGS_VERSION=1", "NRF_SD_BLE_API_VERSION=5", "CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", "MBED_TICKLESS"], - "device_has": ["STCLK_OFF_DURING_SLEEP", "ITM"], - "extra_labels": ["NORDIC", "MCU_NRF52840", "NRF5", "SDK13", "NRF52_COMMON"], + "macros": [ + "BOARD_PCA10056", + "NRF52840_XXAA", + "TARGET_NRF52840", + "CMSIS_VECTAB_VIRTUAL", + "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", + "MBED_TICKLESS" + ], + "device_has": [ + "ANALOGIN", + "FLASH", + "I2C", + "I2C_ASYNCH", + "INTERRUPTIN", + "ITM", + "LOWPOWERTIMER", + "PORTIN", + "PORTINOUT", + "PORTOUT", + "PWMOUT", + "RTC", + "SERIAL", + "SERIAL_ASYNCH", + "SERIAL_FC", + "SLEEP", + "SPI", + "SPI_ASYNCH", + "STCLK_OFF_DURING_SLEEP", + "TRNG" + ], + "extra_labels": [ + "NORDIC", + "NRF5x", + "NRF52", + "SDK_14_2", + "SOFTDEVICE_COMMON", + "SOFTDEVICE_S140" + ], + "config": { + "lf_clock_src": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC", + "help": "Select Low Frequency clock source. Options: NRF_LF_SRC_XTAL, NRF_LF_SRC_SYNTH, and NRF_LF_SRC_RC", + "value": "NRF_LF_SRC_XTAL" + }, + "lf_clock_rc_calib_timer_interval": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL", + "value": 16 + }, + "lf_clock_rc_calib_mode_config": { + "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG", + "value": 0 + } + }, "OUTPUT_EXT": "hex", "is_disk_virtual": true, "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "public": false, "detect_code": ["1101"], "program_cycle_s": 6, - "MERGE_SOFT_DEVICE": true, - "EXPECTED_SOFTDEVICES_WITH_OFFSETS": [ - { - "boot": "", - "name": "s140_nrf52840_5.0.0-1.alpha_softdevice.hex", - "offset": 135168 - } - ], - "bootloader_select_index": 0, - "post_binary_hook": { - "function": "MCU_NRF51Code.binary_hook", - "toolchains": ["ARM_STD", "GCC_ARM", "IAR"] - }, - "MERGE_BOOTLOADER": false, - "features": ["BLE"], - "config": { - "lf_clock_src": { - "value": "NRF_LF_SRC_XTAL", - "macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC" - }, - "uart_hwfc": { - "help": "Value: 1 for enable, 0 for disable", - "value": 1, - "macro_name": "MBED_CONF_NORDIC_UART_HWFC" - } - } + "bootloader_supported": true }, "NRF52840_DK": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF52840"], - "macros_add": ["BOARD_PCA10056", "CONFIG_GPIO_AS_PINRESET", "SWI_DISABLE0", "NRF52_ERRATA_20"], - "device_has_add": ["FLASH", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "TRNG"], - "release_versions": ["2", "5"], - "device_name": "nRF52840_xxAA", - "bootloader_supported": true + "release_versions": ["5"], + "device_name": "nRF52840_xxAA" }, "BLUEPILL_F103C8": { "inherits": ["FAMILY_STM32"], @@ -3930,10 +3920,8 @@ }, "VBLUNO52": { "supported_form_factors": ["ARDUINO"], - "inherits": ["MCU_NRF52"], - "macros_add": ["BOARD_PCA10040", "BOARD_VBLUNO52", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], - "release_versions": ["2"], + "inherits": ["MCU_NRF52832"], + "release_versions": ["5"], "device_name": "nRF52832_xxAA" }, "NUMAKER_PFM_M487": {