From 49a78419bb3aa724d6e4673b2b8686319b804f84 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Thu, 7 Aug 2014 13:59:46 +0100 Subject: [PATCH 01/41] Bugfix: In SingletestRunner.run_host_test function optional named parameters verbose and reset were not assigned with proper values --- workspace_tools/test_api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 1c35656fd91..c18eea0cc2e 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -552,7 +552,8 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): start_host_exec_time = time() host_test_verbose = self.opts_verbose_test_result_only or self.opts_verbose - single_test_result = self.run_host_test(test.host_test, disk, port, duration, host_test_verbose) + host_test_reset = self.opts_mut_reset_type + single_test_result = self.run_host_test(test.host_test, disk, port, duration, verbose=host_test_verbose, reset=host_test_reset) # Store test result test_all_result.append(single_test_result) From 45597fd8e6dcb43f565ea2784b362351fa20b1c8 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 7 Aug 2014 17:01:39 +0100 Subject: [PATCH 02/41] A few changes to the new parallel build system - restored assemble/compile_c/compile_cpp, except now they return the commands that will run, instead of actually running the commands - remove need_update_new, since it doesn't seem to be used anywhere --- workspace_tools/toolchains/__init__.py | 59 ++++++-------------------- workspace_tools/toolchains/arm.py | 7 +-- workspace_tools/toolchains/gcc.py | 7 +-- workspace_tools/toolchains/iar.py | 7 +-- 4 files changed, 16 insertions(+), 64 deletions(-) diff --git a/workspace_tools/toolchains/__init__.py b/workspace_tools/toolchains/__init__.py index 787783be3f6..1f0d382c504 100644 --- a/workspace_tools/toolchains/__init__.py +++ b/workspace_tools/toolchains/__init__.py @@ -233,7 +233,6 @@ def __init__(self, target, options=None, notify=None, macros=None): self.symbols = None self.labels = None self.has_config = False - self.stat_cache = {} self.build_all = False self.timestamp = time() @@ -314,31 +313,6 @@ def need_update(self, target, dependencies): return False - def need_update_new(self, target, dependencies): - if self.build_all: - return True - - if not exists(target): - return True - - target_mod_time = stat(target).st_mtime - for d in dependencies: - # Some objects are not provided with full path and here we do not have - # information about the library paths. Safe option: assume an update - if not d: - return True - - if self.stat_cache.has_key(d): - if self.stat_cache[d] >= target_mod_time: - return True - else: - if not exists(d): return True - - self.stat_cache[d] = stat(d).st_mtime - if self.stat_cache[d] >= target_mod_time: return True - - return False - def scan_resources(self, path): labels = self.get_labels() resources = Resources(path) @@ -487,7 +461,7 @@ def compile_sources(self, resources, build_path, inc_dirs=None): mkdir(work_dir) # Queue mode (multiprocessing) - commands = self._compile_command(source, object, inc_paths) + commands = self.compile_command(source, object, inc_paths) if commands is not None: queue.append({ 'source': source, @@ -514,7 +488,7 @@ def compile_seq(self, queue, objects): self.progress("compile", item['source'], build_update=True) for res in result['results']: self.debug("Command: %s" % ' '.join(res['command'])) - self._compile_output([ + self.compile_output([ res['code'], res['output'], res['command'] @@ -549,7 +523,7 @@ def compile_queue(self, queue, objects): self.progress("compile", result['source'], build_update=True) for res in result['results']: self.debug("Command: %s" % ' '.join(res['command'])) - self._compile_output([ + self.compile_output([ res['code'], res['output'], res['command'] @@ -576,7 +550,7 @@ def compile_queue(self, queue, objects): return objects - def _compile_command(self, source, object, includes): + def compile_command(self, source, object, includes): # Check dependencies _, ext = splitext(source) ext = ext.lower() @@ -586,17 +560,20 @@ def _compile_command(self, source, object, includes): dep_path = base + '.d' deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else [] if len(deps) == 0 or self.need_update(object, deps): - return self._compile(source, object, includes) + if ext == '.c': + return self.compile_c(source, object, includes) + else: + return self.compile_cpp(source, object, includes) elif ext == '.s': deps = [source] if self.need_update(object, deps): - return self._assemble(source, object, includes) + return self.assemble(source, object, includes) else: return False return None - def _compile_output(self, output=[]): + def compile_output(self, output=[]): rc = output[0] stderr = output[1] command = output[2] @@ -610,11 +587,10 @@ def _compile_output(self, output=[]): if rc != 0: raise ToolException(stderr) - def _compile(self, source, object, includes): + def compile(self, cc, source, object, includes): _, ext = splitext(source) ext = ext.lower() - cc = self.cppc if ext == ".cpp" else self.cc command = cc + ['-D%s' % s for s in self.get_symbols()] + ["-I%s" % i for i in includes] + ["-o", object, source] if hasattr(self, "get_dep_opt"): @@ -627,20 +603,11 @@ def _compile(self, source, object, includes): return [command] - def compile(self, source, object, includes): - self.progress("compile", source, build_update=True) - - commands = self._compile(source, object, includes) - for command in commands: - self.debug("Command: %s" % ' '.join(command)) - _, stderr, rc = run_cmd(command, dirname(object)) - self._compile_output([rc, stderr, command]) - def compile_c(self, source, object, includes): - self.compile(source, object, includes) + return self.compile(self.cc, source, object, includes) def compile_cpp(self, source, object, includes): - self.compile(source, object, includes) + return self.compile(self.cppc, source, object, includes) def build_library(self, objects, dir, name): lib = self.STD_LIB_NAME % name diff --git a/workspace_tools/toolchains/arm.py b/workspace_tools/toolchains/arm.py index 1ecb59edb0c..08ba481d8db 100644 --- a/workspace_tools/toolchains/arm.py +++ b/workspace_tools/toolchains/arm.py @@ -80,7 +80,7 @@ def remove_option(self, option): if option in tool: tool.remove(option) - def _assemble(self, source, object, includes): + def assemble(self, source, object, includes): # Preprocess first, then assemble tempfile = object + '.E.s' return [ @@ -88,11 +88,6 @@ def _assemble(self, source, object, includes): self.hook.get_cmdline_assembler(self.asm + ["-o", object, tempfile]) ] - def assemble(self, source, object, includes): - commands = self._assemble(source, object, includes); - for command in commands: - self.default_cmd(command) - def parse_dependencies(self, dep_path): dependencies = [] for line in open(dep_path).readlines(): diff --git a/workspace_tools/toolchains/gcc.py b/workspace_tools/toolchains/gcc.py index 5d29cf59be5..c42f1828eee 100644 --- a/workspace_tools/toolchains/gcc.py +++ b/workspace_tools/toolchains/gcc.py @@ -81,13 +81,8 @@ def __init__(self, target, options=None, notify=None, macros=None, tool_path="") self.ar = join(tool_path, "arm-none-eabi-ar") self.elf2bin = join(tool_path, "arm-none-eabi-objcopy") - def _assemble(self, source, object, includes): - return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])] - def assemble(self, source, object, includes): - commands = self._assemble(source, object, includes); - for command in commands: - self.default_cmd(command) + return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])] def parse_dependencies(self, dep_path): dependencies = [] diff --git a/workspace_tools/toolchains/iar.py b/workspace_tools/toolchains/iar.py index 859d8c71e1b..c843e92f5c0 100644 --- a/workspace_tools/toolchains/iar.py +++ b/workspace_tools/toolchains/iar.py @@ -94,13 +94,8 @@ def parse_dependencies(self, dep_path): return [path.strip() for path in open(dep_path).readlines() if (path and not path.isspace())] - def _assemble(self, source, object, includes): - return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])] - def assemble(self, source, object, includes): - commands = self._assemble(source, object, includes); - for command in commands: - self.default_cmd(command) + return [self.hook.get_cmdline_assembler(self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source])] def archive(self, objects, lib_path): if exists(lib_path): From 4c54ea6a4b9f5786d17bf97600274e803e47794f Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 7 Aug 2014 17:06:56 +0100 Subject: [PATCH 03/41] Added parallel build option to build_travis.py Mostly to test Mihail's parallel build changes --- workspace_tools/build_travis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace_tools/build_travis.py b/workspace_tools/build_travis.py index 2c8a655832d..50a6faf1302 100644 --- a/workspace_tools/build_travis.py +++ b/workspace_tools/build_travis.py @@ -59,7 +59,7 @@ def run_builds(dry_run): toolchain_list = build["toolchains"] if type(toolchain_list) != type([]): toolchain_list = [toolchain_list] for toolchain in toolchain_list: - cmdline = "python workspace_tools/build.py -m %s -t %s -c " % (build["target"], toolchain) + cmdline = "python workspace_tools/build.py -m %s -t %s -j 4 -c " % (build["target"], toolchain) libs = build.get("libs", []) if libs: cmdline = cmdline + " ".join(["--" + l for l in libs]) From 198f6cfbee1f666e4fbf82958613f28671b01dc1 Mon Sep 17 00:00:00 2001 From: 23chrischen <23chrischen@gmail.com> Date: Thu, 7 Aug 2014 11:50:41 -0500 Subject: [PATCH 04/41] Changed stm32f401 to stm32f411 --- .../cmsis/TARGET_STM/TARGET_NUCLEO_F411RE/stm32f411xe.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F411RE/stm32f411xe.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F411RE/stm32f411xe.h index f9d6c411979..0615611891c 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F411RE/stm32f411xe.h +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F411RE/stm32f411xe.h @@ -9,7 +9,7 @@ * This file contains: * - Data structures and the address mapping for all peripherals * - Peripheral's registers declarations and bits definition - * - Macros to access peripheral’s registers hardware + * - Macros to access peripheral’s registers hardware * ****************************************************************************** * @attention @@ -45,12 +45,12 @@ * @{ */ -/** @addtogroup stm32f401xe +/** @addtogroup stm32f411xe * @{ */ -#ifndef __STM32F401xE_H -#define __STM32F401xE_H +#ifndef __STM32F411xE_H +#define __STM32F411xE_H #ifdef __cplusplus extern "C" { From eff3edb0fc099ea4f3ce52fd4e91ebc1c9023930 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Fri, 8 Aug 2014 14:14:13 +0100 Subject: [PATCH 05/41] Restored Nordic soft device directory --- .../s110_nrf51822_7.0.0_API/doc/ble_api.dox | 1334 +++++ .../s110_nrf51822_7.0.0_API/include/ble.h | 385 ++ .../s110_nrf51822_7.0.0_API/include/ble_err.h | 54 + .../s110_nrf51822_7.0.0_API/include/ble_gap.h | 1032 ++++ .../include/ble_gatt.h | 171 + .../include/ble_gattc.h | 406 ++ .../include/ble_gatts.h | 566 ++ .../s110_nrf51822_7.0.0_API/include/ble_hci.h | 96 + .../include/ble_l2cap.h | 144 + .../include/ble_ranges.h | 89 + .../include/ble_types.h | 169 + .../include/nrf_error.h | 51 + .../include/nrf_error_sdm.h | 33 + .../include/nrf_error_soc.h | 49 + .../s110_nrf51822_7.0.0_API/include/nrf_mbr.h | 155 + .../s110_nrf51822_7.0.0_API/include/nrf_sdm.h | 167 + .../s110_nrf51822_7.0.0_API/include/nrf_soc.h | 958 +++ .../s110_nrf51822_7.0.0_API/include/nrf_svc.h | 33 + .../include/softdevice_assert.h | 46 + .../s110_nrf51822_7.0.0_licence_agreement.pdf | Bin 0 -> 5553 bytes ...s110_nrf51822_7.0.0_migration-document.pdf | Bin 0 -> 143012 bytes .../s110_nrf51822_7.0.0_readme.txt | 14 + .../s110_nrf51822_7.0.0_releasenotes.pdf | Bin 0 -> 58183 bytes .../s110_nrf51822_7.0.0_softdevice.hex | 5290 +++++++++++++++++ 24 files changed, 11242 insertions(+) create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/doc/ble_api.dox create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_err.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gap.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatt.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gattc.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatts.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_hci.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_l2cap.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_ranges.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_types.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_sdm.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_soc.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_mbr.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_sdm.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_soc.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_svc.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/softdevice_assert.h create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_licence_agreement.pdf create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_migration-document.pdf create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_readme.txt create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_releasenotes.pdf create mode 100644 libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_softdevice.hex diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/doc/ble_api.dox b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/doc/ble_api.dox new file mode 100644 index 00000000000..feaf4519991 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/doc/ble_api.dox @@ -0,0 +1,1334 @@ +/** + * @addtogroup BLE_COMMON + * @{ + * @defgroup BLE_COMMON_MSC Message Sequence Charts + * @{ + * @defgroup BLE_COMMON_IRQ_EVT_MSC Interrupt-driven Event Retrieval + * @msc + * hscale = "1.5"; + * APP,SD; + * |||; + * APP=>SD [label = "sd_softdevice_enable(clock, assertion_handler);"]; + * APP<SD [label = "sd_nvic_EnableIRQ(SD_EVENT_IRQn)"]; + * APP<APP [label = "SD_EVENT_IRQHandler()"]; + * APP=>SD [label = "sd_ble_evt_get(buffer);"]; + * APP<SD [label = "sd_softdevice_enable(clock, assertion_handler);"]; + * APP<SD [label = "sd_app_evt_wait(void);"]; + * APP rbox APP [label="App Thread Mode blocked, CPU in low power mode"]; + * |||; + * ...; + * |||; + * SD rbox SD [label="Event Available for the App"]; + * APP<SD [label = "sd_ble_evt_get(buffer);"]; + * APP<SD [label = "sd_app_evt_wait(void);"]; + * APP rbox APP [label="App Thread Mode blocked, CPU in low power mode"]; + * |||; + * ...; + * |||; + * SD rbox SD [label="Event Available for the App"]; + * APP<SD [label = "sd_ble_evt_get(buffer);"]; + * APP<SD [label = "sd_app_evt_wait(void);"]; + * APP rbox APP [label="App Thread Mode blocked, CPU in low power mode"]; + * |||; + * ...; + * |||; + * @endmsc + * + * @defgroup BLE_COMMON_APP_BUFF_MSC App Buffer Management + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP=>SD [label = "sd_ble_tx_buffer_count_get();"]; + * APP<SD [label = "sd_ble_gattc_write(handle, value)"]; + * APP<PEER [label = "ATT Write Command", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_TX_COMPLETE {1}"]; + * APP rbox APP [label="available += 1"]; + * |||; + * ...; + * |||; + * APP=>SD [label = "sd_ble_gatts_hvx(NOTIFICATION, app_value)"]; + * APP<PEER [label = "ATT Handle Value Notification", textcolor="#000080", linecolor="#000080"]; + * APP=>SD [label = "sd_ble_gatts_hvx(NOTIFICATION, app_value)"]; + * APP<PEER [label = "ATT Handle Value Notification", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_TX_COMPLETE {2}"]; + * APP rbox APP [label="available += 2"]; + * |||; + * ...; + * |||; + * APP rbox PEER [label="Terminate Connection"]; + * |||; + * APP rbox APP [label="available = N"]; + * |||; + * @endmsc + * @} + * @} + */ + +/** + * @addtogroup BLE_GAP + * @{ + * @defgroup BLE_GAP_MSC Message Sequence Charts + * @{ + * @defgroup BLE_GAP_ADV_MSC GAP Advertisement + * @msc + * hscale = "1.5"; + * APP,SD,SCANNERS; + * |||; + * APP=>SD [label = "sd_ble_gap_address_set(addr)"]; + * APP<SD [label = "sd_ble_gap_adv_data_set(adv, sr)"]; + * APP<SD [label = "sd_ble_gap_adv_start(params)"]; + * APP<SCANNERS [label = "ADV packet", textcolor="#000080", linecolor="#000080"]; + * SD->SCANNERS [label = "ADV packet", textcolor="#000080", linecolor="#000080"]; + * SD->SCANNERS [label = "ADV packet", textcolor="#000080", linecolor="#000080"]; + * ...; + * SD->SCANNERS [label = "ADV packet", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #1 App Stops Advertisement "]; + * APP=>SD [label = "sd_ble_gap_adv_stop()"]; + * APP<CENTRAL [label = "Connection Establishment", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONNECTED"]; + * |||; + * --- [label = " Variant #1 Local Disconnection "]; + * APP=>SD [label = "sd_ble_gap_disconnect(reason)"]; + * APP<CENTRAL [label = "Connection Termination", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_DISCONNECTED {reason}"]; + * |||; + * --- [label = " Variant #2 Remote Disconnection "]; + * SD<:CENTRAL [label = "Connection Termination", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_DISCONNECTED {reason}"]; + * @endmsc + * + * @defgroup BLE_GAP_CPU_MSC GAP Connection Parameter Update + * @msc + * hscale = "1.5"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established with conn. params. CP#1"]; + * |||; + * APP=>SD [label = "sd_ble_gap_conn_param_update(CP#2)"]; + * APP<CENTRAL [label = "L2CAP CPU Request", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #1 Central Accepts "]; + * |||; + * SD<:CENTRAL [label = "L2CAP CPU Response: Accepted", textcolor="#000080", linecolor="#000080"]; + * |||; + * SD<:CENTRAL [label = "Connection Update", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_PARAM_UPDATE {CP#2}"]; + * |||; + * --- [label = " Variant #2 Central Rejects "]; + * |||; + * SD<:CENTRAL [label = "L2CAP CPU Response: Rejected", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_PARAM_UPDATE {CP#1}"]; + * --- [label = " Variant #3 Central Ignores "]; + * |||; + * ...; + * |||; + * SD box SD [label="Timeout"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_PARAM_UPDATE {CP#1}"]; + * @endmsc + * + * @defgroup BLE_GAP_RSSI_MSC GAP RSSI + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gap_rssi_start()"]; + * APP<SD [label = "sd_ble_gap_rssi_stop()"]; + * APP<SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: no_bond, no_mitm, no_io_caps)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 2", textbgcolor="#7f7fff"]; + * |||; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {SUCCESS}"]; + * APP rbox CENTRAL [label = "Encrypted with STK"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_SEC_UPDATE {ENC_NO_MITM}"]; + * @endmsc + * + * @defgroup BLE_GAP_BONDING_JW_MSC GAP Bonding: Just Works + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST {central_params: bond, no_mitm, no_io_caps}"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: bond, no_mitm, no_io_caps)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 2", textbgcolor="#7f7fff"]; + * |||; + * APP rbox CENTRAL [label = "Encrypted with STK"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_SEC_UPDATE {ENC_NO_MITM}"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 3", textbgcolor="#7f7fff"]; + * |||; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {SUCCESS, periph_keys}"]; + * APP rbox APP [label = "Store Peripheral Keys"]; + * @endmsc + * + * @defgroup BLE_GAP_BONDING_PK_PERIPH_MSC GAP Bonding: Passkey Entry, Peripheral displays + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST {central_params: bond, mitm, keyboard}"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: bond, mitm, display)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_PASSKEY_DISPLAY {passkey}"]; + * APP rbox APP [label="Passkey displayed to the user"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 2", textbgcolor="#7f7fff"]; + * |||; + * APP rbox CENTRAL [label = "Encrypted with STK"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_SEC_UPDATE {ENC_MITM}"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 3", textbgcolor="#7f7fff"]; + * |||; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {SUCCESS, periph_keys}"]; + * APP rbox APP [label = "Store Peripheral Keys"]; + * @endmsc + * + * @defgroup BLE_GAP_BONDING_PK_CENTRAL_OOB_MSC GAP Bonding: Passkey Entry (Central display) or OOB MSC + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST {central_params: bond, mitm, display}"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: bond, mitm, keyboard)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_KEY_REQUEST {type}"]; + * APP rbox APP [label="User enters Passkey or data received Out Of Band"]; + * APP=>SD [label = "sd_ble_gap_auth_key_reply(passkey or OOB)"]; + * APP<SD [label = "sd_ble_opt_set(opt_id = BLE_GAP_OPT_PASSKEY, p_opt->p_passkey=passkey)"]; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST {central_params: bond, mitm, keyboard}"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: bond, mitm, io_caps = display)"]; + * + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_PASSKEY_DISPLAY {passkey}"]; + * APP rbox APP [label="Passkey displayed to the user"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 2", textbgcolor="#7f7fff"]; + * |||; + * APP rbox CENTRAL [label = "Encrypted with STK"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_SEC_UPDATE {ENC_MITM}"]; + * |||; + * SD abox CENTRAL [label="SMP Pairing Phase 3", textbgcolor="#7f7fff"]; + * |||; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {SUCCESS, periph_keys}"]; + * APP rbox APP [label = "Store Peripheral Keys"]; + * @endmsc + * + * @defgroup BLE_GAP_SEC_MSC GAP Security Establishment using stored keys + * @msc + * hscale = "1.5"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "LL Encryption Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_INFO_REQUEST {addr, div}"]; + * |||; + * --- [label = " Variant #1 App Replies with Keys "]; + * |||; + * APP rbox APP [label = "Load Peripheral Keys"]; + * APP=>SD [label = "sd_ble_gap_sec_info_reply(div, LTK)"]; + * APP<CENTRAL [label = "LL Encryption Response", textcolor="#000080", linecolor="#000080"]; + * APP rbox CENTRAL [label = "Encrypted with LTK"]; + * APP<<=SD [label = "BLE_GAP_EVT_CONN_SEC_UPDATE"]; + * |||; + * --- [label = " Variant #2 App Replies without Keys "]; + * |||; + * APP=>SD [label = "sd_ble_gap_sec_info_reply(NULL)"]; + * APP<CENTRAL [label = "LL Reject Ind: Pin or Key Missing", textcolor="#000080", linecolor="#000080"]; + * APP rbox CENTRAL [label = "Link Not Encrypted"]; + * @endmsc + * + * @defgroup BLE_GAP_PERIPH_SEC_MSC GAP Peripheral Initiated Security Establishment + * @msc + * hscale = "1.5"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gap_authenticate(params)"]; + * APP<CENTRAL [label = "SMP Security Request", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #1 Central initiates Security Establishment "]; + * |||; + * APP rbox CENTRAL [label="Encryption or Pairing/Bonding initiated by Central"]; + * |||; + * --- [label = " Variant #2 Central ignores "]; + * |||; + * ...; + * |||; + * APP<<=SD [label = "BLE_GAP_EVT_TIMEOUT"]; + * |||; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_KS_OUT_OF_RANGE_MSC GAP Failed Pairing: Keysize out of supported range + * This occurs if the min key size offered by the peer is above 16, or max key size below 7. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: Invalid params, error_src: local}"]; + * SD:>CENTRAL [label = "SMP Pairing failed", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_KS_TOO_SMALL_MSC GAP Failed Pairing: Keysize too small + * This occurs if the max key size offered by the peer is below the min key size specified by + * the app. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * SD<:CENTRAL [label = "SMP Pairing Confirm", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: Enc key size, error_src: local}"]; + * SD:>CENTRAL [label = "SMP Pairing failed", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_APP_ERROR_MSC GAP Failed Pairing: Pairing aborted by the application + * When the application detects that the pairing should not be performed, for example an + * insufficient IO combination, it can use sd_ble_gap_sec_params_reply() to send + * SMP Pairing failed to the peer. + * + * When the stack handles the response from the application it will also validate + * the passkey (SMP_STC_PASSKEY_ENTRY_FAILED). If any error is detected it will be + * reported when sd_ble_gap_sec_params_reply() is called. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST"]; + * SD abox APP [label="Stack looks for errors", textbgcolor="#7f7fff"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply()"]; + * APP<CENTRAL [label = "SMP Pairing failed", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: , error_src: local}"]; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_CONFIRM_FAIL_MSC GAP Failed Pairing: Confirm failed + * This occurs if the random value doesn't match, usually because the user entered a wrong pin + * or out of band data was missing. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST {central_params: mitm, display}"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS, periph_params: mitm, keyboard)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * SD<:CENTRAL [label = "SMP Pairing Confirm", textcolor="#000080", linecolor="#000080"]; + * SD:>CENTRAL [label = "SMP Pairing Confirm", textcolor="#000080", linecolor="#000080"]; + * SD<:CENTRAL [label = "SMP Pairing Random", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: Confirm value, error_src: local}"]; + * SD:>CENTRAL [label = "SMP Pairing failed", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_REMOTE_PAIRING_FAIL_MSC GAP Failed Pairing: Pairing failed from master + * SMP Pairing Failed may be sent from the master at various times. The application should + * prepare for this and gracefully handle the event. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * SD<:CENTRAL [label = "SMP Pairing Failed", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: , error_src: remote}"]; + * @endmsc + * + * @defgroup BLE_GAP_PAIRING_TIMEOUT_MSC GAP Failed Pairing: Timeout + * This occurs if the central device doesn't continue the pairing sequence within 30 seconds. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * SD<:CENTRAL [label = "SMP Pairing Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GAP_EVT_SEC_PARAMS_REQUEST"]; + * APP=>SD [label = "sd_ble_gap_sec_params_reply(SUCCESS)"]; + * APP<CENTRAL [label = "SMP Pairing Response", textcolor="#000080", linecolor="#000080"]; + * --- [ label = "Wait 30 sec" ]; + * APP<<=SD [label = "BLE_GAP_EVT_AUTH_STATUS {auth_status: Timeout, error_src: local}"]; + + * @endmsc + * + * @defgroup BLE_GAP_SECURITY_TIMEOUT_MSC GAP Authenticate request: Timeout + * This occurs if the central device doesn't continue the pairing sequence after + * the security procedure timeout. + * @msc + * hscale = "2"; + * APP,SD,CENTRAL; + * |||; + * APP rbox CENTRAL [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gap_authenticate(..., ble_gap_sec_params_t*)"]; + * APP<CENTRAL [label = "Security Request", textcolor="#000080", linecolor="#000080"]; + --- [ label = "After req_timeout (in ble_gap_sec_params_t)" ]; + * APP<<=SD [label = "BLE_GAP_EVT_TIMEOUT {error_src: BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST}"]; + * @endmsc + * + * @} + * @} + */ + +/** + * @addtogroup BLE_GATTC + * @{ + * @defgroup BLE_GATTC_MSC Message Sequence Charts + * @{ + * @defgroup BLE_GATTC_PRIM_SRVC_DISC_MSC GATTC Primary Service Discovery + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * --- [label = " Variant #1 Discover All Services "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle, NULL)"]; + * APP<PEER [label = "ATT Read By Group Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Group Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {SUCCESS, services}"]; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle + N, NULL)"]; + * APP<PEER [label = "ATT Read By Group Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Group Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {SUCCESS, services}"]; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle + N + M, NULL)"]; + * APP<PEER [label = "ATT Read By Group Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {ATTRIBUTE_NOT_FOUND}"]; + * |||; + * --- [label = " Variant #2 Discover a Specific Service "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle, uuid)"]; + * APP<PEER [label = "ATT Find By Type Value Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Find By Type Value Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {SUCCESS, services}"]; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle + N, uuid)"]; + * APP<PEER [label = "ATT Find By Type Value Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Find By Type Value Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {SUCCESS, services}"]; + * APP=>SD [label = "sd_ble_gattc_primary_services_discover(handle + N + M, uuid)"]; + * APP<PEER [label = "ATT Find By Type Value Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP {ATTRIBUTE_NOT_FOUND}"]; + * @endmsc + * + * @defgroup BLE_GATTC_REL_DISC_MSC GATTC Relationship Discovery + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gattc_relationships_discover(handle_range)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_REL_DISC_RSP {SUCCESS, includes}"]; + * APP=>SD [label = "sd_ble_gattc_relationships_discover(handle_range + N)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_REL_DISC_RSP {SUCCESS, includes}"]; + * APP=>SD [label = "sd_ble_gattc_relationships_discover(handle_range + N + M)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_REL_DISC_RSP {ATTRIBUTE_NOT_FOUND}"]; + * @endmsc + * + * @defgroup BLE_GATTC_CHAR_DISC_MSC GATTC Characteristic Discovery + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gattc_characteristics_discover(handle_range)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_DISC_RSP {SUCCESS, chars}"]; + * APP=>SD [label = "sd_ble_gattc_characteristics_discover(handle_range + N)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_DISC_RSP {SUCCESS, chars}"]; + * APP=>SD [label = "sd_ble_gattc_characteristics_discover(handle_range + N + M)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_DISC_RSP {ATTRIBUTE_NOT_FOUND}"]; + * @endmsc + * + * @defgroup BLE_GATTC_DESC_DISC_MSC GATTC Descriptor Discovery + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gattc_descriptors_discover(handle_range)"]; + * APP<PEER [label = "ATT Find Information Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Find Information Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_DESC_DISC_RSP {SUCCESS, descs}"]; + * APP=>SD [label = "sd_ble_gattc_descriptors_discover(handle_range + N)"]; + * APP<PEER [label = "ATT Find Information Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Find Information Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_DESC_DISC_RSP {SUCCESS, descs}"]; + * APP=>SD [label = "sd_ble_gattc_descriptors_discover(handle_range + N + M)"]; + * APP<PEER [label = "ATT Find Information Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_DESC_DISC_RSP {ATTRIBUTE_NOT_FOUND}"]; + * @endmsc + * + * @defgroup BLE_GATTC_READ_UUID_MSC GATTC Read Characteristic Value by UUID + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP=>SD [label = "sd_ble_gattc_char_value_by_uuid_read(uuid, handle_range)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP {SUCCESS, char_values}"]; + * APP=>SD [label = "sd_ble_gattc_char_value_by_uuid_read(uuid, handle_range + N)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read By Type Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP {SUCCESS, char_values}"]; + * APP=>SD [label = "sd_ble_gattc_char_value_by_uuid_read(uuid, handle_range + N + M)"]; + * APP<PEER [label = "ATT Read By Type Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Attribute Not Found", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP {ATTRIBUTE_NOT_FOUND}"]; + * @endmsc + * + * @defgroup BLE_GATTC_VALUE_READ_MSC GATTC Characteristic or Descriptor Value Read + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * --- [label = " Variant #1 offset == 0 "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_read(handle, 0)"]; + * APP<PEER [label = "ATT Read Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_READ_RSP {SUCCESS, value}"]; + * |||; + * --- [label = " Variant #2 offset != 0 "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_read(handle, offset)"]; + * APP<PEER [label = "ATT Read Blob Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read Blob Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_READ_RSP {SUCCESS, value}"]; + * APP=>SD [label = "sd_ble_gattc_read(handle, offset + N)"]; + * APP<PEER [label = "ATT Read Blob Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read Blob Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_READ_RSP {SUCCESS, value}"]; + * APP=>SD [label = "sd_ble_gattc_read(handle, offset + N + M + 1)"]; + * APP<PEER [label = "ATT Read Blob Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Invalid Offset", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_READ_RSP {INVALID_OFFSET}"]; + * @endmsc + * + * @defgroup BLE_GATTC_READ_MULT_MSC GATTC Read Multiple Characteristic Values + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * --- [label = " Variant #1 Successful request "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_char_values_read(handles)"]; + * APP<PEER [label = "ATT Read Multiple Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Read Multiple Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_VALS_READ_RSP {SUCCESS, char_values}"]; + * |||; + * --- [label = " Variant #2 Failing request (invalid handle) "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_char_values_read(handles)"]; + * APP<PEER [label = "ATT Read Multiple Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Error Response: Invalid Handle", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_CHAR_VALS_READ_RSP {INVALID_HANDLE, error_handle=}"]; + * @endmsc + * + * @defgroup BLE_GATTC_VALUE_WRITE_MSC GATTC Characteristic or Descriptor Value Write + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * --- [label = " Variant #1 write_op == BLE_GATT_OP_WRITE_CMD "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_write(handle, value)"]; + * APP<PEER [label = "ATT Write Command", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_TX_COMPLETE"]; + * |||; + * --- [label = " Variant #2 write_op == BLE_GATT_OP_WRITE_REQ "]; + * |||; + * APP=>SD [label = "sd_ble_gattc_write(handle, value)"]; + * APP<PEER [label = "ATT Write Request", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_WRITE_RSP {SUCCESS}"]; + * @endmsc + * + * @defgroup BLE_GATTC_HVI_MSC GATTC Handle Value Indication + * GATTC Handle Value Indication MSC + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD<:PEER [label = "ATT Handle Value Indication", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_HVX {INDICATION, data}"]; + * APP=>SD [label = "sd_ble_gattc_hv_confirm(handle)"]; + * APP<PEER [label = "ATT Handle Value Confirmation", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTC_HVN_MSC GATTC Handle Value Notification + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD<:PEER [label = "ATT Handle Value Notification", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTC_EVT_HVX {NOTIFICATION, data}"]; + * @endmsc + * + * @defgroup BLE_GATTC_TIMEOUT_MSC GATTC Timeout + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox PEER [label="Any GATTC API used"]; + * SD:>PEER [label = "ATT Packet", textcolor="#000080", linecolor="#000080"]; + * APP note PEER [label = "No Response from Peer"]; + * |||; + * ...; + * |||; + * SD box SD [label="Timeout"]; + * APP<<=SD [label = "BLE_GATTC_EVT_TIMEOUT {source}"]; + * APP rbox PEER [label="No additional ATT Traffic Allowed", textbgcolour="#ff7f7f"]; + * APP=>SD [label = "Any API call"]; + * APP<SD [label = "sd_ble_gatts_service_add(uuid#1)"]; + * APP<SD [label = "sd_ble_gatts_characteristic_add(handle_srvc#1, char_md, value)"]; + * APP<SD [label = "sd_ble_gatts_descriptor_add(handle_char#1, value)"]; + * APP<SD [label = "sd_ble_gatts_descriptor_add(handle_char#1, value)"]; + * APP<SD [label = "sd_ble_gatts_characteristic_add(handle_srvc#1, char_md, value)"]; + * APP<SD [label = "sd_ble_gatts_descriptor_add(handle_char#2, value)"]; + * APP<SD [label = "sd_ble_gatts_service_add(uuid#2)"]; + * APP<SD [label = "sd_ble_gatts_include_add(handle_srvc#2, handle_srvc#1)"]; + * APP<PEER [label = "ATT Read Response", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_WRITE_REQ_NO_AUTH_MSC GATTS Write Request without Authorization + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD<:PEER [label = "ATT Write Request", textcolor="#000080", linecolor="#000080"]; + * SD:>PEER [label = "ATT Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_WRITE {WRITE_REQ, data}"]; + * @endmsc + * + * @defgroup BLE_GATTS_WRITE_CMD_NO_AUTH_MSC GATTS Write Command with or without Authorization + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD<:PEER [label = "ATT Write Command", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_WRITE {WRITE_CMD, data}"]; + * @endmsc + * + * @defgroup BLE_GATTS_READ_REQ_AUTH_MSC GATTS Read Request with Authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * SD<:PEER [label = "ATT Read Request", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {READ, current_value}"]; + * --- [label = " Variant #1 App Authorizes "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(SUCCESS, app_value)"]; + * APP<PEER [label = "ATT Read Response {app_value}", textcolor="#000080", linecolor="#000080"]; + * --- [label = " Variant #2 App Disallows "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(READ_NOT_PERMITTED)"]; + * APP<PEER [label = "ATT Error Response", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_WRITE_REQ_AUTH_MSC GATTS Write Request with Authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * SD<:PEER [label = "ATT Write Request {peer_data}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, peer_value}"]; + * --- [label = " Variant #1 App Authorizes "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(SUCCESS)"]; + * APP<PEER [label = "ATT Write Response", textcolor="#000080", linecolor="#000080"]; + * --- [label = " Variant #2 App Disallows "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE_NOT_PERMITTED)"]; + * APP<PEER [label = "ATT Error Response", textcolor="#000080", linecolor="#000080"]; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * @endmsc + * + * @defgroup BLE_GATTS_QUEUED_WRITE_BUF_NOAUTH_MSC GATTS Queued Writes: Stack handled, no attributes require authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_REQUEST {BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES}"]; + * APP=>SD [label = "sd_ble_user_mem_reply {user_mem_block}"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #1 Attribute Values validation passed "]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: peer_value_2"]; + * APP<<=SD [label = "BLE_GATTS_EVT_WRITE {EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="App parses the memory it provided"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * --- [label = " Variant #2 Attribute Values validation failed "]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Error Response {Invalid Value Length / Offset}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * --- [label = " Variant #3 Peer cancels operation "]; + * SD<:PEER [label = "ATT Execute Write Request {CANCEL}", textcolor="#000080", linecolor="#000080"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * @endmsc + * + * @defgroup BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC GATTS Queued Writes: Stack handled, one or more attributes require authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_REQUEST {BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES}"]; + * APP=>SD [label = "sd_ble_user_mem_reply {user_mem_block}"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_2, offset_2, peer_value_2}"]; + * |||; + * --- [label = " Variant #1 App Authorizes both Prepare Write and Execute Write"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="App parses the memory it provided"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: peer_value_2"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * --- [label = " Variant #2 App Disallows Prepare Write and Authorizes Execute Write "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, INSUF_AUTHORIZATION)"]; + * SD:>PEER [label = "ATT Error Response {Insufficient Authorization}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="App parses the memory it provided"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * --- [label = " Variant #3 App Authorizes Prepare Write and Disallows Execute Write "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="App parses the memory it provided"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, APP_ERROR_CODE)"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Error Response {APP_ERROR_CODE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * @endmsc + * + * @defgroup BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC GATTS Queued Writes: App handled, no attributes require authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_REQUEST {BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES}"]; + * APP=>SD [label = "sd_ble_user_mem_reply {NULL}"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_1, offset_1, peer_value_1}"]; + * APP rbox APP [label="App queues {handle_1, offset_1, peer_value_1}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_2, offset_2, peer_value_2}"]; + * APP rbox APP [label="App queues {handle_2, offset_2, peer_value_2}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * |||; + * --- [label = " Variant #1 Attribute values in stack memory (VLOC_STACK), attribute values validation passed "]; + * APP=>SD [label = "sd_ble_gatts_value_set {handle_1, offset_1, peer_value_1}"]; + * APP<SD [label = "sd_ble_gatts_value_set {handle_2, offset_2, peer_value_2}"]; + * APP<SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #2 Attribute values in user memory (VLOC_USER), attribute values validation passed "]; + * APP rbox APP [label="Application traverses its queue and executes the write operations (memcpy)"]; + * APP rbox APP [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: peer_value_2"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #3 Attribute values validation failed "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, INVALID_OFFSET)"]; + * APP rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Error Response {Invalid Offset}", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC GATTS Queued Writes: App handled, one or more attributes require authorization + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox APP [label="Values in ATT Table (in user memory):\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_REQUEST {BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES}"]; + * APP=>SD [label = "sd_ble_user_mem_reply {NULL}"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_1, offset_1, peer_value_1}"]; + * APP rbox APP [label="App queues {handle_1, offset_1, peer_value_1}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_2, offset_2, peer_value_2}"]; + * |||; + * --- [label = " Variant #1 App Authorizes both Prepare Write and Execute Write"]; + * APP rbox APP [label="App queues {handle_2, offset_2, peer_value_2}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="Application traverses its queue and executes the write operations (memcpy)"]; + * APP rbox APP [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: peer_value_2"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #2 App Disallows Prepare Write and Authorizes Execute Write "]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, INSUF_AUTHORIZATION)"]; + * SD:>PEER [label = "ATT Error Response {Insufficient Authorization}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="Application traverses its queue and executes the write operations (memcpy)"]; + * APP rbox APP [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: current_value_2"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * |||; + * --- [label = " Variant #3 App Authorizes Prepare Write and Disallows Execute Write "]; + * APP rbox APP [label="App queues {handle_2, offset_2, peer_value_2}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, APP_ERROR_CODE)"]; + * APP rbox APP [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Error Response {APP_ERROR_CODE}", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC GATTS Queued Writes: Prepare Queue Full + * @msc + * hscale = "2"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: current_value_1\nhandle_2: current_value_2"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_REQUEST {BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES}"]; + * |||; + * --- [label = " Variant #1 Stack handled "]; + * APP=>SD [label = "sd_ble_user_mem_reply {user_mem_block}"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * SD:>PEER [label = "ATT Error Response {Prepare Queue Full}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: current_value_2"]; + * APP<<=SD [label = "BLE_GATTS_EVT_WRITE {EXEC_WRITE_REQ_NOW}"]; + * APP rbox APP [label="App parses the memory it provided"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_USER_MEM_RELEASE {user_mem_block}"]; + * |||; + * --- [label = " Variant #2 App handled "]; + * APP=>SD [label = "sd_ble_user_mem_reply {NULL}"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_1, offset_1, peer_value_1}"]; + * APP rbox APP [label="App queues {handle_1, offset_1, peer_value_1}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD:>PEER [label = "ATT Prepare Write Response {handle_1, offset_1, peer_value_1}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Prepare Write Request {handle_2, offset_2, peer_value_2}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, PREP_WRITE_REQ, handle_2, offset_2, peer_value_2}"]; + * APP=>SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, PREPARE_QUEUE_FULL)"]; + * SD:>PEER [label = "ATT Error Response {Prepare Queue Full}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Execute Write Request {WRITE}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST {WRITE, EXEC_WRITE_REQ_NOW}"]; + * APP=>SD [label = "sd_ble_gatts_value_set {handle_1, offset_1, peer_value_1}"]; + * APP<SD [label = "sd_ble_gatts_rw_authorize_reply(WRITE, SUCCESS)"]; + * SD rbox SD [label="Values in ATT Table:\nhandle_1: peer_value_1\nhandle_2: current_value_2"]; + * SD:>PEER [label = "ATT Execute Write Response", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_HVI_MSC GATTS Handle Value Indication + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox PEER [label="Indications Enabled in CCCD"]; + * |||; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * APP=>SD [label = "sd_ble_gatts_hvx(INDICATION, app_value)"]; + * APP<PEER [label = "ATT Handle Value Indication {app_value}", textcolor="#000080", linecolor="#000080"]; + * --- [label = " Variant #1 Peer Confirms "]; + * SD<:PEER [label = "ATT Handle Value Confirmation", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_HVC"]; + * --- [label = " Variant #2 Peer Ignores "]; + * |||; + * ...; + * |||; + * SD box SD [label="Timeout"]; + * APP<<=SD [label = "BLE_GATTS_EVT_TIMEOUT"]; + * @endmsc + * + * @defgroup BLE_GATTS_HVN_MSC GATTS Handle Value Notification + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox PEER [label="Notifications Enabled in CCCD"]; + * |||; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * APP=>SD [label = "sd_ble_gatts_hvx(NOTIFICATION, app_value)"]; + * APP<PEER [label = "ATT Handle Value Notification {app_value}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_TX_COMPLETE"]; + * @endmsc + * + * @defgroup BLE_GATTS_HVX_DISABLED_MSC GATTS Handle Value Indication or Notification disabled + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established"]; + * |||; + * APP rbox PEER [label="Indications and Notifications Disabled in CCCD"]; + * |||; + * SD rbox SD [label="Value in ATT Table: current_value"]; + * APP=>SD [label = "sd_ble_gatts_hvx(INDICATION or NOTIFICATION, app_value)"]; + * APP<SD [label = "sd_ble_gatts_hvx(INDICATION or NOTIFICATION, app_value)"]; + * APP<SD [label = "sd_ble_gatts_sys_attr_set()"]; + * APP<SD [label = "sd_ble_gatts_service_changed(N, M)"]; + * APP<PEER [label = "ATT Handle Value Indication {N, M}", textcolor="#000080", linecolor="#000080"]; + * SD<:PEER [label = "ATT Handle Value Confirmation", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_SC_CONFIRM"]; + * |||; + * SD rbox PEER [label="Service Discovery"]; + * @endmsc + * + * @defgroup BLE_GATTS_SYS_ATTRS_UNK_PEER_MSC GATTS System Attributes Handling: Unknown Peer + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established with an Unknown Peer"]; + * |||; + * SD<:PEER [label = "ATT Read Request {sys_attr_handle}", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_GATTS_EVT_SYS_ATTR_MISSING"]; + * APP=>SD [label = "sd_ble_gatts_sys_attr_set(NULL)"]; + * APP<PEER [label = "ATT Read Response {sys_attr_value}", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * + * @defgroup BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC GATTS System Attributes Handling: Bonded Peer + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP rbox PEER [label="Connection Established with a Bonded Peer"]; + * |||; + * APP rbox PEER [label="ATT Traffic"]; + * |||; + * APP rbox PEER [label="Connection Terminated"]; + * APP<<=SD [label = "BLE_GAP_EVT_DISCONNECTED {reason}"]; + * |||; + * APP=>SD [label = "sd_ble_gatts_sys_attr_get()"]; + * APP<SD [label = "sd_ble_gatts_sys_attr_set(sys_attr_data)"]; + * APP<PEER [label = "ATT Read Response {sys_attr_value}", textcolor="#000080", linecolor="#000080"]; + * @endmsc + * @} + * + * @addtogroup BLE_GATTS_QUEUED_WRITES_USER_MEM User memory layout for Queued Writes + * @{ + * The following table shows the memory layout used by the SoftDevice to queue a Queued Write operation (Prepare Write ATT packet) in user memory: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Queued Write
ParameterSize (octets)Description
Handle2Attribute Handle
Offset2Value Offset
Length2Value Length
ValueLengthAttribute Value
+ * + * The application can parse the array of Queued Write instances at any time, but it is recommended to do so whenever an Execute Write ATT packet + * has been received over the air. See the GATT Server Queued Writes MSCs for more details. + * The array will be terminated by an Queued Write instance with its handle set to @ref BLE_GATT_HANDLE_INVALID. + * @} + * @} + */ + +/** + * @addtogroup BLE_L2CAP + * @{ + * @defgroup BLE_L2CAP_MSC Message Sequence Charts + * @{ + * @defgroup BLE_L2CAP_API_MSC L2CAP API + * @msc + * hscale = "1.5"; + * APP,SD,PEER; + * |||; + * APP=>SD [label = "sd_ble_l2cap_cid_register(cid)"]; + * APP<SD [label = "sd_ble_l2cap_tx(data)"]; + * APP<PEER [label = "L2CAP packet", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_EVT_TX_COMPLETE"]; + * SD<:PEER [label = "L2CAP packet", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_L2CAP_EVT_RX"]; + * SD<:PEER [label = "L2CAP packet", textcolor="#000080", linecolor="#000080"]; + * APP<<=SD [label = "BLE_L2CAP_EVT_RX"]; + * |||; + * APP=>SD [label = "sd_ble_l2cap_tx(data)"]; + * APP<PEER [label = "L2CAP packet", textcolor="#000080", linecolor="#000080"]; + * SD=>>APP [label = "BLE_EVT_TX_COMPLETE"]; + * |||; + * APP rbox PEER [label="Terminate Connection"]; + * |||; + * APP=>SD [label = "sd_ble_l2cap_cid_unregister(cid)"]; + * APP<_EVT series. */ + uint16_t evt_len; /**< Length in octets excluding this header. */ +} ble_evt_hdr_t; + +/**@brief Common BLE Event type, wrapping the module specific event reports. */ +typedef struct +{ + ble_evt_hdr_t header; /**< Event header. */ + union + { + ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */ + ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */ + ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */ + ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */ + ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */ + } evt; +} 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 Common BLE Option type, wrapping the module specific options. */ +typedef union +{ + ble_gap_opt_t gap; /**< GAP option, opt_id in BLE_GAP_OPT_* series. */ +} ble_opt_t; + +/** + * @brief BLE GATTS init options + */ +typedef struct +{ + ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init options @ref ble_gatts_enable_params_t. */ +} ble_enable_params_t; + +/** @} */ + +/** @addtogroup BLE_COMMON_FUNCTIONS Functions + * @{ */ + +/**@brief Enable the bluetooth stack + * + * @param[in] p_ble_enable_params Pointer to ble_enable_params_t + * + * @details This call initializes the bluetooth stack, no other BLE related call can be called before this one has been executed. + * + * @return @ref NRF_SUCCESS BLE stack has been initialized successfully + * @return @ref NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + */ +SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(ble_enable_params_t * p_ble_enable_params)); + +/**@brief Get an event from the pending events queue. + * + * @param[in] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length. This buffer must be 4-byte aligned in memory. + * @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 signalled that an event is + * available from the BLE Stack by the triggering of the SD_EVT_IRQn interrupt (mapped to IRQ 22). + * 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 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. + * Please note that because of the variable length nature of some events, sizeof(ble_evt_t) will not always be large enough to fit certain events, + * and so it is the application's responsability to provide an amount of memory large enough so that the relevant event is copied in full. + * The application may "peek" the event length by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return. + * + * @note The pointer supplied must be aligned to the extend defined by @ref BLE_EVTS_PTR_ALIGNMENT + * + * @return @ref NRF_SUCCESS Event pulled and stored into the supplied buffer. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied. + * @return @ref NRF_ERROR_NOT_FOUND No events ready to be pulled. + * @return @ref NRF_ERROR_DATA_SIZE Event ready but could not fit into the supplied buffer. + */ +SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t* p_dest, uint16_t *p_len)); + + +/**@brief Get the total number of available application transmission buffers in the BLE stack. + * + * @details This call allows the application to obtain the total number of + * transmission buffers available for application data. Please note that + * this does not give the number of free buffers, but rather the total amount of them. + * The application has two options to handle its own application transmission buffers: + * - Use a simple arithmetic calculation: at boot time the application should use this function + * to find out the total amount of buffers available to it and store it in a variable. + * Every time a packet that consumes an application buffer is sent using any of the + * exposed functions in this BLE API, the application should decrement that variable. + * Conversely, whenever a @ref BLE_EVT_TX_COMPLETE event is received by the application + * it should retrieve the count field in such event and add that number to the same + * variable storing the number of available packets. + * This mechanism allows the application to be aware at any time of the number of + * application packets available in the BLE stack's internal buffers, and therefore + * it can know with certainty whether it is possible to send more data or it has to + * wait for a @ref BLE_EVT_TX_COMPLETE event before it proceeds. + * - Choose to simply not keep track of available buffers at all, and instead handle the + * @ref BLE_ERROR_NO_TX_BUFFERS error by queueing the packet to be transmitted and + * try again as soon as a @ref BLE_EVT_TX_COMPLETE event arrives. + * + * The API functions that may consume an application buffer depending on + * the parameters supplied to them can be found below: + * + * - @ref sd_ble_gattc_write (write witout response only) + * - @ref sd_ble_gatts_hvx (notifications only) + * - @ref sd_ble_l2cap_tx (all packets) + * + * @param[out] p_count Pointer to a uint8_t which will contain the number of application transmission buffers upon + * successful return. + * + * @return @ref NRF_SUCCESS Number of application transmission buffers retrieved successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_TX_BUFFER_COUNT_GET, uint32_t, sd_ble_tx_buffer_count_get(uint8_t* p_count)); + + +/**@brief Add a Vendor Specific UUID. + * + * @details This call enables the application to add a vendor specific UUID to the BLE stack's table, + * for later use 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. The way that this is accomplished is by extending the + * grouping mechanism that the Bluetooth SIG standard base UUID uses for all other 128-bit UUIDs. The + * type field in the @ref ble_uuid_t structure is an index (relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN) + * to the table populated by multiple calls to this function, and the uuid field in the same structure + * contains the 2 bytes at indices 12 and 13. The number of possible 128-bit UUIDs available to the + * application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536, + * although restricted to modifying bytes 12 and 13 for each of the entries in the supplied array. + * + * @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by + * the 16-bit uuid field in @ref ble_uuid_t. + * + * + * @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 where the type field in @ref ble_uuid_t corresponding to this UUID will be stored. + * + * @return @ref NRF_SUCCESS Successfully added the Vendor Specific UUID. + * @return @ref NRF_ERROR_INVALID_ADDR If p_vs_uuid or p_uuid_type is NULL or invalid. + * @return @ref NRF_ERROR_NO_MEM If there are no more free slots for VS UUIDs. + * @return @ref NRF_ERROR_FORBIDDEN If p_vs_uuid has already been added to the VS UUID table. + */ +SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const * const p_vs_uuid, uint8_t * const 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 pouplated 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[in,out] p_uuid Pointer to a @ref ble_uuid_t structure to be filled in. + * + * @return @ref NRF_SUCCESS Successfully decoded into the @ref ble_uuid_t structure. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_LENGTH Invalid UUID length. + * @return @ref 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 * const p_uuid_le, ble_uuid_t * const 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 validitiy 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. + * + * @return @ref NRF_SUCCESS Successfully encoded into the buffer. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid UUID type. + */ +SVCALL(SD_BLE_UUID_ENCODE, uint32_t, sd_ble_uuid_encode(ble_uuid_t const * const p_uuid, uint8_t * const p_uuid_le_len, uint8_t * const p_uuid_le)); + + +/**@brief Get Version Information. + * + * @details This call allows the application to get the BLE stack version information. + * + * @param[in] p_version Pointer to ble_version_t structure to be filled in. + * + * @return @ref NRF_SUCCESS Version information stored successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_BUSY The 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. + * + * @return @ref NRF_SUCCESS Successfully queued a response to the peer. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_STATE No execute write request pending. + */ +SVCALL(SD_BLE_USER_MEM_REPLY, uint32_t, sd_ble_user_mem_reply(uint16_t conn_handle, ble_user_mem_block_t *p_block)); + + +/**@brief Set a BLE option. + * + * @details This call allows the application to set the value of an option. + * + * @param[in] opt_id Option ID. + * @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 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. + * @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 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)); + +/** @} */ + +#endif /* BLE_H__ */ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_err.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_err.h new file mode 100644 index 00000000000..19f43a92756 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_err.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + /** + @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" + +/* @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_BUFFERS (NRF_ERROR_STK_BASE_NUM+0x004) /**< Buffer capacity exceeded. */ +/** @} */ + + +/** @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. */ +/** @} */ + +#endif + + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gap.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gap.h new file mode 100644 index 00000000000..c4e325a3d9c --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gap.h @@ -0,0 +1,1032 @@ +/* Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @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" + + +/**@addtogroup BLE_GAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief GAP API SVC numbers. + */ +enum BLE_GAP_SVCS +{ + SD_BLE_GAP_ADDRESS_SET = BLE_GAP_SVC_BASE, /**< Set own Bluetooth Address. */ + SD_BLE_GAP_ADDRESS_GET, /**< Get own Bluetooth Address. */ + SD_BLE_GAP_ADV_DATA_SET, /**< Set Advertisement 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_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. */ +}; +/**@} */ + +/**@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. */ +/**@} */ + + +/**@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_ADVERTISEMENT 0x00 /**< Advertisement timeout. */ +#define BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST 0x01 /**< Security request 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 /**< Private Resolvable address. */ +#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03 /**< Private Non-Resolvable address. */ +/**@} */ + +/**@defgroup BLE_GAP_ADDR_CYCLE_MODES GAP Address cycle modes + * @{ */ +#define BLE_GAP_ADDR_CYCLE_MODE_NONE 0x00 /**< Set addresses directly, no automatic address cycling. */ +#define BLE_GAP_ADDR_CYCLE_MODE_AUTO 0x01 /**< Automatically generate and update private addresses. */ +/** @} */ + +/**@brief The default interval in seconds at which a private address is refreshed when address cycle mode is @ref BLE_GAP_ADDR_CYCLE_MODE_AUTO. */ +#define BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S (60 * 15) + +/** @brief BLE address length. */ +#define BLE_GAP_ADDR_LEN 6 + + +/**@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_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. */ + /**@} */ + + +/**@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) = 180s in spec (Addendum 2)). */ +#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_SEC_STATUS GAP Security status + * @{ */ +#define BLE_GAP_SEC_STATUS_SUCCESS 0x00 /**< Successful parameters. */ +#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_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user cancelled 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. */ +/**@} */ + +/**@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 connction interval specified in connect parameters. */ +#define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 /**< Lowest mimimum 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 connction 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 0x03E8 /**< 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. */ +/**@} */ + + +/**@brief GAP device name maximum length. */ +#define BLE_GAP_DEVNAME_MAX_LEN 31 + + +/**@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 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 Key Length. */ +#define BLE_GAP_SEC_KEY_LEN 16 + +/**@brief GAP Passkey Length. */ +#define BLE_GAP_PASSKEY_LEN 6 + +/**@brief Maximum amount of addresses in a whitelist. */ +#define BLE_GAP_WHITELIST_ADDR_MAX_COUNT (8) + +/**@brief Maximum amount of IRKs in a whitelist. + * @note The number of IRKs is limited to 8, even if the hardware supports more. + */ +#define BLE_GAP_WHITELIST_IRK_MAX_COUNT (8) + +/**@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_type; /**< 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. + */ +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 link requirements. + * + * See Bluetooth Core specification, Volume 3 Part C 10.2 for details. + * + * 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 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 or 3), 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 Whitelist structure. */ +typedef struct +{ + ble_gap_addr_t ** pp_addrs; /**< Pointer to array of device address pointers, pointing to addresses to be used in whitelist. NULL if none are given. */ + uint8_t addr_count; /**< Count of device addresses in array, up to @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. */ + ble_gap_irk_t ** pp_irks; /**< Pointer to array of Identity Resolving Key (IRK) pointers, each pointing to an IRK in the whitelist. NULL if none are given. */ + uint8_t irk_count; /**< Count of IRKs in array, up to @ref BLE_GAP_WHITELIST_IRK_MAX_COUNT. */ +} ble_gap_whitelist_t; + + +/**@brief GAP advertising parameters.*/ +typedef struct +{ + uint8_t type; /**< See @ref BLE_GAP_ADV_TYPES. */ + ble_gap_addr_t* p_peer_addr; /**< For BLE_GAP_CONN_MODE_DIRECTED mode only, known peer address. */ + uint8_t fp; /**< Filter Policy, see @ref BLE_GAP_ADV_FILTER_POLICIES. */ + ble_gap_whitelist_t * p_whitelist; /**< Pointer to whitelist, NULL if none is given. */ + uint16_t interval; /**< Advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20ms to 10.24s), see @ref BLE_GAP_ADV_INTERVALS. This parameter must be set to 0 if type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND. */ + uint16_t timeout; /**< Advertising timeout between 0x0001 and 0x3FFF in seconds, 0x0000 disables timeout. See also @ref BLE_GAP_ADV_TIMEOUT_VALUES. This parameter must be set to 0 if type equals @ref BLE_GAP_ADV_TYPE_ADV_DIRECT_IND. */ +} ble_gap_adv_params_t; + + +/**@brief GAP scanning parameters. */ +typedef struct +{ + uint8_t filter; /**< Filter based on discovery mode, see @ref BLE_GAP_DISC_MODES. */ + uint8_t active : 1; /**< If 1, perform active scanning (scan requests). */ + uint8_t selective : 1; /**< If 1, ignore unknown devices (non whitelisted). */ + uint16_t interval; /**< Scan interval between 0x0020 and 0x4000 in 0.625ms units (20ms to 10.24s). */ + uint16_t window; /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ + uint16_t timeout; /**< Scan timeout between 0x0001 and 0x3FFF in seconds, 0x0000 disables timeout. */ +} ble_gap_scan_params_t; + + +/**@brief GAP security parameters. */ +typedef struct +{ + uint16_t timeout; /**< Timeout for SMP transactions or Security Request in seconds, see @ref sd_ble_gap_authenticate and @ref sd_ble_gap_sec_params_reply for more information. */ + uint8_t bond : 1; /**< Perform bonding. */ + uint8_t mitm : 1; /**< Man In The Middle protection required. */ + uint8_t io_caps : 3; /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ + uint8_t oob : 1; /**< Out Of Band data available. */ + uint8_t min_key_size; /**< Minimum encryption key size in octets between 7 and 16. */ + uint8_t max_key_size; /**< Maximum encryption key size in octets between min_key_size and 16. */ +} ble_gap_sec_params_t; + + +/**@brief GAP Encryption Information. */ +typedef struct +{ + uint16_t div; /**< Encryption Diversifier. */ + uint8_t ltk[BLE_GAP_SEC_KEY_LEN]; /**< Long Term Key. */ + uint8_t auth : 1; /**< Authenticated Key. */ + uint8_t ltk_len : 7; /**< LTK length in octets. */ +} ble_gap_enc_info_t; + + +/**@brief GAP Master Identification. */ +typedef struct +{ + uint16_t ediv; /**< Encrypted Diversifier. */ + uint8_t rand[8]; /**< Random Number. */ +} ble_gap_master_id_t; + + +/**@brief GAP Identity Information. */ +typedef struct +{ + ble_gap_addr_t addr; /**< Bluetooth address to which this key applies. */ + uint8_t irk[BLE_GAP_SEC_KEY_LEN]; /**< Identity Resolution Key. */ +} ble_gap_id_info_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 Event IDs. + * Those IDs 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. */ + BLE_GAP_EVT_DISCONNECTED, /**< Disconnected from peer. */ + BLE_GAP_EVT_CONN_PARAM_UPDATE, /**< Connection Parameters updated. */ + BLE_GAP_EVT_SEC_PARAMS_REQUEST, /**< Request to provide security parameters. */ + BLE_GAP_EVT_SEC_INFO_REQUEST, /**< Request to provide security information. */ + BLE_GAP_EVT_PASSKEY_DISPLAY, /**< Request to display a passkey to the user. */ + BLE_GAP_EVT_AUTH_KEY_REQUEST, /**< Request to provide an authentication key. */ + BLE_GAP_EVT_AUTH_STATUS, /**< Authentication procedure completed with status. */ + BLE_GAP_EVT_CONN_SEC_UPDATE, /**< Connection security updated. */ + BLE_GAP_EVT_TIMEOUT, /**< Timeout expired. */ + BLE_GAP_EVT_RSSI_CHANGED, /**< Signal strength measurement report. */ +}; + + +/** + * @brief GAP Option IDs. + * IDs that uniquely identify a GAP option. + */ +enum BLE_GAP_OPTS +{ + BLE_GAP_OPT_LOCAL_CONN_LATENCY = BLE_GAP_OPT_BASE, /**< Local connection latency. */ + BLE_GAP_OPT_PASSKEY, /**< Set passkey to be used during pairing. This option can be used to make the SoftDevice use an application provided passkey instead of generating a random passkey.*/ + BLE_GAP_OPT_PRIVACY, /**< Set or get custom IRK or custom private address cycle interval. */ +}; +/**@} */ + + +/**@brief Event data for connected event. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + uint8_t irk_match :1; /**< If 1, peer device's address resolved using an IRK. */ + uint8_t irk_match_idx :7; /**< Index in IRK list where the address was matched. */ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_connected_t; + + +/**@brief Event data for disconnected event. */ +typedef struct +{ + uint8_t reason; /**< HCI error code. */ +} ble_gap_evt_disconnected_t; + + +/**@brief Event data for connection parameter update event. */ +typedef struct +{ + ble_gap_conn_params_t conn_params; /**< GAP Connection Parameters. */ +} ble_gap_evt_conn_param_update_t; + + +/**@brief Event data for security parameters request event. */ +typedef struct +{ + ble_gap_sec_params_t peer_params; /**< Initiator Security Parameters. */ +} ble_gap_evt_sec_params_request_t; + + +/**@brief Event data for security info request event. */ +typedef struct +{ + ble_gap_addr_t peer_addr; /**< Bluetooth address of the peer device. */ + uint16_t div; /**< Encryption diversifier 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 data for passkey display event. */ +typedef struct +{ + uint8_t passkey[BLE_GAP_PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ +} ble_gap_evt_passkey_display_t; + + +/**@brief Event data for authentication key request event. */ +typedef struct +{ + uint8_t key_type; /**< See @ref BLE_GAP_AUTH_KEY_TYPES. */ +} ble_gap_evt_auth_key_request_t; + + +/**@brief Security levels supported. + * @note See Bluetooth Specification Version 4.1 Volume 3, Part C, Chapter 10. +*/ +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. */ +} ble_gap_sec_levels_t; + + +/**@brief Keys that have been exchanged. */ +typedef struct +{ + uint8_t ltk : 1; /**< Long Term Key. */ + uint8_t ediv_rand : 1; /**< Encrypted Diversifier and Random value. */ + uint8_t irk : 1; /**< Identity Resolving Key. */ + uint8_t address : 1; /**< Public or static random address. */ + uint8_t csrk : 1; /**< Connection Signature Resolving Key. */ +} ble_gap_sec_keys_t; + + +/**@brief Event data for authentication status event. */ +typedef struct +{ + uint8_t auth_status; /**< Authentication status, see @ref BLE_GAP_SEC_STATUS. */ + uint8_t error_src; /**< On error, source that caused the failure, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ + 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_keys_t periph_kex; /**< Bitmap stating which keys were exchanged (distributed) by the peripheral. */ + ble_gap_sec_keys_t central_kex; /**< Bitmap stating which keys were exchanged (distributed) by the central. */ + struct periph_keys_t + { + ble_gap_enc_info_t enc_info; /**< Peripheral's Encryption information. */ + } periph_keys; /**< Actual keys distributed from the Peripheral to the Central. */ + struct central_keys_t + { + ble_gap_irk_t irk; /**< Central's IRK. */ + ble_gap_addr_t id_info; /**< Central's Identity Info. */ + } central_keys; /**< Actual keys distributed from the Central to the Peripheral. */ +} ble_gap_evt_auth_status_t; + + +/**@brief Event data for connection security update event. */ +typedef struct +{ + ble_gap_conn_sec_t conn_sec; /**< Connection security level. */ +} ble_gap_evt_conn_sec_update_t; + + +/**@brief Event data for timeout event. */ +typedef struct +{ + uint8_t src; /**< Source of timeout event, see @ref BLE_GAP_TIMEOUT_SOURCES. */ +} ble_gap_evt_timeout_t; + + +/**@brief Event data for advertisement report event. */ +typedef struct +{ + int8_t rssi; /**< Received Signal Strength Indication in dBm. */ +} ble_gap_evt_rssi_changed_t; + + +/**@brief GAP event callback event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occured. */ + 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_auth_key_request_t auth_key_request; /**< Authentication Key Request Event Parameters. */ + 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. */ + } params; + +} ble_gap_evt_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 default off, and needs to be set 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 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 pre-programmed passkey for authentication + * instead of generating a random one. + * + * @note @ref sd_ble_opt_get is not supported for this option. + * + */ +typedef struct +{ + uint8_t * 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 Custom Privacy Options. + * + * @note The specified address cycle interval is used when the address cycle mode is + * @ref BLE_GAP_ADDR_CYCLE_MODE_AUTO. If 0 is given, the address will not be refreshed at any + * interval, and not at start of advertising. A new address can be generated manually by calling + * @ref sd_ble_gap_address_set with the same type again. The default interval is + * @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. + * + * @note If cycle mode is @ref BLE_GAP_ADDR_CYCLE_MODE_AUTO, the address will immediately be + * refreshed when this option is set. + */ +typedef struct +{ + ble_gap_irk_t * p_irk; /**< When input: Pointer to custom IRK, or NULL to use/reset to the device's default IRK. When output: Pointer to where the current IRK is to be stored, or NULL to not read out the IRK. */ + uint16_t interval_s; /**< When input: Custom private address cycle interval in seconds. When output: The current private address cycle interval. */ +} ble_gap_opt_privacy_t; + + +/**@brief Option structure for GAP options. */ +typedef union +{ + ble_gap_opt_local_conn_latency_t local_conn_latency; /**< Local connection latency. */ + ble_gap_opt_passkey_t passkey; /**< Passkey to be used for pairing.*/ + ble_gap_opt_privacy_t privacy; /**< Custom privacy options. */ +} ble_gap_opt_t; +/**@} */ + + +/**@addtogroup BLE_GAP_FUNCTIONS Functions + * @{ */ + +/**@brief Set local Bluetooth address. + * + * If the address cycle mode is @ref BLE_GAP_ADDR_CYCLE_MODE_AUTO, the address type is required to + * be @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or + * @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. The given address is ignored and the + * SoftDevice will generate a new private address automatically every time advertising is + * (re)started, and every @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S seconds. If this API + * call is used again with the same parameters while advertising, the SoftDevice will immediately + * generate a new private address to replace the current address. + * + * If the application wishes to use a @ref BLE_GAP_ADDR_TYPE_PUBLIC or + * @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC address, the cycle mode must be + * @ref BLE_GAP_ADDR_CYCLE_MODE_NONE. + * + * If this API function is called while advertising, the softdevice will immediately update the + * advertising address without the need to stop advertising in the following cases: + * - If the previously set address is of type @ref BLE_GAP_ADDR_TYPE_PUBLIC and the new address + * is also of type @ref BLE_GAP_ADDR_TYPE_PUBLIC + * - If the previously set address is not @ref BLE_GAP_ADDR_TYPE_PUBLIC and the new address is + * also not @ref BLE_GAP_ADDR_TYPE_PUBLIC. + * + * If the address is changed from a @ref BLE_GAP_ADDR_TYPE_PUBLIC address to another type or from + * another type to a @ref BLE_GAP_ADDR_TYPE_PUBLIC address, the change will take effect the next + * time advertising is started. + * + * @note If the address cycle mode is @ref BLE_GAP_ADDR_CYCLE_MODE_NONE and the application is + * using privacy, the application must take care to generate and set new private addresses + * periodically to comply with the Privacy specification in Bluetooth Core Spec. + * + * @param[in] addr_cycle_mode Address cycle mode, see @ref BLE_GAP_ADDR_CYCLE_MODES. + * @param[in] p_addr Pointer to address structure. + * + * @return @ref NRF_SUCCESS Address successfully set. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameters. + * @return @ref BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address. + * @return @ref NRF_ERROR_BUSY The stack is busy, process pending events and retry. + */ +SVCALL(SD_BLE_GAP_ADDRESS_SET, uint32_t, sd_ble_gap_address_set(uint8_t addr_cycle_mode, ble_gap_addr_t const * const p_addr)); + + +/**@brief Get local Bluetooth address. + * + * @param[out] p_addr Pointer to address structure. + * + * @return @ref NRF_SUCCESS Address successfully retrieved. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_ADDRESS_GET, uint32_t, sd_ble_gap_address_get(ble_gap_addr_t * const p_addr)); + + +/**@brief Set, clear or update advertisement and scan response data. + * + * @note The format of the advertisement 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 advertisement data and scan response data. + * + * @note: To clear the advertisement 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. + * + * @param[in] p_data Raw data to be placed in advertisement packet. If NULL, no changes are made to the current advertisement 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. + * + * @return @ref NRF_SUCCESS Advertisement data successfully updated or cleared. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_FLAGS Invalid combination of advertising flags supplied. + * @return @ref NRF_ERROR_INVALID_DATA Invalid data type(s) supplied, check the advertising data format specification. + * @return @ref NRF_ERROR_INVALID_LENGTH Invalid data length(s) supplied. + * @return @ref BLE_ERROR_GAP_UUID_LIST_MISMATCH Invalid UUID list supplied. + * @return @ref NRF_ERROR_BUSY The stack is busy, process pending events and retry. + */ +SVCALL(SD_BLE_GAP_ADV_DATA_SET, uint32_t, sd_ble_gap_adv_data_set(uint8_t const * const p_data, uint8_t dlen, uint8_t const * const p_sr_data, uint8_t srdlen)); + + +/**@brief Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @param[in] p_adv_params Pointer to advertising parameters structure. + * + * @return @ref NRF_SUCCESS The BLE stack has started advertising. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check the accepted ranges and limits. + * @return @ref BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Bluetooth address supplied. + * @return @ref BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST Discoverable mode and whitelist incompatible. + */ +SVCALL(SD_BLE_GAP_ADV_START, uint32_t, sd_ble_gap_adv_start(ble_gap_adv_params_t const * const p_adv_params)); + + +/**@brief Stop advertising (GAP Discoverable, Connectable modes, Broadcast Procedure). + * + * @return @ref NRF_SUCCESS The BLE stack has stopped advertising. + * @return @ref 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. + * + * @note If both a connection supervision timeout and a maximum connection interval are specified, then the following constraint + * applies: (conn_sup_timeout * 8) >= (max_conn_interval * (slave_latency + 1)) + * + * @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. + * + * @return @ref NRF_SUCCESS The Connection Update procedure has been started successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints. + * @return @ref NRF_ERROR_BUSY Procedure already in progress or not allowed at this time, process pending events and retry. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @return @ref 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 * 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 BLE_GAP_EVT_DISCONNECTED event. + * + * @param[in] conn_handle Connection handle. + * @param[in] hci_status_code HCI status code, see @ref BLE_HCI_STATUS_CODES (accepted values are BTLE_REMOTE_USER_TERMINATED_CONNECTION and BTLE_CONN_INTERVAL_UNACCEPTABLE). + * + * @return @ref NRF_SUCCESS The disconnection procedure has been started successfully. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation (disconnection is already in progress or not connected at all). + */ +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, -30, -20, -16, -12, -8, -4, 0, and 4 dBm). + * + * @note -40 dBm will not actually give -40 dBm, but will instead be remapped to -30 dBm. + * + * @return @ref NRF_SUCCESS Successfully changed the transmit power. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_BUSY The stack is busy, process pending events and retry. + */ +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. + * + * @return @ref NRF_SUCCESS Appearance value set successfully. + * @return @ref 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 Appearance (16-bit), see @ref BLE_APPEARANCES. + * + * @return @ref NRF_SUCCESS Appearance value retrieved successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + */ +SVCALL(SD_BLE_GAP_APPEARANCE_GET, uint32_t, sd_ble_gap_appearance_get(uint16_t * const 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. + * + * @return @ref NRF_SUCCESS Peripheral Preferred Connection Parameters set successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * 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. + * + * @return @ref NRF_SUCCESS Peripheral Preferred Connection Parameters retrieved successfully. + * @return @ref 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 * const p_conn_params)); + + +/**@brief Set GAP device name. + * + * @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). + * + * @return @ref NRF_SUCCESS GAP device name and permissions set successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + */ +SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const * const p_write_perm, uint8_t const * const p_dev_name, uint16_t len)); + + +/**@brief Get GAP device name. + * + * @param[in] 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. + * + * @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. + * + * @return @ref NRF_SUCCESS GAP device name retrieved successfully. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const p_dev_name, uint16_t * const p_len)); + + +/**@brief Initiate GAP Authentication procedure. + * + * @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 procedure. + * + * @details In the central role, this function will send an SMP Pairing Request, otherwise in the peripheral role, an SMP Security Request will be sent. + * In the peripheral role, only the timeout, bond and mitm fields of @ref ble_gap_sec_params_t are used. + * + * @note The GAP Authentication procedure may be triggered by the central without calling this function when accessing a secure service. + * @note Calling this function may result in the following events depending on the outcome and parameters: @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST, + * @ref BLE_GAP_EVT_SEC_INFO_REQUEST, @ref BLE_GAP_EVT_AUTH_KEY_REQUEST, @ref BLE_GAP_EVT_AUTH_STATUS. + * @note The timeout parameter in @ref ble_gap_sec_params_t is interpreted here as the Security Request timeout + * + * + * @return @ref NRF_SUCCESS Successfully initiated authentication procedure. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref 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 * const p_sec_params)); + + +/**@brief Reply with GAP security parameters. + * + * @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. + * + * @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 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 The timeout parameter in @ref ble_gap_sec_params_t is interpreted here as the SMP procedure timeout, and must be 30 seconds. The function will fail + * if the application supplies a different value. + * + * @return @ref NRF_SUCCESS Successfully accepted security parameter from the application. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + */ +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 * const p_sec_params)); + + +/**@brief Reply with an authentication key. + * + * @param[in] conn_handle Connection handle. + * @param[in] key_type See @ref BLE_GAP_AUTH_KEY_TYPES. + * @param[in] key If key type is BLE_GAP_AUTH_KEY_TYPE_NONE, then NULL. + * If key type is BLE_GAP_AUTH_KEY_TYPE_PASSKEY, then a 6-byte ASCII string (digit 0..9 only, no NULL termination). + * If key type is BLE_GAP_AUTH_KEY_TYPE_OOB, then a 16-byte OOB key value in Little Endian format. + * + * @details This function is only used to reply to a @ref BLE_GAP_EVT_AUTH_KEY_REQUEST, calling it at other times will result in an 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. + * + * @return @ref NRF_SUCCESS Authentication key successfully set. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref 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 * const key)); + + +/**@brief Reply with GAP security information. + * + * @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_sign_info Pointer to a @ref ble_gap_sign_info_t signing information structure. May be NULL to signal none is available. + * + * @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 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 implemented yet. p_sign_info must therefore be NULL. + * + * @return @ref NRF_SUCCESS Successfully accepted security information. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied. + * @return @ref NRF_ERROR_BUSY The stack is busy, process pending events and retry. + */ +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 * const p_enc_info, ble_gap_sign_info_t const * 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. + * + * @return @ref NRF_SUCCESS Current connection security successfully retrieved. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const 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. + * + * @param[in] conn_handle Connection handle. + * + * @return @ref NRF_SUCCESS Successfully activated RSSI reporting. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref 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)); + + +/**@brief Stop reporting the received singnal strength. + * + * 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. + * + * @param[in] conn_handle Connection handle. + * + * @return @ref NRF_SUCCESS Successfully deactivated RSSI reporting. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref 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)); +/**@} */ + +#endif // BLE_GAP_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatt.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatt.h new file mode 100644 index 00000000000..2ca27ac3aec --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatt.h @@ -0,0 +1,171 @@ +/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + /** + @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" + + +/** @addtogroup BLE_GATT_DEFINES Defines + * @{ */ + +/** @brief Default MTU size. */ +#define GATT_MTU_SIZE_DEFAULT 23 + +/** @brief Only the default MTU size of 23 is currently supported. */ +#define GATT_RX_MTU 23 + + +/**@brief Invalid Attribute Handle. */ +#define BLE_GATT_HANDLE_INVALID 0x0000 + +/** @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 +#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE 0x01 +/** @} */ + +/** @defgroup BLE_GATT_HVX_TYPES GATT Handle Value operations + * @{ */ +#define BLE_GATT_HVX_INVALID 0x00 /**< Invalid Operation. */ +#define BLE_GATT_HVX_NOTIFICATION 0x01 /**< Handle Value Notification. */ +#define BLE_GATT_HVX_INDICATION 0x02 /**< Handle Value Indication. */ +/** @} */ + +/** @defgroup BLE_GATT_STATUS_CODES GATT Status Codes + * @{ */ +#define BLE_GATT_STATUS_SUCCESS 0x0000 /**< Success. */ +#define BLE_GATT_STATUS_UNKNOWN 0x0001 /**< Unknown or not applicable status. */ +#define BLE_GATT_STATUS_ATTERR_INVALID 0x0100 /**< ATT Error: Invalid Error Code. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_HANDLE 0x0101 /**< ATT Error: Invalid Attribute Handle. */ +#define BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED 0x0102 /**< ATT Error: Read not permitted. */ +#define BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED 0x0103 /**< ATT Error: Write not permitted. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_PDU 0x0104 /**< ATT Error: Used in ATT as Invalid PDU. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION 0x0105 /**< ATT Error: Authenticated link required. */ +#define BLE_GATT_STATUS_ATTERR_REQUEST_NOT_SUPPORTED 0x0106 /**< ATT Error: Used in ATT as Request Not Supported. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_OFFSET 0x0107 /**< ATT Error: Offset specified was past the end of the attribute. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHORIZATION 0x0108 /**< ATT Error: Used in ATT as Insufficient Authorisation. */ +#define BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL 0x0109 /**< ATT Error: Used in ATT as Prepare Queue Full. */ +#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND 0x010A /**< ATT Error: Used in ATT as Attribute not found. */ +#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_LONG 0x010B /**< ATT Error: Attribute cannot be read or written using read/write blob requests. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_ENC_KEY_SIZE 0x010C /**< ATT Error: Encryption key size used is insufficient. */ +#define BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH 0x010D /**< ATT Error: Invalid value size. */ +#define BLE_GATT_STATUS_ATTERR_UNLIKELY_ERROR 0x010E /**< ATT Error: Very unlikely error. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION 0x010F /**< ATT Error: Encrypted link required. */ +#define BLE_GATT_STATUS_ATTERR_UNSUPPORTED_GROUP_TYPE 0x0110 /**< ATT Error: Attribute type is not a supported grouping attribute. */ +#define BLE_GATT_STATUS_ATTERR_INSUF_RESOURCES 0x0111 /**< ATT Error: Encrypted link required. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_BEGIN 0x0112 /**< ATT Error: Reserved for Future Use range #1 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_END 0x017F /**< ATT Error: Reserved for Future Use range #1 end. */ +#define BLE_GATT_STATUS_ATTERR_APP_BEGIN 0x0180 /**< ATT Error: Application range begin. */ +#define BLE_GATT_STATUS_ATTERR_APP_END 0x019F /**< ATT Error: Application range end. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_BEGIN 0x01A0 /**< ATT Error: Reserved for Future Use range #2 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_END 0x01DF /**< ATT Error: Reserved for Future Use range #2 end. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_BEGIN 0x01E0 /**< ATT Error: Reserved for Future Use range #3 begin. */ +#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_END 0x01FC /**< ATT Error: Reserved for Future Use range #3 end. */ +#define BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR 0x01FD /**< ATT Common Profile and Service Error: Client Characteristic Configuration Descriptor improperly configured. */ +#define BLE_GATT_STATUS_ATTERR_CPS_PROC_ALR_IN_PROG 0x01FE /**< ATT Common Profile and Service Error: Procedure Already in Progress. */ +#define BLE_GATT_STATUS_ATTERR_CPS_OUT_OF_RANGE 0x01FF /**< ATT Common Profile and Service Error: Out Of Range. */ +/** @} */ + + +/** @defgroup BLE_GATT_CPF_FORMATS Characteristic Presentation Formats + * @note Found at http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml + * @{ */ +#define BLE_GATT_CPF_FORMAT_RFU 0x00 /**< Reserved For Future Use. */ +#define BLE_GATT_CPF_FORMAT_BOOLEAN 0x01 /**< Boolean. */ +#define BLE_GATT_CPF_FORMAT_2BIT 0x02 /**< Unsigned 2-bit integer. */ +#define BLE_GATT_CPF_FORMAT_NIBBLE 0x03 /**< Unsigned 4-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT8 0x04 /**< Unsigned 8-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT12 0x05 /**< Unsigned 12-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT16 0x06 /**< Unsigned 16-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT24 0x07 /**< Unsigned 24-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT32 0x08 /**< Unsigned 32-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT48 0x09 /**< Unsigned 48-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT64 0x0A /**< Unsigned 64-bit integer. */ +#define BLE_GATT_CPF_FORMAT_UINT128 0x0B /**< Unsigned 128-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT8 0x0C /**< Signed 2-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT12 0x0D /**< Signed 12-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT16 0x0E /**< Signed 16-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT24 0x0F /**< Signed 24-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT32 0x10 /**< Signed 32-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT48 0x11 /**< Signed 48-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT64 0x12 /**< Signed 64-bit integer. */ +#define BLE_GATT_CPF_FORMAT_SINT128 0x13 /**< Signed 128-bit integer. */ +#define BLE_GATT_CPF_FORMAT_FLOAT32 0x14 /**< IEEE-754 32-bit floating point. */ +#define BLE_GATT_CPF_FORMAT_FLOAT64 0x15 /**< IEEE-754 64-bit floating point. */ +#define BLE_GATT_CPF_FORMAT_SFLOAT 0x16 /**< IEEE-11073 16-bit SFLOAT. */ +#define BLE_GATT_CPF_FORMAT_FLOAT 0x17 /**< IEEE-11073 32-bit FLOAT. */ +#define BLE_GATT_CPF_FORMAT_DUINT16 0x18 /**< IEEE-20601 format. */ +#define BLE_GATT_CPF_FORMAT_UTF8S 0x19 /**< UTF-8 string. */ +#define BLE_GATT_CPF_FORMAT_UTF16S 0x1A /**< UTF-16 string. */ +#define BLE_GATT_CPF_FORMAT_STRUCT 0x1B /**< Opaque Structure. */ +/** @} */ + +/** @defgroup BLE_GATT_CPF_NAMESPACES GATT Bluetooth Namespaces + * @{ + */ +#define BLE_GATT_CPF_NAMESPACE_BTSIG 0x01 +#define BLE_GATT_CPF_NAMESPACE_DESCRIPTION_UNKNOWN 0x0000 +/** @} */ + +/** @} */ + +/** @addtogroup BLE_GATT_STRUCTURES Structures + * @{ */ + +/**@brief GATT Characteristic Properties. */ +typedef struct +{ + /* Standard properties */ + uint8_t broadcast :1; /**< Broadcasting of value permitted. */ + uint8_t read :1; /**< Reading value permitted. */ + uint8_t write_wo_resp :1; /**< Writing value with Write Command permitted. */ + uint8_t write :1; /**< Writing value with Write Request permitted. */ + uint8_t notify :1; /**< Notications of value permitted. */ + uint8_t indicate :1; /**< Indications of value permitted. */ + uint8_t auth_signed_wr :1; /**< Writing 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 value with Queued Write Request permitted. */ + uint8_t wr_aux :1; /**< Writing the Characteristic User Description permitted. */ +} ble_gatt_char_ext_props_t; + +#endif // BLE_GATT_H__ + +/** @} */ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gattc.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gattc.h new file mode 100644 index 00000000000..14bad6b1e1c --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gattc.h @@ -0,0 +1,406 @@ +/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @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" + +/** @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_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. */ +}; + +/** @} */ + +/** @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) +/** @} */ + +/**@brief Last Attribute Handle. */ +#define BLE_GATTC_HANDLE_END 0xFFFF + +/** @} */ + +/** @addtogroup BLE_GATTC_STRUCTURES Structures + * @{ */ + +/**@brief Operation Handle Range. */ +typedef struct +{ + uint16_t start_handle; /**< Start Handle. */ + uint16_t end_handle; /**< End Handle. */ +} ble_gattc_handle_range_t; + + +/**@brief GATT service. */ +typedef struct +{ + ble_uuid_t uuid; /**< Service UUID. */ + ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ +} ble_gattc_service_t; + + +/**@brief GATT include. */ +typedef struct +{ + uint16_t handle; /**< Include Handle. */ + ble_gattc_service_t included_srvc; /**< Handle of the included service. */ +} ble_gattc_include_t; + + +/**@brief GATT characteristic. */ +typedef struct +{ + ble_uuid_t uuid; /**< Characteristic UUID. */ + ble_gatt_char_props_t char_props; /**< Characteristic Properties. */ + uint8_t char_ext_props : 1; /**< Extended properties present. */ + uint16_t handle_decl; /**< Handle of the Characteristic Declaration. */ + uint16_t handle_value; /**< Handle of the Characteristic Value. */ +} ble_gattc_char_t; + + +/**@brief GATT descriptor. */ +typedef struct +{ + uint16_t handle; /**< Descriptor Handle. */ + ble_uuid_t uuid; /**< Descriptor UUID. */ +} ble_gattc_desc_t; + + +/**@brief Write Parameters. */ +typedef struct +{ + uint8_t write_op; /**< Write Operation to be performed, see @ref BLE_GATT_WRITE_OPS. */ + 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* p_value; /**< Pointer to the value data. */ + uint8_t flags; /**< Flags, see @ref BLE_GATT_EXEC_WRITE_FLAGS. */ +} ble_gattc_write_params_t; + + +/** + * @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. */ + BLE_GATTC_EVT_REL_DISC_RSP, /**< Relationship Discovery Response event. */ + BLE_GATTC_EVT_CHAR_DISC_RSP, /**< Characteristic Discovery Response event. */ + BLE_GATTC_EVT_DESC_DISC_RSP, /**< Descriptor Discovery Response event. */ + BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP, /**< Read By UUID Response event. */ + BLE_GATTC_EVT_READ_RSP, /**< Read Response event. */ + BLE_GATTC_EVT_CHAR_VALS_READ_RSP, /**< Read multiple Response event. */ + BLE_GATTC_EVT_WRITE_RSP, /**< Write Response event. */ + BLE_GATTC_EVT_HVX, /**< Handle Value Notification or Indication event. */ + BLE_GATTC_EVT_TIMEOUT /**< Timeout event. */ +}; + +/**@brief Event structure for BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Service count. */ + ble_gattc_service_t services[1]; /**< Service data, variable length. */ +} ble_gattc_evt_prim_srvc_disc_rsp_t; + +/**@brief Event structure for BLE_GATTC_EVT_REL_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Include count. */ + ble_gattc_include_t includes[1]; /**< Include data, variable length. */ +} ble_gattc_evt_rel_disc_rsp_t; + +/**@brief Event structure for BLE_GATTC_EVT_CHAR_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Characteristic count. */ + ble_gattc_char_t chars[1]; /**< Characteristic data, variable length. */ +} ble_gattc_evt_char_disc_rsp_t; + +/**@brief Event structure for BLE_GATTC_EVT_DESC_DISC_RSP. */ +typedef struct +{ + uint16_t count; /**< Descriptor count. */ + ble_gattc_desc_t descs[1]; /**< Descriptor data, variable length. */ +} ble_gattc_evt_desc_disc_rsp_t; + +/**@brief GATT read by UUID handle value pair. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + uint8_t *p_value; /**< Pointer to value, variable length (length available as value_len in ble_gattc_evt_read_by_uuid_rsp_t). + Please note that this pointer is absolute to the memory provided by the user when retrieving the event, + so it will effectively point to a location inside the handle_value array. */ +} ble_gattc_handle_value_t; + +/**@brief Event structure for 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. */ + ble_gattc_handle_value_t handle_value[1]; /**< Handle-Value(s) list, variable length. */ +} ble_gattc_evt_char_val_by_uuid_read_rsp_t; + +/**@brief Event structure for 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, variable length. */ +} ble_gattc_evt_read_rsp_t; + +/**@brief Event structure for BLE_GATTC_EVT_CHAR_VALS_READ_RSP. */ +typedef struct +{ + uint16_t len; /**< Concatenated Attribute values length. */ + uint8_t values[1]; /**< Attribute values, variable length. */ +} ble_gattc_evt_char_vals_read_rsp_t; + +/**@brief Event structure for 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, variable length. */ +} ble_gattc_evt_write_rsp_t; + +/**@brief Event structure for 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, variable length. */ +} ble_gattc_evt_hvx_t; + +/**@brief Event structure for BLE_GATTC_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */ +} ble_gattc_evt_timeout_t; + +/**@brief GATTC event type. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occured. */ + uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */ + uint16_t error_handle; /**< In case of error: The handle causing the error. In all other cases 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_timeout_t timeout; /**< Timeout Event Parameters. */ + } params; /**< Event Parameters. @note Only valid if @ref gatt_status == 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 a Primary Service discovery, starting from the supplied handle. + * If the last service has not been reached, this 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 BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Primary Service Discovery procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref 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 * const p_srvc_uuid)); + + +/**@brief Initiate or continue a GATT Relationship Discovery procedure. + * + * @details This function initiates 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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Relationship Discovery procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref 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 * const p_handle_range)); + + +/**@brief Initiate or continue a GATT Characteristic Discovery procedure. + * + * @details This function initiates 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 BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Characteristic Discovery procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const p_handle_range)); + + +/**@brief Initiate or continue a GATT Characteristic Descriptor Discovery procedure. + * + * @details This function initiates the 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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Descriptor Discovery procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const p_handle_range)); + + +/**@brief Initiate or continue a GATT Read using Characteristic UUID procedure. + * + * @details This function initiates the 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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Read using Characteristic UUID procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const p_uuid, ble_gattc_handle_range_t const * const p_handle_range)); + + +/**@brief Initiate or continue a GATT Read (Long) Characteristic or Descriptor procedure. + * + * @details This function initiates a GATT Read (Long) Characteristic or Descriptor procedure. If the Characteristic or Descriptor + * to be read is longer than GATT_MTU - 1, this function must be called multiple times with appropriate offset to read the + * complete value. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started or resumed the Read (Long) procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started the Read Multiple Characteristic Values procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref 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 * const p_handles, uint16_t handle_count)); + + +/**@brief Perform a Write (Characteristic Value or Descriptor, with or without response, signed or not, long or reliable) procedure. + * + * @details This function can perform all write procedures described in GATT. + * + * @note It is important to note that a write without response will consume an application buffer, and will therefore + * generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted. A write on the other hand will use the + * standard client internal buffer and thus will only generate a @ref BLE_GATTC_EVT_WRITE_RSP event as soon as the write response + * has been received from the peer. Please see the documentation of @ref sd_ble_tx_buffer_count_get for more details. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully started the Write procedure. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + * @return @ref NRF_ERROR_BUSY Procedure already in progress. + * @return @ref BLE_ERROR_NO_TX_BUFFERS There are no available buffers left. + */ +SVCALL(SD_BLE_GATTC_WRITE, uint32_t, sd_ble_gattc_write(uint16_t conn_handle, ble_gattc_write_params_t const * const p_write_params)); + + +/**@brief Send a Handle Value Confirmation to the GATT Server. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully queued the Handle Value Confirmation for transmission. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_STATE No Indication pending to be confirmed. + * @return @ref BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle. + * @return @ref BLE_ERROR_NO_TX_BUFFERS There are no available buffers left. + */ +SVCALL(SD_BLE_GATTC_HV_CONFIRM, uint32_t, sd_ble_gattc_hv_confirm(uint16_t conn_handle, uint16_t handle)); + +/** @} */ + +#endif /* BLE_GATTC_H__ */ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatts.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatts.h new file mode 100644 index 00000000000..dec649f28a4 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_gatts.h @@ -0,0 +1,566 @@ +/* Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @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" + +/** @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, /**< Get updated persistent system attributes after terminating a connection. */ +}; + +/** @} */ + +/** @addtogroup BLE_GATTS_DEFINES Defines + * @{ */ + +/** @brief Only the default MTU size of 23 is currently supported. */ +#define GATT_RX_MTU 23 + +/** @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. */ +/** @} */ + + +/** @} */ + +/** @addtogroup BLE_GATTS_STRUCTURES Structures + * @{ */ + +/** + * @brief BLE GATTS init options + */ +typedef struct +{ + uint8_t service_changed:1; /**< Include the Service Changed characteristic in the local attributes. */ +} ble_gatts_enable_params_t; + +/**@brief Attribute metadata. */ +typedef struct +{ + ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ + ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ + uint8_t vlen :1; /**< Variable length attribute. */ + uint8_t vloc :2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/ + uint8_t rd_auth :1; /**< Read Authorization and value will be requested from the application on every read operation. */ + uint8_t wr_auth :1; /**< Write Authorization will be requested from the application on every Write Request operation (but not Write Command). */ +} ble_gatts_attr_md_t; + + +/**@brief GATT Attribute. */ +typedef struct +{ + ble_uuid_t* p_uuid; /**< Pointer to the attribute UUID. */ + ble_gatts_attr_md_t* p_attr_md; /**< Pointer to the attribute metadata structure. */ + uint16_t init_len; /**< Initial attribute value length in bytes. */ + uint16_t init_offs; /**< Initial attribute value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ + uint16_t max_len; /**< Maximum attribute value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ + uint8_t* p_value; /**< Pointer to the attribute data. Please note that if the @ref BLE_GATTS_VLOC_USER value location is selected in the attribute metadata, this will have to point to a buffer + that remains valid through the lifetime of the attribute. This excludes usage of automatic variables that may go out of scope or any other temporary location. + The stack may access that memory directly without the application's knowledge. */ +} ble_gatts_attr_t; + + +/**@brief GATT Attribute Context. */ +typedef struct +{ + ble_uuid_t srvc_uuid; /**< Service UUID. */ + ble_uuid_t char_uuid; /**< Characteristic UUID if applicable (BLE_UUID_TYPE_UNKNOWN if N/A). */ + ble_uuid_t desc_uuid; /**< Descriptor UUID if applicable (BLE_UUID_TYPE_UNKNOWN if N/A). */ + uint16_t srvc_handle; /**< Service Handle. */ + uint16_t value_handle; /**< Characteristic Handle if applicable (BLE_GATT_HANDLE_INVALID if N/A). */ + uint8_t type; /**< Attribute Type, see @ref BLE_GATTS_ATTR_TYPES. */ +} ble_gatts_attr_context_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; /**< UUID from Bluetooth Assigned Numbers. */ + uint8_t name_space; /**< Namespace from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */ + uint16_t desc; /**< Namespace description from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */ +} ble_gatts_char_pf_t; + + +/**@brief GATT Characteristic metadata. */ +typedef struct +{ + ble_gatt_char_props_t char_props; /**< Characteristic Properties. */ + ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic Extended Properties. */ + uint8_t* p_char_user_desc; /**< Pointer to a UTF-8, NULL if the descriptor is not required. */ + uint16_t char_user_desc_max_size; /**< The maximum size in bytes of the user description descriptor. */ + uint16_t char_user_desc_size; /**< The size of the user description, must be smaller or equal to char_user_desc_max_size. */ + ble_gatts_char_pf_t* p_char_pf; /**< Pointer to a presentation format structure or NULL if the descriptor is not required. */ + ble_gatts_attr_md_t* p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */ + ble_gatts_attr_md_t* p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */ + ble_gatts_attr_md_t* p_sccd_md; /**< Attribute metadata for the Server Characteristic Configuration Descriptor, or NULL for default values. */ +} ble_gatts_char_md_t; + + +/**@brief GATT Characteristic Definition Handles. */ +typedef struct +{ + uint16_t value_handle; /**< Handle to the characteristic value. */ + uint16_t user_desc_handle; /**< Handle to the User Description descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ + uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ + uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ +} ble_gatts_char_handles_t; + + +/**@brief GATT HVx parameters. */ +typedef struct +{ + uint16_t handle; /**< Characteristic Value Handle. */ + uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */ + uint16_t offset; /**< Offset within the attribute value. */ + uint16_t* p_len; /**< Length in bytes to be written, length in bytes written after successful return. */ + uint8_t* p_data; /**< Actual data content, use NULL to use the current attribute value. */ +} ble_gatts_hvx_params_t; + +/**@brief GATT Read 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 in the ATT response. */ + 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* p_data; /**< Pointer to new value used to update the attribute value. */ +} ble_gatts_read_authorize_params_t; + +/**@brief GATT Write Authorisation parameters. */ +typedef struct +{ + uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */ +} ble_gatts_write_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_read_authorize_params_t read; /**< Read authorization parameters. */ + ble_gatts_write_authorize_params_t write; /**< Write authorization parameters. */ + } params; +} ble_gatts_rw_authorize_reply_params_t; + + +/** + * @brief GATT Server Event IDs. + */ +enum BLE_GATTS_EVTS +{ + BLE_GATTS_EVT_WRITE = BLE_GATTS_EVT_BASE, /**< Write operation performed. */ + BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, /**< Read/Write Authorization request. */ + BLE_GATTS_EVT_SYS_ATTR_MISSING, /**< A persistent system attribute access is pending, awaiting a sd_ble_gatts_sys_attr_set(). */ + BLE_GATTS_EVT_HVC, /**< Handle Value Confirmation. */ + BLE_GATTS_EVT_SC_CONFIRM, /**< Service Changed Confirmation. */ + BLE_GATTS_EVT_TIMEOUT /**< Timeout. */ +}; + + +/**@brief Event structure for BLE_GATTS_EVT_WRITE. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + uint8_t op; /**< Type of write operation, see @ref BLE_GATTS_OPS. */ + ble_gatts_attr_context_t context; /**< Attribute Context. */ + uint16_t offset; /**< Offset for the write operation. */ + uint16_t len; /**< Length of the incoming data. */ + uint8_t data[1]; /**< Incoming data, variable length. */ +} ble_gatts_evt_write_t; + +/**@brief Event structure for authorize read request. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ + ble_gatts_attr_context_t context; /**< Attribute Context. */ + uint16_t offset; /**< Offset for the read operation. */ +} ble_gatts_evt_read_t; + +/**@brief Event structure for 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; +} ble_gatts_evt_rw_authorize_request_t; + +/**@brief Event structure for BLE_GATTS_EVT_SYS_ATTR_MISSING. */ +typedef struct +{ + uint8_t hint; +} ble_gatts_evt_sys_attr_missing_t; + + +/**@brief Event structure for BLE_GATTS_EVT_HVC. */ +typedef struct +{ + uint16_t handle; /**< Attribute Handle. */ +} ble_gatts_evt_hvc_t; + +/**@brief Event structure for BLE_GATTS_EVT_TIMEOUT. */ +typedef struct +{ + uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */ +} ble_gatts_evt_timeout_t; + + +/**@brief GATT Server event callback event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which 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_timeout_t timeout; /**< Timeout Event. */ + } params; +} ble_gatts_evt_t; + +/** @} */ + +/** @addtogroup BLE_GATTS_FUNCTIONS Functions + * @{ */ + +/**@brief Add a service declaration to the local server ATT table. + * + * @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. + * + * @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 ATT table. + * + * @return @ref NRF_SUCCESS Successfully added a service declaration. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, Vendor Specific UUIDs need to be present in the table. + * @return @ref NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @return @ref 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*const p_uuid, uint16_t *const p_handle)); + + +/**@brief Add an include declaration to the local server ATT table. + * + * @note It is currently only possible to add an include declaration to the last added service (i.e. only sequential addition is supported at this time). + * + * @note The included service must already be present in the ATT table prior to this call. + * + * @param[in] service_handle Handle of the service where the included service is to be placed, if 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. + * + * @return @ref NRF_SUCCESS Successfully added an include declaration. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, handle values need to match previously added services. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation. + * @return @ref NRF_ERROR_FORBIDDEN Forbidden value supplied, self inclusions are not allowed. + * @return @ref NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @return @ref 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 *const p_include_handle)); + + +/**@brief Add a characteristic declaration, a characteristic value declaration and optional characteristic descriptor declarations to the local server ATT table. + * + * @note It is currently only possible to add a characteristic to the last added service (i.e. only sequential addition is supported at this time). + * + * @note Several restrictions apply to the parameters, such as matching permissions between the user description descriptor and the writeable auxiliaries bits, + * readable (no security) and writeable (selectable) CCCDs and SCCDs and valid presentation format values. + * + * @note If no metadata is provided for the optional descriptors, their permissions will be derived from the characteristic permissions. + * + * @param[in] service_handle Handle of the service where the characteristic is to be placed, if 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. + * + * @return @ref NRF_SUCCESS Successfully added a characteristic. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, service handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation, a service context is required. + * @return @ref NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @return @ref NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @return @ref 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*const p_char_md, ble_gatts_attr_t const*const p_attr_char_value, ble_gatts_char_handles_t *const p_handles)); + + +/**@brief Add a descriptor to the local server ATT table. + * + * @note It is currently only possible to add a descriptor to the last added characteristic (i.e. only sequential addition is supported at this time). + * + * @param[in] char_handle Handle of the characteristic where the descriptor is to be placed, if 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. + * + * @return @ref NRF_SUCCESS Successfully added a descriptor. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, characteristic handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation, a characteristic context is required. + * @return @ref NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack. + * @return @ref NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @return @ref 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 * const p_attr, uint16_t* const p_handle)); + +/**@brief Set the value of a given attribute. + * + * @param[in] handle Attribute handle. + * @param[in] offset Offset in bytes to write from. + * @param[in,out] p_len Length in bytes to be written, length in bytes written after successful return. + * @param[in] p_value Pointer to a buffer (at least len bytes long) containing the desired attribute value. If value is stored in user memory, only the attribute length is updated when p_value == NULL. + * + * @return @ref NRF_SUCCESS Successfully set the value of the attribute. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_NOT_FOUND Attribute not found. + * @return @ref NRF_ERROR_FORBIDDEN Forbidden handle supplied, certain attributes are not modifiable by the application. + * @return @ref NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX. + */ +SVCALL(SD_BLE_GATTS_VALUE_SET, uint32_t, sd_ble_gatts_value_set(uint16_t handle, uint16_t offset, uint16_t* const p_len, uint8_t const * const p_value)); + +/**@brief Get the value of a given attribute. + * + * @param[in] handle Attribute handle. + * @param[in] offset Offset in bytes to read from. + * @param[in,out] p_len Length in bytes to be read, total length of attribute value (in bytes, starting from offset) after successful return. + * @param[in,out] p_data Pointer to a buffer (at least len bytes long) where to store the attribute value. Set to NULL to obtain the complete length of attribute value. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully retrieved the value of the attribute. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_NOT_FOUND Attribute not found. + */ +SVCALL(SD_BLE_GATTS_VALUE_GET, uint32_t, sd_ble_gatts_value_get(uint16_t handle, uint16_t offset, uint16_t *const p_len, uint8_t* const p_data)); + +/**@brief Notify or Indicate an attribute value. + * + * @details This function checks for the relevant Client Characteristic Configuration descriptor value to verify that the relevant operation + * (notification or indication) has been enabled by the client. It is also able to update the attribute value before issuing the PDU, so that + * the application can atomically perform a value update and a server initiated transaction with a single API call. + * If the application chooses to indicate an attribute value, a @ref BLE_GATTS_EVT_HVC will be sent up as soon as the confirmation arrives from + * the peer. + * + * @note The local attribute value may be updated even if an outgoing packet is not sent to the peer due to an error during execution. + * When receiveing the error codes @ref NRF_ERROR_INVALID_STATE, @ref NRF_ERROR_BUSY, @ref BLE_ERROR_GATTS_SYS_ATTR_MISSING and + * @ref BLE_ERROR_NO_TX_BUFFERS the ATT table has been updated. + * The caller can check whether the value has been updated by looking at the contents of *(p_hvx_params->p_len). + * + * @note It is important to note that a notification will consume an application buffer, and will therefore + * generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted. An indication on the other hand will use the + * standard server internal buffer and thus will only generate a @ref BLE_GATTS_EVT_HVC event as soon as the confirmation + * has been received from the peer. Please see the documentation of @ref sd_ble_tx_buffer_count_get for more details. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully queued a notification or indication for transmission, and optionally updated the attribute value. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied. Only attributes added directly by the application are available to notify and indicate. + * @return @ref BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated. + * @return @ref NRF_ERROR_NOT_FOUND Attribute not found. + * @return @ref NRF_ERROR_DATA_SIZE Invalid data size(s) supplied. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation, notifications or indications must be enabled in the CCCD. + * @return @ref NRF_ERROR_BUSY Procedure already in progress. + * @return @ref BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value. + * @return @ref BLE_ERROR_NO_TX_BUFFERS There are no available buffers to send the data, applies only to notifications. + */ +SVCALL(SD_BLE_GATTS_HVX, uint32_t, sd_ble_gatts_hvx(uint16_t conn_handle, ble_gatts_hvx_params_t const*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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully queued the Service Changed indication for transmission. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied, handles must be in the range populated by the application. + * @return @ref NRF_ERROR_INVALID_STATE Invalid state to perform operation, notifications or indications must be enabled in the CCCD. + * @return @ref NRF_ERROR_BUSY Procedure already in progress. + * @return @ref 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. + * + * @param[in] conn_handle Connection handle. + * @param[in] p_rw_authorize_reply_params Pointer to a structure with the attribute provided by the application. + * + * @return @ref NRF_SUCCESS Successfully queued a response to the peer, and in the case of a write operation, ATT table updated. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_STATE No authorization request pending. + * @return @ref NRF_ERROR_INVALID_PARAM Authorization op invalid, + * or for Read Authorization reply: requested handles not replied with, + * or for Write Authorization reply: handle supplied does not match requested handle. + */ +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*const p_rw_authorize_reply_params)); + + +/**@brief Update persistent system attribute information. + * + * @details Supply to the stack information about persistent system attributes. + * This call is legal in the connected state only, and is usually + * made immediately after a connection is established and the bond identified. + * usually as a response to a BLE_GATTS_EVT_SYS_ATTR_MISSING. + * + * p_sysattrs may point directly to the application's stored copy of the struct. + * If the pointer is NULL, the system attribute info is initialized, assuming that + * the application does not have any previously saved data for this bond. + * + * @note The state of persistent system attributes is reset upon connection 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. + * + * @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. + * + * @return @ref NRF_SUCCESS Successfully set the system attribute information. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_DATA Invalid data supplied, the data should be exactly the same as retrieved with @ref sd_ble_gatts_sys_attr_get. + * @return @ref 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*const p_sys_attr_data, uint16_t len)); + + +/**@brief Retrieve persistent system attribute information from the stack. + * + * @details This call is used to retrieve information about values to be stored perisistently by the application + * after a connection has been terminated. When a new connection is made to the same bond, the values + * should be restored using @ref sd_ble_gatts_sys_attr_set. + * The data should be read before any new advertising is started, or any new connection established. The connection handle for + * the previous now defunct connection will remain valid until a new one is created to allow this API call to refer to it. + * + * @param[in] conn_handle Connection handle of the recently terminated connection. + * @param[in] p_sys_attr_data Pointer to a buffer where updated information about system attributes will be filled in. NULL can be provided to + * obtain the length of the data + * @param[in,out] p_len Size of application buffer if p_sys_attr_data is not NULL. Unconditially updated to actual length of system attribute data. + * + * @return @ref NRF_SUCCESS Successfully retrieved the system attribute information. + * @return @ref BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_DATA_SIZE The system attribute information did not fit into the provided buffer. + */ +SVCALL(SD_BLE_GATTS_SYS_ATTR_GET, uint32_t, sd_ble_gatts_sys_attr_get(uint16_t conn_handle, uint8_t * const p_sys_attr_data, uint16_t* const p_len)); + +/** @} */ + +#endif // BLE_GATTS_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_hci.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_hci.h new file mode 100644 index 00000000000..925776bd7d1 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_hci.h @@ -0,0 +1,96 @@ +/* + Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + + The information contained herein is confidential property of Nordic Semiconductor. The use, + copying, transfer or disclosure of such information is prohibited except by express written + agreement with Nordic Semiconductor. + */ +/** + @addtogroup BLE_COMMON + @{ +*/ + + +#ifndef BLE_HCI_H__ +#define BLE_HCI_H__ + +/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes + * @{ */ + +#define BLE_HCI_STATUS_CODE_SUCCESS 0x00 +#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01 +#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 +/*0x03 Hardware Failure +0x04 Page Timeout +*/ +#define BLE_HCI_AUTHENTICATION_FAILURE 0x05 +#define BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING 0x06 +#define BLE_HCI_MEMORY_CAPACITY_EXCEEDED 0x07 +#define BLE_HCI_CONNECTION_TIMEOUT 0x08 +/*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 +/*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 +#define BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 +#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 +#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 +#define BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 +/* +0x17 Repeated Attempts +0x18 Pairing Not Allowed +0x19 Unknown LMP PDU +*/ +#define BLE_HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A +/* +0x1B SCO Offset Rejected +0x1C SCO Interval Rejected +0x1D SCO Air Mode Rejected*/ +#define BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS 0x1E +#define BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR 0x1F +/*0x20 Unsupported LMP Parameter Value +0x21 Role Change Not Allowed +*/ +#define BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT 0x22 +/*0x23 LMP Error Transaction Collision*/ +#define BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED 0x24 +/*0x25 Encryption Mode Not Acceptable +0x26 Link Key Can Not be Changed +0x27 Requested QoS Not Supported +*/ +#define BLE_HCI_INSTANT_PASSED 0x28 +#define BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED 0x29 +#define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A +/* +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 +#define BLE_HCI_CONN_INTERVAL_UNACCEPTABLE 0x3B +#define BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT 0x3C +#define BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE 0x3D +#define BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED 0x3E + +/** @} */ + + +#endif // BLE_HCI_H__ + +/** @} */ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_l2cap.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_l2cap.h new file mode 100644 index 00000000000..d74ee218655 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_l2cap.h @@ -0,0 +1,144 @@ +/* Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @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" + +/**@addtogroup BLE_L2CAP_ENUMERATIONS Enumerations + * @{ */ + +/**@brief L2CAP API SVC numbers. */ +enum BLE_L2CAP_SVCS +{ + SD_BLE_L2CAP_CID_REGISTER = BLE_L2CAP_SVC_BASE, /**< Register a CID. */ + SD_BLE_L2CAP_CID_UNREGISTER, /**< Unregister a CID. */ + SD_BLE_L2CAP_TX /**< Transmit a packet. */ +}; + +/** @} */ + +/**@addtogroup BLE_L2CAP_DEFINES Defines + * @{ */ + +/**@defgroup BLE_ERRORS_L2CAP SVC return values specific to L2CAP + * @{ */ +#define BLE_ERROR_L2CAP_CID_IN_USE (NRF_L2CAP_ERR_BASE + 0x000) /**< CID already in use. */ +/** @} */ + +/**@brief Default L2CAP MTU. */ +#define BLE_L2CAP_MTU_DEF (23) + +/**@brief Invalid Channel Identifier. */ +#define BLE_L2CAP_CID_INVALID (0x0000) + +/**@brief Dynamic Channel Identifier base. */ +#define BLE_L2CAP_CID_DYN_BASE (0x0040) + +/**@brief Maximum amount of dynamic CIDs. */ +#define BLE_L2CAP_CID_DYN_MAX (8) + +/** @} */ + +/**@addtogroup BLE_L2CAP_STRUCTURES Structures + * @{ */ + +/**@brief Packet header format for L2CAP transmission. */ +typedef struct +{ + uint16_t len; /**< Length of valid info in data member. */ + uint16_t cid; /**< Channel ID on which packet is transmitted. */ +} ble_l2cap_header_t; + +/**@brief L2CAP Event IDs. */ +enum BLE_L2CAP_EVTS +{ + BLE_L2CAP_EVT_RX = BLE_L2CAP_EVT_BASE /**< L2CAP packet received. */ +}; + + +/**@brief L2CAP Received packet event report. */ +typedef struct +{ + ble_l2cap_header_t header; /** L2CAP packet header. */ + uint8_t data[1]; /**< Packet data, variable length. */ +} ble_l2cap_evt_rx_t; + + +/**@brief L2CAP event callback event structure. */ +typedef struct +{ + uint16_t conn_handle; /**< Connection Handle on which event occured. */ + union + { + ble_l2cap_evt_rx_t rx; /**< RX Event parameters. */ + } params; +} ble_l2cap_evt_t; + + +/**@brief Register a CID with L2CAP. + * + * @details This registers a higher protocol layer with the L2CAP multiplexer, and is requried prior to all operations on the CID. + * + * @param[in] cid L2CAP CID. + * + * @return @ref NRF_SUCCESS Successfully registered a CID with the L2CAP layer. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, CID must be above @ref BLE_L2CAP_CID_DYN_BASE. + * @return @ref BLE_ERROR_L2CAP_CID_IN_USE L2CAP CID already in use. + * @return @ref NRF_ERROR_NO_MEM Not enough memory to complete operation. + */ +SVCALL(SD_BLE_L2CAP_CID_REGISTER, uint32_t, sd_ble_l2cap_cid_register(uint16_t cid)); + +/**@brief Unregister a CID with L2CAP. + * + * @details This unregisters a previously registerd higher protocol layer with the L2CAP multiplexer. + * + * @param[in] cid L2CAP CID. + * + * @return @ref NRF_SUCCESS Successfully unregistered the CID. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied. + * @return @ref NRF_ERROR_NOT_FOUND CID not previously registered. + */ +SVCALL(SD_BLE_L2CAP_CID_UNREGISTER, uint32_t, sd_ble_l2cap_cid_unregister(uint16_t cid)); + +/**@brief Transmit an L2CAP packet. + * + * @note It is important to note that a call to this function will consume an application buffer, and will therefore + * generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted. + * Please see the documentation of @ref sd_ble_tx_buffer_count_get for more details. + * + * @param[in] conn_handle Connection Handle. + * @param[in] p_header Pointer to a packet header containing length and CID. + * @param[in] p_data Pointer to the data to be transmitted. + * + * @return @ref NRF_SUCCESS Successfully queued an L2CAP packet for transmission. + * @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied. + * @return @ref NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, CIDs must be registered beforehand with @ref sd_ble_l2cap_cid_register. + * @return @ref NRF_ERROR_NOT_FOUND CID not found. + * @return @ref NRF_ERROR_NO_MEM Not enough memory to complete operation. + * @return @ref BLE_ERROR_NO_TX_BUFFERS Not enough application buffers available. + * @return @ref NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, see @ref BLE_L2CAP_MTU_DEF. + */ +SVCALL(SD_BLE_L2CAP_TX, uint32_t, sd_ble_l2cap_tx(uint16_t conn_handle, ble_l2cap_header_t const * const p_header, uint8_t const * const p_data)); + +/** @} */ + +#endif // BLE_L2CAP_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_ranges.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_ranges.h new file mode 100644 index 00000000000..dfd9b63bcf7 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_ranges.h @@ -0,0 +1,89 @@ +/* + Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + + The information contained herein is confidential property of Nordic Semiconductor. The use, + copying, transfer or disclosure of such information is prohibited except by express written + agreement with Nordic Semiconductor. + */ +/** + @addtogroup BLE_COMMON + @{ + @defgroup ble_ranges Module specific SVC and event number subranges + @{ + + @brief Definition of SVC and event number subranges for each API module. + + @note + SVCs and event 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 and event 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__ + +#define BLE_SVC_BASE 0x60 +#define BLE_SVC_LAST 0x6B /* Total: 12. */ + +#define BLE_RESERVED_SVC_BASE 0x6C +#define BLE_RESERVED_SVC_LAST 0x6F /* Total: 4. */ + +#define BLE_GAP_SVC_BASE 0x70 +#define BLE_GAP_SVC_LAST 0x8F /* Total: 32. */ + +#define BLE_GATTC_SVC_BASE 0x90 +#define BLE_GATTC_SVC_LAST 0x9F /* Total: 16. */ + +#define BLE_GATTS_SVC_BASE 0xA0 +#define BLE_GATTS_SVC_LAST 0xAF /* Total: 16. */ + +#define BLE_L2CAP_SVC_BASE 0xB0 +#define BLE_L2CAP_SVC_LAST 0xBF /* Total: 16. */ + + +#define BLE_EVT_INVALID 0x00 + +#define BLE_EVT_BASE 0x01 +#define BLE_EVT_LAST 0x0F /* Total: 15. */ + +#define BLE_GAP_EVT_BASE 0x10 +#define BLE_GAP_EVT_LAST 0x2F /* Total: 32. */ + +#define BLE_GATTC_EVT_BASE 0x30 +#define BLE_GATTC_EVT_LAST 0x4F /* Total: 32. */ + +#define BLE_GATTS_EVT_BASE 0x50 +#define BLE_GATTS_EVT_LAST 0x6F /* Total: 32. */ + +#define BLE_L2CAP_EVT_BASE 0x70 +#define BLE_L2CAP_EVT_LAST 0x8F /* Total: 32. */ + +#define BLE_OPT_INVALID 0x00 /**< Invalid BLE Option. */ + +#define BLE_OPT_BASE 0x01 /**< Common BLE Option base. */ +#define BLE_OPT_LAST 0x1F /**< Total: 31. */ + +#define BLE_GAP_OPT_BASE 0x20 /**< GAP BLE Option base. */ +#define BLE_GAP_OPT_LAST 0x3F /**< Total: 32. */ + +#define BLE_GATTC_OPT_BASE 0x40 /**< GATTC BLE Option base. */ +#define BLE_GATTC_OPT_LAST 0x5F /**< Total: 32. */ + +#define BLE_GATTS_OPT_BASE 0x60 /**< GATTS BLE Option base. */ +#define BLE_GATTS_OPT_LAST 0x7F /**< Total: 32. */ + +#define BLE_L2CAP_OPT_BASE 0x80 /**< L2CAP BLE Option base. */ +#define BLE_L2CAP_OPT_LAST 0x9F /**< Total: 32. */ + +#endif /* BLE_RANGES_H__ */ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_types.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_types.h new file mode 100644 index 00000000000..820553f0a98 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/ble_types.h @@ -0,0 +1,169 @@ +/* Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @addtogroup BLE_COMMON + @{ + @defgroup ble_types Common types and macro definitions + @{ + + @brief Common types and macro definitions for the S110 SoftDevice. + */ + +#ifndef BLE_TYPES_H__ +#define BLE_TYPES_H__ + +#include + +/** @addtogroup BLE_COMMON_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_PPF 0x2A02 /**< Peripheral Privacy Flag Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */ +#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */ +/** @} */ + + +/** @defgroup BLE_UUID_TYPES Types of UUID + * @{ */ +#define BLE_UUID_TYPE_UNKNOWN 0x00 /**< Invalid UUID type. */ +#define BLE_UUID_TYPE_BLE 0x01 /**< Bluetooth SIG UUID (16-bit). */ +#define BLE_UUID_TYPE_VENDOR_BEGIN 0x02 /**< Vendor UUID types start at this index (128-bit). */ +/** @} */ + + +/** @defgroup BLE_APPEARANCES Bluetooth Appearance values + * @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml + * @{ */ +#define BLE_APPEARANCE_UNKNOWN 0 /**< Unknown. */ +#define BLE_APPEARANCE_GENERIC_PHONE 64 /**< Generic Phone. */ +#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /**< Generic Computer. */ +#define BLE_APPEARANCE_GENERIC_WATCH 192 /**< Generic Watch. */ +#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /**< Watch: Sports Watch. */ +#define BLE_APPEARANCE_GENERIC_CLOCK 256 /**< Generic Clock. */ +#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /**< Generic Display. */ +#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /**< Generic Remote Control. */ +#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /**< Generic Eye-glasses. */ +#define BLE_APPEARANCE_GENERIC_TAG 512 /**< Generic Tag. */ +#define BLE_APPEARANCE_GENERIC_KEYRING 576 /**< Generic Keyring. */ +#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /**< Generic Media Player. */ +#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /**< Generic Barcode Scanner. */ +#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /**< Generic Thermometer. */ +#define BLE_APPEARANCE_THERMOMETER_EAR 769 /**< Thermometer: Ear. */ +#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /**< Generic Heart rate Sensor. */ +#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /**< Heart Rate Sensor: Heart Rate Belt. */ +#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /**< Generic Blood Pressure. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /**< Blood Pressure: Arm. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /**< Blood Pressure: Wrist. */ +#define BLE_APPEARANCE_GENERIC_HID 960 /**< Human Interface Device (HID). */ +#define BLE_APPEARANCE_HID_KEYBOARD 961 /**< Keyboard (HID Subtype). */ +#define BLE_APPEARANCE_HID_MOUSE 962 /**< Mouse (HID Subtype). */ +#define BLE_APPEARANCE_HID_JOYSTICK 963 /**< Joystiq (HID Subtype). */ +#define BLE_APPEARANCE_HID_GAMEPAD 964 /**< Gamepad (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /**< Digitizer Tablet (HID Subtype). */ +#define BLE_APPEARANCE_HID_CARD_READER 966 /**< Card Reader (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /**< Digital Pen (HID Subtype). */ +#define BLE_APPEARANCE_HID_BARCODE 968 /**< Barcode Scanner (HID Subtype). */ +#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /**< Generic Glucose Meter. */ +#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /**< Generic Running Walking Sensor. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /**< Running Walking Sensor: In-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /**< Running Walking Sensor: On-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /**< Running Walking Sensor: On-Hip. */ +#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /**< Generic Cycling. */ +#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /**< Cycling: Cycling Computer. */ +#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /**< Cycling: Speed Sensor. */ +#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /**< Cycling: Cadence Sensor. */ +#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /**< Cycling: Power Sensor. */ +#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /**< Cycling: Speed and Cadence Sensor. */ +#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /**< Generic Pulse Oximeter. */ +#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /**< Fingertip (Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /**< Wrist Worn(Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /**< Generic Weight Scale. */ +#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /**< Generic Outdoor Sports Activity. */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /**< Location Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /**< Location Pod (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */ +/** @} */ + +/** @brief Set .type and .uuid fields of ble_uuid_struct to specified uuid value. */ +#define BLE_UUID_BLE_ASSIGN(instance, value) do {\ + instance.type = BLE_UUID_TYPE_BLE; \ + instance.uuid = value;} while(0) + +/** @brief Copy type and uuid members from src to dst ble_uuid_t pointer. Both pointers must be valid/non-null. */ +#define BLE_UUID_COPY_PTR(dst, src) do {\ + (dst)->type = (src)->type; \ + (dst)->uuid = (src)->uuid;} while(0) + +/** @brief Copy type and uuid members from src to dst ble_uuid_t struct. */ +#define BLE_UUID_COPY_INST(dst, src) do {\ + (dst).type = (src).type; \ + (dst).uuid = (src).uuid;} while(0) + +/** @brief Compare for equality both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */ +#define BLE_UUID_EQ(p_uuid1, p_uuid2) \ + (((p_uuid1)->type == (p_uuid2)->type) && ((p_uuid1)->uuid == (p_uuid2)->uuid)) + +/** @brief Compare for difference both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */ +#define BLE_UUID_NEQ(p_uuid1, p_uuid2) \ + (((p_uuid1)->type != (p_uuid2)->type) || ((p_uuid1)->uuid != (p_uuid2)->uuid)) + +/** @} */ + +/** @addtogroup BLE_TYPES_STRUCTURES Structures + * @{ */ + +/** @brief 128 bit UUID values. */ +typedef struct +{ + unsigned char uuid128[16]; +} 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 BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */ +} ble_uuid_t; + +/** @} */ + +#endif /* BLE_TYPES_H__ */ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error.h new file mode 100644 index 00000000000..518ef82b8f9 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + /** + @defgroup nrf_error SoftDevice Global Error Codes + @{ + + @brief Global Error definitions +*/ + +/* Header guard */ +#ifndef NRF_ERROR_H__ +#define NRF_ERROR_H__ + +/** @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 + +#endif // NRF_ERROR_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_sdm.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_sdm.h new file mode 100644 index 00000000000..ea5413ff3f4 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_sdm.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + /** + @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" + +#define NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN (NRF_ERROR_SDM_BASE_NUM + 0) ///< Unknown lfclk source +#define NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION (NRF_ERROR_SDM_BASE_NUM + 1) ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts) +#define NRF_ERROR_SDM_INCORRECT_CLENR0 (NRF_ERROR_SDM_BASE_NUM + 2) ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing) + +#endif // NRF_ERROR_SDM_H__ + +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_soc.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_soc.h new file mode 100644 index 00000000000..08dc13c3e7d --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_error_soc.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + /** + @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" + +/* 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 + +#endif // NRF_ERROR_SOC_H__ +/** + @} + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_mbr.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_mbr.h new file mode 100644 index 00000000000..4f323aefc20 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_mbr.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @defgroup nrf_mbr_api Master Boot Record API + @{ + + @brief APIs for updating SoftDevice and BootLoader + +*/ + +/* Header guard */ +#ifndef NRF_MBR_H__ +#define NRF_MBR_H__ + +#include "nrf_svc.h" +#include + + +/** @addtogroup NRF_MBR_DEFINES Defines + * @{ */ + +/**@brief MBR SVC Base number. */ +#define MBR_SVC_BASE 0x18 +/** @} */ + +/** @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 a new BootLoader. @see sd_mbr_command_copy_bl_t */ + SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/ + SD_MBR_COMMAND_INIT_SD, /**< Init forwarding interrupts to SD, and run reset function in SD*/ + SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/ + SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Start forwarding all exception to this address @see ::sd_mbr_command_vector_table_base_set_t*/ +}; + +/** @} */ + +/** @addtogroup NRF_MBR_TYPES Types + * @{ */ + +/**@brief This command copies part of a new SoftDevice + * The destination area is erased before copying. + * If dst is in the middle of a flash page, that whole flash page will be erased. + * If (dst+len) is in the middle of a flash page, that whole flash page will be erased. + * + * The user of this function is responsible for setting the PROTENSET 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 256 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_INVALID_STATE indicates that something was wrong. + * @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 is invalid. + */ +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 thiss function should be called with @param address set to 0. + * The MBR will then start forwarding to interrupts to the adress in NFR_UICR->BOOTADDR or to the SoftDevice if the BOOTADDR is not set. + * + * @retval ::NRF_SUCCESS + */ +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*/ + sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy SoftDevice and BootLoader*/ + sd_mbr_command_compare_t compare; /**< Parameters for verify*/ + sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base 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 + * + * @param[in] param Pointer to a struct describing the command + * + *@note for retvals see ::sd_mbr_command_copy_sd_t ::sd_mbr_command_copy_bl_t ::sd_mbr_command_compare_t + +*/ +SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param)); + +/** @} */ +#endif // NRF_MBR_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_sdm.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_sdm.h new file mode 100644 index 00000000000..dc24036b4da --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_sdm.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ +/** + @defgroup nrf_sdm_api SoftDevice Manager API + @{ + + @brief APIs for SoftDevice management. + +*/ + +/* Header guard */ +#ifndef NRF_SDM_H__ +#define NRF_SDM_H__ + +#include "nrf_svc.h" +#include "nrf51.h" +#include "nrf_soc.h" +#include "nrf_error_sdm.h" + +/** @addtogroup NRF_SDM_DEFINES Defines + * @{ */ + +/**@brief SoftDevice Manager SVC Base number. */ +#define SDM_SVC_BASE (0x10) + +/** @} */ + +/** @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 */ +}; + +/**@brief Possible lfclk oscillator sources. */ +enum NRF_CLOCK_LFCLKSRCS +{ + NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, /**< LFCLK Synthesized from HFCLK. */ + NRF_CLOCK_LFCLKSRC_XTAL_500_PPM, /**< LFCLK crystal oscillator 500 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_250_PPM, /**< LFCLK crystal oscillator 250 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_150_PPM, /**< LFCLK crystal oscillator 150 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_100_PPM, /**< LFCLK crystal oscillator 100 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_75_PPM, /**< LFCLK crystal oscillator 75 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_50_PPM, /**< LFCLK crystal oscillator 50 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_30_PPM, /**< LFCLK crystal oscillator 30 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, /**< LFCLK crystal oscillator 20 PPM accuracy. */ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, /**< LFCLK RC oscillator, 250ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_500MS_CALIBRATION, /**< LFCLK RC oscillator, 500ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_1000MS_CALIBRATION, /**< LFCLK RC oscillator, 1000ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_2000MS_CALIBRATION, /**< LFCLK RC oscillator, 2000ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, /**< LFCLK RC oscillator, 4000ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_8000MS_CALIBRATION, /**< LFCLK RC oscillator, 8000ms calibration interval.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_1000MS_CALIBRATION, /**< LFCLK RC oscillator. Temperature checked every 1000ms, if changed above a threshold, a calibration is done.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_2000MS_CALIBRATION, /**< LFCLK RC oscillator. Temperature checked every 2000ms, if changed above a threshold, a calibration is done.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION, /**< LFCLK RC oscillator. Temperature checked every 4000ms, if changed above a threshold, a calibration is done.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_8000MS_CALIBRATION, /**< LFCLK RC oscillator. Temperature checked every 8000ms, if changed above a threshold, a calibration is done.*/ + NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_16000MS_CALIBRATION, /**< LFCLK RC oscillator. Temperature checked every 16000ms, if changed above a threshold, a calibration is done.*/ +}; + +/** @} */ + +/** @addtogroup NRF_SDM_TYPES Types + * @{ */ + +/**@brief Type representing lfclk oscillator source. */ +typedef uint32_t nrf_clock_lfclksrc_t; + + +/**@brief SoftDevice Assertion Handler type. + * + * When an unexpected error occurs within the SoftDevice it will call the SoftDevice assertion handler callback. + * 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(). + * + * @note This callback is executed in HardFault context, thus SVC functions cannot be called from the SoftDevice assert callback. + * + * @param[in] pc The program counter of the failed assert. + * @param[in] line_number Line number where the assert failed. + * @param[in] file_name File name where the assert failed. + */ +typedef void (*softdevice_assertion_handler_t)(uint32_t pc, uint16_t line_number, const uint8_t * p_file_name); + +/** @} */ + +/** @addtogroup NRF_SDM_FUNCTIONS Functions + * @{ */ + +/**@brief Enables the SoftDevice and by extension the protocol stack. + * + * Idempotent function to enable the SoftDevice. + * + * @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 clock_source Low frequency clock source and accuracy. (Note: 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 assertion_handler Callback for SoftDevice assertions. + * + * @retval ::NRF_SUCCESS + * @retval ::NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION SoftDeviceinterrupt 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_lfclksrc_t clock_source, softdevice_assertion_handler_t assertion_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)); + +/** @} */ + +#endif // NRF_SDM_H__ + +/** + @} +*/ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_soc.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_soc.h new file mode 100644 index 00000000000..9d13de386d0 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_soc.h @@ -0,0 +1,958 @@ +/* Copyright (c) 2011 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + +/** + * @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 "nrf51.h" +#include "nrf51_bitfields.h" +#include "nrf_error_soc.h" + +/** @addtogroup NRF_SOC_DEFINES Defines + * @{ */ + +/**@brief The number of the lowest SVC number reserved for the SoC library. */ +#define SOC_SVC_BASE (0x20) +#define SOC_SVC_BASE_NOT_AVAILABLE (0x23) + +/**@brief Guranteed time for application to process radio inactive notification. */ +#define NRF_RADIO_NOTIFICATION_INACTIVE_GUARANTEED_TIME_US (62) + +/**@brief The minimum allowed timeslot extension time. */ +#define NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US (200) + +#define SOC_ECB_KEY_LENGTH (16) /**< ECB key length. */ +#define SOC_ECB_CLEARTEXT_LENGTH (16) /**< ECB cleartext length. */ +#define SOC_ECB_CIPHERTEXT_LENGTH (SOC_ECB_CLEARTEXT_LENGTH) /**< ECB ciphertext length. */ + +#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. */ + +#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 NRF_RADIO_CALLBACK_SIGNAL_TYPE_START relative to the requested start time. */ + +/** @} */ + +/** @addtogroup NRF_SOC_TYPES Types + * @{ */ + +/**@brief The SVC numbers used by the SVC functions in the SoC library. */ +enum NRF_SOC_SVCS +{ + SD_FLASH_PAGE_ERASE = SOC_SVC_BASE, + SD_FLASH_WRITE, + SD_FLASH_PROTECT, + SD_MUTEX_NEW = SOC_SVC_BASE_NOT_AVAILABLE, + SD_MUTEX_ACQUIRE, + SD_MUTEX_RELEASE, + SD_NVIC_ENABLEIRQ, + SD_NVIC_DISABLEIRQ, + SD_NVIC_GETPENDINGIRQ, + SD_NVIC_SETPENDINGIRQ, + SD_NVIC_CLEARPENDINGIRQ, + SD_NVIC_SETPRIORITY, + SD_NVIC_GETPRIORITY, + SD_NVIC_SYSTEMRESET, + SD_NVIC_CRITICAL_REGION_ENTER, + SD_NVIC_CRITICAL_REGION_EXIT, + SD_RAND_APPLICATION_POOL_CAPACITY, + SD_RAND_APPLICATION_BYTES_AVAILABLE, + SD_RAND_APPLICATION_GET_VECTOR, + SD_POWER_MODE_SET, + SD_POWER_SYSTEM_OFF, + SD_POWER_RESET_REASON_GET, + SD_POWER_RESET_REASON_CLR, + SD_POWER_POF_ENABLE, + SD_POWER_POF_THRESHOLD_SET, + SD_POWER_RAMON_SET, + SD_POWER_RAMON_CLR, + SD_POWER_RAMON_GET, + SD_POWER_GPREGRET_SET, + SD_POWER_GPREGRET_CLR, + SD_POWER_GPREGRET_GET, + SD_POWER_DCDC_MODE_SET, + SD_APP_EVT_WAIT, + SD_CLOCK_HFCLK_REQUEST, + SD_CLOCK_HFCLK_RELEASE, + SD_CLOCK_HFCLK_IS_RUNNING, + SD_PPI_CHANNEL_ENABLE_GET, + 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_RADIO_NOTIFICATION_CFG_SET, + SD_ECB_BLOCK_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 Possible values of ::nrf_app_irq_priority_t. */ +enum NRF_APP_PRIORITIES +{ + NRF_APP_PRIORITY_HIGH = 1, + NRF_APP_PRIORITY_LOW = 3 +}; + +/**@brief Possible values of ::nrf_power_mode_t. */ +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 Possible values of ::nrf_power_failure_threshold_t */ +enum NRF_POWER_THRESHOLDS +{ + NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */ + NRF_POWER_THRESHOLD_V27 /**< 2.7 Volts power failure threshold. */ +}; + + +/**@brief Possible values of ::nrf_power_dcdc_mode_t. */ +enum NRF_POWER_DCDC_MODES +{ + NRF_POWER_DCDC_MODE_OFF, /**< The DCDC is always off. */ + NRF_POWER_DCDC_MODE_ON, /**< The DCDC is always on. */ + NRF_POWER_DCDC_MODE_AUTOMATIC /**< The DCDC is automatically managed. */ +}; + +/**@brief Possible values of ::nrf_radio_notification_distance_t. */ +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 Possible values of ::nrf_radio_notification_type_t. */ +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 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 signal callback handler return was invalid. */ + NRF_EVT_RADIO_SESSION_IDLE, /**< Event indicating that a radio session is idle. */ + NRF_EVT_RADIO_SESSION_CLOSED, /**< Event indicating that a radio session is closed. */ + NRF_EVT_NUMBER_OF_EVTS +}; + +/** @} */ + +/** @addtogroup NRF_SOC_TYPES Types + * @{ */ + +/**@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 The interrupt priorities available to the application while the softdevice is active. */ +typedef uint8_t nrf_app_irq_priority_t; + +/**@brief Represents a power mode, used in power mode functions */ +typedef uint8_t nrf_power_mode_t; + +/**@brief Represents a power failure threshold value. */ +typedef uint8_t nrf_power_failure_threshold_t; + +/**@brief Represents a DCDC mode value. */ +typedef uint32_t nrf_power_dcdc_mode_t; + +/**@brief Radio notification distances. */ +typedef uint8_t nrf_radio_notification_distance_t; + +/**@brief Radio notification types. */ +typedef uint8_t nrf_radio_notification_type_t; + +/** @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_DEFAULT, /**< Use the currently selected oscillator as HF clock source during the timeslot (i.e. the source is not specified). */ + NRF_RADIO_HFCLK_CFG_FORCE_XTAL, /**< Force external crystal to be used as HF clock source during whole the timeslot. */ +}; + +/** @brief Radio timeslot priorities. */ +enum NRF_RADIO_PRIORITY +{ + NRF_RADIO_PRIORITY_HIGH, /**< High (equal priority as the normal connection priority of the SoftDevice stack(s)). */ + NRF_RADIO_PRIORITY_NORMAL, /**< Normal (equal priority as the priority of secondary activites of the SoftDevice stack(s)). */ +}; + +/** @brief Radio timeslot request type. */ +enum NRF_RADIO_REQUEST_TYPE +{ + NRF_RADIO_REQ_TYPE_EARLIEST, /**< Request timeslot as early as possible. This should always be used for the first request in a session. */ + NRF_RADIO_REQ_TYPE_NORMAL /**< Normal timeslot request. */ +}; + +/** @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 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 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 a request for a timeslot as early as possible. */ + nrf_radio_request_normal_t normal; /**< Parameters for a normal radio request. */ + } params; +} 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 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; +} nrf_radio_signal_callback_return_param_t; + +/**@brief The radio 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 data structure */ +typedef struct +{ + uint8_t key[SOC_ECB_KEY_LENGTH]; /**< Encryption key. */ + uint8_t cleartext[SOC_ECB_CLEARTEXT_LENGTH]; /**< Clear Text data. */ + uint8_t ciphertext[SOC_ECB_CIPHERTEXT_LENGTH]; /**< Cipher Text data. */ +} nrf_ecb_hal_data_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 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. + */ +SVCALL(SD_NVIC_ENABLEIRQ, 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. + */ +SVCALL(SD_NVIC_DISABLEIRQ, 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. + */ +SVCALL(SD_NVIC_GETPENDINGIRQ, 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. + */ +SVCALL(SD_NVIC_SETPENDINGIRQ, 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. + */ +SVCALL(SD_NVIC_CLEARPENDINGIRQ, 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. + */ +SVCALL(SD_NVIC_SETPRIORITY, uint32_t, sd_nvic_SetPriority(IRQn_Type IRQn, nrf_app_irq_priority_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. + */ +SVCALL(SD_NVIC_GETPRIORITY, uint32_t, sd_nvic_GetPriority(IRQn_Type IRQn, nrf_app_irq_priority_t * p_priority)); + +/**@brief System Reset. + * @note Corresponds to NVIC_SystemReset in CMSIS. + * + * @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN + */ +SVCALL(SD_NVIC_SYSTEMRESET, 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 + */ +SVCALL(SD_NVIC_CRITICAL_REGION_ENTER, 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 + */ +SVCALL(SD_NVIC_CRITICAL_REGION_EXIT, uint32_t, sd_nvic_critical_region_exit(uint8_t is_nested_critical_region)); + +/**@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, 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, 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_GET_VECTOR, 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. @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(nrf_power_mode_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. + * + * @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(nrf_power_failure_threshold_t threshold)); + +/**@brief Sets bits in the NRF_POWER->RAMON register. + * + * @param[in] ramon Contains the bits needed to be set in the NRF_POWER->RAMON register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAMON_SET, uint32_t, sd_power_ramon_set(uint32_t ramon)); + +/** @brief Clears bits in the NRF_POWER->RAMON register. + * + * @param ramon Contains the bits needed to be cleared in the NRF_POWER->RAMON register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAMON_CLR, uint32_t, sd_power_ramon_clr(uint32_t ramon)); + +/**@brief Get contents of NRF_POWER->RAMON register, indicates power status of ram blocks. + * + * @param[out] p_ramon Content of NRF_POWER->RAMON register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_POWER_RAMON_GET, uint32_t, sd_power_ramon_get(uint32_t * p_ramon)); + +/**@brief Set bits in the NRF_POWER->GPREGRET register. + * + * @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_msk)); + +/**@brief Clear bits in the NRF_POWER->GPREGRET register. + * + * @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_msk)); + +/**@brief Get contents of the NRF_POWER->GPREGRET register. + * + * @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 *p_gpregret)); + +/**@brief Sets the DCDC mode. + * + * Depending on the internal state of the SoftDevice, the mode change may not happen immediately. + * The DCDC mode switch will be blocked when occurring in close proximity to radio transmissions. When + * the radio transmission is done, the last mode will be used. + * + * @param[in] dcdc_mode The mode of the DCDC. + * + * @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(nrf_power_dcdc_mode_t dcdc_mode)); + +/**@brief Request the high frequency crystal oscillator. + * + * Will start the high frequency crystal oscillator, the startup time of the crystal varies + * and the ::sd_clock_hfclk_is_running function can be polled to check if it has started. + * + * @see sd_clock_hfclk_is_running + * @see sd_clock_hfclk_release + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_REQUEST, uint32_t, sd_clock_hfclk_request(void)); + +/**@brief Releases the high frequency crystal oscillator. + * + * Will stop the high frequency crystal oscillator, this happens immediately. + * + * @see sd_clock_hfclk_is_running + * @see sd_clock_hfclk_request + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_RELEASE, uint32_t, sd_clock_hfclk_release(void)); + +/**@brief Checks if the high frequency crystal oscillator is running. + * + * @see sd_clock_hfclk_request + * @see sd_clock_hfclk_release + * + * @param[out] p_is_running 1 if the external crystal oscillator is running, 0 if not. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_CLOCK_HFCLK_IS_RUNNING, uint32_t, sd_clock_hfclk_is_running(uint32_t * p_is_running)); + +/**@brief Waits for an application event. + * + * An application event is either an application interrupt or a pended interrupt when the + * interrupt is disabled. When the interrupt is enabled it will be taken immediately since + * this function will wait in thread mode, then the execution will return in the application's + * main thread. When an interrupt is disabled and gets pended it will return to the application's + * thread main. The application must ensure that the pended flag is cleared using + * ::sd_nvic_ClearPendingIRQ in order to sleep using this function. This is only necessary for + * disabled interrupts, as the interrupt handler will clear the pending flag automatically for + * enabled interrupts. + * + * In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M0 + * System Control Register (SCR). @sa CMSIS_SCB + * + * @note If an application interrupt has happened since the last time sd_app_evt_wait was + * called this function will return immediately and not go to sleep. This is to avoid race + * conditions that can occur when a flag is updated in the interrupt handler and processed + * in the main loop. + * + * @post An application interrupt has happened or a interrupt pending flag is set. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_APP_EVT_WAIT, uint32_t, sd_app_evt_wait(void)); + +/**@brief Get PPI channel enable register contents. + * + * @param[out] p_channel_enable The contents of the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_GET, uint32_t, sd_ppi_channel_enable_get(uint32_t * p_channel_enable)); + +/**@brief Set PPI channel enable register. + * + * @param[in] channel_enable_set_msk Mask containing the bits to set in the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_SET, uint32_t, sd_ppi_channel_enable_set(uint32_t channel_enable_set_msk)); + +/**@brief Clear PPI channel enable register. + * + * @param[in] channel_enable_clr_msk Mask containing the bits to clear in the PPI CHEN register. + * + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ENABLE_CLR, uint32_t, sd_ppi_channel_enable_clr(uint32_t channel_enable_clr_msk)); + +/**@brief Assign endpoints to a PPI channel. + * + * @param[in] channel_num Number of the PPI channel to assign. + * @param[in] evt_endpoint Event endpoint of the PPI channel. + * @param[in] task_endpoint Task endpoint of the PPI channel. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_CHANNEL The channel number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_CHANNEL_ASSIGN, uint32_t, sd_ppi_channel_assign(uint8_t channel_num, const volatile void * evt_endpoint, const volatile void * task_endpoint)); + +/**@brief Task to enable a channel group. + * + * @param[in] group_num Number of the channel group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_TASK_ENABLE, uint32_t, sd_ppi_group_task_enable(uint8_t group_num)); + +/**@brief Task to disable a channel group. + * + * @param[in] group_num Number of the PPI group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_TASK_DISABLE, uint32_t, sd_ppi_group_task_disable(uint8_t group_num)); + +/**@brief Assign PPI channels to a channel group. + * + * @param[in] group_num Number of the channel group. + * @param[in] channel_msk Mask of the channels to assign to the group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_ASSIGN, uint32_t, sd_ppi_group_assign(uint8_t group_num, uint32_t channel_msk)); + +/**@brief Gets the PPI channels of a channel group. + * + * @param[in] group_num Number of the channel group. + * @param[out] p_channel_msk Mask of the channels assigned to the group. + * + * @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_PPI_GROUP_GET, uint32_t, sd_ppi_group_get(uint8_t group_num, uint32_t * p_channel_msk)); + +/**@brief Configures the Radio Notification signal. + * + * @note + * - The notification signal latency depends on the interrupt priority settings of SWI used + * for notification signal. + * - 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. + * @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. + * This parameter is ignored when @ref NRF_RADIO_NOTIFICATION_TYPE_NONE or + * @ref NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE is used. + * + * @retval ::NRF_ERROR_INVALID_PARAM The group number is invalid. + * @retval ::NRF_SUCCESS + */ +SVCALL(SD_RADIO_NOTIFICATION_CFG_SET, uint32_t, sd_radio_notification_cfg_set(nrf_radio_notification_type_t type, nrf_radio_notification_distance_t distance)); + +/**@brief Encrypts a block according to the specified parameters. + * + * 128-bit AES encryption. + * + * @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 Gets any pending events generated by the SoC API. + * + * The application should keep calling this function to get events, until ::NRF_ERROR_NOT_FOUND is returned. + * + * @param[out] p_evt_id Set to one of the values in @ref NRF_SOC_EVTS, if any events are pending. + * + * @retval ::NRF_SUCCESS An event was pending. The event id is written in the p_evt_id parameter. + * @retval ::NRF_ERROR_NOT_FOUND No pending events. + */ +SVCALL(SD_EVT_GET, uint32_t, sd_evt_get(uint32_t * p_evt_id)); + +/**@brief Get the temperature measured on the chip + * + * This function will block until the temperature measurement is done. + * It takes around 50us from call to return. + * + * @note Pan #28 in PAN-028 v 1.6 "Negative measured values are not represented correctly" is corrected by this function. + * + * @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 + * + * This call initiates the flash access command, and its completion will be communicated to the + * application with exactly one of the following events: + * - NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed. + * - NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started. + * + * @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] 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 32bit words. + * + * @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 more than 256 words. + * @retval ::NRF_ERROR_FORBIDDEN Tried to write to or read from protected location. + * @retval ::NRF_SUCCESS The command was accepted. + */ +SVCALL(SD_FLASH_WRITE, uint32_t, sd_flash_write(uint32_t * const p_dst, uint32_t const * const p_src, uint32_t size)); + + +/**@brief Flash Erase page + * + * Commands to erase a flash page + * + * This call initiates the flash access command, and its completion will be communicated to the + * application with exactly one of the following events: + * - NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed. + * - NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started. + * + * @note + * - This call takes control over the radio and the CPU during flash erase and write to make sure that + * they will not interfere with the flash access. This means that all interrupts will be blocked + * for a predictable time (depending on the NVMC specification in nRF51 Series Reference Manual + * and the command parameters). + * + * + * @param[in] page_number Pagenumber of the page to erase + * @retval ::NRF_ERROR_INTERNAL If a new session could not be opened due to an internal error. + * @retval ::NRF_ERROR_INVALID_ADDR Tried to erase to a non existing flash page. + * @retval ::NRF_ERROR_BUSY The previous command has not yet completed. + * @retval ::NRF_ERROR_FORBIDDEN Tried to erase a protected page. + * @retval ::NRF_SUCCESS The command was accepted. + */ +SVCALL(SD_FLASH_PAGE_ERASE, uint32_t, sd_flash_page_erase(uint32_t page_number)); + + +/**@brief Flash Protection set + * + * Commands to set the flash protection registers PROTENSETx + * + * @note To read the values in PROTENSETx you can read them directly. They are only write-protected. + * + * @param[in] protenset0 Value to be written to PROTENSET0 + * @param[in] protenset1 Value to be written to PROTENSET1 + * + * @retval ::NRF_ERROR_FORBIDDEN Tried to protect the SoftDevice + * @retval ::NRF_SUCCESS Values successfully written to PROTENSETx + */ +SVCALL(SD_FLASH_PROTECT, uint32_t, sd_flash_protect(uint32_t protenset0, uint32_t protenset1)); + +/**@brief Opens a session for radio requests. + * + * @note Only one session can be open at a time. + * @note p_radio_signal_callback(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(NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0) is called whenever the NRF_TIMER0 + * interrupt occurs. + * @note p_radio_signal_callback(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 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 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 timing of the radio timeslot is specified by p_request->distance_us. For the first + * request in a session, p_request->distance_us is required to be 0 by convention, and + * the timeslot is scheduled at the first possible opportunity. All following radio timeslots are + * requested with a distance of p_request->distance_us measured from the start of the + * previous radio timeslot. + * @note A too small p_request->distance_us will lead to a NRF_EVT_RADIO_BLOCKED event. + * @note Timeslots scheduled too close will lead to a NRF_EVT_RADIO_BLOCKED event. + * @note See the SoftDevice Specification for more on radio timeslot scheduling, distances and lengths. + * @note If an opportunity for the first radio timeslot is not found before 100ms after the call to this + * function, it is not scheduled, and instead a 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(NRF_RADIO_CALLBACK_SIGNAL_TYPE_START). + * Unsuccessful requests will result in a NRF_EVT_RADIO_BLOCKED event, see @ref NRF_SOC_EVTS. + * @note The jitter in the start time of the radio timeslots is +/- NRF_RADIO_START_JITTER_US us. + * @note The nrf_radio_signal_callback_t(NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) call has a latency relative to the + * specified radio timeslot start, but this does not affect the actual start time of the timeslot. + * @note NRF_TIMER0 is reset at the start of the radio timeslot, and is clocked at 1MHz from the high frequency + * (16 MHz) clock source. If p_request->hfclk_force_xtal is true, the high frequency clock is + * guaranteed to be clocked from the external crystal. + * @note The SoftDevice will neither access the NRF_RADIO peripheral nor the NRF_TIMER0 peripheral + * during the radio timeslot. + * + * @param[in] p_request Pointer to the request parameters. + * + * @retval ::NRF_ERROR_FORBIDDEN If session not opened or the session is not IDLE. + * @retval ::NRF_ERROR_INVALID_ADDR If the p_request pointer is invalid. + * @retval ::NRF_ERROR_INVALID_PARAM If the parameters of p_request are not valid. + * @retval ::NRF_SUCCESS Otherwise. + */ + SVCALL(SD_RADIO_REQUEST, uint32_t, sd_radio_request(nrf_radio_request_t * p_request )); + +/** @} */ + +#endif // NRF_SOC_H__ + +/**@} */ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_svc.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_svc.h new file mode 100644 index 00000000000..e75083ed86d --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/nrf_svc.h @@ -0,0 +1,33 @@ +#ifndef NRF_SVC__ +#define NRF_SVC__ + +#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__) +#define SVCALL(number, return_type, signature) \ + _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \ + _Pragma("GCC diagnostic ignored \"-Wunused-function\"") \ + __attribute__((naked)) static return_type signature \ + { \ + __asm( \ + "svc %0\n" \ + "bx r14" : : "I" (number) : "r0" \ + ); \ + } +#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 +#endif // NRF_SVC__ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/softdevice_assert.h b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/softdevice_assert.h new file mode 100644 index 00000000000..42494477bf4 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_API/include/softdevice_assert.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is confidential property of Nordic Semiconductor. The use, + * copying, transfer or disclosure of such information is prohibited except by express written + * agreement with Nordic Semiconductor. + * + */ + +/** @brief Utilities for verifying program logic + */ + +#ifndef SOFTDEVICE_ASSERT_H_ +#define SOFTDEVICE_ASSERT_H_ + +#include + +/** @brief This function handles assertions. + * + * + * @note + * This function is called when an assertion has triggered. + * + * + * @param line_num The line number where the assertion is called + * @param file_name Pointer to the file name + */ +void assert_softdevice_callback(uint16_t line_num, const uint8_t *file_name); + + +/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */ +/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \ +/** @brief Check intended for production code + * + * Check passes if "expr" evaluates to true. */ +#define ASSERT(expr) \ +if (expr) \ +{ \ +} \ +else \ +{ \ + assert_softdevice_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \ + /*lint -unreachable */ \ +} + +#endif /* SOFTDEVICE_ASSERT_H_ */ diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_licence_agreement.pdf b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_licence_agreement.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7aab95c8e7ae8c764467d3d81fa9069d2ff9c2ef GIT binary patch literal 5553 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 z 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�pD^)L_7d!c|mv$i4N_Sj2Q$M_JVgr+7ZYX~5ZZ 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
  • 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 literal 0 HcmV?d00001 diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_readme.txt b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_readme.txt new file mode 100644 index 00000000000..ffc8c2f47ea --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_readme.txt @@ -0,0 +1,14 @@ +s110_nrf51822_7.0.0 + +This release consists of the following: +- This readme file +- The s110_nrf51822_7.0.0 license +- The s110_nrf51822_7.0.0 softdevice (binary hex file) +- The s110_nrf51822_7.0.0 API (softdevice header files) +- The s110_nrf51822_7.0.0 release notes +- The s110_nrf51822_7.0.0 migration document + + +IMPORTANT NOTE: If you intend to use the softdevice with the nRF51 +SDK only, you do _not_ need the API files. The API header files are +already installed as part of the nRF51 SDK versions 6.0.0. diff --git a/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_releasenotes.pdf b/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_0_0/s110_nrf51822_7.0.0_releasenotes.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1ef406f8f5c25fd2e1ef4ceb1389556def0a2043 GIT binary patch literal 58183 zcmd43bzEFaw=D`JKycR(TobH;1{!w@?k>UIU4jOJTkzn7;O_2j!QCM^2^#b@N{w#u@kd0Gtq+&03b6xkcpU;g^8Y#MT>_A z-q6Yb3;-U$@<&L(H~tSK;5&er{tXfUBNz%37z2Lz(Bu3Vf`a04_E#5et;kVJrMlCfBSwOt-=VT2M_~T z+3A_VCVIfd`YRH)KSJ_w)n7;+UOkvO{}u=k1bi?afQ6MF07miv>o=x=?fM6==i#cq zkN`m-dLZbZKw)R4X9Y6_2Z%hIA@dr>IuKEkgKa~%Vjg6j#=`Z;JA8`Fj z6s8C9{-1I7L7@LgK0q)Hz}T=|OCNspk>buS{VAJA*$k z${(o*$O3wBga48b5D21Y{FNz8f97caNIoo#^gysn`6-`AT)#2p&m1k_fna};mI=W4 z?|uG*PXRImz>)`mtpNfz9)SHul|OT|zd`xO`e6bG957XYKzcTopSXUb%AYyfUw!^R z*AIY+p8fCe0|WyD{6>{O^R&N0`R4*+WTt2RJNy72fc?gmKXbKzBp?Lyum3BO zf2vnj|9X7qGtyW5dI~g z2VB1~<B6LP6Jy^&; zv!6#?zcPj8&m8TqOkn~5ACk_0pZ+kjfdk>gNCljoG7~@I`jsl+B;fxmAv3dr;|-W8 zKZX2&3-~KjSpLk>{*jQGfvoh559!aNk{^Nn#*{yEw7-(}pDLLdY>mH#{0QqeqC9l@ zKX-q5Zcd6>!mwnGqZY!At>x$8O*T7}l>u0shO)5`$}dl7?2s4klo4t9ommhdhqACt7K_qx&E9i6>$NrZrGczyUi%UOIB$}|~* zA8{j-21@voB}JSAX&(>wJtZ&jgu9_9x60sY+v?sVA`x<61%u&z^VO~qR+8;uQu6%d zvX%03iI+|Q>#4rgQc3+5QR(I0%XeGzlP&icN%KlcNdU5&W zr-_t#i_arr?>U!Bx@V;8@UHR>+g0c;XhyZmilE$iexzY&Ou&vQO^RV2L0sVie{#VX!{!cC(_SUvd?) z79`@S4omjfzGS5G7@k0U4MnIF>zaJ>xhMxSG@dx~m`#M)DcULl@lfUy5yz`$_C7=_%pxeHS9z*<+^8Qo85D9!MuaX(a`rQ2;v$WGoxqf>2SsH0*3gG2v)#B$< zVxuD=W$BUvC_x{fSwNccrT_RgsM^!Xt#+wxM;yd0P8rLNm7uVCvQWeSI^vCFYE*37 ze155{E_DC?4dON&y<;WFkLjGr`1{lNB!ibhqad!-k}`E-zRDmrcD&h>?=db z9frRq*~lt(sm6Qw7tkhgM;zn50tF2xX~lj>$(i`jewrY!-q$mMto{v9^U<03RY`3z zJY4r=0`Lj~XAbA9;4<>k{u9(6;D_aW4Y|RN6+5vKxNttV?}|IO@}jqY$5Ba_x>Tg- z8?#4d`beJC(mr1Cv`kn3S2cK&p1jr+n6yAv^$Nd)##uE`V=+7ev@+P@zUFk49?~}3 z7VXzHit z&B_XPp`nfW1--%MLj6ljTop29G8oqLwj#+x7_MZlQ(|9rJT%rfs{OdD)L5}&B8UkA z*~*mb%{;0i=&WxHq}ZwR-xL-gxx2j#e$kfZlGOvL6@?x2VKO-<_QSfOu56T#D{oIl>kF!4MQ+`;h@C-dPTog)|Pen-fvXX3Mh#Cp9Lzk4H!@)Gfe=AU+JQ|}mZm_Od zODQKZBEJJ>))tG)%#gd~)zfPaF>Mri8M1f0MPfCaS>J{j9 z-m8EeKu%?}UrN-eCDrn| zmrshomogMe?)K%ImNzqK#!&ki)A$qQ`bOh(TWo!lcEPN0CViDVt>lx@ieJ@z)SD0T z3N(_6am=%k$_!1-L6uJ+RFLqiiEr{xZnz+MMK!IodK^CH(G~RGV9Y51(acbO&?MM^ zxU>|lL%#c&Xk7v)5kMDP1Z<;=vo@yaQZ%xE8RNhkdnn{ZZ?-8UpRl!qva)5IynMKV z52$EP7qcA5VX^bkndlV*ST+OM)%|?0&b=tps_mterJ~PHWWjF-o*^2J0<3$bD?*-S zjV!_9mBpU?^!R__P6Ok<^EZ;($u0X8cOc4FyN%!{Ubn`Z&u$jev0f_&uvU7JBvlAd zrEPsJ?GQ~qyk*BK7LNssfiGOaMZ)Zun95VuePJAyL3HB?wn(+y%w~LM;xq6rNO@=n z_WBAX#^-@pkGkB+(UtZKq_P_Qbfjl~aRe*;AWe0}2Xf%PTdZIKmyyd0-OY(F*25EhH2a=ge>vfacE7juu(&ABEa3HY=nl$7-!fLxJ zJr}N_xRUJ>m@~~rN>p6MZ0O)@Jojk5~0;CEWU{yOhvPhNVqvTbAqkn?b7 z$)~V!t=`P$=^gtDbd|H{ykbAUOz;pwAe9z;eF(W^8Hq~mslEw^*g!isyay7_r{ zXi|r>&2r-`e;xSTM<@R1P_iP6X7!98AF`qvM5jU71Fy2cyu$p{ z6Z>UF@Ac7#7d6gc=QCVfAixxqXE(SDLNXZN2O({YZ>++>Sw?ZG((dyc(#VjB=B0<8 zXSX{MP7J5x!Va*1SMmERAids4w(8TJ&=Ni9a+Q6`9r!E18K|4VV$umS z?oY;+mKr+!)Gt$_Js8irYh%=gxx6{W$!4316BfbGh{k{*=Z&sPkzFT;=|oUi4xXqL z2lw+5I9Oq&P$he38wQEArGPe1H`tmb&w6T0tEh!Gf=@mAJL3)M%N?z9tK-6I=JWYB zl2T!+dZLW(_Ig^fu*q9!9vN>NXe8={nNm9I5*F))ZbWlkW8boD4jL^=Q~wM_VJKE5 zxIt(s>DP{mhtt9jAr9={6jrCnF1b(k9zU0Z_MpD0e+u^GoV86~N<>S252x4JvAwin z+bS>x!W97VUfjNm%q@g%IQ2R>587|cINpn^YDf8?6LBeo$IWBz^->w^wVu&Pt_to< zlko)hBlm!B25KmVS955w0-@a&Bv0zxg|i_Oj3a5n-O@mM;fNudb@Dq`Xm~mW18y35 zmp0kknBQs=#-Ev*o(G=TUEOS{-0Z+p2XI%Ad);vG*8J)o4RZ&G z?bqz3dUV7P40n1S1X!j!N^Z!#-D>3CpN^P637pP4k+inPy)8Mga@W@1hc+IP6 z=(r5{=DbvuM=Bqx(wOc9Zo>=@dLW%8L+^|(4qaTdow}4y@1X+G-WGVA-F`g@Y8h|3 z@;Wtb*U4>eB-$yz9=l+^6FBL=9)rD+T64U}Lb$wcs9B1@{T6Scoq7atcV{E+GLh<5eAO3hQ_*Tq{mN zKml`ov6eK)i%q^oY#*MDmo(TZyjS=FxPF&Q7p}H_pd?6(>^HnHkS71N z?wMfW$Q&ur8CRTZh&5Er0G-qK^>YWSDVx1-`XlBhJ!|}`Y!~y}hSnF)HH?1nfxI-9 zJ|^pg&u<Dgp{@`w@*JfDPeVK0WWE{<_RO78ly6N-?D&G-jnn#fH{59F+5@FMH+H#P6+)>+f zpfgeU{B@xH$+&TH8c*P1i08>7nZ$!L}FB5GI zP6`TTVIxGoMi=j!d#^L9&qoVv4+{YPl~w$;6yWa^T2{}_(8_@r__JOuXl>;HZrT$+ zCM@y{iVtfHWc7>CqM?feF@v}z_%wlk z9R>e&6xU)90e1<$Mg&0oGp!O~B7UeO$n$`I7^DmhO!Wk;T^^T0u!0jWHV~5*1HYA( zwS&FJuPp!u8Z;QLv4VhlsvYX`kKP+Hv*aAszc@nZ;vW3Ar|0BqW&}Uz|*FGRd4<)>iy)& z|BKXP`ge@`k2Nw6<->>K(l2Ia27y5Ty`4X5EXK{VA~#=^B-$;C+5z$PiCE8hD} zr*CF;myX}INfF!GWx8%j(eHiRc(IuKnOs|4bArSz@ua4pU+`FZMSWlB<&=qe3PalS)GA2@2F2*E1 z3cF(pn{HoV?YeP_Ix^4E51ZD4*+|#42(BB>A`u34Ig9EYbVr;xYCIPl95(BF7<^L@ zB(3@k6T&|HcU-2(56F-aptX;H!&QS2zD*s^l@PZ3d(Aj8+=$Y~^vEfZFvlX*0xKWyO7DNdmu3o0<6^w*2DdA{nnM{5$H)(3_ zQ<{WuTu*%HJbhwuWbO!jMs-_wM|j?;+1|DYy)$gjLJV{ntmIPzn@AH>GoTmikMOR9 zs2;$UiMjM^WKaY?L0N)83aVB&M^h>0Dp3a)YPKN-T--J}K79-}LYedvT8acxRhq8- zHW&p7Ixf60JY4kwQFceigs1Q0F=J4%_dQ;S@b4rDM4tiQcV}ex__CUPM1o_kmh@S` zu0M|2xEacV2~|!JIMX70@*#TSiVKGR+Yh`a5wA_T44yjGq4kwycaF>vHgLf#b$72{ zYTD&9LAj^&AU;z}T1j@{lFlR!PU%?}QbFv7v_*GwU_p0Z2-;A}0^g^fFd~NinSGl& z0Q=cgc3ff4!Dq-UtX$dLV?7l1{Yr!x#lk(9)FASZk3xPCr>a3OY-X&Xb355#4k?FI z;|OdB4OKl7o<}N7R3Z`BG-1r3KMRi*DX$f0Ij+R#HIKmt?brMJ2vVTe6Gv}&pM2(z zhOxr3822OGoF&H-aovs9i>16FnU-!J6Z=3n#y~H|q|_96q3KpSPB6?pMN_I;3WJbOzVBc(LCoJoBgva5Bu=%E-0Wuo+s5B8cf8PjcGS$FjfG@u~PkUaAA+Eo6 z6jlH#T@7Oy~-qF)qU^3&SgT+Vk0FX2YSVMiINQTI$>V!bHJ0S?K@2nzt>=uQJb#(1jOw^v#_6-YM92&O-l&fc zta>6_@U4Q?w2X=-HmWcNI_g1z91-~BpV?B5W=*i>IZ|l6wGMX~L%tIy|ef#XtYn-KuIRKd%QCGHRwnvq-hzQ$wI@+;LKv z6thFno5Ecu)DI>jJwTVz`S(K^W*26o1sZ7=4ObQTmE|~UE;lEL75ipYSo*o1XXT)R zGC#gSvIyb}^m%EsCnBsLv{|0MZEX=JezF{NlZp0~SwDEO!Ah}%x0$=B*=XoEsq;%^ zwW(6RLK|=G6i%)}$LHmX#paT5(c`6LC&k<1 zIS6t0v+cS=z|{wLXFi=Gz_a8-7btlPKi3J_s(9qe9x*2zk2xo@wV71MOX%7sXdMdB zjdKLMF|`F(^=3UJs7I!Ge)4WK%T;V8XGS>F-f+6b=0mAz1!X0?Z*$)tP<{+d=GT&_ z^Ztgk?N%77R9PJmI_i*1c8Ebdi}G=)7RLSf@_>f46s4=0ZRnt46MA4qu@*)5j(HTn znw0)UCilyrJvf2sySqDA>X28s$vXP^=Bi7s^M}orx()ipWcSVn%K}UTetG8-R5(vo zw5F~1!YprWQ&(Lp=hr)w-o@u7d7NQqZGo!VNkbeFIwFPkrUr&V(_2?} zPbalIxHKe<&lpq2qTs)uFgoSN7~NnC@J{)8Ew#mYYgL-(uM%_E01xnq>7E+3z;+c$ z16LxjPt17lx;hE%FgNn;E3jI%B-u}NW8`%bh*g7X=O*a}E0hCwiw}oy*AFU)ti9YW zxQ0VcC64v=2r&}-=a04%J{!}V9>5$(Lr+w|wvKEY6&|>j6-Jnu=*Bd=+>0#mWU*8f zT#fW!z<*C0yNRavNt3QbHzc{75stPA!|M?k!ruIyDzz@sGzzR#L~V z*N(L{2GV6H-`dnu$GR8`D0_)=+h)DPNa<%)7DpF}?|S*NRQukn(3@P0*(R0ehtDf> zXwkHJz&w76ddUa}PP+&d&f3>Jm4r;)cz2lNoaXt@bTF$BG^pRzxCtiCp+1*y7|1l3 zDts)vdoqXoWJ7geT=SjE+TzgObW5W;eOm5jBh_g<3`H6oZ<8uLuckNbT#?7SttnV% zEX)u4iFU-f6;>+cD#HhnU4nL-0- zpHaNMmJItAEj9PV;PbtC{GO7VYGg4MIgywTcPecCS9uB;~?(yW}4o3EJ%$7}9Ef@o9UX}?s< z7ngfAB}3%HAJfvtzw9~@oSz={pa;u zP}f?pFe&9F^Z9_{a%1AITUAe}OaT?oObrAU^MR1r#VCO~1u>$O`4`LQps6-lysLpL z&V`8Mxk)3R#6h&cD-AZ8ZCgLBx}lvW4&bCnpeYyEa3qDqvAOifOsN(UDoj2|Wko0G zs}s=a)zRGQ`E2Ef8(%@GV2TL@PMFnU-D%Cq6E0ey-7dmUk3a4lm4=(mUBgqXl zDV49O33$Px8`o2xy_|No*?Leh-LgQNhQo9QAG6P}d8%?AoBaIi=>)V6oCUu9yUXKw z;PU%Kgt8xRs3ja692oA-C!xo?;Jng&k6K2t5S;?W!VBsIc%{F^qop=yfrl;X{Pr9v z8EyXRaF+5z5QgijDoBTN7WFiOqi2irDh@?I#OT}?mmJfG+3iC+Id5kIp$7TmB6nPO zb5>3&6Yvw%JaNZy-qLtQ6*yxScVUMmB+tP%5qr)DPxF214GV5Ot;Os+HBGz6VydgV zvHZ3P^h$irgd|TN%V5$(CidLc=v5eqC-#cPh9gemD$|=)E2mE`S<&1XuQr6CZ296$ ztI8GC=5jXf8N7eNKy-BSqAUcbRYjEw&Jn+w(E?Ge5jg{c*?>XRiQ^#WjPxA^dW!l7 zTq0?B1}YIxB2hzlySHvgo}Uk6YvQ?NdIw}TpqI;azt)nbhot5&&a9yXL5ONu_XA(h zjH{MxlZLm1wWlG~=4leea|QeeSY!C2Bk#7mx{Z35oKx009Aq6yzk6Yz{{0s2RGxcZ zY_bCn$?#fKm2-mh@HNUERQ6sOi_0jo+N%=oZ^JD187|j_OK^>zKCGp#-fn345cfsN zIJ`PgfQ@kG_KT5wPJ*(>%UHh1rdw#e+U&AaK_XDkd{Kvro!*oFek@liyE80!K3)7;JEc`}K zjmy}9j)B9M#|;*y3QHT$`Le?9t$RvB?jh;@us8p63F6;ZARY@d|2KM{!LNhgZjMPya>AIw#s0Z7KOe~o9D8D+IKSywQwP-s;ap+ z{H?M=0#Jw$5(T&TZ+FiP>Aek-#d2PDua>$a*SlXaO{9ff3Hw}Xk4zsw8(6`JOCzD^N&y4h~kV;-kQ7(_Edb3uOA?$OCD-pF3Q5QEFh!U-r} zz%%orHHM(6T4=jsVp@RYGf?~BPvBmW-xs+OyBq73;BLy8No1rQr+Ve>J8{_6`^ES( zO?e7r_QaP64+d$(Tk7NNif3e^%Y{sM*eUX!{L2@<0MA7CFJtkEIL1y4B5^!|Qc;_T zp7LfpPX_638IRFL)1tDhmFeoZ&=m3&uD)E9+a5!lYaKtW!>Mn=Rl7n&@{G18ehwXh z*f;?b5v#r78~AWO5Dz^?{^MxG>alQM7SZ;X*8+mP!%r9@2DS0=uJDA(*GJk@6( z&%hLcN7h|YL@z%*$fp$aRmhi2W0p%1sP46>4pq1m`CMU`BH`gYY>A&>kw;=IL}v(L z$}-C&O>!izm%UO7t4szNLpPMP#V?N$u23L2cf1}oiE$YYbc6aasumOlMh0GpP z=aS&&1!BWSQi5+{Zrk+9HFCm#ePV5uy|<$i;f?tbV|P=iE3TS5^Mr^Y=!pm#;U`6y zO0n)u!9B8#K}%&MI(quJjo2zlxh67t3KYy+?+a2XSY4q-RMnLdQBJ6<^Pp^ zn9ON#nE%BFS|^`Lv^NZ8FK~lT1ns($+t24Xf)O1wWuHa2y=LXK29$ybpj@E*6h4Z# z+B>z6tZ&ZOJOqKSrolW>Z3KEEmIrWpdKmb$FsBro;{s6LU0slb2q&E8cCw+_LWmM-% z4O4>|bCa2@1ovSro(S2pRpchGjmExSTegBExPB?q@O3W#H7bSY+a#DG8vGqBHdu;J zFn00ngv@E4h-JM$N9|85N`GbnJ=yBtpf=7$s={B?9o5yr-krV(B1mM#bL^6(u$<3{ z0)hmq3*wlGr(iqU7b>;%Qf&0Il_&{1oH{xyrIIuW-_uN%O;R|#Rx>D~FN^7~nnX*8 z3QY?e!Yfm&3WCfYPS6y{@~=`x5LV2n;(_Yk08jQ4=fSnT?=yta!OgKx6sK*Sg9`HC zG&V7iEG7Yy2aiu8tdBynFUoYn5ZgX+>Lr|7%)F8m#}uwS=C)1?>dn| z#eqnqhKW8<6^)?>E~F)~s$A9gn*@Ml5S(gkk-qpUqz>NR+I_1*5aV`fj5~hm!284% zZX_~deao)K#eTjx5M{TFesX^E$c6XxMP6%{_wyPZ`@6+p3^lM3S@C$e!Frv_JmnVg!r$p(48}OY z%|3Rq^{nuS@7q5tV$;V+sEj^!xAMEd53b*7BUKUR{Vd&R-L}h?Z_yyJ&{XI4*8bvL zh|6-^AT?O}J;OCT9UO!0x6Q*MlWB%fW)a#V%WO?Bs@Ny4kfBMC_pK8qu+)q#kI&TZ51d`#O42flgKZTp@y5vG) z-m?ddY)7`q&PFZzMbgs@)d;Iu?74f23}j|N)aB0TOrr!!D}9B%)RpDr7&wmlJfRK5 zB3x-;>jVtl;t+I9KNmcr(Qo)RG<$Y18(I^cASFetlU~x>6p0^c`b~90!=aM8+7p4K zASpf&vsrDD+bfsJp@K2d_zQ8D6P`1#W#^e!dP3U)n=p!q&rs{Vmc|Q-YK5{zs66Y9 zG;JhIdX!7+GgTI9U5mkGvnscstQN1>(r2A9h3E#Wh0dWB1e{6M*}+F5e&G%{*W6xn ztnd|lB`ads^JS1%a^I~d#;1vT#AA(AnME6~%qE`{1)CHRD!FcW@YkSbLgBB^Q0|`- z^Pr_!(bE@?#1A-&J8{KJ@MfdU=aC+DB+e4LBCr-=J)g4z>LL~&hG-WN6C5rrG~IsN zatIJ*8~qGvHiT$QDO+FReTgOfgF{IJza66F5r zDX^2&yIG7mj%JHAz5T~6PS?G4xI9*KTZ><_xXp+rR6ZXbo1z3HE}6h|5VxBm;|Z)O zF3Ku&@<$WQ2b$lrFFAKH8!wh@W)P*fG&KHrAA~jWh8RwcC*DBu*<8;XchWyLFi4cDrY+6%KAiko>&22X`koYCXIYoiKR-IZ+31S6CaJ_ znX)O&$VER;@awW}f!5y-X}%Za4%y{%B=B5A^9w2}s)dG7k6(hVTmp(gglbt;ZrJ#v1$!UgzRsH$# zu~~2{?YW{Lc0=w2;=Ekq$2PX0Z&T|UWGIzXgZDRR3)A!6J!yDG>>cH>)@jdWm!|KZ z$j>aa>fN8DE@xp{?R2rU9|9Xnoq(SBs>)*eymaCvlGmc zn#j(;3KZjn-C3j$enehNonr0D|IM)?39fwo-kUV&2NQyWwKq4_`NXzIC)n!hOmHDP_vKw9))} z1p?)Z(ipb_tS`@}*c?BUmuS7R=8H9)Rc%XWco{wkN=<}lpm9qYrTyS7h+_9Uk<*dY-Q+z41->_U z-rPT=pS^nVPOvUdZzlZ-jHvM_Cdx%Anh`PkOk`Zf_X|}viMA6zy1R3M?Ot~D+yn#B zSO>pL*?kptobwaWC3wm{Au*GYTZg#@w>7(4vo{_u@d@)8ZP(WDlbW&Ho8|YQ>?T9l z##yA(w-mnko#zOS6Q}-2GH?<-GF-k!YS=h^ejsLK7EgBGs)Hv$Lc%OW=C|-FNWid3 z4W*~v+2Ft-l7Y}@SeXgFk@ohLtK>WM`$mzp4E+mQa8>4j46jU~!M#v>Pvy>qj_?Yt zKdkFIgEQ9QzWmeIyE5OI_|%l%R~FC~P@Hd6QxJU1*u$T{NPn9Zj(s2d<{~xj(;IV z`~CH~_km!MMPGROKZC~G5?-COqUMFvWdb&#NYTq&Du<}hp|r&5bcd>m zqA$Xk$g(bpP>W$3-`0Duc`@%>_i7OGpVqS~6m{n>oVYZ0?|pOPm z8Q*mesiQa%@t>1w@V6xX-Ms$eI*0!sWz`QWE&i9RnjOUY-%s^FWYy~;(cr9F@v<*G zQf~o{YhSQN{ovq*vj$liH=wMk&AXKpj!k?Ng1YKXB(0u`c@N5@o04i_wUwWwLfUY% zDELbM+zEg%*%&(c2H2oBc*k?Cj}4>8G%_(xt9R!;$EOCDJLK)Fko(^ zoNF`p1uvE<>L-`(DMZMRnEV_*1F9sbQ&oqbp&> z4fweS28bQ?UC{;+UQx7~bOyqR@T0$q>ThR%MwT_^?M7KK3lI#+p(HRb)J1xZn<Zi7}gC!9wYRC7Ac)oWi89hGY>`U3RqA!nkxeA7wD zI7o0!j)czpfw)IIU60z1FgDdA8uppSD;5;_mXE$%uAFAIr7QlQZQ|L*f*E_6a0>be z!Yu?oq-yEn=?YHr!HJ?Vjbx69n8^zTL6a%8j!6{Acq1ut8nH)>`Y(4b^rbv;Jp%NU ztG)G|_0YsKIIz?;b*V^!E}X#UN+eq=tU;w-z{cM|JQP8C$o4;e89DX@WTFt%t4cA6 z)eZrB$8b!jgHvFIS9grX8EeXt41!vE3k)`P{(fvUn;+D#DQTK*_aQyh8GFlcOmNE+ zJdHktb7jt4xe2UpIV(hNTZtlJL??eqxpYf`E^|J^&4^diiNFYUSx<&aDM4UCrjy5x z6xiOgm0mRuKy}Vj=xqfx;4!nPnhn~R9R^j5c!iQ3(aCX0K*NCC5m-d9KqwMvvoX{t z@Y{4_T)j8g@ZYg(vfd#gNaux15oV>v@-(4_hW4#sMC!HCOunyB zU?E?cr6GXdJAf!Vk%kd*H_4Z$V9 zOH>>~?y(}}53k`9l-}T?ZW<$-vvr>f8jUlMCVMin5Q;}R*1P?&AK*-GER?jJ8pto_ zcBsdgNeH9A<&OwLD<@{ku+SZ(YeJKt9!_Z&${Zdt5DTR5lTO*s{BBd;oV;IvJ+hIFQSpe){dNJy`|t%o4*%`il(P|P?%=#C3C$V00XXc z0ve7p3NTVQ{Jr~LFj@C&*tqaWcsbttP&$El&BAgtt(5cb)%Sim5yP$kcxlMEVqy{s zrth@7v|0qOv^3Xd19KomXTssKOfX}Vi2z;=3Ad+&=6w@Tr$1mqi)|yt?OiZFY3v&> zU&w(|uSJfKV0P_HRhU(jkmVhw@GgB|t}MYT?*e1?xM4MqGE29~osY$CMfsEYDz`f> z77hGG^U}9fpK#BpLwn{F9aTS~No4uQaiZf_tKZ%jmC2qJj|KWTp4PihXr*_b-lUpP(^1Xl0etD8ezFi=|bY}Ji7d~%yH z?NT^1GZ~>Htd{v<6{e`v&|I~3SY|Ovup6#iFCRF5$M2l4Rj_=j7m#-tQExRR71pWp zIS^*~?cL3)7ExoXkoscH-s(p$3p1n_s$2E#!OJ zY6hE^lmn4mRLrLL0jm-(UL_DJlcc%Ya~&qt<0qY`TQxY1D_wJ2oVVexz~kSu1GS#O ze!i(`ltRJxb8O&ccm(| zCA4RQ`$Pc_ptcN$I(+)`m8JV!(ZtTPm=c!6lV$P@gwWu8{0L3Gjn1Ik)M_kilmoto z29C+bv1iOonBch;WaKXdllqfDRrId*B9hN%1I~dB7m}h{`pIR{fkxAaBfI)QhoPDy zcCUNK?vrfh=D1i%2n4*MY|9*?vtsT;DdcOolJM|LJo}Xefbwl-vxkhWrxhA78b;G~ zF?B_6vXy6DXmBG4&!QUdX2Pl96HiNjECb+uf7241qdT#b>S&CYu4h|3QMW{-SImme zfZ{uzXG55IuI_V%$<|kr^_xVDcCSv>F195PMX%%5N+l5xnOItq2&P{f5adNkc8UKcZ^ug$ZyG?kHetef9wACdJ}fCQ24Ng)UE{CAd=O2 z1pQ-{>s-g-52$DpvS<@c(UpPh;NFCUdoh|-U}A*iyV^9jeq+g-J7sQLa#9PK2A?%d zuk`65NOhvqYA7}IJBN$A+Y+{rt_X3KmU?e;`~_LoW${n8UO7wmZZ(&-+Jh}OHr>f; z2#s}-o*oflI&Jcc5=E~_&BCTmZ{M>*4y&CA>{jndi`q`=9F`U%!LzE>C?s!11<&hO znVYnUslo25aLjR7d=cXm(61PKG1*YWgE7{Q*<-d2;vwP6xGPLb?Y}m&5VXjs5=zuG zdLLVYFMdCCHvh`e^ES%)`%p5cqtI)+h0J${vap;(hrzX7=9jorpJ0O*(CAz*Hm{wX zdEZ_E#M=j>>TER7n|aBZoGE9s8hKJ=NvF-j6rs24-zw#k(&#aiEN9UWV>qLWQq$Hy zPfEST@|sC+waXVVVi~bn^)iVNZL0S+8B_@%c==VkHfSD?y^9cy1m6=iXDJwIwwU^z z>~6!kMnwq>((_E$L*Qn~orO-4!Zvpjt4juEBh#TSRFPGiPYsHMUeS2sMC^vW#4cHt z)6rUj8PuH{I*7DD2l!nG>{VSOZ*ms|tc8wI0pF%Bk7RaKaWu~Il8b4V!a zqNK+sR=D2v-T3;rwIX>VGA zIiOsM$T>i|KSbWfcZs_He!{EdiLhq#E*kz5rFyR_At`mM{B`t1%l8;^RY&n3c@9%s zJR%TZPZfZCL)&D#B;UyLTxf~`X?Bhb?_ysL31Yvn-Mwm7laDiIYH!`9K!&%+{Sd4p zxA&x~oX_ARistn5t1F4c#pSmvP6z14B)0*GwmC0@t7j(gl|H`1-b^Q{9$COF4HGS7 znGCdzVt8HCChjn$cr$Jx)N(J5N{2m-a~$^OYBDV5odazOLc{K;3T2?a0x(CWRHS;o ziXGAUO__F6Gmu|IN97rMLzn4YJ;`MZCHJRSRI}^mJl1JPWBR8~Wk(6hIMrVP_;mKI zuJ+fE4(2#vGX=<0h&+Mv-__HQyI~eu*M0E$PiGcr-sTbo9&M=RKR>;k)V^?9wN2^7 z`N6tr<=)LtW^JX(Q4PU$e1Sp4qScvgKW&N?zax`L9CLf?p{eAjrdA;eblJdu7sBFv z8E6)msDdQ@g}ty)nn2OXtgx3|AH3h;g{sgYfZ;~pgFlcc>$$kWy%25R0j79dDjU(g zY{KY>01i$VyX4ntT&r!5a?}yEFEI3MZY#0;&*^WQ*neF4cg#r>v35)mMtyac2)L`O z8S@e0%e-Fo-)*Bh?lE!{@4)*&bBoqpD~!-F@WnvUz=4eREUo?f)D*W-;F3c`Vc(%7 zl~ZymizuB|&Nm8DX-@Xe{jYq2D$L}jah5*}W`AgQddOxBy&(IxNWvGj0`dmcRB%=VgA*Y#xn&5y&5+q051o<&UttEEKtD!DkScwv5jc>I2(2|D>3 zmD|D@>|^UuP&;{0$Yfs3r`Pm*wQ4S9LQ5XnHy7Wn+3q#z?_Aw0Zcg`dp9kMWVURRg z$IH?JM+vj&)8nvx7BXT&xFd>J_em=-SGR%%G~dP3;R!Rx46Hd@dS;5nZ(%jmTO+^D z=X{OqPGFStq_DZkEd*5*(T2mT3B>PYdeEFSoA1RVc4?5?dr z)iYJ`#p248#_qQLE5z{i4{F!3W+FIn)jIw3eJpaA(9!JLcUKzu`mgT$k{Tfks&vX42y!yK4KbH$0zTWV24~PHiTL6#WgZRH$E%-+> z@Be}GpKso&Bri^F;^1Jz!N6c+XKe=FoYTSD+QOdR3cTy5slL6Tr78GN1~XGTJ%%@S z*3R~Z4ASxN*2A7}EZ_~2 ze)*~h>;Go60Y>J3U)YGAuSN5mR#_PYGV-WYcnhs|5q7i0iEI&T$lm1IMOS>l(GNNNf7jI*v~Kp6o9Ad9KFRYc1PZ5^Tvg`EB%XU9rRlkxM)f#{T!i3%UwM0wD~#`= zR``YbA{yemYJ#h2Cd5-XNTRGJ>e6&g^19qbRVdyOi&*GbG_PLS>r40dUn1G7@$h01 z5~aEmU`3_a<4S$$Oj?(J%pusX9N27_7NP3V^Pck6wQj%1{ScBO&N!Gz*rUcLz8VOn z&)^Ms4_<75FOU8b$4USXiwP5)wPvJklxJBeU=WOM3`tRS zinirbF84kj5f6?1yVD?G;0bWEZ^4x1JIW#A?HJ1E6dqHV}oC!z;X_Ir;>p ztfHxH+Db!0Va5(VM~+Q3KbfTQJfGl8(=x2^2@5=+Sn0(;_aZQWG;~;i+^X9=^rQGf zLXzRr@WOHMyQY+@bZyUmUI*^=`%OZ>z^uVxir#XZUQ7xr2-lUbJ-Tmd{VWuBcU;88 zd&iu!1l~bC)Mc1e4|_qjFoBC8SUJYQuHG?YYD~~Dl*H~=<2)RV?M}6=fYr$8QNHDH zcs%$N`4?%^>{5X3wzj9>eQWt`;R}#99pFm0m59^C-9_Caey0=aNobtVZ4{zc^~6;qoLexX*A`n=UX)08%Omwto699)ET}n@!%i*plOmPK zSm~SxWAJdJrbZUTvjZS)D_%fGf=?E0dgw59*%5yPshsVKaMVz5>#T6MKaH>yyR=fE zHVNV67u>mkiAi~(=7s=h&?H`PIRTY-498>!XskM}o8uHJKB_gnE)RueDQwvNv z7jqRvly?neml4a)Jq{65M?&pC%Qe}1BK3NCNJWw46akqsI}xjZC~s#`X++HhPTdy6BM+#hf}nPioQE(W?8a6}2Y1^?@rQxPe++4vPnf~fl?R@(n1)_as^3S#LvZil4sdg*moig6jn1k==Z z(8J(E(sq)jq;Oms9+T-Fr7okf5NR_m|6STm@=qkjtdw^6FmJ@0#E4|jK`Ng8Oq>B# z(#3>@1YDUClG*4!Oag-oYx2GQXdNxEqrq8PW0CkFDw8t!fNPTF1IXX2U0smB!M*)u zw}?HQ1H@D8b`f)7@&xg*_TKQ)S@zR;>{xLz$q0A~CzkYUu>89~z4tIXgHq?GC^o5l zPQ#z6RH}yd*R0H!3V$oOaucfh^7^pXShb%2Ialy$dh%Bex#iCpJ)rl`@LFs>|FoF2 z(oQ|!>RQprUB}FQwUDi;?6i?v$c#P5Cn*r*@6!5odSksm_&wx&GnNd=gSot5Lb5&; zulDy!mZ0~365Qt^KzPgS!_j`ZOr-_jf3-Yf_OQ1Weo|>iq}suDbRsWsDccu(H1s#3 z&kN*rY}uzKOQp?U6$K2Q<{a^}h-0IaqmmoRd{jT|OnLK^<&1}Qo!0~71 z0LOU4)^L6FbpxZjtx7PBRToodE^mhDqF`ls>p9|?vDT_JFgI?j^h%s-)dK^|yr&2- zfYD>wCT_{!vaYrjpaxjl#Rp<)gLmf7b7iY&1M`oWpYGBmN+HMZf#n+ZwQ6fiEu^Wu ztL52UN9U$lrYAMwuzTvkUCD7#JOqZ8AF!OgY_8B@`8^U`w%2o6oU@|w<~_8$<1F%4 z=U~+_el@}b3E~V)H`h$kuQcz~j4yJ30Io9?KRwrUm9F~~MM!fbK@qabX1}?K6Xs^B z_}XL>v4@)GpZA>cy8bzSbvqkM0(PyW|9Ceve>L1vnEBB49<>bNf}i~}HDcxZJ=nD9 z4)a?B|ARHRtP(3y!c1_o?Avo5!h0#GFq6AD{3nYo@W~dMEHi6XMQ_{DIpzJWt$6r=Z@!{ucEvIz`AZ2!N!@ zXwl#u5HWc;j;GMwr4(;*d{_N?}LI2K!o@K3|aLjw+dN+c?yn=21%=A;;G-U-S zkbA;3o5EzH*a%zoz{pQ68(_Oma}a*Q_DnB(m+3y5C+;V~iv;?>HFG_H^43(FTWpy^ zp(hCV)g4sT@KmVY`~IvYp!z1Typ>g2?8O;upR=p& zd>Bm|ec;F>i`lF&{r9!1!dt_W?R&m+k43xQ{jIqS=vG7457%H0;%Vo4@jsY3xxJRJ zx#uO)rb$av6?Pi^>xO&npI~sOi8F^Ikk{D(KPlRt=df>(&%TM-Jw58mEZ= zh9-mat`@GWePyclLjJbhdOQUy=AnAjzJ(IG8&R~jdus%(YU~_BjjP4ufO`qbX{xKA zl5hSKyA6 zmvBCuwz{ygY(6=kZpUYYJ3JOOA~ftQ`L?WknFaJ?jqFH8-{2G;(a$w)Eu@L}kRY#J z?_ga+=k7m7h)gmtIJ{>BX-9W}&ITa3(>rtX%fG`%m1KLm1G8T~&sT8ypi>!4l6&pf z=OCA6yhM*)HcMzyt8O!e{=f(KkV@&%Ky=?`S%ofR%SN#|9rzXS92|CgA?m(!?xi4P_=~xqW$|b88zXU z)z~scDqfkU4Vo3pF`2U^;DO_HsRJ8-g3-K0=1KGbraK+_#4e$imkWQ4QfY9a)IlBp zMB}9DKzSt^%*lcK4=(3lr;H!le1HEeQidLkQ8*bZ^9i3$sZnY)DCiO|*9&M@e&jxM zEd~(3U*zRPEO3(q5~~~s6N8gaqJss5f{5S+u{>qyoycb>?p%hj#2OhJ1-L-Z0W$jY zIAttw0RCu)ah|E`O*u&+^f1Rl{_tSsbNn6wpl7&lqCqgeo~TboLg(UeNAg8dG#NBr zlXhUc7(`3Vg{YU7=ZsI_7s`d3EKKZOSuyN7%DTT!7-N6O2>!4j(0&cjG}`%@@UyO< zwEU7?QJ%qf)&d3hHAjU=D;-Ymai*4v8ZliJ(-#wk36}PR)3}>LNLUT0XSmF;NVGa| z0vA!u$l@D#iDWXn9-0yt*(jX|N30~Q?5_-g8Br|;ZbsFYA{_XlJckk&_1>a{b&zic z>>5%Nm9Yp3M6ri32O&7cViV<{c0}Rqd56c21zj{ABD1CDAXd0Y_3!_#@RCYWkB(br96HeG8M}WkuM^D+H+}{sk0| zFbNwd9sUa?uy5^ai#EFG&yi*ONba5fJ)t!LHoGME`y&zYmY6}%9tWjvdM_~@mW#IF zSk8G+DJn0IL&r?r5Hj8gFu)A&fPu)w*pd%3jpq{d)NwE2#-dZPo#?zrTLvjzPFu;! zM#gX(nvGIwQ_-+olKk~62kN{j9i7B#+WA^)Pwkt%hOtJvaPqaFBR7Ik`2^i%%y0xO z!i>jX3SFswS@HIi_Ppi@)X%5xv(rYhq=!Cig0@rkMc=(=Ng`urEVuHAT5@@za^3(g z<0nZg(1t?3jJjLbjmKx38%Iw-E~@W({=fgmvti%Fpa}l??VIe5lMuAD*49X5tt{0d zoh+o3aqAOnn0Ar%Kd>y@j`AO&_2|6^>s@iq1Q3JoaQEl2bz9G(05vh6Z*PTtWbp?=lWe>{itIvyks`5- zb|U%l#XzC^c9KxVy2*}&kWMu_{4u&N0lTOH`$Wl>mx}tcCe99w2NOG9b_V*b_io zQav-qQ@!gsw#Pzoh(Z&KVst7EF$Qwna`>cqcL4#IN%F(%c8gc(*FNf-W1oE&Xf%lF)brb90tBkm9|%ICq)u}2wG-RL2m+bf zGw4K2>g0-B$R}|xzwhPzqfFj(<=Hc3@a?QCCWob=e-`@Z%UKAdo}hS#=3D1aUwg)> zZ4HreUb+zI0MIPK%t5Y+u9BLrtlvlw>pjOMc^e?Jslu_soNZT#Ncj4#c2YT3b%d5u zU&wguQ~j+vZT7=TV?1Gab5kS7h)nYyIbs(cFg#8d#VnuBRs&#s|LAigyEx%M>|el) z@g;RzJuo?pHcW-`@T-D`5R2+?23yp}AJ~MA!U&))g*J!uW*q4=j{71_U{-i~xqG`u zlLngw&h&=f|FQ&fims?*c0-HlZDSea5K_h>ffsGpg@vDqrR3BWLW+*RHsIC5Y}!0- z(%h3NG(hSLEk@tk(G0a%k5w{9f*mJFp*I0|`rG>hDZG6Ip1}c}5l>@nXW`*H8pJC6 z9=P=_&~F$Twu?~E+&@qJ65=kLhD_?-DSY$MvI#I%+Iwtdxxd z^QR`tJO&FDC{8r{^vbD0)EVJ{r&O zRN;vRs)E8htP^!LDY6OQu5faru~&XE&KT^TDjjAKB9vyI4S zubCgA-SA|vSfk(5WE0S-(r>z%0a>y^kCMwT79peulcn!SB0bG8sY$B$p)^Mjmn!kT z!KX-8c_ftZw?;urOY~MtLRRm)&D<)gv&FHEfP2KpVIUiI8)H)M@{AxhM&Xy60?nQQ z9nDeDVrw)+0SzY@T;sIY>WJu#*^4=}M1wRr7{~&QtY3G$Tb(S<%iV^0ZbOSPzcJa&@cZg%%eOV$Td`9260#L*As+S(CN7$LP3kU#(;#d#;a15-& zs{1~)2BEFiX5OY8#hmC`B`kkd6}XEKrxze6Es``15gKLi%a7RIu!eaT>1D?=TVyPV zPn1c^TC_P#QucDra|G#x@dy?a$nw4d?h+hctP+ar3Jc4x=oRG&eN({2YFlJHQ4|<4 zvraeEL?v)%D`t&GqRZLaHSa{6jA~H@NL)0k1EX;eY^}n zhw6C6mxOUmxyyLV;=N%9$zR)XlXnjh3llnPFdPmsS>KxzAt#Fu;+Su3UnmlYcvLO+ z?KBY4O}S4hI*dhLH@sIRZ9;>~S;D+n;x%KU2TQ9y_FZq@wmYvm6Z7F3;@anWxT?Ne z6e%BDIH@pS+F#-?psl_xM+TbGrk_SR}mWI9*rm7vSj3chg^ zTpbPmZLGGESW|C*tML5pJ#C^lRXp{^4Z78mS6w}q9tuFzH+-%4qTHyFzR~TM@bS%! z$$e&V3;%Pv7CPU`Rs-XSaY8r`+dk+qA z%FBUm-!nJ8HK)z0%u|~^rzkCP6wQYb?Yu`FeR~ z#4s@(QNF;J;>$k`u(f=$z5XOAgsTCR`%_kBQ^5bqIt8&Cjq@L12>E* z>=Wb9Kcxz_1ZTv;7+;cN1@vm4y#eY81T2cS25*C=Lc$PX)kM;qky42XaTAgNMP$!!?`X~?8gZ|oSgpnyu6-2%yE5>)HI0*WDAM+ zd5=l;NAK{Llb%_q;Na2lCEodFn5A@{yareD(7L52E?Dkx0odXvl}71IK&o^%wne}D zY2sa4FuY+Bufh1;*HpBH%aQ-Zmnoc@))C&bK_I+j%$JaStYhnVgo~%XaO%P@zC6tM z)8|9j z>^3={s)y{W@6|Od}AH25uwKwig z9|>(2J_M~7_V@MICS82|qM=5Yyd_uHA+=F@7@=h!1;4b8RbC|uU;NMB8WV&EMGZrAYI<`9FwYoe(KyScImle>7mtm&CJQaY z7*wuiEu&lFw4lUUb5ST+%zHvyBbTGfXu7H#gubmX?5=_VGGjoGCys|X}S;L8E^`OkKB@^3A24OvAk zxXN^z?QP}~a5?#B9`pG3K^ zhE^*uD$ga^DO43=B%3@6SS}I5#@AJm=j?FcekB7{Gs!BA_oz}dzK3pqQ`ftc8!e}i z3_rW?DM83-OW0FLhJxAXT5-2eNINC*jV4$gA65Cfvg#R1^`U=`l+Tcd=ebKmOsW@MdDJq{b{&hBO#?>aBlN&yh z_9OAEm8$h{;iva2pWAnm{7w*1MdeQFs|tRxF^v8pQ52A?Pv0k>9ym4iVXGcp-5QO) z>MtUF;c~WOJB@}{XoSz!D3K?#r<=baR$Veqsi7UbwX#|5Wx?K)$t1G7xMAk;?7jLQ zomTzGpBJ?n0E|P4pGv3};C>Ltfl9XoKW}p&Jt0N|;~-S4nqknsryUEYH6`-%`QH)^ za3dIvaNg!%@5c+Z?00y?NO2cK_Q9>*7<{|~aK!Mq;gOru?6T^N7R)tN-Er?%e5v#SkET{_ma+&1lwtkFAei!>$#YVpH*1Uo)JQO znzDsh5~1}`xEl|-rIMtP!>R6BCv|f6f@mDewwNL5IUW{_;8rR+;1*#z5nNhkHw<3HrTehDs= zY@Tk6;!epILf;w|gq38G2=Albl+1$Meq{YPcc`S^u0SfHRsV%kmh1`Rxet*^xCSdl zwQd>YH!=)CmHE!YewU_H82WcciV=_vv86DKNU!C+AFyvp_QeGzd@Sh(mZLJal|d34 z+9kb^?tV5utSgZj!}bpXwsQMPKZIi&G;EGjJYcl0FOnxHTq^ZX2L*j|VG3L*VL@BU z!pPnjR$TM;l1}cQEZxk6zqk>NCeEnBd4_%-YAPM0f^+APQ3a{Vql*4BV^hj5*u$oXK#|lx5rLCQvZ$gKNjm>) zOyPq`vuv_3Hy+O*MV53Tc>=;_r_+aP9gl~FT7QzGOiiPNMA)wRCuQgDq@9TvU^`=c z+bNi{CwO#{$g*WP!C|q(Fwku%`#m4;z~~QT_aUvLkcGem^*mxSd8;7DLieQub%U_^ zCv=PZ(I`9xt5##g9K$HSZLl~9ir+!dNz){ekNZHd-Y2~&m10Rtzlf!8vT2x8-{Y!l z-9eH(FAR=5Q;$RBX7cl;=XqlpR~X@smw$0!7e;o*uqJa$0h5lCyw0tz!~{aKPRRwN zhX7~BhaKo9K_=AwJWq#(I+oJ0u&P-O>oOwf-ngc$vkua(sFzSvHSw+o=L}<=fg>^| zthWvF2}9Y{5Cx*JPY_np6cwn#c^=_NQsq-Piw^3}VLv9&HH|rw`2z_bDp;iV0YI}u zO6u{(q+F1br5{N32}>CiiX>$)6ztNB#d$iYRg^$V-z%-q0|f7Dt+`50^0{1+hX>fa zEzf;LBj0iZhMc1K`C)B|Ovo=Vah6>r})LSg65m4GREcIw6)!3K|@<mckx`jx{DV3kJtfZ2jwKo8J-bez+32-j3$MNLqS!^+qL zD#SQx=&t62>)8_-qs>|gJ5+G7gHvU}BF#vh-(c~wy5N^Y!gvnAHdg*ivQeUMg_POW zr?NVZhUrLhQByR@6K9+}WxVP9Q2B=El<|gwooazqIB?ylGq@3_2-1L7G(|;4Ih1RK zYF>wD;p@DfWA=R>%tS2|9VsHwiCOcuBAj#2y(wxkhIcBZNHQ?-XY4lj&0POqv~5PNr$ZHkSB?N*v{4+t78^BP`07emI^yrx5Ack#v4|(NyJV!weiyDRjZ9`3Rd_JsL%+~PB1>Y<^ zt1>cQaqfE3roBYwF~3g3-y8N>qQ;QnI-1vp<8F#WcC15-SVO_9pxv^Qa8r8U!#Ic; zCcoBy=mud#2O60>U>}+<1}QIorRx=WW3Fa5)2m!~nK{@K<_j=`s2c?X$85AO+VRwOLMsTjHn<~1+X{G%l zx~8h$!j~Gpw+df&Us{cPlpdTaeIRuK|MWaGm3~vZe34(o|M&e->5pvQo+}h=cWrjv zxvQsn7n_GU4;C(a7eUu7XK>|uDRDftBp!{M8=pD}E=*Nkt~@kg&bmO4EBLDOj{ULn zlD=AkaQzt1gx~cU$|rEG);fOj)3C}B#1M$|T%=090c2?3L^O8{LASPu-uf)eck(vw zD!je}n7|kNP-#~`88;?6uLu`Dq@$E+o2)$h#=beyBX>1aY&tpq32%Mn%@ax#jrA2OZ-6VrzGw6wQcaPpi#*jf16fU z^KT_^-s}Cz(TyE0cF_I$-_=vE-nKjxwNs+SyHt z_NZ+*(SZ8QQ8Fg6xyZt`FU|LUykCACEF}{tyWXL=uCB%XZftLlvZo)C9^Ko~OBi`vA zqjPqEp0I};hBr~14zFAJtJ+%8$v4@t(cpZyMFUfVMXX?YB^V?EndxzPNq>ZCzQD@! z84%Vi$Pxak>0g$EcV28e7ATW6>;lWP7h><1uSs;jD=Jx*w4Fr5PaRcnOv4?ud@*I8 zVR?6UfO{b$((O1t@&0%Qgja3cN(w;PNeiSvrRz}JF#Jt$t=iItVjqly>`q;^YY~$? zyl!GHT}|HYLzZeCG33|O;tK>)TL^LQ<&`U&C#2} z`N693uQy^m1a+_+uM)J@qf(;lj|=tpTZmW$%co;!r&J*R8xoRtuHgk2I~Y z8>!Ce4@m1jWPC>LG4lkIjhluSx;9ghA=hZM`i6~%@=(Y~y!H)SB4eBGrqn(W2&8F z1e@)CHFjf?B4df6ti&ppLc}Ih+s^|BpyAk+zu#pF?~oo2f_{V+t11p~?K(R@)jb`r zl|Ain5wFZG=L;&&ifoyQgDmS3t`iwAT871r_AGTW%_)Ia)=v-&RgNshoz1u1obdqJ z!pcK3>=nYV27r7Z1s3E!K5IEYKC z6k?l>IdTY%-GtUl%p+X-v3Tk!8srhA;JdXq4XX|H1Jx;fchpKGauc5?C}jyxM2?+7 z4iJ0qgk(Pc`PCd@i1>Qk3~)!{b#y)X1xOv(cw1yi?5v<|$iYU^AH|3Jjzxe7cOU9M zF0eAQXw<)W{MvrBNzz=$E#t25+9%)XGg6>_GM-jv*|j-h-^{eGt7jW`g{Bd+4_2`e zC<70UDo0K?y8T}+fZ;RIQ`qU*TsL|;dxrim$7`=ZN`faZ&l=dJuH##&3{vEG@N`*- zF0O&DbfztJe(q%?v$H$=9f@1Sp{PyQbvaIgRFFa4L<&i`^${+o8t{{yD{?{wxY%q;&! zC~&O$hTSG7hR=#djwHSmK$rGxAzd!3RF5w%iliJ~xU{`1%AFRF(zxm;C)g6sRg+qT zKNK*7%2T{|OQ1EkZMyd-;g}SorH!ULe!J-e{kshMsyFF-T(W*oe>nb4U7v4x4|nj= zoWTht`*Lv&ktxfaF~PxObYbR>N4`KH?|GSiv8GTX#IJ}X8lgg1YKqbVMIqD?iW!tY zR*B-%Q_d};gZwIe40E6iQSc11sTsyU&jpf8B&M_VEX-?g<#M!5+mln9el&%c+${)> z*q(GW)hQn8nFg@gC)}A!BUy-_^fP8W}c1TL+z(L*x;?LO7GJ;Wp#7wMVHPaHc#N?for+Q5W1s`GP**n;(QHpY-y{Sqd3yJs%hyUhT<{9 zD<_HFp@RIDJUtOq{oT_ zDc}@)3Kfardvka7`nSDP#)$sid&iunrw}g5%trzfm^dbG?y!BSKmYSE4#@|y(RvAM z!uK2_N-o?Cj-azYT6k563XaVYrvc-TTyGzSsPowX!lQb5M*ZwM7f!K)wXM6^GsqeX zBlq-*{0`D3F)2}Snr7FA|ww1BaifqX!P$+IK3L(vT*+R3;kW6NCv zytHhqE?{U(E+Fu5yte8yp!idJNYz_CxaujdE`c0px!uOyCwS)0Lr8svi|?>|&>~<5 z;@Kod5ENhjdXdY(2<{A-g_MVE;@$ig*bce>NzeKX>F$zVLg*ibQ` z^|oX!*6g5gFVAsk$AgKbY$Ect^6m5ko)b!W_21ud|C1l#pMoF%=OQ7T|3BkN3<#zHBU_%y#$r zdc_q{jZWLvO1I3i6dN2Y;SPTP+3DriB%{0K<=&**(+&7&esxWyveZkzwmjPU+rQhV z4mkJI{J8o1)2@pSPope$qi(XYK!NXd2}4?|-yBEJ=kV?g_+1_PHux|8jk;?Z`_HOh z^b>Tq#msW|)4<1c(+w&$q~+flV4PKza&Y)nStWK$GN8Ca*pROjp)8FeiqWE<-GDnC zRx*ll3bJ<4*ESN658X90X>E`*NO|q_pCWv6a3CW117<)tYcU2?^kNXL*E}HuaATts zYH>mWwDoEmPFzeX6PyQ=>+YP!Kqiw?_qBfF)N@1<6;FtaZ3KWygR&5j+D+p`a-)-# z8bvRAJcOzvAv%!>reh3conhvc$o)FCnqg9~p>~#7jI2vo5&Z@&Nm;3vE`?`do4Sf#Q6kkrw|9o?+cL*(2Hwq~>ezSXcc2(gx0tyaBxQg*;#+@bCzOd^RoHBeJ-}LrCI-5419@FGA%wha!lIf3gG`;0s`t^n~`y zIVPjg$X1}!Lu6g?Fj`iti4ad{@8X{2wo3QR^FdlK;sj6&Ys8+%?1rM<|*uF zI((0_jkerPH%H4|u~lq7K<-bc)Kssmx#Oi3bXH?G5{kbXNux0MY z#;GNZn8&Z?3%^Wx(1|f%oRc+KVv}w_D6cr}3Uaoon`!Ldi0WiGZ8dVf&zLuCim>Sh zDW_Iz&=eX;M|FgvX^Mn_c;%;hAC^VsLA)%K$E^8^Z&HS?quc@5$lzk~+TbR}?h{4H zG(@~9-%y-ZhCErRF!b-|6%KQ1e=QHJ7e(>z5rKf^{k*`Do*3A8<#W$noG}6Q6w^&? zH$q{3@i-1Za7yBcfM}#`tBR03!*yXs3DygU6|s)Gk9h;Esp`0@))F|7+s5e}{rN{u zX!{&|}fqfj8iY5Or4az|KUk2 z2Ndod_CL7{kG@Leg0Ts;3lYT%a7NxeC)*zo5hfZ}3C>aAj~* zwB`~|LUa$O2yWbvBT!-EDW z$k!M!e?m;&j%ScS8y}dc9DNEz74t$CSem9$^#nq&Ftk&fGLjQ&u~0}X(-ykBy#<}L zcREY-$?^o!p$w~Pf4%Xc5~K5Psxh03LnTrpG?xJ}QR7Ax<+~bULzI}VEg_Y7NT9{_ zki7q65=Zj-jQZ3)OoJCCFPS2x{LSqLM0wu1Gt# zA!Jua=~4TtGyZc3S&@dqVh^EUT$K`T@yQjls7n^C!mdjW5}7_NXMwLvK6b@rv!tv` zj;g4b-vY<5>MB5CW2I9fO^c%QlVR6c6fM@`d@LyP!}ly&0+_1eG?)%^X^Ac`--}gb z?EF~8FIxIaq_dt^GOI|7vhq`4-*k{9O=IX0tK3oFrgc@v#gvG3V+p)ry=JTaB)x7b zMY>4=fd5!76%H8f5sI^IP@bpXp=B%o^DG}(z!846pQ|hpB8IatE9_A*(|l(5fNN}TQ!>W->TtnoCKTz0`VyfM{e~bG zye<8brWApTn_7-C6|gS8X-fb_Cmta#L2Blrs@e24ljXjmQpQt#W&N@!5IDp% zk`2%>GPVs^gR)l0d6^WiwaJ20?=BlyIPHRBk+`o9-5plS5-^m3rlL-TCCY6<`>Tbd zn5#+$QE{_vR`=VSVErZEhS9*AXDQI^nA7>l=KyvNJ$@tm9{e#w~Wiv_YA6Z_@W=F$HuA z#xzC{j~ z{}@~=YO_sfe}esSP=EG!lkUeIu@ZX*aN+XAl6$jb)BpW?=lb=0&2b%}OP7mSaz)Or ziO){3^UMQ}t7ik*{iSKcrL4mJWvkt_ZOf8tXl%mw^etF)RQu&KTEo81J`d>n+~V#0 zaSq%_=i-|4$?E-k|8BHP7M`Mq93F4C;(I;@uMQ@u_57JV=688*P$qw{N^AzL?aAG_ zh1zQC@*+g^nPG^n`*#D}hQ-0R6MCH*&0yU%UO<-jC48m~Lfvq4kHq&%Psji57_gic z>to~NHxWeV^(5)Ek05fx zf+!*)Jp7ZnFpXcL%t@gJeDd8@`RhS;ALp{xu=X&%@_2+ndw!IVwrFwKOlU`D2Ejj*cLP zb>8>K>mW?i$BdX(CJu;`w>yu{F8_d!;1<~-dnBJglk9i_8u%%fB095@JrF#8w=V8x z_aVOwo`+4OcwaQm_TO7kpCoq}u?ldQc*&ap%qTkaXzZ~WOJv6t(t!sw49cEzhuW*H z)tgtl{SQ2(>@8R)#!KK12{49`+VJi#m)sbR^vkWQCWC*~SbTez!#g!|LqWu^+dq_; zkLp3we!Q+-dv2>bouvd`9D*%7gk`ux&VqJveDa2*-)BEUHkNET#~h=lK(@yp{#-B3 zjUD*JYx{Z=yljCQ;r3loMW7jr6q;?jfqRSgggEr|1XPc$z^-@r;awx4(0}jo`1t(s z`(ZBDSNuw$-v6(ulNm1zTDvZ`c`*N`&qDbH^LOa>=MeSkXA{`s+=$0n>3Q2mhrQqX=kyxoGRKw+@buZG;F8rb zHt~LMJD21SKN31Sn8ubJ7eLP!$Gi4X0X*cgSvNnEWo$?F%&3xWFjL3>X#2wnGsoz7 zyQry-@mBp8hfXZLz?C5N?=KjYOlfB^PV~OqiUi;B)mjSo~sNx#`6et04oWcjp z-yYqUa3q+%@Z_Vs4z9GF!kr*_gy&sw)zD#qaAikmPrt$I04u?ic0=$r@LTBViu%y_ z=#Rpi>YG>Er=)w*AIanYQu&21Jo)ERn^nXWv05i9lg4pp5KNaAK6uH zD=SQOcFP)d`n?_U4GQxLntf*UeVR4fL~i+vyO1r>#aK=h8N_+Q6e6{ucmZ96t=C23 zgRxcBu8GENgmKmeCLL})9X;9#^tjc}GI0zqcx^+51tIjIP;~dOApyR4mgrRFR`XD# za;H&dGAFlcrv^gI;hA+CzKA=#*d{!m%$oaEmIT>--{9F5kiU3&m95S0eHQ%8<(!4l z9_2#ovR(dqeB8f--nynb41LbHc{|>|RgUtt(8NPOy5O~5j9G5kwvlo91XVsi%qbE# zOZ57kQCWRAM;NRlge1pQ!WqGbg|V3>X*|Ab&g^&z?%DXIv9L#p@S`i70e5fGC{ zt12umH3h$$g5rCgFHS)jKFidiq!tq8Gdzuu{_%&u(&{rj9D+sTE}r)Afw_fleYUvF zgYL`Q!NE}%EcR=bJ34i!?y#pJ6E%XfA>5eDif#W%xWe^=x1S)V?{m7H^8Cy}p9b83 zXC_j65qtUt(tY>Eu_vN9J{r3YFBQsT=9?qGAktF*Kjx9BBaQ64kpE>#L)}(E~ z{LGfWw!H>szt#Qw)jq$|&MUx*yVUV8IjX07W&g2eNmf(aFK)40e)|JqeRO>q#2UJo zp5S|K;nfSGFH}%|2m1qUD{HyS@6XiCYj}44%HQtS>y4+UE_fpZ9m=1>tMNM*;0ut8 zZy5eev5*B@dC4eNI^_8z$me=PYhh`98_EoY&he6;@3UsOpT8>jyaxnQw-GkJuLIuw z?Y@uzWYet&;J+g){}Yw{-^dE*zlwh{{omzR|Al1y_oK)E2Zl@z_WuGsPSw(O-WbL7 zJE>ch{GyQw7-3}eRk2x9I#`VoT|ssY2Tx2038BD2X|DXt`drGpU`$xX;*+L&ck!6@ z^M2lR`}rN~J3V# zX}djm$^6#G3Mc9FUA72nVt`-Y@8;ED!gup_?G%8rr^>OK@{xh0Vdhdn0wqAWf4Ly{ zFf-_>s2m;JL_9Sm)ryuR`c^#9RXIhXnP8P}i7fa@L>)czmZS!EjN@__%cuW)(=B8H zAqo94A{jd*4Fkv>Z_ILZ77ufECgBCGQ1-0=X&x1lSfeiUWstbUMQClAa^a6CwxU6S z6XKspzHQOm3IydRHuNpcsX6IJ5I+D^WXe+n;wp&;IrQS5>{C9>7!iLCnrfHQG;}3>%4!M~HfB?4OwIF`{WfMSwhPj!% zTW?^aRHaoTXul;9r{XJxyCJ27BRCmmR1q%fYAim@R7tZT_*a%Y{W>K^TY<9Sa28u{ z69r8aE3MCT&{rs`1scgXD)$*xkZBFcpwQTRXJA~ zk9!|^_QFT4Occ&{B)BLtp7-J;1piNwMM8D?K&5m+N$E>b&^U|YhKYqJcEm)_67ZG;kkr0i*@E;#O?+2T=< zwRVi+cF;sP$puxDp9FNX4Sylz!fR+(T{qhX|EFZ9ym#%6eREX{_q_BeThha#`>nh& z3J^6&xYQPu1E5-VUdcvG(0`H*iBLk}TJ)*mE*jL(4gsdU$KmuxGF}p}O>0@=X%M%R z5+r(rkZc#w`z1Iod*;y0DKC54lFun=LVOe8c$9NgazkUohsUW6Z%8@1C1S%>t3_7f z;gpJ%zr9N3d z{zr##MHLa3qlB6`c%m(0suE3cG62nFQ;~3>naK%$0BX@R6@I|LPr5-U5L3thrS*S$ zAolO>N7n~7OI63a!HzJLe>r2vF*o$kI%*W#qXZ7A3Q_ZRgwq?Yr*T2-&=5{J(RpC3 zl{~wZtP?+qwH8^_|D|-+lCO|#J}~Hm;Swj_3~HTmP-t{HT)LbB2QWHQ;;K?Ic6_A% z0hnY@bPPi$_XYYw2M}Sp5KZSvw_Z>h2TPtc&=^ckSsSD<9O85%40jS`QrfJjal1{h zUEafnU>Plw1;)a5$W*AX77pj$2LYkITB=YOht&Wko-$9;|FML>${&b{CJJEOuqG*3 zvMb$(P#ucXsh(#n44kL%EnOSo3CCfn8VCIPQoodb$)FNDCQz&11lqwrO8eGCu$?kF z=%+k-MZMV!?vCY+t75P2X%CW2*UI+AZBj*#M!>UP;HH824-nj??TZ2z?W-ObtE(Qc z=9fxYsl?@!z3%H>^(pBsVU3Wl4t}^^bp?vLiSe=XEVx=iUQ#*` zA8oJ9nP6Mp?kGWpb4DO(y#uEcfR9c2y%ejRFkcOf)J(8JU@u>96mcJE7|yaKLuH3# zu@>e$3{oYA7)DnqRpCHBQPOcQIGNs;Z`F#rEo4tllU*?-f8LzK7BN~9esGqShXzut zV6-q-S;*X(%PC3ZgcTJP>{s;;;&s)~3G2r{!&pRpX)s|qW_NRunY1MN>sksEQgH@Z z8pe|Hf?dn7eYs^7A&KC!yXy*CD?_0>QgKLe|0?!`XjI~A`7=@HtWntJq2DGkG_&hL zVBTSa2~QX%$<)U1GtB(B8~pkFxbRVjYIHi6hZCBy@`I33KDNf~AhJ)X+akdePpNuB zFgRgonAMn|ra>a%fdyK5#4&3{C%ZtPCKdlCh0oId@DZ+#>*RzA0P3ZHjz5(Yu3|z+ zU^b$MP6m#@4Jj0|6;q9_VGkmh(!IDoODYtWcGi>ig*YwxMqf03IMD!ByHG!4*C3AR z{IRuulOb=*W&^0p7B>bwHfy=co;fkk&;PFf8P?bRCoHt6bmRYO?k%I@+LlFOf(Ca2 z1Shz4H{D2p;O_2Dz%#7bIuOuo%`N+cZ~b^ z(LK7DYgVnQTC-}+S#tZW%f7nFrk@it$+h{81EIefWBKw4@8>MbWzpuH_L`>?epcse zN71!!`^O}wC>IUN7WG(D+RNDQ>-270ZW^vUZ-1D0dG%d+1(x4ieqX&BDmlo2m8kf< zs{QIf{WvE0tl~MwZ8mvdnLwGu@mnucL7T6pe6IbKx*3d+>$}d(*iw=M-RgahW{g!N-kB;Ui zx1ps<>xS3!N9xykx`MSU1WVOutVOOW8JK|39k z7gk$K-|D8>vz;Z)JwE|{3RlyV=vbWAXIvxR3)oLF$%KvFh9d$mVL7PYba4 zdnH+-6hAcl{CHM3FM7dEz+vPxO@>P#z!(qh zmY#IGMf-IpTY%z9-~=UMDAXvV z%4N~8XpHy8xwgqq{P-D!w6*P`u{>F;BJX=er_b3#8rhVNZ6i(a?jP3HDBL}E?~uCK zcsATE?|C{&1cP(|mvOgN0U%lXrAnvlm(bc9KZ98{;+iJtAWD?QzC7Wg^2yc;nT^d!pNfzdQ>4_95Mk zct*Lt;L*nw60sF$HAi$#TTZbkE$P^~~M?KjhXH==22;x4#M=eSllbcAngPa8af z&hi7{1Vx^9J^pY9i`wgmqUWM&cz@P>M)AB4b5SQ-e^+P|BPXxdFkOY*=-T*k;e<#5 zziy9rxPR@{@Ty=ES#{yVx7fc<+yBE`?Ee!r9J&6g;rK6kwLmW5e~~g$t2J*wFM$Iq zhlugh?8#v0xokX9JRPs{+6B!xaIT4p(V5Op&Kc^=Bz~LjV{IWFK}62?L74#AEb{xO ztTbL1bItQs{PKc;J?mxh*4NX`KNijja<=MFGqRA|*SgCE)B{Ib+wU}}evn|zL?TF! z)%Szkap)8p2eaX$I84eg?7y|_oEQ`TE@ zDXz5~PvNo(t$5aRijH0@UqPKZl1Dt^My@QuB}?N|E}QnN6UMgI+D+zBj+NMW*qs;fKld}27cOFc2y5s^7-`zHFz zPq#S^&1KeeT)>jn+1_+>8wqamUDhy5*jY^q&9V!Q>=p5ijnN=;KB_#D>=T?0X+5RR zMy*8(Xnnt9A2&e8s&1xB4RMA1u*Nk}L1Fl+(^F^;H;rBSM@hS{Fk`3)nXdy+_Bqn9 zOoc{aPKRBUx`CdUctrn>qUOhhhcG42D&fj{3#juFAwng2|*i%;!b?;o`LIedB;(3Sw5Z))F;nd>R# zktH**hEy@lVKl>ipdm76KHQWwU>%1@JJb%>K~{<-YtxoU6^AUyad3;&lx3ATM+lMF zsxPY7Sv_3;<|4oSamc{!`qlg%?$AhRMBYiy2CLZ5BQT1_w#L9jQs_^j3WCI1ER)8& z=)OXw;)L&eATvf%r#(=(?^g`{c7ZY)Ysj?z+nEs^Z@ty@W7gNWvZ=K`B5gUwOA^)CG#1;?3t2s)W72%O|MX#+9 z^9G3`b5&Lh4v)g=+2S~6hL(4(2U+))ip~PHgn(MpD3ZQvxQ1eGCrIka+fQnFEseQf z)Ny;<@asNimKFBYk!C(O-6qdO(zO+49rj(1lPDiXt;SGVhHoIvqFyRL8#R)0sgpA1 z_d#KZ3|-h>q^K{@a)FqT#wc%j?WIB_8Jgxgd|E|X#mT0qj`;n5oVM;12{sVN<}*^b zB&(1GGc64KjDjERr8V&#Lf#@~hSDm+9=GZ@ahdd}9ND zU`a|%K)oFX66s-mR7S9fbKCkFKW|`=bUgMqkHe zjP8t2?nEw#Xj}hus+u1g2&$dW@Qn11b%pNwoF=@-r-!jzuiaTs? z+vdbc@-nwu^EthEe|OqdJGiJgdyHRk&vK)me@n`0ihl06NHOR3EO#Ms6}C9|tuh^K z4Z4NrzA#Bl8tU$nYsc_8h?6CAN^J_BPrUNe1iF2@jZ=@)WD&pa-NK@X&k$|0-woAMEF^3RwTsDVN+2%LxOyA>98(%B7Z-1I&KHqUwNKDbHV3Z}<|} zKkAoE=!@mZW>uSVv#K9`dK*J4_PO2f3@Ks{}kr`5FI`m?+L8DG0Rr+J@HIC=4({Ep9 zOWW43-IP_fJ79R$QQ{J&nT%TJT#+LY0rz5aOH0j8Z#)k#kY_k^U#-$0^a2~74H*w< zA)7?BA3Lz_d#vd`vu)|%aO5y&HfK?oEx)x8$nf-I=t(4+3lRq<0@j%LLgYTvUq&W; zSjykQ>G!Q{*pALuq;ejb0IP_Y2%}4DV|`>~n+f>B%U)UXq^mdQ(?v@>Eu$dE|M*wWxg|D$moiX)GvmYVlYdXbRCM7qQ&(a%Zt zul!!-E9%uRQOK_YUP=hrUcWpuYf1ZrBC#1t4K!pNp(^}F^{jJ8X(T0KgibX$+ZiF) zvs`p)?kU=vos6E!t36EQ;p%~%4HMFdL6M%4!6y{h&V9?O^j~Lsyke_CJrPko%k9hJ z62K>ka*Qw5YBHly-;O-BSdY5xBhR>ibUFH{$$Q?tyyqRJE1S-|{`B>UxP;qdo_uT0 z<(6$&pUP3%S^als)tNRIJ-cTcZ$se}#*QO9+3^tjQ1?^UL8XF1@Pm$zl=GKZQN@U4 zr+5>)F(UHC2x;u_IH_Bed9xLRDn`EF4tn}5y^F#}?Ab~9BAty#eOb@^tslX*kMN0j zmi=hcB*CjnlO<7gUsSu<~paMMhGG*2RUbwur9o6+EB`aY*Mj&2W=$A*{hCl<;M z5nm(u)FTA*rt9Lp-~mF`Jf)yWf-jcAm`iAoSMfATxOpOd&>}JIQV%U-x{yAC-iY`p z#_pjX^_2tBb-0hX#H=t$khtX3HB=3>N2smwh^dgsyG!$yNro@=5gKKYJ^;@;NAE6u(D)g)w(a9MRQp2hpX}n^lqanbxE&YwlCT zK#5mbTErR<6a0bKdExfOhmi#!MZ$ZJ=PQ8*H+ed(A40e&EUXbJ`<$%ej~zWy5%+i}A(8pJSWK0)O-mqUnDrUH9r{nMuw` zWsv=#ArNuXm^&S7?K@WdM2x|-=B2opqxG2xNz$r*3&kkO51}eMzJ7}M_k<0lc>S-m z*lV({KmGJsxegdKeZ}D>v2H)T3MgQd0|*j4)7=QW zR5mxnzrjcCD_77W~CoStuMa4*y^vYkT=nI>*nLyuM+wN+QEd+A>_8-%8`)` z%kjD&Zj=00%-HY7(|&7)8%!*C8U{6y)?qCZ)BAwn48#?7Y0f^7pO|4%zjxw$wsO|Q zHS@9d>kBXs59B`^@KUY$*m*7-Sj_|+uQ`IJ66dnY1gGAuuQJT4Yu^xv z*W)x0L91WWg?-pA z+|iZ%^vaUYag5{eXL+DqwnwnwU5yggAq{~Jt`6o+$Asc5zes*tuS1M--MEqK_2qhD zRQE~2HYJp{HW#JvHDbEUj<4H?t!py}>_wPKGpdU+Qyfg0DDD8KBi3m^n7mbe#bxI@56ibYpEh=Wu9W4c2 zo{rcrQK5*^T(Nn+I9ufmJU?(n*hTCwY@c%B>-q}R=02sdFf2sX(+J6R&oNhLhjl4) znQNYoGbL*XYpu8@^!7}Bf0>X($2JzEd8*?RCjr@vZ#D@l#=GO!h2KaOG85Gj&O(bc zd-Xkmrpn-nEf$U%-CZPo-W{+UIE1H!5~i6he0F z%X!i@NqXM0+GP8yu?vx2i9RMHd;T18UG3g`skbzodc)olJ_4%#goJrJ)S3LPNq3}A zj+D@%`uq7vf4qLOSCw`NG^5=LlY!p!gE#o_Ix6gA@@(!>QZy?eWYP*Ul_nx^$4YN# zkpm$7wuchhrP5bwo4lT=M#n9MbqtG$?zXE*JEk8q?#C@%uf37|$C5c6&E+o_v9neA z48L453^20Xzafv)jN_gZe*SZ!audJ0-L@x9k{{ zxAJtkCvFM|!1o7G7!a(?Y$Ng!z;}ttD)r@hSY8~$wLcEmoWxmS!+)tcZaKAu_(5M% zQiH%Lp%U!^!3>3Jk>0^z!uhj@4LNa`glr(iXn?lrkW+iVadbC3ZOOp1FE}9$8DB#e zY^aXuN5Y>Ky{B?_n|((0v2aF~+%?#_+*nr}3BDoesY(ULmk(;YgjX3qW%%3p6GXA` zq_ow^wDI8x0V=LqlRu`4Vi(3hPJ$JcYwu(y>)1A#gSZ515%fNC4Q6}Cp;wzC>t-Ql zMKHYh#Hc^?4OT+LvxzR7(--kX2&%(-EQY8))Fs1X(1C}PNYv|~raS85$o)34W&0>c zL!dQK_eiFSu+$n=dRa&T34Xwi@BHeO)H-BN9m12Vb1m{H!hSJU6(`2^1}L34*nD)2 zElq0@G-sB6T49F8 zb$?O4I`S({2Ah^i$lWS~k%0KQ&@K7<4vig=>NInXnhtDA`i`|A)r7q{2Sw_T%5w0W zP`1Eu|B(|ZgpzTAkw10};NKlx2bd$0SZJIrq-_xP$xIuSLa9iRox&7mtJ7J0uL_>D zNm+gECz9(4>uLGfT~fIl-ZDx^kq}2-9!@OaQ!;)I=Lwmay)VL-Y?J1 z7hTewVHew`&^SD1B4{B0i2Fw&S&-kG*n)}kiIa`)-Se-X3f4wG!uLI?-G5&Zr%9EH zy!DdnZ0$4ube|wX$txB6H-UbpWx)%}IhCrEfa;BgnKO1R)t_@xvN|?1pXBBoD{DAX zlMKJO)#iQsCOq8TNw;f+CaayM$yBgoVqrEKv9joe`T|RJv55G}PTUc{6>)J-}0-?Qlsy=hn_zwoS>Ugd^^p`CD`RR_T(wc^d44y3bEUp+fkq= z(48Z%ps}fdF4O#zILsRRM$Fm;qpJq9Z%v3B7gArT6tle1Ug3?636`DI$g6sX*Oski zi}G?Y?bF_-Mf@tccfmmNc;*{9I?0paD$~Z9N^)s zhfIGGylngCGhV7)J3CQs!k}{6xhiB}>zN&*OXxm7BPxVEa80FnRDJpAXL(sKN?W(3 zf%^feOgLik}u0`{=A6<1Ge zKZsgBGPv$7@k={K#dnC9IBr6+P2pW?kp@ZpiuECb1XA%`NL*7rs#|SJ+z1M9IxO9H z^7;wA6AjFl8|+pZPLZZu&!Wl6Lc{Eo2s~a2(C;ah|B$^Y5B7&!-5TEdHx9&Kr62#- zTLHgp`2Uy#@v!I;kQc!DpB;!iEjx$#0o*&-4nTvV!isH!&n7h+PP_iM83mf{ba*%F zl7Tlhz(Huk2ZDw2LB+k@1RAELQ?Yu05iU&_AIB)?adewJ`vyLG&_Jjcs4+|Ng<_jL zs|jx)N^=CJe}9G{!(`C)VEdh&Fvv;taS2XU#AfpbGek36mi0;b(b;lUV|$uU+V=~J zTg|f5KnHu<$5I5HK9KBl0L!c#0T|wEy6_Z+_w@7O{re(y*$F z>!KA=vzpgonk=_+1PYr+6u_UN$k!Wm{dnNJ{L+)Z`K_O)4`j7)jDFH8HmKf#;$lDl z^P0>+X5PhI`&+-jgZKe~mgQ+ZGw~r#*GLB1Xn_>O8ot}Sud#|PpU<%yzpdBHOzFh{ zY7tg3@c0uyG6SXWE^F8@Bc_ZIM-01P7BQ<{@x2!8B%eRV(;AdtIByAZfS9|`c{*bS zIl@PP>$z-)13NcAHsijk62bG9ENGkmnE=aGbJI2%0*`T-w02hG=JFmMAjPr7e8C*e z)*yY#JSCZ5vg*|mMi-}D3jV;Wbboj2a5x%QEqhC$4#ZSnW?c;Ea8A-q#tWJ1KH1n< zJN3Cs*STB!m}u})Sw? zCBqH0YQ1mVD-$Xb*YS77Y6GL1ZT4Q?xIWJ|FvC43nXoAMc?4abMj1?(FM;r6)OZX)pmSaXjr+OeG5~b2Z~jiC!j#Pi zX=@YXc|#*Xp?T3*Qt47nyrAJ*J@xv9vB%V7agmi2X}dY6&XBujDAPF|q-$wAc-NjY zKBSL?`f0y938ly*NS(8F$hoH9gQh0}^N2-mo@ufaiiJw|Dw&_ZGlEv>JLX%3C?A&; zPV%-P?3vn9X}u8^?Bg=R>xiV;JN$;wIfi}k?riByYNjT{bkfx=ua1-cWqE8QV)Sc{h8y||0-CNV`yQ6p#9YqM(~>Dhf$!>o`@pm>3= zH@|@^%0z!0r|8wQTSKi88Q91~SK<>V-TDv@B&f6dsV=^FcxB#};zTq8(uKCY)9s7X z@hD-Hx*mUQoQ`n`Jk)K0E&Hn*6RR6%_I?8TdOn#j-=_Cz-4@rpaAv3iPv1D;+3Q<| z*jNv9_se}_@7v4!6NYdpzISp3tBAsBp=?ymB(%2pj^h>@R>r$T2uQ3@p0bH?P(3l`3pDxXGE;h2Sj z6=J6XjGq^)e^wKXckMq*zb1|`hhNf&f|PqxknzoV7GA>-pWA&hcZFgwaAC2KErV<} zx-S}cy}2rPX%#}s`0{JYSS*e!WPl z@Y4!ibJDtI^GwKCrl$q&SlqOF+COKJ}FwlCD?UxepL~(Z`NTR;qD5bu3`5Uyh_ziZEr}MHn~lFUQt!UF%rE>Giz~Q!|Nsu z9@rjG-5X#Kb_85EOreDzNX!_cw)h=o*!XdMcThL!*O;w&V{w#u9ssP^ahqM!j(FB4 zs${U)qIY1NKkJDDxjgC1&9>{_Tek|D6P6-t9v(!`Ic5`SR(Fb=kV@*C#$B!vh!S%Z zstg=1h|v$xpY*!vO59Tr?3$NNBOI8_Bd#Z#e@w~exexhN_9Bz3HWcK5b0{rKn%(hZ z=U61g3J0g1<%@W$LBxS+6Uu3KY}Q&Y>uJs-fe}l)XIhm;5E^`^=(n#kP(RSgHG{WN z^B_Cv#+;=`*^?c_n@s!CGkcEJ8s6~KPima^o`f3pkY(FXI^9)N%N*~-F8&}a<5Vwr zg#NiU^e*ywMfNt715I$HIMIpC#*aZ3=0UhcO_spUK4$QpQkf-B@`)y-_d%*4Db$f_671>qw8|8=qP-XdGyXy33`51&_YC3@7(>$1&ZeM+)%ts zi5RTsdtOM4$PHt*PNrf?cE;8Vwl8n374D;#HiuY4uB%%|!q;bPb8fL|_IxB@2~V6O z3I65CtM@halhn!n&n$NVr1<&k@ng4d_if#IO7WcNjmW0%-tUf2^dOd+hSTi}S4s!S z+3Z=Bzah84z|AorxFx}U-bFwE>T+QqK&cSnLatLhb_ds6lT0ex+u|k*`Ko?tH1Qrz z4_k%(-?$Y2WsEuZuMLF%&eMhelRb%tsrn#J5a2(%6usK>&htEYzj_qTI^!6KgCMo) zRlCwPPGr3aiRn5Hl~i~M0BY1wI69j)^A~PU-+LZI#T4zP=CC&i`4@bfuE94hu9ajY z1L&+Z(UO|O;)vi&TND0~-O-l~Dx}FtW2|J7jl|$t` zSaZUky>!Nr8e=8eTD@Yv0i=a#E+wygx4#7Hu`&!dBjxa=OV=!Y!C3!bG>Z%jq{-Sq zeM7MDPJhv_!OLdO^!jcjWBp)gIb|gp0e{{e`!jR)O6Ygvo@&+*?07KiajKNJzxzFM zrQ8=9T2wqd_UzPN#x*>EQQ(8Bz)yYigb_K2}j@S>>Tsp6u}QQ*DF8 z@IL6c2=}hhW7nmw{Dok@Zso3OOg0?cAR-kiElu8Vb7iLix;5?f`lQDIghRj}T(!_k z`g+SVx=e+QsKbdVhbM;g^(iasw!rqRn@}mD;E!nrGUQPqyNt|*1C3}&-j`s#(XK!V zUH^>+?~C<~rmG$_4b^v+qFb0p-7|fr2O*SHcy4;@qN&FMY$C!?LKP!yX}s{bv!KYq z+u7J>tf3i)^&hrMO~Hj^rZ~*goeH9?Cvoh<)4PF@=LIQ_dbZje#L14rggcO0S3N>^ z9fFpCk3jLhU|)44-HuYrk7O*oO>c7;SH`hBhiR;tEW9^xa(A7OP;P(j=X|r|yYsqY zo9J%SZs%FR0~ih1gvKqrU+ct9Tz7Vwv$MxpCbi(m%Ofx*rXi6AA;=5NDO%82O^>+YVYoNSj zu7inbBZA4=6*AVRtXUU!MBU1eK?EHH4riUm0cFJu1muIXSyYVLh+2TR3LK;3K}6~A z)uT-s;8HrtS(wiWQYXL2Pkus0UN789^CWA*!C%)PB#x*P3mB#ya$gqCxg}4I@5uh? zkeU#tR3XU7lPr}q&dkVywkJ|ddsQ9M^eO7O_;O|O;@Pw?>Ij!}lwvT2?hJ{CC@ygy zj;a1rU4_vZy7ya8zx`xH?BW+4NLCp^&{cQSWX55Nn{BFk2US+-tFfj-e6E;(lUjuA z;!ku0ioi|vBdtMTYt2!d@}QpXic8Fpqs zX4*`-EX^=V3-^JksIb7AjYe5bqz7AFAfH5=u8FK0A;%8A7AbiXyRzf3VpeU+BY3!Y z?V6|J$GQF1-85)|NnY(O@nPE&qjJqRn*{%t@4DAz=d5z{Y>bU+TwvOXBE>oMwugIsnBn&BhmO#?@h0K-< zi0agSacwpQy+ANHTjtr#`XH9)V-VK+!1|qxH+U_#h?eOpK5DNeC*RhbhgsV8S619l zrp2uqj$uyZs6j9HOn@I<+bl&lv0gLA+L_i5k2(NkJ0hbpC6rWXTs^p()uPgq+f7v7 z(I{{5a+ukq?qD&U#IC!BqFj8fg^(v<=3i?yDmGJ$4HuRnEpXwg@34Cs0GOqnEWJH; zNGHg|h`W3JMHOc|FCyCVuS1P>_@dg{0%+#8VOba=Jd6fP1|xe-=q)nZGi}pbwv55$ zGa*$>IT)!yBLew`P*AmOB&#enR&y+vYeHw;2Zp7+l~_Z7ipZcqLnDWC+(|wWlTEr(Y$gxsG>CXo2K-D zw7L^Z3S(e1O%P3T0;ccPBd{_&tufQEnzQ@{XN=lZWHAp=d>>?!e-4p-Zi0o4lTZhp zPHzkHl%5`IC6K~=ExH;nqkeC=oaS!fTqsROCnr7le5BWj{%XlM3fY)5)7&xO#1HDN zb4ScwyMmA5Ix83M94=GEkF9HRWsYwrj_Sz}<`;J|lA#$hJ|C7n$=luESxhAr zzHnN}D%R4qw0qtIFvC+X7J_5Sk6OztK^Zq4B4RF3--!~QC~zGx&dHt-hmZ&WRVY5=`z6|+Mo_LMQZIrgI%af!fQYpsIQ_4eJx?UJLAk?A?O><`B zE)BY8*Sy4UCWiVVsoySeVI3fmNnL2^@Z`)#dbBCuwK)sH zE#V#NTBdOfqJHY)Kq61k@Acc>zLx@)1Q2q{j9ZyGjS=R9TDR~Q-}!@wqlIE<$FbWC zXa`js*;A`7_@{qj<*O8P-*#H3Z{S(d)O(Basy2Sv)^Nk#{Ved)Dk!VZ;aZY#Npb!2 z36B|LFv)Rcarr7K(L%_wXewfYq*s#Yfk zEeZs!X#*d=p#FHr%y-DCdM${Wq%a|cvSmC0vOZec{X8FB!aZVcLvGgl@q@6@bi#d# zM?E;ZWB-coG_JNh_a5F@5#Q_I_!x=$dV87ZEv3-)gZ%Kuh6t9FR8jvtmepKKttU~~0pnl_?pG;{P z-ptd?W8tyF(HAuXpbobUS6zeJws5x*(*xgj1lJmOA6%?6bc0s9E{-|yRk|^$0is%@ zSqEH-UdIGYJ+4P2?fU|COB~UH(eSrhije82F9fQosgx0&%(X_EkS>}iUp+gaG9Z=o z=s#k>+~ng3qd&T>#w{|jn_SU zTKYXaP&A3?k7Uf4p)6Sy#xC=;+06?l+gti00T+v3cNZenSw4U5cBjZ+tUVYPX<5cQ z)MO(zYe_&W=CY!yGCvXq<1Y_`EMzqp4L${SMYWjAJg#lvEw+zciP7pF4pKkHloC%I zrHbs6KU(=zEixZ^j31P-3g5i2_X=((lL$#RY$XiWYTP0xh(&`LzRqgaYz7oAMd0f7 zg37c_JSdj16346ReG9Si)@;u_?iz#Vh$q&mBs*_DQjz(Nq03AhEG%X3a?mRq?ugru z#w0z;m@-zD_2Xvlw?ZVH`DavI*~60_VZJl$sJQ}^HU>Orqjl?vXGP!McN4k$?XC!y?qGQnUk=uy%yYqXt%_?w@ICd`7e z0H7PKPspChW^N&9H0a~R^j3#+_~jeRL?qFpPs9nCc2JO<6Zd23We)u=BrE9_92KmiRt%M6=4L z+Y)|JvP4f`D49CtV%dVpIe8>kg}wqu5WBFAqv$Ohb;-zCQZBG95Smq!B>^Xyef9xD z8c6OXVB8Abscw=YAObz#pV=K-dIBr)#ud2fg{8gJ>c;^E6=>!o zq$%H?Io`PAoVZ;f1bP}Pew-HPmaK3MseHO;oAQ=W1Fbi$Erysb2o&Lz>u+>+1dc-aa-*}Vjt z#WM2Co#~7ovJoB1%*t^@`4`q*KQl}*yosAk?RF;P)+G=4nI*lEozI;K`sWYx@^|u& zq8Ma%^g6|TFca<<ehQcZ^62TcW4Z?)D+e(p$CqDqu1NAe*3G6g7vHKN3$InO2TRMzS@|+%?joM|C`V zK^8*T*t30}!yS~rr?>RsSzhGl^hdtZo4bOOSk9s=*)c|8gx)~cve!8tw|s&{R*GTJqlmh%*UX9QsnbCg${GcG)rW}9JytY1D%Q$Hn=Dx$Ce?J$k+wqa)f6DjHJeSHBn z{E{c0HeH^;LZ~jS%+OQn9QCd*qzKwBEoxtjQAyiL0=sG=@ONXlOD0AXA}4x(Xq7Gg_=ao5T1ndiAX?svPd!xT|j9MwKn@4`Pq>?zPp1 z%;?MrnlLT4H;cxG;+rF8q5PAB-2!55Cfgs>54b)^2&+ZV?I)N%-id^D%6acL%pOx` z<#`KuenBVyg0mK>;6CDf@dBlzGm-J%7`VSe`TxT?$$xvw!T-Ug2G7GtNlq~6KksS0 zQZbb629WuT7Bol_7Tq@20emWWChdl-J5gSLsokC{m92YLyHzkNS?fJSyDZYUw2}U zsQv_-=Mc$@rsQ-xS<4N9gPvY*y>qHE|yDtu~L^@>dQtvC(k`kZ0vXZLaf6g zgl?qqy}<1Pa$bm9gc6ufva71Im}O%A4I2OGI05uDMP)Mjjcp#e!*W`>F(xJ;3$$3F z%VfjM5hp8|yfNSEO7MK@PlD|@I5tlET|y(<-vL(bU6mFgD>DllDj{>P7hPVrX& z5$v%Ofnktvuy^Hcy-=^{YuC?CY1Tss0@BYbpEJ{>Km8`~MYk-am2w zD$h#w%jKu~6>Y9U^(#~j_Vp(v+<%VX{u3YfpA`LiR{pi`@-Hm^qCiT<7XQ?q{~y(# zg#Y=z@h>#<{Bs-nm-2}kyBga%So}i?ss2**KjxHoFoSZayFmY;puZ4N{dtrBR2ZIr z$vbm)Fmp47Ix||SK|NimKJ!P6OPjs~FO;YI`eOmRkP`&_9R`7L{lU1ujpO72!)E_G3=DdBEhmT@ z3=_uRujSj{Y472=d2b@f(Z_ z{D4;=Zk`A9!C3!*K2E>``2t`^F%RU%$@xI9VBOdMSTz1l3nv%w0k1e=2_p~2@$f$2 z3m7)z@8iJ0hq?w+mj`kKgTW8*f*}ui0Oo$k12E4+9zbB4`a3NU*y8aU3~I@ce>!Vf#40;pGJJ{^6_qO*dc~^gy2>5FXy&b%T?K>jCemV04@;J#GIE4Y|0H2qZubm5)f{4GvgQf9MbmY4phJFw+e@ Date: Fri, 8 Aug 2014 16:08:41 +0100 Subject: [PATCH 06/41] [Exporters] Nordic - uvision - RAM fix and mergehex removal --- workspace_tools/export/uvision4_nrf51822.uvopt.tmpl | 2 +- workspace_tools/export/uvision4_nrf51822.uvproj.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace_tools/export/uvision4_nrf51822.uvopt.tmpl b/workspace_tools/export/uvision4_nrf51822.uvopt.tmpl index 1d3b4630178..4b4e8166e62 100644 --- a/workspace_tools/export/uvision4_nrf51822.uvopt.tmpl +++ b/workspace_tools/export/uvision4_nrf51822.uvopt.tmpl @@ -125,7 +125,7 @@ 0 JL2CM3 - -U480204337 -O78 -S0 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8004 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO31 -FD20000000 -FC800 -FN1 -FF0nrf51xxx.flm -FS00 -FL0200000 -FP0($$Device:nRF51822_xxAA$Flash\nrf51xxx.flm) + -U480204337 -O78 -S0 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8004 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO31 -FD20000000 -FC2000 -FN1 -FF0nrf51xxx.flm -FS00 -FL0200000 -FP0($$Device:nRF51822_xxAA$Flash\nrf51xxx.flm) 0 diff --git a/workspace_tools/export/uvision4_nrf51822.uvproj.tmpl b/workspace_tools/export/uvision4_nrf51822.uvproj.tmpl index b14d1afa35f..df70e697c25 100644 --- a/workspace_tools/export/uvision4_nrf51822.uvproj.tmpl +++ b/workspace_tools/export/uvision4_nrf51822.uvproj.tmpl @@ -76,7 +76,7 @@ 1 0 - mergehex -m !H {% for hex in hex_files %} {{hex}} {% endfor %} -o $H@H.hex + 0 0 From 441099212a2c22e957f447e6f5a5c9ceb950ab38 Mon Sep 17 00:00:00 2001 From: "Aron L. Phillips" Date: Fri, 8 Aug 2014 11:33:19 -0400 Subject: [PATCH 07/41] Added the symbol PinMap_I2C_SDA[] and PinMap_I2C_SCL[] to the PeripheralPins.c file. Compiled against uARM, ARM, and GCC_ARM. --- .../TARGET_GHI_MBUINO/PeripheralPins.c | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_GHI_MBUINO/PeripheralPins.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_GHI_MBUINO/PeripheralPins.c index adba905abea..8819609c3ea 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_GHI_MBUINO/PeripheralPins.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_GHI_MBUINO/PeripheralPins.c @@ -30,18 +30,25 @@ const PinMap PinMap_ADC[] = { {NC , NC , 0 } }; +/************I2C***************/ +const PinMap PinMap_I2C_SDA[] = { + {P0_5, I2C_0, 1}, + {NC , NC , 0} +}; + +const PinMap PinMap_I2C_SCL[] = { + {P0_4, I2C_0, 1}, + {NC , NC, 0} +}; + /************UART***************/ const PinMap PinMap_UART_TX[] = { {P0_19, UART_0, 1}, -// {P1_13, UART_0, 3}, -// {P1_27, UART_0, 2}, { NC , NC , 0} }; const PinMap PinMap_UART_RX[] = { {P0_18, UART_0, 1}, -// {P1_14, UART_0, 3}, -// {P1_26, UART_0, 2}, {NC , NC , 0} }; @@ -49,30 +56,25 @@ const PinMap PinMap_UART_RX[] = { const PinMap PinMap_SPI_SCLK[] = { {P0_6 , SPI_0, 0x02}, {P0_10, SPI_0, 0x02}, -// {P1_29, SPI_0, 0x01}, {P1_15, SPI_1, 0x03}, -// {P1_20, SPI_1, 0x02}, {NC , NC , 0} }; const PinMap PinMap_SPI_MOSI[] = { {P0_9 , SPI_0, 0x01}, {P0_21, SPI_1, 0x02}, -// {P1_22, SPI_1, 0x02}, {NC , NC , 0} }; const PinMap PinMap_SPI_MISO[] = { {P0_8 , SPI_0, 0x01}, {P0_22, SPI_1, 0x03}, -// {P1_21, SPI_1, 0x02}, {NC , NC , 0} }; const PinMap PinMap_SPI_SSEL[] = { {P0_2 , SPI_0, 0x01}, {P1_19, SPI_1, 0x02}, -// {P1_23, SPI_1, 0x02}, {NC , NC , 0} }; From 67e9feeab7552ab0699df2fc445e429edacb1af7 Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Thu, 19 Jun 2014 12:37:32 +0200 Subject: [PATCH 08/41] [LPC1549] Add support for GCC_ARM --- .../TOOLCHAIN_GCC_ARM/LPC1549.ld | 154 +++++++++++ .../TOOLCHAIN_GCC_ARM/startup_LPC15xx.s | 247 ++++++++++++++++++ workspace_tools/build_release.py | 2 +- workspace_tools/targets.py | 2 +- 4 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/LPC1549.ld create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/startup_LPC15xx.s diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/LPC1549.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/LPC1549.ld new file mode 100644 index 00000000000..7358b9da433 --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/LPC1549.ld @@ -0,0 +1,154 @@ +/* Linker script for mbed LPC1549 */ + +/* Linker script to configure memory regions. */ +MEMORY +{ + /* Define each memory region */ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K + Ram0_16 (rwx) : ORIGIN = 0x2000000 + 0x100, LENGTH = (16K - 0x100) + Ram1_16 (rwx) : ORIGIN = 0x2004000, LENGTH = 16K + Ram2_4 (rwx) : ORIGIN = 0x2008000, LENGTH = 4K + +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which 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(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + Image$$RW_IRAM1$$Base = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE (__fini_array_end = .); + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > Ram0_16 + + + .bss : + { + __bss_start__ = .; + *(.bss*) + *(COMMON) + __bss_end__ = .; + Image$$RW_IRAM1$$ZI$$Limit = . ; + } > Ram0_16 + + + .heap : + { + __end__ = .; + end = __end__; + *(.heap*) + __HeapLimit = .; + } > Ram0_16 + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy : + { + *(.stack) + } > Ram0_16 + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(Ram0_16) + LENGTH(Ram0_16); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/startup_LPC15xx.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/startup_LPC15xx.s new file mode 100644 index 00000000000..814aa4262cb --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/TOOLCHAIN_GCC_ARM/startup_LPC15xx.s @@ -0,0 +1,247 @@ +/* File: startup_ARMCM3.s + * Purpose: startup file for Cortex-M3/M4 devices. Should use with + * GNU Tools for ARM Embedded Processors + * Version: V1.1 + * Date: 17 June 2011 + * + * Copyright (C) 2011 ARM Limited. All rights reserved. + * ARM Limited (ARM) is supplying this software for use with Cortex-M3/M4 + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + */ + .syntax unified + .arch armv7-m + +/* Memory Model + The HEAP starts at the end of the DATA section and grows upward. + + The STACK starts at the end of the RAM and grows downward. + + The HEAP and stack STACK are only checked at compile time: + (DATA_SIZE + HEAP_SIZE + STACK_SIZE) < RAM_SIZE + + This is just a check for the bare minimum for the Heap+Stack area before + aborting compilation, it is not the run time limit: + Heap_Size + Stack_Size = 0x80 + 0x80 = 0x100 + */ + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0xc00 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + .equ Heap_Size, 0x800 +#endif + .globl __HeapBase + .globl __HeapLimit +__HeapBase: + .space Heap_Size + .size __HeapBase, . - __HeapBase +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .isr_vector + .align 2 + .globl __isr_vector +__isr_vector: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts */ + .long WDT_IRQHandler /* 0: Windowed watchdog timer */ + .long BOD_IRQHandler /* 1: Brown-Out Detect */ + .long FMC_IRQHandler /* 2: Flash controller */ + .long EEPROM_IRQHandler /* 3: EEPROM controller */ + .long DMA_IRQHandler /* 4: DMA */ + .long GINT0_IRQHandler /* 5: GPIO group 0 */ + .long GINT1_IRQHandler /* 6: GPIO group 1 */ + .long PIN_INT0_IRQHandler /* 7: PIO INT0 */ + .long PIN_INT1_IRQHandler /* 8: PIO INT1 */ + .long PIN_INT2_IRQHandler /* 9: PIO INT2 */ + .long PIN_INT3_IRQHandler /* 10: PIO INT3 */ + .long PIN_INT4_IRQHandler /* 11: PIO INT4 */ + .long PIN_INT5_IRQHandler /* 12: PIO INT5 */ + .long PIN_INT6_IRQHandler /* 13: PIO INT6 */ + .long PIN_INT7_IRQHandler /* 14: PIO INT7 */ + .long RIT_IRQHandler /* 15: Repetitive Interrupt Timer */ + .long SCT0_IRQHandler /* 16: State configurable timer */ + .long SCT1_IRQHandler /* 17: State configurable timer */ + .long SCT2_IRQHandler /* 18: State configurable timer */ + .long SCT3_IRQHandler /* 19: State configurable timer */ + .long MRT_IRQHandler /* 20: Multi-Rate Timer */ + .long UART0_IRQHandler /* 21: UART0 */ + .long UART1_IRQHandler /* 22: UART1 */ + .long UART2_IRQHandler /* 23: UART2 */ + .long I2C0_IRQHandler /* 24: I2C0 controller */ + .long SPI0_IRQHandler /* 25: SPI0 controller */ + .long SPI1_IRQHandler /* 26: SPI1 controller */ + .long CAN_IRQHandler /* 27: C_CAN0 */ + .long USB_IRQHandler /* 28: USB IRQ */ + .long USB_FIQHandler /* 29: USB FIQ */ + .long USBWakeup_IRQHandler /* 30: USB wake-up */ + .long ADC0A_IRQHandler /* 31: ADC0 sequence A completion */ + .long ADC0B_IRQHandler /* 32: ADC0 sequence B completion */ + .long ADC0_THCMP_IRQHandler /* 33: ADC0 threshold compare */ + .long ADC0_OVR_IRQHandler /* 34: ADC0 overrun */ + .long ADC1A_IRQHandler /* 35: ADC1 sequence A completion */ + .long ADC1B_IRQHandler /* 36: ADC1 sequence B completion */ + .long ADC1_THCMP_IRQHandler /* 37: ADC1 threshold compare */ + .long ADC1_OVR_IRQHandler /* 38: ADC1 overrun */ + .long DAC_IRQHandler /* 39: DAC */ + .long ACMP0_IRQHandler /* 40: Analog Comparator 0 */ + .long ACMP1_IRQHandler /* 41: Analog Comparator 1 */ + .long ACMP2_IRQHandler /* 42: Analog Comparator 2 */ + .long ACMP3_IRQHandler /* 43: Analog Comparator 3 */ + .long QEI_IRQHandler /* 44: Quadrature Encoder Interface */ + .long RTC_ALARM_IRQHandler /* 45: RTC alarm */ + .long RTC_WAKE_IRQHandler /* 46: RTC wake-up */ + + .size __isr_vector, . - __isr_vector + + .text + .thumb + .thumb_func + .align 2 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* 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__ + +.Lflash_to_ram_loop: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .Lflash_to_ram_loop + + ldr r0, =SystemInit + blx r0 + ldr r0, =_start + bx r0 + .pool + .size Reset_Handler, . - Reset_Handler + + .text +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_default_handler handler_name + .align 1 + .thumb_func + .weak \handler_name + .type \handler_name, %function +\handler_name : + b . + .size \handler_name, . - \handler_name + .endm + + def_default_handler NMI_Handler + def_default_handler HardFault_Handler + def_default_handler MemManage_Handler + def_default_handler BusFault_Handler + def_default_handler UsageFault_Handler + def_default_handler SVC_Handler + def_default_handler DebugMon_Handler + def_default_handler PendSV_Handler + def_default_handler SysTick_Handler + def_default_handler Default_Handler + + .macro def_irq_default_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_default_handler WDT_IRQHandler + def_irq_default_handler BOD_IRQHandler + def_irq_default_handler FMC_IRQHandler + def_irq_default_handler EEPROM_IRQHandler + def_irq_default_handler DMA_IRQHandler + def_irq_default_handler GINT0_IRQHandler + def_irq_default_handler GINT1_IRQHandler + def_irq_default_handler PIN_INT0_IRQHandler + def_irq_default_handler PIN_INT1_IRQHandler + def_irq_default_handler PIN_INT2_IRQHandler + def_irq_default_handler PIN_INT3_IRQHandler + def_irq_default_handler PIN_INT4_IRQHandler + def_irq_default_handler PIN_INT5_IRQHandler + def_irq_default_handler PIN_INT6_IRQHandler + def_irq_default_handler PIN_INT7_IRQHandler + def_irq_default_handler RIT_IRQHandler + def_irq_default_handler SCT0_IRQHandler + def_irq_default_handler SCT1_IRQHandler + def_irq_default_handler SCT2_IRQHandler + def_irq_default_handler SCT3_IRQHandler + def_irq_default_handler MRT_IRQHandler + def_irq_default_handler UART0_IRQHandler + def_irq_default_handler UART1_IRQHandler + def_irq_default_handler UART2_IRQHandler + def_irq_default_handler I2C0_IRQHandler + def_irq_default_handler SPI0_IRQHandler + def_irq_default_handler SPI1_IRQHandler + def_irq_default_handler CAN_IRQHandler + def_irq_default_handler USB_IRQHandler + def_irq_default_handler USB_FIQHandler + def_irq_default_handler USBWakeup_IRQHandler + def_irq_default_handler ADC0A_IRQHandler + def_irq_default_handler ADC0B_IRQHandler + def_irq_default_handler ADC0_THCMP_IRQHandler + def_irq_default_handler ADC0_OVR_IRQHandler + def_irq_default_handler ADC1A_IRQHandler + def_irq_default_handler ADC1B_IRQHandler + def_irq_default_handler ADC1_THCMP_IRQHandler + def_irq_default_handler ADC1_OVR_IRQHandler + def_irq_default_handler DAC_IRQHandler + def_irq_default_handler ACMP0_IRQHandler + def_irq_default_handler ACMP1_IRQHandler + def_irq_default_handler ACMP2_IRQHandler + def_irq_default_handler ACMP3_IRQHandler + def_irq_default_handler QEI_IRQHandler + def_irq_default_handler RTC_ALARM_IRQHandler + def_irq_default_handler RTC_WAKE_IRQHandler + def_irq_default_handler DEF_IRQHandler + + .end + diff --git a/workspace_tools/build_release.py b/workspace_tools/build_release.py index fcf5e10b875..c057b00bc26 100755 --- a/workspace_tools/build_release.py +++ b/workspace_tools/build_release.py @@ -38,7 +38,7 @@ ('LPC1114', ('uARM','GCC_ARM')), ('LPC11U35_401', ('ARM', 'uARM','GCC_ARM','GCC_CR')), ('LPC11U35_501', ('ARM', 'uARM','GCC_ARM','GCC_CR')), - ('LPC1549', ('uARM','GCC_CR')), + ('LPC1549', ('uARM','GCC_ARM','GCC_CR')), ('XADOW_M0', ('ARM', 'uARM','GCC_ARM','GCC_CR')), ('ARCH_GPRS', ('ARM', 'uARM', 'GCC_ARM', 'GCC_CR')), diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 2a90d9e5e9e..7c213e922a4 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -461,7 +461,7 @@ def __init__(self): Target.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC15XX'] - self.supported_toolchains = ["uARM", "GCC_CR"] + self.supported_toolchains = ["uARM", "GCC_CR", "GCC_ARM"] self.default_toolchain = "uARM" self.supported_form_factors = ["ARDUINO"] From bc62d0b66d5f12b653cbf4e652fc79127ce9da6e Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Sat, 21 Jun 2014 14:12:40 +0200 Subject: [PATCH 09/41] [LPC1549][GCC_ARM] Add export functionality --- workspace_tools/export/README.md | 10 ++++ workspace_tools/export/gcc_arm_lpc1549.tmpl | 57 +++++++++++++++++++++ workspace_tools/export/gccarm.py | 1 + workspace_tools/export_test.py | 1 + 4 files changed, 69 insertions(+) create mode 100644 workspace_tools/export/gcc_arm_lpc1549.tmpl diff --git a/workspace_tools/export/README.md b/workspace_tools/export/README.md index a434c13b42a..06bb2c0f339 100644 --- a/workspace_tools/export/README.md +++ b/workspace_tools/export/README.md @@ -22,6 +22,16 @@ Exporter Toolchain/Platform Support ✓ ✓ + + NXP LPC1549 + ✓ + + + + ✓ + + ✓ + NXP LPC11U24 diff --git a/workspace_tools/export/gcc_arm_lpc1549.tmpl b/workspace_tools/export/gcc_arm_lpc1549.tmpl new file mode 100644 index 00000000000..aa3bfdab4b0 --- /dev/null +++ b/workspace_tools/export/gcc_arm_lpc1549.tmpl @@ -0,0 +1,57 @@ +# This file was automagically generated by mbed.org. For more information, +# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded + +GCC_BIN = +PROJECT = {{name}} +OBJECTS = {% for f in to_be_compiled %}{{f}} {% endfor %} +SYS_OBJECTS = {% for f in object_files %}{{f}} {% endfor %} +INCLUDE_PATHS = {% for p in include_paths %}-I{{p}} {% endfor %} +LIBRARY_PATHS = {% for p in library_paths %}-L{{p}} {% endfor %} +LIBRARIES = {% for lib in libraries %}-l{{lib}} {% endfor %} +LINKER_SCRIPT = {{linker_script}} + +############################################################################### +AS = $(GCC_BIN)arm-none-eabi-as +CC = $(GCC_BIN)arm-none-eabi-gcc +CPP = $(GCC_BIN)arm-none-eabi-g++ +LD = $(GCC_BIN)arm-none-eabi-gcc +OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy + +CPU = -mcpu=cortex-m3 -mthumb +CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections +CC_FLAGS += -MMD -MP +CC_SYMBOLS = {% for s in symbols %}-D{{s}} {% endfor %} + +LD_FLAGS = -mcpu=cortex-m3 -mthumb -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float +LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys + +ifeq ($(DEBUG), 1) + CC_FLAGS += -DDEBUG -O0 +else + CC_FLAGS += -DNDEBUG -Os +endif + +all: $(PROJECT).bin + +clean: + rm -f $(PROJECT).bin $(PROJECT).elf $(OBJECTS) $(DEPS) + +.s.o: + $(AS) $(CPU) -o $@ $< + +.c.o: + $(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $@ $< + +.cpp.o: + $(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 $(INCLUDE_PATHS) -o $@ $< + + +$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS) + $(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS) + +$(PROJECT).bin: $(PROJECT).elf + $(OBJCOPY) -O binary $< $@ + +DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d) +-include $(DEPS) + diff --git a/workspace_tools/export/gccarm.py b/workspace_tools/export/gccarm.py index 0850f598c37..01e37a13915 100644 --- a/workspace_tools/export/gccarm.py +++ b/workspace_tools/export/gccarm.py @@ -24,6 +24,7 @@ class GccArm(Exporter): TARGETS = [ 'LPC1768', + 'LPC1549', 'KL05Z', 'KL25Z', 'KL46Z', diff --git a/workspace_tools/export_test.py b/workspace_tools/export_test.py index 4e0e538de85..a4ddcbc163a 100755 --- a/workspace_tools/export_test.py +++ b/workspace_tools/export_test.py @@ -108,6 +108,7 @@ def test_export(toolchain, target, expected_error=None): # Linux path: /home/emimon01/bin/gcc-arm/bin/ # Windows path: C:/arm-none-eabi-gcc-4_7/bin/ ('gcc_arm', 'LPC1768'), + ('gcc_arm', 'LPC1549'), ('gcc_arm', 'LPC1114'), ('gcc_arm', 'LPC11U35_401'), ('gcc_arm', 'LPC11U35_501'), From 24ea3bcafaad376540644ca8a9a5df37f2ac3b02 Mon Sep 17 00:00:00 2001 From: Janek Mann Date: Mon, 11 Aug 2014 00:30:06 +0100 Subject: [PATCH 10/41] fixes to NRF51822 GCC template --- workspace_tools/export/gcc_arm_nrf51822.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace_tools/export/gcc_arm_nrf51822.tmpl b/workspace_tools/export/gcc_arm_nrf51822.tmpl index bea937d85ee..b9b6425dd21 100644 --- a/workspace_tools/export/gcc_arm_nrf51822.tmpl +++ b/workspace_tools/export/gcc_arm_nrf51822.tmpl @@ -23,7 +23,7 @@ CPU = -mcpu=cortex-m0 -mthumb CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections CC_SYMBOLS = {% for s in symbols %}-D{{s}} {% endfor %} -LD_FLAGS = -mcpu=cortex-m0 -mthumb -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float +LD_FLAGS = -mcpu=cortex-m0 -mthumb -Wl,--wrap=main --specs=nano.specs -u _printf_float -u _scanf_float LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys ifeq ($(DEBUG), 1) From 0b7b75881aecdec8e986e69b007d5f78810d588e Mon Sep 17 00:00:00 2001 From: Yihui Xiong Date: Mon, 11 Aug 2014 12:37:06 +0800 Subject: [PATCH 11/41] fixed L6235E link error for Xadow M0 --- .../LPC11U35.sct | 0 .../startup_LPC11xx.s | 0 .../PeripheralNames.h | 0 .../PeripheralPins.c | 0 .../TARGET_LPC11U35_501/PinNames.h | 0 .../TARGET_LPC11U35_501/device.h | 0 .../TARGET_XADOW_M0/PinNames.h | 179 ++++++++++++++++++ .../TARGET_XADOW_M0/device.h | 59 ++++++ workspace_tools/targets.py | 21 +- 9 files changed, 252 insertions(+), 7 deletions(-) rename libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/{TARGET_LPC11U35_501 => TARGET_MCU_LPC11U35_501}/LPC11U35.sct (100%) rename libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/{TARGET_LPC11U35_501 => TARGET_MCU_LPC11U35_501}/startup_LPC11xx.s (100%) rename libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/{TARGET_LPC11U35_501 => TARGET_MCU_LPC11U35_501}/PeripheralNames.h (100%) rename libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/{TARGET_LPC11U35_501 => TARGET_MCU_LPC11U35_501}/PeripheralPins.c (100%) rename libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/{ => TARGET_MCU_LPC11U35_501}/TARGET_LPC11U35_501/PinNames.h (100%) rename libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/{ => TARGET_MCU_LPC11U35_501}/TARGET_LPC11U35_501/device.h (100%) create mode 100644 libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/PinNames.h create mode 100644 libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/device.h diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_501/LPC11U35.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_MCU_LPC11U35_501/LPC11U35.sct similarity index 100% rename from libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_501/LPC11U35.sct rename to libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_MCU_LPC11U35_501/LPC11U35.sct diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_501/startup_LPC11xx.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_MCU_LPC11U35_501/startup_LPC11xx.s similarity index 100% rename from libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_501/startup_LPC11xx.s rename to libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_MCU_LPC11U35_501/startup_LPC11xx.s diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PeripheralNames.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/PeripheralNames.h similarity index 100% rename from libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PeripheralNames.h rename to libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/PeripheralNames.h diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PeripheralPins.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/PeripheralPins.c similarity index 100% rename from libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PeripheralPins.c rename to libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/PeripheralPins.c diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PinNames.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_LPC11U35_501/PinNames.h similarity index 100% rename from libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/PinNames.h rename to libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_LPC11U35_501/PinNames.h diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/device.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_LPC11U35_501/device.h similarity index 100% rename from libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U35_501/device.h rename to libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_LPC11U35_501/device.h diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/PinNames.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/PinNames.h new file mode 100644 index 00000000000..203ca83a759 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/PinNames.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 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 5 + +typedef enum { + // LPC11U Pin Names + P0_0 = 0, + P0_1 = 1, + P0_2 = 2, + P0_3 = 3, + P0_4 = 4, + P0_5 = 5, + P0_6 = 6, + P0_7 = 7, + P0_8 = 8, + P0_9 = 9, + P0_10 = 10, + P0_11 = 11, + P0_12 = 12, + P0_13 = 13, + P0_14 = 14, + P0_15 = 15, + P0_16 = 16, + P0_17 = 17, + P0_18 = 18, + P0_19 = 19, + P0_20 = 20, + P0_21 = 21, + P0_22 = 22, + P0_23 = 23, + P0_24 = 24, + P0_25 = 25, + P0_26 = 26, + P0_27 = 27, + + P1_0 = 32, + P1_1 = 33, + P1_2 = 34, + P1_3 = 35, + P1_4 = 36, + P1_5 = 37, + P1_6 = 38, + P1_7 = 39, + P1_8 = 40, + P1_9 = 41, + P1_10 = 42, + P1_11 = 43, + P1_12 = 44, + P1_13 = 45, + P1_14 = 46, + P1_15 = 47, + P1_16 = 48, + P1_17 = 49, + P1_18 = 50, + P1_19 = 51, + P1_20 = 52, + P1_21 = 53, + P1_22 = 54, + P1_23 = 55, + P1_24 = 56, + P1_25 = 57, + P1_26 = 58, + P1_27 = 59, + P1_28 = 60, + P1_29 = 61, + + P1_31 = 63, + + // mbed DIP Pin Names + // CN1-1 (GND) + // CN1-2 (EXTPOWER) + // CN1-3 (NC) + p4 = P0_0, // CN1-4 + p5 = P0_9, // CN1-5 + p6 = P0_8, // CN1-6 + p7 = P0_10, // CN1-7 + p8 = P0_7, // CN1-8 + p9 = P0_19, // CN1-9 + p10 = P0_18, // CN1-10 + p11 = P0_21, // CN1-11 + p12 = P0_22, // CN1-12 + p13 = P1_15, // CN1-13 + p14 = P0_6, // CN1-14 + p15 = P0_11, // CN1-15 + p16 = P0_12, // CN1-16 + p17 = P0_13, // CN1-17 + p18 = P0_14, // CN1-18 + p19 = P0_15, // CN1-19 + p20 = P0_16, // CN1-20 + + p21 = P0_14, // CN2-20 + p22 = P0_2, // CN2-19 + p23 = P0_23, // CN2-18 + p24 = P0_17, // CN2-17 + p25 = P0_20, // CN2-16 + p26 = P1_15, // CN2-15 + p27 = P0_4, // CN2-14 + p28 = P0_5, // CN2-13 + p29 = P1_19, // CN2-12 + p30 = P0_1, // CN2-11 + // CN2-10 (D+USB) + // CN2-9 (D-USB) + p33 = P0_3, // CN2-8 (USB-VBUS) + // CN2-7 (NC) + // CN2-6 (NC) + // CN2-5 (NC) + // CN2-4 (NC) + // CN2-3 (NC) + // CN2-2 (VDD) + // CN2-1 (VDD) + + // Other mbed Pin Names + LED1 = P0_20, + LED2 = P0_23, + LED3 = P0_20, + LED4 = P0_23, + + UART_TX = P0_19, + UART_RX = P0_18, + + I2C_SCL = P0_4, + I2C_SDA = P0_5, + + // Not connected + NC = (int)0xFFFFFFFF, +} PinName; + +typedef enum { + CHANNEL0 = FLEX_INT0_IRQn, + CHANNEL1 = FLEX_INT1_IRQn, + CHANNEL2 = FLEX_INT2_IRQn, + CHANNEL3 = FLEX_INT3_IRQn, + CHANNEL4 = FLEX_INT4_IRQn, + CHANNEL5 = FLEX_INT5_IRQn, + CHANNEL6 = FLEX_INT6_IRQn, + CHANNEL7 = FLEX_INT7_IRQn +} Channel; + +typedef enum { + PullUp = 2, + PullDown = 1, + PullNone = 0, + Repeater = 3, + OpenDrain = 4, + PullDefault = PullDown +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/device.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/device.h new file mode 100644 index 00000000000..120ca9edb6a --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11UXX/TARGET_MCU_LPC11U35_501/TARGET_XADOW_M0/device.h @@ -0,0 +1,59 @@ +/* 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 + +#define DEVICE_PORTIN 1 +#define DEVICE_PORTOUT 1 +#define DEVICE_PORTINOUT 1 + +#define DEVICE_INTERRUPTIN 1 + +#define DEVICE_ANALOGIN 1 +#define DEVICE_ANALOGOUT 0 + +#define DEVICE_SERIAL 1 + +#define DEVICE_I2C 1 +#define DEVICE_I2CSLAVE 1 + +#define DEVICE_SPI 1 +#define DEVICE_SPISLAVE 1 + +#define DEVICE_CAN 0 + +#define DEVICE_RTC 0 + +#define DEVICE_ETHERNET 0 + +#define DEVICE_PWMOUT 1 + +#define DEVICE_SEMIHOST 0 +#define DEVICE_LOCALFILESYSTEM 0 +#define DEVICE_ID_LENGTH 32 +#define DEVICE_MAC_OFFSET 20 + +#define DEVICE_SLEEP 1 + +#define DEVICE_DEBUG_AWARENESS 0 + +#define DEVICE_STDIO_MESSAGES 0 + +#define DEVICE_ERROR_PATTERN 1 + +#include "objects.h" + +#endif diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 2a90d9e5e9e..199d7b36850 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -376,7 +376,7 @@ class LPC11U35_501(Target): def __init__(self): Target.__init__(self) self.core = "Cortex-M0" - self.extra_labels = ['NXP', 'LPC11UXX'] + self.extra_labels = ['NXP', 'LPC11UXX', 'MCU_LPC11U35_501'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] self.default_toolchain = "uARM" @@ -512,11 +512,12 @@ def __init__(self): self.default_toolchain = "uARM" -class XADOW_M0(LPC11U35_501): +class XADOW_M0(Target): def __init__(self): - LPC11U35_501.__init__(self) - self.extra_labels = ['NXP', 'LPC11UXX', 'LPC11U35_501'] - self.macros = ['TARGET_LPC11U35_501'] + Target.__init__(self) + self.core = "Cortex-M0" + self.extra_labels = ['NXP', 'LPC11UXX', 'MCU_LPC11U35_501'] + self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] class ARCH_BLE(NRF51822): @@ -524,6 +525,7 @@ def __init__(self): NRF51822.__init__(self) self.extra_labels = ['NORDIC', 'MCU_NRF51822'] self.macros = ['TARGET_NRF51822'] + self.supported_form_factors = ["ARDUINO"] class ARCH_PRO(Target): @@ -536,9 +538,14 @@ def __init__(self): self.supported_form_factors = ["ARDUINO"] -class ARCH_GPRS(LPC11U37_501): +class ARCH_GPRS(Target): def __init__(self): - LPC11U37_501.__init__(self) + Target.__init__(self) + self.core = "Cortex-M0" + self.extra_labels = ['NXP', 'LPC11UXX', 'LPC11U37_501'] + self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] + self.default_toolchain = "uARM" + self.supported_form_factors = ["ARDUINO"] class LPCCAPPUCCINO(LPC11U37_501): From 7e2001b98020f7c72c8d2f4b7a91f775c866df11 Mon Sep 17 00:00:00 2001 From: Janek Mann Date: Mon, 11 Aug 2014 11:23:13 +0100 Subject: [PATCH 12/41] workaround for --gc-sections issue with NRF51822 --- workspace_tools/toolchains/gcc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/workspace_tools/toolchains/gcc.py b/workspace_tools/toolchains/gcc.py index c42f1828eee..ab422562662 100644 --- a/workspace_tools/toolchains/gcc.py +++ b/workspace_tools/toolchains/gcc.py @@ -75,7 +75,10 @@ def __init__(self, target, options=None, notify=None, macros=None, tool_path="") self.cc = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "-std=gnu99", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cppc.replace('\\', '/'), "-std=gnu++98", "-fno-rtti", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags - self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu + if target.name in ["NRF51822"]: + self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--wrap,main"] + self.cpu + else: + self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"] self.ar = join(tool_path, "arm-none-eabi-ar") From c5f07dc672abee55a011dff92b66c31faafc596c Mon Sep 17 00:00:00 2001 From: Janek Mann Date: Mon, 11 Aug 2014 11:42:41 +0100 Subject: [PATCH 13/41] fix for NRF51822 linker script --- .../TOOLCHAIN_GCC_ARM/NRF51822.ld | 17 ++++++++--------- workspace_tools/toolchains/gcc.py | 5 +---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/NRF51822.ld b/libraries/mbed/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/NRF51822.ld index e2d062ef7e5..43e0ac80dab 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/NRF51822.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/NRF51822.ld @@ -43,8 +43,8 @@ SECTIONS KEEP(*(.Vectors)) *(.text*) - *(.init) - *(.fini) + KEEP(*(.init)) + KEEP(*(.fini)) /* .ctors */ *crtbegin.o(.ctors) @@ -62,7 +62,7 @@ SECTIONS *(.rodata*) - *(.eh_frame*) + KEEP(*(.eh_frame*)) } > FLASH @@ -89,22 +89,22 @@ SECTIONS . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); - *(.preinit_array) + KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); - *(SORT(.init_array.*)) - *(.init_array) + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); - *(SORT(.fini_array.*)) - *(.fini_array) + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); *(.jcr) @@ -149,4 +149,3 @@ SECTIONS /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } - diff --git a/workspace_tools/toolchains/gcc.py b/workspace_tools/toolchains/gcc.py index ab422562662..c42f1828eee 100644 --- a/workspace_tools/toolchains/gcc.py +++ b/workspace_tools/toolchains/gcc.py @@ -75,10 +75,7 @@ def __init__(self, target, options=None, notify=None, macros=None, tool_path="") self.cc = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "-std=gnu99", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cppc.replace('\\', '/'), "-std=gnu++98", "-fno-rtti", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags - if target.name in ["NRF51822"]: - self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--wrap,main"] + self.cpu - else: - self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu + self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"] self.ar = join(tool_path, "arm-none-eabi-ar") From 4357cdb2292988080e613cb204c03b685b5047ce Mon Sep 17 00:00:00 2001 From: Janek Mann Date: Mon, 11 Aug 2014 11:51:58 +0100 Subject: [PATCH 14/41] adding --gc-sections back in to the template --- workspace_tools/export/gcc_arm_nrf51822.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace_tools/export/gcc_arm_nrf51822.tmpl b/workspace_tools/export/gcc_arm_nrf51822.tmpl index b9b6425dd21..823298e9d13 100644 --- a/workspace_tools/export/gcc_arm_nrf51822.tmpl +++ b/workspace_tools/export/gcc_arm_nrf51822.tmpl @@ -23,7 +23,7 @@ CPU = -mcpu=cortex-m0 -mthumb CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections CC_SYMBOLS = {% for s in symbols %}-D{{s}} {% endfor %} -LD_FLAGS = -mcpu=cortex-m0 -mthumb -Wl,--wrap=main --specs=nano.specs -u _printf_float -u _scanf_float +LD_FLAGS = -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -Wl,--wrap=main --specs=nano.specs -u _printf_float -u _scanf_float LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys ifeq ($(DEBUG), 1) From beaec030410f19fecb6a361292cc52f405a5a61d Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Mon, 11 Aug 2014 15:14:20 +0100 Subject: [PATCH 15/41] Compile LPC1549 with GCC_ARM under Travis --- workspace_tools/build_travis.py | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace_tools/build_travis.py b/workspace_tools/build_travis.py index 50a6faf1302..c6d0f6f321a 100644 --- a/workspace_tools/build_travis.py +++ b/workspace_tools/build_travis.py @@ -49,6 +49,7 @@ { "target": "K64F", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] }, { "target": "LPC4088", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] }, { "target": "ARCH_PRO", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] }, + { "target": "LPC1549", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] }, ) ################################################################################ From c8704284bd73463dba634f58c8a43b2d378e628b Mon Sep 17 00:00:00 2001 From: Yihui Xiong Date: Tue, 12 Aug 2014 11:48:06 +0800 Subject: [PATCH 16/41] add DISCO_F407VG's uvision support --- .../TOOLCHAIN_ARM_STD/STM32F407.sct | 17 + .../TOOLCHAIN_ARM_STD/startup_STM32F40x.s | 369 +++++++++++++++ .../TOOLCHAIN_ARM_STD/sys.cpp | 31 ++ workspace_tools/build_release.py | 3 +- workspace_tools/export/uvision4.py | 1 + .../export/uvision4_disco_f407vg.uvopt.tmpl | 210 +++++++++ .../export/uvision4_disco_f407vg.uvproj.tmpl | 425 ++++++++++++++++++ workspace_tools/targets.py | 2 +- 8 files changed, 1056 insertions(+), 2 deletions(-) create mode 100755 libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/STM32F407.sct create mode 100755 libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/startup_STM32F40x.s create mode 100755 libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/sys.cpp create mode 100755 workspace_tools/export/uvision4_disco_f407vg.uvopt.tmpl create mode 100755 workspace_tools/export/uvision4_disco_f407vg.uvproj.tmpl diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/STM32F407.sct b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/STM32F407.sct new file mode 100755 index 00000000000..acffd8ae004 --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/STM32F407.sct @@ -0,0 +1,17 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00100000 { ; load region size_region + ER_IROM1 0x08000000 0x00100000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x10000000 0x00010000 { ; CCM + } + RW_IRAM2 0x20000188 0x0001FE78 { + .ANY (+RW +ZI) + } +} + diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/startup_STM32F40x.s b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/startup_STM32F40x.s new file mode 100755 index 00000000000..60ac114a64e --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/startup_STM32F40x.s @@ -0,0 +1,369 @@ +;/***************************************************************************** +; * @file: startup_STM32F40x.s +; * @purpose: CMSIS Cortex-M4 Core Device Startup File +; * for the ST STM32F40x Device Series +; * @version: V1.20 +; * @date: 16. January 2012 +; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +; * +; * Copyright (C) 2012 ARM Limited. All rights reserved. +; * ARM Limited (ARM) is supplying this software for use with Cortex-M4 +; * processor based microcontrollers. This file can be freely distributed +; * within development tools that are supporting such ARM based processors. +; * +; * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR +; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. +; * +; *****************************************************************************/ + + + +__initial_sp EQU 0x20020000 ; Top of RAM from LPC4088 + + PRESERVE8 + THUMB + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + DCD WWDG_IRQHandler ; Window WatchDog + DCD PVD_IRQHandler ; PVD through EXTI Line detection + DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line + DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line + DCD FLASH_IRQHandler ; FLASH + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line0 + DCD EXTI1_IRQHandler ; EXTI Line1 + DCD EXTI2_IRQHandler ; EXTI Line2 + DCD EXTI3_IRQHandler ; EXTI Line3 + DCD EXTI4_IRQHandler ; EXTI Line4 + DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 + DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 + DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 + DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 + DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 + DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 + DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 + DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s + DCD CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; External Line[9:5]s + DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 + DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 + DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; External Line[15:10]s + DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line + DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line + DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12 + DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13 + DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14 + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare + DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 + DCD FSMC_IRQHandler ; FSMC + DCD SDIO_IRQHandler ; SDIO + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 + DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 + DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 + DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 + DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 + DCD ETH_IRQHandler ; Ethernet + DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line + DCD CAN2_TX_IRQHandler ; CAN2 TX + DCD CAN2_RX0_IRQHandler ; CAN2 RX0 + DCD CAN2_RX1_IRQHandler ; CAN2 RX1 + DCD CAN2_SCE_IRQHandler ; CAN2 SCE + DCD OTG_FS_IRQHandler ; USB OTG FS + DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 + DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 + DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 + DCD USART6_IRQHandler ; USART6 + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out + DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In + DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI + DCD OTG_HS_IRQHandler ; USB OTG HS + DCD DCMI_IRQHandler ; DCMI + DCD CRYP_IRQHandler ; CRYP crypto + DCD HASH_RNG_IRQHandler ; Hash and Rng + DCD FPU_IRQHandler ; FPU + + + AREA |.text|, CODE, READONLY + + +; Reset Handler + +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + LDR R0, =SystemInit + 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 +MemManage_Handler\ + PROC + EXPORT MemManage_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 +DebugMon_Handler\ + PROC + EXPORT DebugMon_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 WWDG_IRQHandler [WEAK] + EXPORT PVD_IRQHandler [WEAK] + EXPORT TAMP_STAMP_IRQHandler [WEAK] + EXPORT RTC_WKUP_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Stream0_IRQHandler [WEAK] + EXPORT DMA1_Stream1_IRQHandler [WEAK] + EXPORT DMA1_Stream2_IRQHandler [WEAK] + EXPORT DMA1_Stream3_IRQHandler [WEAK] + EXPORT DMA1_Stream4_IRQHandler [WEAK] + EXPORT DMA1_Stream5_IRQHandler [WEAK] + EXPORT DMA1_Stream6_IRQHandler [WEAK] + EXPORT ADC_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM10_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT OTG_FS_WKUP_IRQHandler [WEAK] + EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK] + EXPORT TIM8_UP_TIM13_IRQHandler [WEAK] + EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK] + EXPORT TIM8_CC_IRQHandler [WEAK] + EXPORT DMA1_Stream7_IRQHandler [WEAK] + EXPORT FSMC_IRQHandler [WEAK] + EXPORT SDIO_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Stream0_IRQHandler [WEAK] + EXPORT DMA2_Stream1_IRQHandler [WEAK] + EXPORT DMA2_Stream2_IRQHandler [WEAK] + EXPORT DMA2_Stream3_IRQHandler [WEAK] + EXPORT DMA2_Stream4_IRQHandler [WEAK] + EXPORT ETH_IRQHandler [WEAK] + EXPORT ETH_WKUP_IRQHandler [WEAK] + EXPORT CAN2_TX_IRQHandler [WEAK] + EXPORT CAN2_RX0_IRQHandler [WEAK] + EXPORT CAN2_RX1_IRQHandler [WEAK] + EXPORT CAN2_SCE_IRQHandler [WEAK] + EXPORT OTG_FS_IRQHandler [WEAK] + EXPORT DMA2_Stream5_IRQHandler [WEAK] + EXPORT DMA2_Stream6_IRQHandler [WEAK] + EXPORT DMA2_Stream7_IRQHandler [WEAK] + EXPORT USART6_IRQHandler [WEAK] + EXPORT I2C3_EV_IRQHandler [WEAK] + EXPORT I2C3_ER_IRQHandler [WEAK] + EXPORT OTG_HS_EP1_OUT_IRQHandler [WEAK] + EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK] + EXPORT OTG_HS_WKUP_IRQHandler [WEAK] + EXPORT OTG_HS_IRQHandler [WEAK] + EXPORT DCMI_IRQHandler [WEAK] + EXPORT CRYP_IRQHandler [WEAK] + EXPORT HASH_RNG_IRQHandler [WEAK] + EXPORT FPU_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_IRQHandler +TAMP_STAMP_IRQHandler +RTC_WKUP_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Stream0_IRQHandler +DMA1_Stream1_IRQHandler +DMA1_Stream2_IRQHandler +DMA1_Stream3_IRQHandler +DMA1_Stream4_IRQHandler +DMA1_Stream5_IRQHandler +DMA1_Stream6_IRQHandler +ADC_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM9_IRQHandler +TIM1_UP_TIM10_IRQHandler +TIM1_TRG_COM_TIM11_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTC_Alarm_IRQHandler +OTG_FS_WKUP_IRQHandler +TIM8_BRK_TIM12_IRQHandler +TIM8_UP_TIM13_IRQHandler +TIM8_TRG_COM_TIM14_IRQHandler +TIM8_CC_IRQHandler +DMA1_Stream7_IRQHandler +FSMC_IRQHandler +SDIO_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler +DMA2_Stream0_IRQHandler +DMA2_Stream1_IRQHandler +DMA2_Stream2_IRQHandler +DMA2_Stream3_IRQHandler +DMA2_Stream4_IRQHandler +ETH_IRQHandler +ETH_WKUP_IRQHandler +CAN2_TX_IRQHandler +CAN2_RX0_IRQHandler +CAN2_RX1_IRQHandler +CAN2_SCE_IRQHandler +OTG_FS_IRQHandler +DMA2_Stream5_IRQHandler +DMA2_Stream6_IRQHandler +DMA2_Stream7_IRQHandler +USART6_IRQHandler +I2C3_EV_IRQHandler +I2C3_ER_IRQHandler +OTG_HS_EP1_OUT_IRQHandler +OTG_HS_EP1_IN_IRQHandler +OTG_HS_WKUP_IRQHandler +OTG_HS_IRQHandler +DCMI_IRQHandler +CRYP_IRQHandler +HASH_RNG_IRQHandler +FPU_IRQHandler + + B . + + ENDP + + + ALIGN + END diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/sys.cpp b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/sys.cpp new file mode 100755 index 00000000000..2f1024ace8b --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_DISCO_F407VG/TOOLCHAIN_ARM_STD/sys.cpp @@ -0,0 +1,31 @@ +/* mbed Microcontroller Library - stackheap + * Copyright (C) 2009-2011 ARM Limited. All rights reserved. + * + * Setup a fixed single stack/heap memory model, + * between the top of the RW/ZI region and the stackpointer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +extern char Image$$RW_IRAM1$$ZI$$Limit[]; + +extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) { + uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit; + uint32_t sp_limit = __current_sp(); + + zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned + + struct __initial_stackheap r; + r.heap_base = zi_limit; + r.heap_limit = sp_limit; + return r; +} + +#ifdef __cplusplus +} +#endif diff --git a/workspace_tools/build_release.py b/workspace_tools/build_release.py index fcf5e10b875..9e4bd5d6a7f 100755 --- a/workspace_tools/build_release.py +++ b/workspace_tools/build_release.py @@ -64,7 +64,8 @@ ('RBLAB_NRF51822', ('ARM', )), ('LPC11U68', ('uARM','GCC_ARM','GCC_CR')), - ('GHI_MBUINO', ('ARM', 'uARM', 'GCC_ARM')), + ('GHI_MBUINO', ('ARM', 'uARM', 'GCC_ARM')), + ('DISCO_F407VG', ('ARM', 'GCC_ARM')), ) diff --git a/workspace_tools/export/uvision4.py b/workspace_tools/export/uvision4.py index 467253d5e1c..f591b06f0b7 100644 --- a/workspace_tools/export/uvision4.py +++ b/workspace_tools/export/uvision4.py @@ -50,6 +50,7 @@ class Uvision4(Exporter): 'NRF51822', 'ARCH_PRO', 'ARCH_BLE', + 'DISCO_F407VG', ] USING_MICROLIB = [ diff --git a/workspace_tools/export/uvision4_disco_f407vg.uvopt.tmpl b/workspace_tools/export/uvision4_disco_f407vg.uvopt.tmpl new file mode 100755 index 00000000000..fc8c58653f8 --- /dev/null +++ b/workspace_tools/export/uvision4_disco_f407vg.uvopt.tmpl @@ -0,0 +1,210 @@ + + + + 1.0 + +
    ### uVision Project, (C) Keil Software
    + + + *.c + *.s*; *.src; *.a* + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + + + + 0 + 0 + + + + STM32F407 + 0x4 + ARM-ADS + + 25000000 + + 1 + 1 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + + 0 + Datasheet + DATASHTS\ST\STM32F4xx\DM00037051.pdf + + + 1 + Reference Manual + DATASHTS\ST\STM32F4xx\DM00031020.pdf + + + 2 + Technical Reference Manual + datashts\arm\cortex_m4\r0p1\DDI0439C_CORTEX_M4_R0P1_TRM.PDF + + + 3 + Generic User Guide + datashts\arm\cortex_m4\r0p1\DUI0553A_CORTEX_M4_DGUG.PDF + + + + SARMCM3.DLL + -MPU -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 13 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + CMSIS_AGDI + -X"MBED CMSIS-DAP" -UA000000001 -O4559 -S0 -C0 -P00 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -FO15 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000 + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + + + + + + + + src + 1 + 0 + 0 + 0 + + 1 + 1 + 8 + 0 + 0 + 1 + 0 + 1 + 18 + 0 + main.cpp + main.cpp + 0 + 0 + + + +
    diff --git a/workspace_tools/export/uvision4_disco_f407vg.uvproj.tmpl b/workspace_tools/export/uvision4_disco_f407vg.uvproj.tmpl new file mode 100755 index 00000000000..088f28a06c3 --- /dev/null +++ b/workspace_tools/export/uvision4_disco_f407vg.uvproj.tmpl @@ -0,0 +1,425 @@ + + + + 1.1 + +
    ###This file was automagically generated by mbed.org. For more information, see http://mbed.org/handbook/Exporting-To-Uvision
    + + + + STM32F407 + 0x4 + ARM-ADS + + + STM32F407VG + STMicroelectronics + IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\ST\STM32F4xx\startup_stm32f4xx.s" ("STM32F4xx Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024 -FS08000000 -FL0100000) + 6103 + stm32f4xx.h + + + + + + + + + + SFD\ST\STM32F4xx\STM32F40x.sfr + 0 + + + + ST\STM32F4xx\ + ST\STM32F4xx\ + + 0 + 0 + 0 + 0 + 1 + + .\build\ + {{name}} + 1 + 0 + 0 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + 0 + fromelf --bin -o build\{{name}}_STM32F407.bin build\{{name}}.axf + + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + + + SARMCM3.DLL + -MPU -REMAP + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + + 0 + 13 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4105 + + BIN\CMSIS_AGDI.dll + "" () + + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + --gnu + {% for s in symbols %} {{s}}, {% endfor %} + + {% for path in include_paths %} {{path}}; {% endfor %} + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x10000000 + {{scatter_file}} + + + + {% for file in object_files %} + {{file}} + {% endfor %} + --any_placement=first_fit + + + + + + + + {% for group,files in source_files %} + + {{group}} + + {% for file in files %} + + {{file.name}} + {{file.type}} + {{file.path}} + {%if file.type == "1" %} + + + + + --c99 + + + + + {% endif %} + + {% endfor %} + + + {% endfor %} + + + + +
    diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 199d7b36850..a4ba53964e7 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -499,7 +499,7 @@ def __init__(self): Target.__init__(self) self.core = "Cortex-M4F" self.extra_labels = ['STM', 'STM32F4', 'STM32F407', 'STM32F407VG'] - self.supported_toolchains = ["GCC_ARM"] + self.supported_toolchains = ["ARM", "GCC_ARM"] self.default_toolchain = "uARM" From 25926ae75d07958810b24cc3ec116fbdbd0b3bfc Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Tue, 12 Aug 2014 14:59:50 +0100 Subject: [PATCH 17/41] Re-implemented LPC patching step Now implemented as a 'post binary hook'. Targets that need this will have to inherit from LPCTarget instead of Target, the rest should be automatic (but see LPC4088 for an exception (currently, hooks can't be chained automatically)) --- workspace_tools/targets.py | 105 ++++++++++++++----------- workspace_tools/toolchains/__init__.py | 4 - workspace_tools/toolchains/gcc.py | 2 + workspace_tools/toolchains/iar.py | 2 + 4 files changed, 63 insertions(+), 50 deletions(-) diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index ea48c6dbd76..6352cbee2ad 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -26,7 +26,7 @@ import os import shutil - +from workspace_tools.patch import patch class Target: def __init__(self): @@ -59,35 +59,47 @@ def get_labels(self): def init_hooks(self, hook, toolchain_name): pass - -class LPC2368(Target): +# This class implements the post-link patching step needed by LPC targets +class LPCTarget(Target): def __init__(self): Target.__init__(self) + + def init_hooks(self, hook, toolchain_name): + hook.hook_add_binary("post", self.lpc_patch) + + @staticmethod + def lpc_patch(t_self, resources, elf, binf): + t_self.debug("LPC Patch: %s" % os.path.split(binf)[1]) + patch(binf) + +class LPC2368(LPCTarget): + def __init__(self): + LPCTarget.__init__(self) self.core = "ARM7TDMI-S" self.extra_labels = ['NXP', 'LPC23XX'] self.supported_toolchains = ["ARM", "GCC_ARM", "GCC_CR"] -class LPC1768(Target): +class LPC1768(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC176X', 'MBED_LPC1768'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CS", "GCC_CR", "IAR"] -class LPC11U24(Target): +class LPC11U24(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX', 'LPC11U24_401'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM"] self.default_toolchain = "uARM" -class LPC11U24_301(Target): +class LPC11U24_301(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM"] @@ -145,9 +157,9 @@ def __init__(self): self.default_toolchain = "ARM" -class LPC812(Target): +class LPC812(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0+" self.extra_labels = ['NXP', 'LPC81X'] self.supported_toolchains = ["uARM"] @@ -156,9 +168,9 @@ def __init__(self): self.is_disk_virtual = True -class LPC810(Target): +class LPC810(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0+" self.extra_labels = ['NXP', 'LPC81X'] self.supported_toolchains = ["uARM"] @@ -166,9 +178,9 @@ def __init__(self): self.is_disk_virtual = True -class LPC4088(Target): +class LPC4088(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M4F" self.extra_labels = ['NXP', 'LPC408X'] self.supported_toolchains = ["ARM", "GCC_CR", "GCC_ARM"] @@ -182,6 +194,7 @@ def init_hooks(self, hook, toolchain_name): def binary_hook(t_self, resources, elf, binf): if not os.path.isdir(binf): # Regular binary file, nothing to do + LPCTarget.lpc_patch(t_self, resources, elf, binf) return outbin = open(binf + ".temp", "wb") partf = open(os.path.join(binf, "ER_IROM1"), "rb") @@ -205,27 +218,27 @@ def binary_hook(t_self, resources, elf, binf): shutil.rmtree(binf, True) os.rename(binf + '.temp', binf) t_self.debug("Generated custom binary file (internal flash + SPIFI)") + LPCTarget.lpc_patch(t_self, resources, elf, binf) - -class LPC4330_M4(Target): +class LPC4330_M4(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M4F" self.extra_labels = ['NXP', 'LPC43XX'] self.supported_toolchains = ["ARM", "GCC_CR", "IAR", "GCC_ARM"] -class LPC4330_M0(Target): +class LPC4330_M0(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC43XX'] self.supported_toolchains = ["ARM", "GCC_CR", "IAR"] -class LPC1800(Target): +class LPC1800(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC43XX'] self.supported_toolchains = ["ARM", "GCC_CR", "IAR"] @@ -338,61 +351,61 @@ def __init__(self): self.default_toolchain = "uARM" -class LPC1347(Target): +class LPC1347(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC13XX'] self.supported_toolchains = ["ARM", "GCC_ARM"] -class LPC1114(Target): +class LPC1114(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11XX_11CXX', 'LPC11XX'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] self.default_toolchain = "uARM" -class LPC11C24(Target): +class LPC11C24(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11XX_11CXX', 'LPC11CXX'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM"] -class LPC11U35_401(Target): +class LPC11U35_401(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] self.default_toolchain = "uARM" -class LPC11U35_501(Target): +class LPC11U35_501(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX', 'MCU_LPC11U35_501'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] self.default_toolchain = "uARM" -class LPC11U37_501(Target): +class LPC11U37_501(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] self.default_toolchain = "uARM" -class UBLOX_C027(Target): +class UBLOX_C027(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC176X'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CS", "GCC_CR", "IAR"] @@ -456,9 +469,9 @@ def binary_hook(t_self, resources, elf, binf): sdh.tofile(f, format='hex') -class LPC1549(Target): +class LPC1549(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC15XX'] self.supported_toolchains = ["uARM", "GCC_CR", "GCC_ARM"] @@ -466,9 +479,9 @@ def __init__(self): self.supported_form_factors = ["ARDUINO"] -class LPC11U68(Target): +class LPC11U68(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0+" self.extra_labels = ['NXP', 'LPC11U6X'] self.supported_toolchains = ["uARM", "GCC_CR", "GCC_ARM"] @@ -512,9 +525,9 @@ def __init__(self): self.default_toolchain = "uARM" -class XADOW_M0(Target): +class XADOW_M0(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX', 'MCU_LPC11U35_501'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] @@ -528,9 +541,9 @@ def __init__(self): self.supported_form_factors = ["ARDUINO"] -class ARCH_PRO(Target): +class ARCH_PRO(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M3" self.extra_labels = ['NXP', 'LPC176X'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CS", "GCC_CR", "IAR"] @@ -538,9 +551,9 @@ def __init__(self): self.supported_form_factors = ["ARDUINO"] -class ARCH_GPRS(Target): +class ARCH_GPRS(LPCTarget): def __init__(self): - Target.__init__(self) + LPCTarget.__init__(self) self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX', 'LPC11U37_501'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] diff --git a/workspace_tools/toolchains/__init__.py b/workspace_tools/toolchains/__init__.py index 1f0d382c504..acc6d730b2d 100644 --- a/workspace_tools/toolchains/__init__.py +++ b/workspace_tools/toolchains/__init__.py @@ -639,10 +639,6 @@ def link_program(self, r, tmp_path, name): self.binary(r, elf, bin) - if self.target.name.startswith('LPC'): - self.debug("LPC Patch: %s" % filename) - patch(bin) - self.var("compile_succeded", True) self.var("binary", filename) diff --git a/workspace_tools/toolchains/gcc.py b/workspace_tools/toolchains/gcc.py index c42f1828eee..50dc17b279d 100644 --- a/workspace_tools/toolchains/gcc.py +++ b/workspace_tools/toolchains/gcc.py @@ -20,6 +20,7 @@ from workspace_tools.toolchains import mbedToolchain from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH from workspace_tools.settings import GOANNA_PATH +from workspace_tools.hooks import hook_tool class GCC(mbedToolchain): LINKER_EXT = '.ld' @@ -163,6 +164,7 @@ def link(self, output, objects, libraries, lib_dirs, mem_map): self.default_cmd(self.hook.get_cmdline_linker(self.ld + ["-T%s" % mem_map, "-o", output] + objects + ["-L%s" % L for L in lib_dirs] + libs)) + @hook_tool def binary(self, resources, elf, bin): self.default_cmd(self.hook.get_cmdline_binary([self.elf2bin, "-O", "binary", elf, bin])) diff --git a/workspace_tools/toolchains/iar.py b/workspace_tools/toolchains/iar.py index c843e92f5c0..810dd000be4 100644 --- a/workspace_tools/toolchains/iar.py +++ b/workspace_tools/toolchains/iar.py @@ -21,6 +21,7 @@ from workspace_tools.toolchains import mbedToolchain from workspace_tools.settings import IAR_PATH from workspace_tools.settings import GOANNA_PATH +from workspace_tools.hooks import hook_tool class IAR(mbedToolchain): LIBRARY_EXT = '.a' @@ -106,5 +107,6 @@ def link(self, output, objects, libraries, lib_dirs, mem_map): args = [self.ld, "-o", output, "--config", mem_map] self.default_cmd(self.hook.get_cmdline_linker(args + objects + libraries)) + @hook_tool def binary(self, resources, elf, bin): self.default_cmd(self.hook.get_cmdline_binary([self.elf2bin, '--bin', elf, bin])) From c2327523bd093282707d42705b364a71db73250d Mon Sep 17 00:00:00 2001 From: jesusalvarez Date: Tue, 12 Aug 2014 19:25:25 -0400 Subject: [PATCH 18/41] LP4330_M4 i2c/spi update --- .../hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c | 11 +-- .../TARGET_NXP/TARGET_LPC43XX/serial_api.c | 72 ++++++++++--------- .../hal/TARGET_NXP/TARGET_LPC43XX/spi_api.c | 67 +++++++++-------- 3 files changed, 83 insertions(+), 67 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c index 4d4747fc454..27c8f018b1b 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c @@ -20,17 +20,20 @@ #include "pinmap.h" #include "error.h" +// SCU mode for I2C SCL/SDA pins +#define SCU_PINIO_I2C SCU_PINIO_PULLNONE + static const PinMap PinMap_I2C_SDA[] = { {P_DED, I2C_0, 0}, - {P2_3, I2C_1, 1}, - {PE_13, I2C_1, 2}, + {P2_3, I2C_1, (SCU_PINIO_I2C | 1)}, + {PE_13, I2C_1, (SCU_PINIO_I2C | 2)}, {NC, NC, 0} }; static const PinMap PinMap_I2C_SCL[] = { {P_DED, I2C_0, 0}, - {P2_4, I2C_1, 1}, - {PE_14, I2C_1, 2}, + {P2_4, I2C_1, (SCU_PINIO_I2C | 1)}, + {PE_14, I2C_1, (SCU_PINIO_I2C | 2)}, {NC, NC, 0} }; diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/serial_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/serial_api.c index ed3df6eab7d..997581e552c 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/serial_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/serial_api.c @@ -31,45 +31,49 @@ ******************************************************************************/ #define UART_NUM 4 +// SCU mode for UART pins +#define SCU_PINIO_UART_TX SCU_MODE_PULLDOWN +#define SCU_PINIO_UART_RX SCU_PINIO_PULLNONE + static const PinMap PinMap_UART_TX[] = { - {P1_13, UART_1, (SCU_MODE_PULLDOWN | 1)}, - {P1_15, UART_2, (SCU_MODE_PULLDOWN | 1)}, - {P2_0, UART_0, (SCU_MODE_PULLDOWN | 1)}, - {P2_3, UART_3, (SCU_MODE_PULLDOWN | 2)}, - {P2_10, UART_2, (SCU_MODE_PULLDOWN | 2)}, - {P3_4, UART_1, (SCU_MODE_PULLDOWN | 4)}, - {P4_1, UART_3, (SCU_MODE_PULLDOWN | 6)}, - {P5_6, UART_1, (SCU_MODE_PULLDOWN | 4)}, - {P6_4, UART_0, (SCU_MODE_PULLDOWN | 2)}, - {P7_1, UART_2, (SCU_MODE_PULLDOWN | 6)}, - {P9_3, UART_3, (SCU_MODE_PULLDOWN | 7)}, - {P9_5, UART_0, (SCU_MODE_PULLDOWN | 7)}, - {PA_1, UART_2, (SCU_MODE_PULLDOWN | 3)}, - {PC_13, UART_1, (SCU_MODE_PULLDOWN | 2)}, - {PE_11, UART_1, (SCU_MODE_PULLDOWN | 2)}, - {PF_2, UART_3, (SCU_MODE_PULLDOWN | 1)}, - {PF_10, UART_0, (SCU_MODE_PULLDOWN | 1)}, + {P1_13, UART_1, (SCU_PINIO_UART_TX | 1)}, + {P1_15, UART_2, (SCU_PINIO_UART_TX | 1)}, + {P2_0, UART_0, (SCU_PINIO_UART_TX | 1)}, + {P2_3, UART_3, (SCU_PINIO_UART_TX | 2)}, + {P2_10, UART_2, (SCU_PINIO_UART_TX | 2)}, + {P3_4, UART_1, (SCU_PINIO_UART_TX | 4)}, + {P4_1, UART_3, (SCU_PINIO_UART_TX | 6)}, + {P5_6, UART_1, (SCU_PINIO_UART_TX | 4)}, + {P6_4, UART_0, (SCU_PINIO_UART_TX | 2)}, + {P7_1, UART_2, (SCU_PINIO_UART_TX | 6)}, + {P9_3, UART_3, (SCU_PINIO_UART_TX | 7)}, + {P9_5, UART_0, (SCU_PINIO_UART_TX | 7)}, + {PA_1, UART_2, (SCU_PINIO_UART_TX | 3)}, + {PC_13, UART_1, (SCU_PINIO_UART_TX | 2)}, + {PE_11, UART_1, (SCU_PINIO_UART_TX | 2)}, + {PF_2, UART_3, (SCU_PINIO_UART_TX | 1)}, + {PF_10, UART_0, (SCU_PINIO_UART_TX | 1)}, {NC, NC, 0} }; static const PinMap PinMap_UART_RX[] = { - {P1_14, UART_1, (SCU_PINIO_PULLNONE | 1)}, - {P1_16, UART_2, (SCU_PINIO_PULLNONE | 1)}, - {P2_1, UART_0, (SCU_PINIO_PULLNONE | 1)}, - {P2_4, UART_3, (SCU_PINIO_PULLNONE | 2)}, - {P2_11, UART_2, (SCU_PINIO_PULLNONE | 2)}, - {P3_5, UART_1, (SCU_PINIO_PULLNONE | 4)}, - {P4_2, UART_3, (SCU_PINIO_PULLNONE | 6)}, - {P5_7, UART_1, (SCU_PINIO_PULLNONE | 4)}, - {P6_5, UART_0, (SCU_PINIO_PULLNONE | 2)}, - {P7_2, UART_2, (SCU_PINIO_PULLNONE | 6)}, - {P9_4, UART_3, (SCU_PINIO_PULLNONE | 7)}, - {P9_6, UART_0, (SCU_PINIO_PULLNONE | 7)}, - {PA_2, UART_2, (SCU_PINIO_PULLNONE | 3)}, - {PC_14, UART_1, (SCU_PINIO_PULLNONE | 2)}, - {PE_12, UART_1, (SCU_PINIO_PULLNONE | 2)}, - {PF_3, UART_3, (SCU_PINIO_PULLNONE | 1)}, - {PF_11, UART_0, (SCU_PINIO_PULLNONE | 1)}, + {P1_14, UART_1, (SCU_PINIO_UART_RX | 1)}, + {P1_16, UART_2, (SCU_PINIO_UART_RX | 1)}, + {P2_1, UART_0, (SCU_PINIO_UART_RX | 1)}, + {P2_4, UART_3, (SCU_PINIO_UART_RX | 2)}, + {P2_11, UART_2, (SCU_PINIO_UART_RX | 2)}, + {P3_5, UART_1, (SCU_PINIO_UART_RX | 4)}, + {P4_2, UART_3, (SCU_PINIO_UART_RX | 6)}, + {P5_7, UART_1, (SCU_PINIO_UART_RX | 4)}, + {P6_5, UART_0, (SCU_PINIO_UART_RX | 2)}, + {P7_2, UART_2, (SCU_PINIO_UART_RX | 6)}, + {P9_4, UART_3, (SCU_PINIO_UART_RX | 7)}, + {P9_6, UART_0, (SCU_PINIO_UART_RX | 7)}, + {PA_2, UART_2, (SCU_PINIO_UART_RX | 3)}, + {PC_14, UART_1, (SCU_PINIO_UART_RX | 2)}, + {PE_12, UART_1, (SCU_PINIO_UART_RX | 2)}, + {PF_3, UART_3, (SCU_PINIO_UART_RX | 1)}, + {PF_11, UART_0, (SCU_PINIO_UART_RX | 1)}, {NC, NC, 0} }; diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/spi_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/spi_api.c index e510f66d33e..d5818cc97ec 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/spi_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC43XX/spi_api.c @@ -23,48 +23,51 @@ #include "pinmap.h" #include "error.h" +// SCU mode for SPI pins +#define SCU_PINIO_SPI SCU_PINIO_FAST + static const PinMap PinMap_SPI_SCLK[] = { - {P1_19, SPI_1, (SCU_PINIO_FAST | 1)}, - {P3_0, SPI_0, (SCU_PINIO_FAST | 4)}, - {P3_3, SPI_0, (SCU_PINIO_FAST | 2)}, - {PF_0, SPI_0, (SCU_PINIO_FAST | 0)}, - {PF_4, SPI_1, (SCU_PINIO_FAST | 0)}, + {P1_19, SPI_1, (SCU_PINIO_SPI | 1)}, + {P3_0, SPI_0, (SCU_PINIO_SPI | 4)}, + {P3_3, SPI_0, (SCU_PINIO_SPI | 2)}, + {PF_0, SPI_0, (SCU_PINIO_SPI | 0)}, + {PF_4, SPI_1, (SCU_PINIO_SPI | 0)}, {NC, NC, 0} }; static const PinMap PinMap_SPI_MOSI[] = { - {P0_1, SPI_1, (SCU_PINIO_FAST | 1)}, - {P1_2, SPI_0, (SCU_PINIO_FAST | 5)}, - {P1_4, SPI_1, (SCU_PINIO_FAST | 5)}, - {P3_7, SPI_0, (SCU_PINIO_FAST | 5)}, - {P3_8, SPI_0, (SCU_PINIO_FAST | 2)}, - {P9_2, SPI_0, (SCU_PINIO_FAST | 7)}, - {PF_3, SPI_0, (SCU_PINIO_FAST | 2)}, - {PF_7, SPI_1, (SCU_PINIO_FAST | 2)}, + {P0_1, SPI_1, (SCU_PINIO_SPI | 1)}, + {P1_2, SPI_0, (SCU_PINIO_SPI | 5)}, + {P1_4, SPI_1, (SCU_PINIO_SPI | 5)}, + {P3_7, SPI_0, (SCU_PINIO_SPI | 5)}, + {P3_8, SPI_0, (SCU_PINIO_SPI | 2)}, + {P9_2, SPI_0, (SCU_PINIO_SPI | 7)}, + {PF_3, SPI_0, (SCU_PINIO_SPI | 2)}, + {PF_7, SPI_1, (SCU_PINIO_SPI | 2)}, {NC, NC, 0} }; static const PinMap PinMap_SPI_MISO[] = { - {P0_0, SPI_1, (SCU_PINIO_FAST | 1)}, - {P1_1, SPI_0, (SCU_PINIO_FAST | 5)}, - {P1_3, SPI_1, (SCU_PINIO_FAST | 5)}, - {P3_6, SPI_0, (SCU_PINIO_FAST | 5)}, - {P3_7, SPI_0, (SCU_PINIO_FAST | 2)}, - {P9_1, SPI_0, (SCU_PINIO_FAST | 7)}, - {PF_2, SPI_0, (SCU_PINIO_FAST | 2)}, - {PF_6, SPI_1, (SCU_PINIO_FAST | 2)}, + {P0_0, SPI_1, (SCU_PINIO_SPI | 1)}, + {P1_1, SPI_0, (SCU_PINIO_SPI | 5)}, + {P1_3, SPI_1, (SCU_PINIO_SPI | 5)}, + {P3_6, SPI_0, (SCU_PINIO_SPI | 5)}, + {P3_7, SPI_0, (SCU_PINIO_SPI | 2)}, + {P9_1, SPI_0, (SCU_PINIO_SPI | 7)}, + {PF_2, SPI_0, (SCU_PINIO_SPI | 2)}, + {PF_6, SPI_1, (SCU_PINIO_SPI | 2)}, {NC, NC, 0} }; static const PinMap PinMap_SPI_SSEL[] = { - {P1_0, SPI_0, (SCU_PINIO_FAST | 5)}, - {P1_5, SPI_1, (SCU_PINIO_FAST | 5)}, - {P1_20, SPI_1, (SCU_PINIO_FAST | 2)}, - {P3_6, SPI_0, (SCU_PINIO_FAST | 2)}, - {P3_8, SPI_0, (SCU_PINIO_FAST | 5)}, - {P9_0, SPI_0, (SCU_PINIO_FAST | 7)}, - {PF_1, SPI_0, (SCU_PINIO_FAST | 2)}, - {PF_5, SPI_1, (SCU_PINIO_FAST | 2)}, + {P1_0, SPI_0, (SCU_PINIO_SPI | 5)}, + {P1_5, SPI_1, (SCU_PINIO_SPI | 5)}, + {P1_20, SPI_1, (SCU_PINIO_SPI | 2)}, + {P3_6, SPI_0, (SCU_PINIO_SPI | 2)}, + {P3_8, SPI_0, (SCU_PINIO_SPI | 5)}, + {P9_0, SPI_0, (SCU_PINIO_SPI | 7)}, + {PF_1, SPI_0, (SCU_PINIO_SPI | 2)}, + {PF_5, SPI_1, (SCU_PINIO_SPI | 2)}, {NC, NC, 0} }; @@ -82,6 +85,12 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel obj->spi = (LPC_SSP_T*)pinmap_merge(spi_data, spi_cntl); MBED_ASSERT((int)obj->spi != NC); + + // enable clocking + switch ((int)obj->spi) { + case SPI_0: LPC_CGU->BASE_CLK[CLK_BASE_SSP0] = (1 << 11) | (CLKIN_MAINPLL << 24); break; + case SPI_1: LPC_CGU->BASE_CLK[CLK_BASE_SSP1] = (1 << 11) | (CLKIN_MAINPLL << 24); break; + } // set default format and frequency if (ssel == NC) { From cde156cadc0561a6129ec7c345687744b001208d Mon Sep 17 00:00:00 2001 From: Alexander Valitov Date: Wed, 13 Aug 2014 10:19:03 +0100 Subject: [PATCH 19/41] Added implementation for "rename" on FAT file system --- libraries/fs/fat/FATFileSystem.cpp | 9 +++++++++ libraries/fs/fat/FATFileSystem.h | 1 + libraries/mbed/common/retarget.cpp | 10 +++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/fs/fat/FATFileSystem.cpp b/libraries/fs/fat/FATFileSystem.cpp index fb0eb5253f9..da7e8e086f4 100644 --- a/libraries/fs/fat/FATFileSystem.cpp +++ b/libraries/fs/fat/FATFileSystem.cpp @@ -108,6 +108,15 @@ int FATFileSystem::remove(const char *filename) { return 0; } +int FATFileSystem::rename(const char *oldname, const char *newname) { + FRESULT res = f_rename(oldname, newname); + if (res) { + debug_if(FFS_DBG, "f_rename() failed: %d\n", res); + return -1; + } + return 0; +} + int FATFileSystem::format() { FRESULT res = f_mkfs(_fsid, 0, 512); // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) if (res) { diff --git a/libraries/fs/fat/FATFileSystem.h b/libraries/fs/fat/FATFileSystem.h index 1d8f56d9b58..0e1cc6355bd 100644 --- a/libraries/fs/fat/FATFileSystem.h +++ b/libraries/fs/fat/FATFileSystem.h @@ -41,6 +41,7 @@ class FATFileSystem : public FileSystemLike { virtual FileHandle *open(const char* name, int flags); virtual int remove(const char *filename); + virtual int rename(const char *oldname, const char *newname); virtual int format(); virtual DirHandle *opendir(const char *name); virtual int mkdir(const char *name, mode_t mode); diff --git a/libraries/mbed/common/retarget.cpp b/libraries/mbed/common/retarget.cpp index 57bf22f29ca..7362eddb3f9 100644 --- a/libraries/mbed/common/retarget.cpp +++ b/libraries/mbed/common/retarget.cpp @@ -323,7 +323,15 @@ extern "C" int remove(const char *path) { } extern "C" int rename(const char *oldname, const char *newname) { - return -1; + FilePath fpOld(oldname); + FilePath fpNew(newname); + FileSystemLike *fsOld = fpOld.fileSystem(); + FileSystemLike *fsNew = fpNew.fileSystem(); + + /* rename only if both files are on the same FS */ + if (fsOld != fsNew || fsOld == NULL) return -1; + + return fsOld->rename(fpOld.fileName(), fpNew.fileName()); } extern "C" char *tmpnam(char *s) { From 5947838b2b0d6664150bcf02d1c908c504ee98c7 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Fri, 8 Aug 2014 13:57:19 +0100 Subject: [PATCH 20/41] BUgfix: jobs (-j) value was not properly set in SingletestRunner class parameters --- workspace_tools/singletest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workspace_tools/singletest.py b/workspace_tools/singletest.py index 0620bbad716..90d123a0607 100644 --- a/workspace_tools/singletest.py +++ b/workspace_tools/singletest.py @@ -184,7 +184,8 @@ def get_version(): _opts_suppress_summary=opts.suppress_summary, _opts_test_x_toolchain_summary=opts.test_x_toolchain_summary, _opts_copy_method=opts.copy_method, - _opts_mut_reset_type=opts.mut_reset_type + _opts_mut_reset_type=opts.mut_reset_type, + _opts_jobs=opts.jobs ) # Runs test suite in CLI mode From 64640c88803b91c4a8ac6fd4089ca20d51adea57 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Fri, 8 Aug 2014 16:46:20 +0100 Subject: [PATCH 21/41] Feature: MPS2 reset functionality implementation (not finished and will not break current implementation) --- workspace_tools/host_tests/host_test.py | 9 ++++----- workspace_tools/test_api.py | 7 +++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/workspace_tools/host_tests/host_test.py b/workspace_tools/host_tests/host_test.py index 9f6f31de856..4cda45f1cd6 100644 --- a/workspace_tools/host_tests/host_test.py +++ b/workspace_tools/host_tests/host_test.py @@ -133,17 +133,16 @@ def safe_sendBreak(self, serial): return result def touch_file(self, path, name): - with os.open(path, 'a'): + with open(path, 'a'): os.utime(path, None) def reset(self): """ reboot.txt - startup from standby state, reboots when in run mode. shutdown.txt - shutdown from run mode reset.txt - reset fpga during run mode """ - if self.options.forced_reset_type: - path = os.path.join([self.disk, self.options.forced_reset_type.lower()]) - if self.options.forced_reset_type.endswith('.txt'): - self.touch_file(path) + if self.options.forced_reset_type and self.options.forced_reset_type.endswith('.txt'): + reset_file_path = os.path.join(self.disk, self.options.forced_reset_type.lower()) + self.touch_file(reset_file_path) else: self.safe_sendBreak(self.serial) # Instead of serial.sendBreak() # Give time to wait for the image loading diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index c18eea0cc2e..900280f7e88 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -510,6 +510,7 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): disk = mut['disk'] port = mut['port'] + reset_type = mut.get('reset_type') target_by_mcu = TARGET_MAP[mut['mcu']] # Program @@ -552,8 +553,10 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): start_host_exec_time = time() host_test_verbose = self.opts_verbose_test_result_only or self.opts_verbose - host_test_reset = self.opts_mut_reset_type - single_test_result = self.run_host_test(test.host_test, disk, port, duration, verbose=host_test_verbose, reset=host_test_reset) + host_test_reset = self.opts_mut_reset_type if reset_type is None else reset_type + single_test_result = self.run_host_test(test.host_test, disk, port, duration, + verbose=host_test_verbose, + reset=host_test_reset) # Store test result test_all_result.append(single_test_result) From c1ebcb498b6d261b9ab45ade0ee62039b2c9de5b Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Mon, 11 Aug 2014 10:38:06 +0100 Subject: [PATCH 22/41] Simple indent for function call parameters --- workspace_tools/singletest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/workspace_tools/singletest.py b/workspace_tools/singletest.py index 90d123a0607..cbba6b610a4 100644 --- a/workspace_tools/singletest.py +++ b/workspace_tools/singletest.py @@ -185,8 +185,7 @@ def get_version(): _opts_test_x_toolchain_summary=opts.test_x_toolchain_summary, _opts_copy_method=opts.copy_method, _opts_mut_reset_type=opts.mut_reset_type, - _opts_jobs=opts.jobs - ) + _opts_jobs=opts.jobs) # Runs test suite in CLI mode singletest_in_cli_mode(single_test) From 0f8c5dc494bcc68b4c3bfa77f0d29b7e550ff03e Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Mon, 11 Aug 2014 10:41:58 +0100 Subject: [PATCH 23/41] MPS2: Added function which will modify image cfg. file for MPS2 board. Added skeleton for log functionality --- workspace_tools/test_api.py | 86 ++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 900280f7e88..66504e71d71 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -20,6 +20,7 @@ import os import re import json +import time import pprint import random import optparse @@ -35,10 +36,11 @@ from subprocess import Popen, PIPE, call # Imports related to mbed build api +from workspace_tools.tests import TESTS +from workspace_tools.tests import TEST_MAP from workspace_tools.paths import BUILD_DIR from workspace_tools.paths import HOST_TESTS -from workspace_tools.tests import TEST_MAP -from workspace_tools.tests import TESTS +from workspace_tools.utils import construct_enum from workspace_tools.targets import TARGET_MAP from workspace_tools.build_api import build_project, build_mbed_libs, build_lib from workspace_tools.build_api import get_target_supported_toolchains @@ -962,6 +964,86 @@ def singletest_in_cli_mode(single_test): print "Completed in %d sec"% (elapsed_time) +def mps2_check_board_image_file(disk, board_image_path, image0file_path, image_name='images.txt'): + """ This function will modify 'Versatile Express Images Configuration File' file + for Versatile Express V2M-MPS2 board. + Main goal of this function is to change number of images to 1, comment all + existing image entries and append at the end of file new entry with test. + """ + MBED_SDK_TEST_STAMP = 'test suite entry' + image_path = os.path.join(disk, board_image_path, image_name) + new_file_lines = [] # New configuration file lines (entries) + + # Check each line of the image configuration file + try: + with open(image_path, 'r') as file: + for line in file: + if re.search('^TOTALIMAGES', line): + # Check number of total images, should be 1 + new_file_lines.append(re.sub('^TOTALIMAGES:[\t ]*[\d]+', 'TOTALIMAGES: 1', line)) + pass + + elif re.search('; - %s[\n\r]*$'% MBED_SDK_TEST_STAMP, line): + # Look for test suite entries and remove them + pass # Omit all test suite entries + + elif re.search('^IMAGE[\d]+FILE', line): + # Check all image entries and mark the ';' + new_file_lines.append(';' + line) # Comment non test suite lines + else: + # Append line to new file + new_file_lines.append(line) + except IOError as e: + return False + + # Add new image entry with proper commented stamp + new_file_lines.append('IMAGE0FILE: %s ; - %s\r\n'% (image0file_path, MBED_SDK_TEST_STAMP)) + + # Write all lines to file + try: + with open(image_path, 'w') as file: + for line in new_file_lines: + file.write(line), + except IOError as e: + return False + + return True + + +class TestLogger(): + """ Super-class for logging and printing ongoing events for test suite pass """ + def __init__(self): + self.Log = [] + + self.LogType = construct_enum(INFO='Info', + NOTIF='Notification', + WARN='Warning', + ERROR='Error') + + self.LogToFileAttr = construct_enum(CREATE=1, # Create or overwrite existing log file + APPEND=2) # Append to existing log file + + def log_line(self, LogType, log_line, log_time=None): + log_timestamp = time.time() if log_time is None else log_time + log_entry = {'log_type' : LogType, + 'log_timestamp' : log_timestamp, + 'log_line' : log_line, + '_future' : None} + self.Log.append(log_entry) + + def log_to_file(self, LogToFileAttr, file_name): + """ Class will log to file current log entries. + Note: you should be able to see log file like this: + + tail -f log_file.txt + """ + pass + + +class CLITestLogger(TestLogger): + pass + + def get_default_test_options_parser(): """ Get common test script options used by CLI, webservices etc. """ parser = optparse.OptionParser() From 17c0132d56c1a2fc2a19f55c161fbcd043249b62 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 10:20:41 +0100 Subject: [PATCH 24/41] Added parts of functionality related to extra reset types, global timeout increments and image configuration file modifications --- workspace_tools/host_tests/host_test.py | 23 +++++++-- workspace_tools/singletest.py | 3 +- workspace_tools/test_api.py | 69 +++++++++++++++++++------ workspace_tools/test_webapi.py | 2 +- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/workspace_tools/host_tests/host_test.py b/workspace_tools/host_tests/host_test.py index 4cda45f1cd6..09a477357e8 100644 --- a/workspace_tools/host_tests/host_test.py +++ b/workspace_tools/host_tests/host_test.py @@ -63,8 +63,17 @@ def __init__(self): dest="forced_reset_type", help="Forces different type of reset") + parser.add_option("-R", "--reset-timeout", + dest="forced_reset_timeout", + metavar="NUMBER", + type="int", + help="When forcing a reset using option -r you can set up after reset timeout in seconds") + (self.options, _) = parser.parse_args() + self.DEFAULT_RESET_TOUT = 2 + self.DEFAULT_TOUT = 10 + if self.options.port is None: raise Exception("The serial port of the target mbed have to be provided as command line arguments") @@ -73,7 +82,7 @@ def __init__(self): self.extra_port = self.options.extra self.extra_serial = None self.serial = None - self.timeout = 10 if self.options.timeout is None else self.options.timeout + self.timeout = self.DEFAULT_TOUT if self.options.timeout is None else self.options.timeout print 'Mbed: "%s" "%s"' % (self.port, self.disk) def init_serial(self, baud=9600, extra_baud=9600): @@ -132,21 +141,27 @@ def safe_sendBreak(self, serial): result = False return result - def touch_file(self, path, name): + def touch_file(self, path): with open(path, 'a'): os.utime(path, None) + def reset_timeout(self, timeout): + for n in range(0, timeout): + sleep(1) + def reset(self): """ reboot.txt - startup from standby state, reboots when in run mode. shutdown.txt - shutdown from run mode - reset.txt - reset fpga during run mode """ + reset.txt - reset FPGA during run mode + """ if self.options.forced_reset_type and self.options.forced_reset_type.endswith('.txt'): reset_file_path = os.path.join(self.disk, self.options.forced_reset_type.lower()) self.touch_file(reset_file_path) else: self.safe_sendBreak(self.serial) # Instead of serial.sendBreak() # Give time to wait for the image loading - sleep(2) + reset_tout_s = self.options.forced_reset_timeout if self.options.forced_reset_timeout is not None else self.DEFAULT_RESET_TOUT + self.reset_timeout(reset_tout_s) def flush(self): self.serial.flushInput() diff --git a/workspace_tools/singletest.py b/workspace_tools/singletest.py index cbba6b610a4..3d867aeb7ea 100644 --- a/workspace_tools/singletest.py +++ b/workspace_tools/singletest.py @@ -185,7 +185,8 @@ def get_version(): _opts_test_x_toolchain_summary=opts.test_x_toolchain_summary, _opts_copy_method=opts.copy_method, _opts_mut_reset_type=opts.mut_reset_type, - _opts_jobs=opts.jobs) + _opts_jobs=opts.jobs, + _opts_extend_test_timeout=opts.extend_test_timeout) # Runs test suite in CLI mode singletest_in_cli_mode(single_test) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 66504e71d71..69dfec4f8c2 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -19,6 +19,7 @@ import os import re +import sys import json import time import pprint @@ -88,7 +89,7 @@ def run(self): # prints well-formed summary with results (SQL table like) # table shows text x toolchain test result matrix print self.single_test.generate_test_summary_by_target(test_summary, shuffle_seed) - print "Completed in %d sec"% (elapsed_time) + print "Completed in %.2f sec"% (elapsed_time) class SingleTestRunner(object): @@ -146,7 +147,8 @@ def __init__(self, _opts_test_x_toolchain_summary=False, _opts_copy_method=None, _opts_mut_reset_type=None, - _opts_jobs=None + _opts_jobs=None, + _opts_extend_test_timeout=None ): """ Let's try hard to init this object """ PATTERN = "\\{(" + "|".join(self.TEST_RESULT_MAPPING.keys()) + ")\\}" @@ -186,7 +188,8 @@ def __init__(self, self.opts_test_x_toolchain_summary = _opts_test_x_toolchain_summary self.opts_copy_method = _opts_copy_method self.opts_mut_reset_type = _opts_mut_reset_type - self.opts_jobs = _opts_jobs + self.opts_jobs = _opts_jobs if _opts_jobs is not None else 1 + self.opts_extend_test_timeout = _opts_extend_test_timeout def shuffle_random_func(self): return self.shuffle_random_seed @@ -312,9 +315,14 @@ def execute(self): # With this option we are skipping testing phase continue + # Test duration can be increased by global value + test_duration = test.duration + if self.opts_extend_test_timeout is not None: + test_duration += self.opts_extend_test_timeout + # For an automated test the duration act as a timeout after # which the test gets interrupted - test_spec = self.shape_test_request(target, path, test_id, test.duration) + test_spec = self.shape_test_request(target, path, test_id, test_duration) test_loops = self.get_test_loop_count(test_id) single_test_result = self.handle(test_spec, target, toolchain, test_loops=test_loops) if single_test_result is not None: @@ -435,7 +443,6 @@ def file_store_firefox(self, file_path, dest_disk): profile.set_preference('browser.download.manager.showWhenStarting', False) profile.set_preference('browser.download.dir', dest_disk) profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream') - # Launch browser with profile and get file browser = webdriver.Firefox(profile) browser.get(file_path) @@ -449,7 +456,6 @@ def file_copy_method_selector(self, image_path, disk, copy_method): if copy_method == 'cp' or copy_method == 'copy' or copy_method == 'xcopy': source_path = image_path.encode('ascii', 'ignore') destination_path = os.path.join(disk.encode('ascii', 'ignore'), basename(image_path).encode('ascii', 'ignore')) - cmd = [copy_method, source_path, destination_path] try: ret = call(cmd, shell=True) @@ -512,8 +518,12 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): disk = mut['disk'] port = mut['port'] - reset_type = mut.get('reset_type') target_by_mcu = TARGET_MAP[mut['mcu']] + # Some extra stuff can be declared in MUTs structure + reset_type = mut.get('reset_type') + reset_tout = mut.get('reset_tout') + images_config = mut.get('images_config') + mobo_config = mut.get('mobo_config') # Program # When the build and test system were separate, this was relative to a @@ -558,7 +568,8 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): host_test_reset = self.opts_mut_reset_type if reset_type is None else reset_type single_test_result = self.run_host_test(test.host_test, disk, port, duration, verbose=host_test_verbose, - reset=host_test_reset) + reset=host_test_reset, + reset_tout=reset_tout) # Store test result test_all_result.append(single_test_result) @@ -597,7 +608,7 @@ def shape_global_test_loop_result(self, test_all_result): result = test_all_result[0] return result - def run_host_test(self, name, disk, port, duration, reset=None, verbose=False, extra_serial=None): + def run_host_test(self, name, disk, port, duration, reset=None, reset_tout=None, verbose=False, extra_serial=None): """ Function creates new process with host test configured with particular test case. Function also is pooling for serial port activity from process to catch all data printed by test runner and host test during test execution.""" @@ -609,6 +620,11 @@ def run_host_test(self, name, disk, port, duration, reset=None, verbose=False, e cmd += ["-e", extra_serial] if reset is not None: cmd += ["-r", reset] + if reset_tout is not None: + cmd += ["-R", str(reset_tout)] + + if verbose: + print "Host test cmd: " + " ".join(cmd) proc = Popen(cmd, stdout=PIPE, cwd=HOST_TESTS) obs = ProcessObserver(proc) @@ -617,7 +633,7 @@ def run_host_test(self, name, disk, port, duration, reset=None, verbose=False, e output = [] while (time() - start_time) < duration: try: - c = obs.queue.get(block=True, timeout=1) + c = obs.queue.get(block=True, timeout=0.5) except Empty, _: c = None @@ -625,7 +641,8 @@ def run_host_test(self, name, disk, port, duration, reset=None, verbose=False, e output.append(c) # Give the mbed under test a way to communicate the end of the test if c in ['\n', '\r']: - if '{end}' in line: break + if '{end}' in line: + break line = '' else: line += c @@ -961,17 +978,17 @@ def singletest_in_cli_mode(single_test): # prints well-formed summary with results (SQL table like) # table shows text x toolchain test result matrix print single_test.generate_test_summary_by_target(test_summary, shuffle_seed) - print "Completed in %d sec"% (elapsed_time) + print "Completed in %.2f sec"% (elapsed_time) -def mps2_check_board_image_file(disk, board_image_path, image0file_path, image_name='images.txt'): - """ This function will modify 'Versatile Express Images Configuration File' file - for Versatile Express V2M-MPS2 board. +def mps2_set_board_image_file(disk, images_cfg_path, image0file_path, image_name='images.txt'): + """ This function will alter image cfg file. Main goal of this function is to change number of images to 1, comment all - existing image entries and append at the end of file new entry with test. + existing image entries and append at the end of file new entry with test path. + @return True when all steps succeed. """ MBED_SDK_TEST_STAMP = 'test suite entry' - image_path = os.path.join(disk, board_image_path, image_name) + image_path = os.path.join(disk, images_cfg_path, image_name) new_file_lines = [] # New configuration file lines (entries) # Check each line of the image configuration file @@ -1010,6 +1027,18 @@ def mps2_check_board_image_file(disk, board_image_path, image0file_path, image_n return True +def mps2_select_core(disk, mobo_config_name=""): + """ Function selects actual core """ + # TODO: implement core selection + pass + + +def mps2_switch_usb_auto_mounting_after_restart(disk, usb_config_name=""): + """ Function alters configuration to allow USB MSD to be mounted after restarts """ + # TODO: implement USB MSD restart detection + pass + + class TestLogger(): """ Super-class for logging and printing ongoing events for test suite pass """ def __init__(self): @@ -1170,6 +1199,12 @@ def get_default_test_options_parser(): default=None, help='For some commands you can use filter to filter out results') + parser.add_option('', '--inc-timeout', + dest='extend_test_timeout', + metavar="NUMBER", + type="int", + help='You can increase global timeout for each test by specifying additional test timeout in seconds') + parser.add_option('', '--verbose-skipped', dest='verbose_skipped_tests', default=False, diff --git a/workspace_tools/test_webapi.py b/workspace_tools/test_webapi.py index 59fb97c0166..0f2c22c0b4f 100644 --- a/workspace_tools/test_webapi.py +++ b/workspace_tools/test_webapi.py @@ -54,7 +54,7 @@ def __init__(self): def get_rest_result_template(self, result, command, success_code): """ Returns common part of every web service request """ - result = {"result": result, + result = {"result" : result, "command" : command, "success_code": success_code} # 0 - OK, >0 - Error number return result From 28b48ae4d012cb4128bfbd4a13c2a3c61b616521 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 11:40:17 +0100 Subject: [PATCH 25/41] reset functionality extensions: adding 'image_copy_method_selector' - function which will apply if necessary image configuration file modifications when image is copied onto MUT --- workspace_tools/test_api.py | 41 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 69dfec4f8c2..f789061d5f0 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -448,14 +448,33 @@ def file_store_firefox(self, file_path, dest_disk): browser.get(file_path) browser.close() - def file_copy_method_selector(self, image_path, disk, copy_method): + def image_copy_method_selector(self, target, image_path, disk, copy_method, + images_config=None, image_dest=None): + """ Function copied image file and fiddles with image configuration files in needed. + This function will select proper image configuration (modify image config file + if needed) after image is copied. + """ + image_dest = image_dest if image_dest is not None else '' + _copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method, image_dest=image_dest) + + if images_config is not None: + if target == 'ARM_MPS2': + images_cfg_path = images_config + image0file_path = os.path.join(disk, image_dest, basename(image_path)) + mps2_set_board_image_file(disk, images_cfg_path, image0file_path): + + return _copy_res, _err_msg, _copy_method + + def file_copy_method_selector(self, image_path, disk, copy_method, + image_dest='', image_cfg_func=None, image_cfg_func_params=None): """ Copy file depending on method you want to use. Handles exception - and return code from shell copy commands. """ + and return code from shell copy commands. + """ result = True resutl_msg = "" if copy_method == 'cp' or copy_method == 'copy' or copy_method == 'xcopy': source_path = image_path.encode('ascii', 'ignore') - destination_path = os.path.join(disk.encode('ascii', 'ignore'), basename(image_path).encode('ascii', 'ignore')) + destination_path = os.path.join(disk.encode('ascii', 'ignore'), image_dest, basename(image_path).encode('ascii', 'ignore')) cmd = [copy_method, source_path, destination_path] try: ret = call(cmd, shell=True) @@ -465,10 +484,10 @@ def file_copy_method_selector(self, image_path, disk, copy_method): except Exception, e: resutl_msg = e result = False - if copy_method == 'firefox': + elif copy_method == 'firefox': try: source_path = image_path.encode('ascii', 'ignore') - destination_path = disk.encode('ascii', 'ignore') + destination_path = os.path.join(disk.encode('ascii', 'ignore'), image_dest) self.file_store_firefox(source_path, destination_path) except Exception, e: resutl_msg = e @@ -481,6 +500,7 @@ def file_copy_method_selector(self, image_path, disk, copy_method): except Exception, e: resutl_msg = e result = False + return result, resutl_msg, copy_method def delete_file(self, file_path): @@ -520,10 +540,11 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): port = mut['port'] target_by_mcu = TARGET_MAP[mut['mcu']] # Some extra stuff can be declared in MUTs structure - reset_type = mut.get('reset_type') - reset_tout = mut.get('reset_tout') - images_config = mut.get('images_config') - mobo_config = mut.get('mobo_config') + reset_type = mut.get('reset_type') # reboot.txt, reset.txt, shutdown.txt + reset_tout = mut.get('reset_tout') # COPY_IMAGE -> RESET_PROC -> SLEEP(RESET_TOUT) + image_dest = mut.get('image_dest') # Image file destination DISK + IMAGE_DEST + BINARY_NAME + images_config = mut.get('images_config') # Available images selection via config file + mobo_config = mut.get('mobo_config') # Available board configuration selection e.g. core selection etc. # Program # When the build and test system were separate, this was relative to a @@ -545,7 +566,7 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): test_all_result = [] for test_index in range(test_loops): # Choose one method of copy files to mbed virtual drive - _copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method) + _copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method, image_dest=image_dest) # Host test execution start_host_exec_time = time() From fd23d125db56fc8f3ffa5bd20c06f107d0f8261e Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 13:19:00 +0100 Subject: [PATCH 26/41] reset functionality extensions: added function which will handle image configuration file changes after binary (image) copy to target. Now we can copy binary (image) into specified directory on MUTs disk --- workspace_tools/test_api.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index f789061d5f0..11efc6031af 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -331,7 +331,8 @@ def execute(self): def generate_test_summary_by_target(self, test_summary, shuffle_seed=None): """ Prints well-formed summary with results (SQL table like) - table shows text x toolchain test result matrix """ + table shows text x toolchain test result matrix + """ RESULT_INDEX = 0 TARGET_INDEX = 1 TOOLCHAIN_INDEX = 2 @@ -448,7 +449,7 @@ def file_store_firefox(self, file_path, dest_disk): browser.get(file_path) browser.close() - def image_copy_method_selector(self, target, image_path, disk, copy_method, + def image_copy_method_selector(self, target_name, image_path, disk, copy_method, images_config=None, image_dest=None): """ Function copied image file and fiddles with image configuration files in needed. This function will select proper image configuration (modify image config file @@ -458,15 +459,16 @@ def image_copy_method_selector(self, target, image_path, disk, copy_method, _copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method, image_dest=image_dest) if images_config is not None: + # For different targets additional configuration file has to be changed + # Here we select target and proper function to handle configuration change if target == 'ARM_MPS2': images_cfg_path = images_config image0file_path = os.path.join(disk, image_dest, basename(image_path)) - mps2_set_board_image_file(disk, images_cfg_path, image0file_path): + mps2_set_board_image_file(disk, images_cfg_path, image0file_path) return _copy_res, _err_msg, _copy_method - def file_copy_method_selector(self, image_path, disk, copy_method, - image_dest='', image_cfg_func=None, image_cfg_func_params=None): + def file_copy_method_selector(self, image_path, disk, copy_method, image_dest=''): """ Copy file depending on method you want to use. Handles exception and return code from shell copy commands. """ @@ -566,7 +568,10 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): test_all_result = [] for test_index in range(test_loops): # Choose one method of copy files to mbed virtual drive - _copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method, image_dest=image_dest) + #_copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, self.opts_copy_method, image_dest=image_dest) + + _copy_res, _err_msg, _copy_method = self.image_copy_method_selector(target_name, image_path, disk, self.opts_copy_method, + images_config, image_dest) # Host test execution start_host_exec_time = time() From 698fe930e622ebb7ec74598a9c11955937c1488b Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 13:24:04 +0100 Subject: [PATCH 27/41] Changed functions' docstring format a little to mach singletest, test api and test webapi files --- workspace_tools/singletest.py | 3 +- workspace_tools/test_api.py | 91 ++++++++++++++++++++++------------ workspace_tools/test_webapi.py | 18 ++++--- 3 files changed, 73 insertions(+), 39 deletions(-) diff --git a/workspace_tools/singletest.py b/workspace_tools/singletest.py index 3d867aeb7ea..608f23ce0f3 100644 --- a/workspace_tools/singletest.py +++ b/workspace_tools/singletest.py @@ -91,7 +91,8 @@ def get_version(): - """ Returns test script version """ + """ Returns test script version + """ single_test_version_major = 1 single_test_version_minor = 1 return (single_test_version_major, single_test_version_minor) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 11efc6031af..98360fe6aa5 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -71,7 +71,8 @@ def stop(self): class SingleTestExecutor(threading.Thread): - """ Example: Single test class in separate thread usage """ + """ Example: Single test class in separate thread usage + """ def __init__(self, single_test): self.single_test = single_test threading.Thread.__init__(self) @@ -93,8 +94,8 @@ def run(self): class SingleTestRunner(object): - """ Object wrapper for single test run which may involve multiple MUTs.""" - + """ Object wrapper for single test run which may involve multiple MUTs + """ RE_DETECT_TESTCASE_RESULT = None # Return codes for test script @@ -150,7 +151,8 @@ def __init__(self, _opts_jobs=None, _opts_extend_test_timeout=None ): - """ Let's try hard to init this object """ + """ Let's try hard to init this object + """ PATTERN = "\\{(" + "|".join(self.TEST_RESULT_MAPPING.keys()) + ")\\}" self.RE_DETECT_TESTCASE_RESULT = re.compile(PATTERN) # Settings related to test loops counters @@ -195,7 +197,8 @@ def shuffle_random_func(self): return self.shuffle_random_seed def is_shuffle_seed_float(self): - """ return true if function parameter can be converted to float """ + """ return true if function parameter can be converted to float + """ result = True try: float(self.shuffle_random_seed) @@ -372,7 +375,8 @@ def generate_test_summary_by_target(self, test_summary, shuffle_seed=None): def generate_test_summary(self, test_summary, shuffle_seed=None): """ Prints well-formed summary with results (SQL table like) - table shows target x test results matrix across """ + table shows target x test results matrix across + """ result = "Test summary:\n" # Pretty table package is used to print results pt = PrettyTable(["Result", "Target", "Toolchain", "Test ID", "Test Description", @@ -410,7 +414,8 @@ def generate_test_summary(self, test_summary, shuffle_seed=None): return result def test_loop_list_to_dict(self, test_loops_str): - """ Transforms test_id=X,test_id=X,test_id=X into dictionary {test_id : test_id_loops_count} """ + """ Transforms test_id=X,test_id=X,test_id=X into dictionary {test_id : test_id_loops_count} + """ result = {} if test_loops_str: test_loops = test_loops_str.split(',') @@ -427,7 +432,8 @@ def test_loop_list_to_dict(self, test_loops_str): def get_test_loop_count(self, test_id): """ This function returns no. of loops per test (deducted by test_id_. - If test is not in list of redefined loop counts it will use default value. """ + If test is not in list of redefined loop counts it will use default value. + """ result = self.GLOBAL_LOOPS_COUNT if test_id in self.TEST_LOOPS_DICT: result = self.TEST_LOOPS_DICT[test_id] @@ -506,7 +512,8 @@ def file_copy_method_selector(self, image_path, disk, copy_method, image_dest='' return result, resutl_msg, copy_method def delete_file(self, file_path): - """ Remove file from the system """ + """ Remove file from the system + """ result = True resutl_msg = "" try: @@ -518,7 +525,8 @@ def delete_file(self, file_path): def handle(self, test_spec, target_name, toolchain_name, test_loops=1): """ Function determines MUT's mbed disk/port and copies binary to - target. Test is being invoked afterwards. """ + target. Test is being invoked afterwards. + """ data = json.loads(test_spec) # Get test information, image and test timeout test_id = data['test_id'] @@ -609,7 +617,8 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): def print_test_result(self, test_result, target_name, toolchain_name, test_id, test_description, elapsed_time, duration): - """ Use specific convention to print test result and related data.""" + """ Use specific convention to print test result and related data + """ tokens = [] tokens.append("TargetTest") tokens.append(target_name) @@ -622,13 +631,15 @@ def print_test_result(self, test_result, target_name, toolchain_name, return result def shape_test_loop_ok_result_count(self, test_all_result): - """ Reformats list of results to simple string """ + """ Reformats list of results to simple string + """ test_loop_count = len(test_all_result) test_loop_ok_result = test_all_result.count(self.TEST_RESULT_OK) return "%d/%d"% (test_loop_ok_result, test_loop_count) def shape_global_test_loop_result(self, test_all_result): - """ Reformats list of results to simple string """ + """ Reformats list of results to simple string + """ result = self.TEST_RESULT_FAIL if all(test_all_result[0] == res for res in test_all_result): result = test_all_result[0] @@ -637,7 +648,8 @@ def shape_global_test_loop_result(self, test_all_result): def run_host_test(self, name, disk, port, duration, reset=None, reset_tout=None, verbose=False, extra_serial=None): """ Function creates new process with host test configured with particular test case. Function also is pooling for serial port activity from process to catch all data - printed by test runner and host test during test execution.""" + printed by test runner and host test during test execution + """ # print "{%s} port:%s disk:%s" % (name, port, disk), cmd = ["python", "%s.py" % name, '-p', port, '-d', disk, '-t', str(duration)] @@ -692,7 +704,8 @@ def run_host_test(self, name, disk, port, duration, reset=None, reset_tout=None, return result def is_peripherals_available(self, target_mcu_name, peripherals=None): - """ Checks if specified target should run specific peripheral test case.""" + """ Checks if specified target should run specific peripheral test case + """ if peripherals is not None: peripherals = set(peripherals) for id, mut in self.muts.iteritems(): @@ -709,7 +722,8 @@ def is_peripherals_available(self, target_mcu_name, peripherals=None): return False def shape_test_request(self, mcu, image_path, test_id, duration=10): - """ Function prepares JOSN structure describing test specification.""" + """ Function prepares JOSN structure describing test specification + """ test_spec = { "mcu": mcu, "image": image_path, @@ -720,7 +734,8 @@ def shape_test_request(self, mcu, image_path, test_id, duration=10): def get_unique_value_from_summary(test_summary, index): - """ Gets list of unique target names """ + """ Gets list of unique target names + """ result = [] for test in test_summary: target_name = test[index] @@ -730,7 +745,8 @@ def get_unique_value_from_summary(test_summary, index): def get_unique_value_from_summary_ext(test_summary, index_key, index_val): - """ Gets list of unique target names and return dictionary """ + """ Gets list of unique target names and return dictionary + """ result = {} for test in test_summary: key = test[index_key] @@ -741,7 +757,8 @@ def get_unique_value_from_summary_ext(test_summary, index_key, index_val): def show_json_file_format_error(json_spec_filename, line, column): - """ Prints JSON broken content """ + """ Prints JSON broken content + """ with open(json_spec_filename) as data_file: line_no = 1 for json_line in data_file: @@ -755,7 +772,8 @@ def show_json_file_format_error(json_spec_filename, line, column): def json_format_error_defect_pos(json_error_msg): """ Gets first error line and column in JSON file format. - Parsed from exception thrown by json.loads() string """ + Parsed from exception thrown by json.loads() string + """ result = None line, column = 0, 0 # Line value search @@ -775,7 +793,8 @@ def json_format_error_defect_pos(json_error_msg): def get_json_data_from_file(json_spec_filename, verbose=False): - """ Loads from file JSON formatted string to data structure """ + """ Loads from file JSON formatted string to data structure + """ result = None try: with open(json_spec_filename) as data_file: @@ -801,7 +820,8 @@ def get_json_data_from_file(json_spec_filename, verbose=False): def print_muts_configuration_from_json(json_data, join_delim=", "): - """ Prints MUTs configuration passed to test script for verboseness. """ + """ Prints MUTs configuration passed to test script for verboseness + """ muts_info_cols = [] # We need to check all unique properties for each defined MUT for k in json_data: @@ -830,7 +850,8 @@ def print_muts_configuration_from_json(json_data, join_delim=", "): def print_test_configuration_from_json(json_data, join_delim=", "): - """ Prints test specification configuration passed to test script for verboseness. """ + """ Prints test specification configuration passed to test script for verboseness + """ toolchains_info_cols = [] # We need to check all toolchains for each device for k in json_data: @@ -893,7 +914,8 @@ def print_test_configuration_from_json(json_data, join_delim=", "): def get_avail_tests_summary_table(cols=None, result_summary=True, join_delim=','): """ Generates table summary with all test cases and additional test cases information using pretty print functionality. Allows test suite user to - see test cases. """ + see test cases + """ # get all unique test ID prefixes unique_test_id = [] for test in TESTS: @@ -980,7 +1002,8 @@ def get_avail_tests_summary_table(cols=None, result_summary=True, join_delim=',' def progress_bar(percent_progress, saturation=0): - """ This function creates progress bar with optional simple saturation mark""" + """ This function creates progress bar with optional simple saturation mark + """ step = int(percent_progress / 2) # Scale by to (scale: 1 - 50) str_progress = '#' * step + '.' * int(50 - step) c = '!' if str_progress[38] == '.' else '|' @@ -991,7 +1014,8 @@ def progress_bar(percent_progress, saturation=0): def singletest_in_cli_mode(single_test): - """ Runs SingleTestRunner object in CLI (Command line interface) mode """ + """ Runs SingleTestRunner object in CLI (Command line interface) mode + """ start = time() # Execute tests depending on options and filter applied test_summary, shuffle_seed = single_test.execute() @@ -1054,19 +1078,22 @@ def mps2_set_board_image_file(disk, images_cfg_path, image0file_path, image_name def mps2_select_core(disk, mobo_config_name=""): - """ Function selects actual core """ + """ Function selects actual core + """ # TODO: implement core selection pass def mps2_switch_usb_auto_mounting_after_restart(disk, usb_config_name=""): - """ Function alters configuration to allow USB MSD to be mounted after restarts """ + """ Function alters configuration to allow USB MSD to be mounted after restarts + """ # TODO: implement USB MSD restart detection pass class TestLogger(): - """ Super-class for logging and printing ongoing events for test suite pass """ + """ Super-class for logging and printing ongoing events for test suite pass + """ def __init__(self): self.Log = [] @@ -1089,8 +1116,7 @@ def log_line(self, LogType, log_line, log_time=None): def log_to_file(self, LogToFileAttr, file_name): """ Class will log to file current log entries. Note: you should be able to see log file like this: - - tail -f log_file.txt + tail -f log_file.txt """ pass @@ -1100,7 +1126,8 @@ class CLITestLogger(TestLogger): def get_default_test_options_parser(): - """ Get common test script options used by CLI, webservices etc. """ + """ Get common test script options used by CLI, webservices etc. + """ parser = optparse.OptionParser() parser.add_option('-i', '--tests', dest='test_spec_filename', diff --git a/workspace_tools/test_webapi.py b/workspace_tools/test_webapi.py index 0f2c22c0b4f..0a70b0c4b2f 100644 --- a/workspace_tools/test_webapi.py +++ b/workspace_tools/test_webapi.py @@ -53,7 +53,8 @@ def __init__(self): REST_TEST_RESULTS='test_results') def get_rest_result_template(self, result, command, success_code): - """ Returns common part of every web service request """ + """ Returns common part of every web service request + """ result = {"result" : result, "command" : command, "success_code": success_code} # 0 - OK, >0 - Error number @@ -61,22 +62,26 @@ def get_rest_result_template(self, result, command, success_code): # REST API handlers for Flask framework def rest_api_status(self): - """ Returns current test execution status. E.g. running / finished etc. """ + """ Returns current test execution status. E.g. running / finished etc. + """ with self.resource_lock: pass def rest_api_config(self): - """ Returns configuration passed to SingleTest executor """ + """ Returns configuration passed to SingleTest executor + """ with self.resource_lock: pass def rest_api_log(self): - """ Returns current test log """ + """ Returns current test log + """ with self.resource_lock: pass def rest_api_request_handler(self, request_type): - """ Returns various data structures. Both static and mutable during test """ + """ Returns various data structures. Both static and mutable during test + """ result = {} success_code = 0 with self.resource_lock: @@ -97,7 +102,8 @@ def singletest_in_webservice_mode(): def get_default_test_webservice_options_parser(): - """ Get test script web service options used by CLI, webservices etc. """ + """ Get test script web service options used by CLI, webservices etc. + """ parser = get_default_test_options_parser() # Things related to web services offered by test suite scripts From 0e6803b7873d505f31a196426d9125cac4859cb0 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 13:47:08 +0100 Subject: [PATCH 28/41] Bugfix: fixed function printing table with test results per target (switch -t) --- workspace_tools/test_api.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 98360fe6aa5..7454dcb0f70 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -348,14 +348,18 @@ def generate_test_summary_by_target(self, test_summary, shuffle_seed=None): unique_toolchains = get_unique_value_from_summary(test_summary, TOOLCHAIN_INDEX) result = "Test summary:\n" - result_dict = {} # test : { toolchain : result } for target in unique_targets: + result_dict = {} # test : { toolchain : result } + unique_target_toolchains = [] for test in test_summary: - if test[TEST_INDEX] not in result_dict: - result_dict[test[TEST_INDEX]] = {} - result_dict[test[TEST_INDEX]][test[TOOLCHAIN_INDEX]] = test[RESULT_INDEX] - - pt_cols = ["Target", "Test ID", "Test Description"] + unique_toolchains + if test[TARGET_INDEX] == target: + if test[TOOLCHAIN_INDEX] not in unique_target_toolchains: + unique_target_toolchains.append(test[TOOLCHAIN_INDEX]) + if test[TEST_INDEX] not in result_dict: + result_dict[test[TEST_INDEX]] = {} + result_dict[test[TEST_INDEX]][test[TOOLCHAIN_INDEX]] = test[RESULT_INDEX] + + pt_cols = ["Target", "Test ID", "Test Description"] + unique_target_toolchains pt = PrettyTable(pt_cols) for col in pt_cols: pt.align[col] = "l" @@ -365,7 +369,8 @@ def generate_test_summary_by_target(self, test_summary, shuffle_seed=None): test_results = result_dict[test] row = [target, test, unique_test_desc[test]] for toolchain in unique_toolchains: - row.append(test_results[toolchain]) + if toolchain in test_results: + row.append(test_results[toolchain]) pt.add_row(row) result += pt.get_string() shuffle_seed_text = "Shuffle Seed: %.*f"% (self.SHUFFLE_SEED_ROUND, From 23bcf850b3486d58fb3ad0696fb9767859e186db Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 14:04:21 +0100 Subject: [PATCH 29/41] Small update to new functionality for logger --- workspace_tools/test_api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 7454dcb0f70..f818cc65583 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -1103,9 +1103,10 @@ def __init__(self): self.Log = [] self.LogType = construct_enum(INFO='Info', - NOTIF='Notification', WARN='Warning', - ERROR='Error') + NOTIF='Notification', + ERROR='Error', + EXCEPT='Exception') self.LogToFileAttr = construct_enum(CREATE=1, # Create or overwrite existing log file APPEND=2) # Append to existing log file From f80d0302a7e92e9e1a9e636df59d9fc132e6eb69 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 15:12:57 +0100 Subject: [PATCH 30/41] Added simple logger CLI logger (with logging to file) plus simple logger super class --- workspace_tools/test_api.py | 59 +++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index f818cc65583..866d3437909 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -149,8 +149,7 @@ def __init__(self, _opts_copy_method=None, _opts_mut_reset_type=None, _opts_jobs=None, - _opts_extend_test_timeout=None - ): + _opts_extend_test_timeout=None): """ Let's try hard to init this object """ PATTERN = "\\{(" + "|".join(self.TEST_RESULT_MAPPING.keys()) + ")\\}" @@ -193,6 +192,8 @@ def __init__(self, self.opts_jobs = _opts_jobs if _opts_jobs is not None else 1 self.opts_extend_test_timeout = _opts_extend_test_timeout + self.logger = CLITestLogger() # Default test logger + def shuffle_random_func(self): return self.shuffle_random_seed @@ -1099,8 +1100,14 @@ def mps2_switch_usb_auto_mounting_after_restart(disk, usb_config_name=""): class TestLogger(): """ Super-class for logging and printing ongoing events for test suite pass """ - def __init__(self): - self.Log = [] + def __init__(self, store_log=True): + """ We can control if logger actually stores log in memory + or just handled all log entries immediately + """ + self.log = [] + self.log_to_file = False + self.log_file_name = None + self.store_log = store_log self.LogType = construct_enum(INFO='Info', WARN='Warning', @@ -1111,24 +1118,46 @@ def __init__(self): self.LogToFileAttr = construct_enum(CREATE=1, # Create or overwrite existing log file APPEND=2) # Append to existing log file - def log_line(self, LogType, log_line, log_time=None): - log_timestamp = time.time() if log_time is None else log_time + def log_line(self, LogType, log_line): + """ Log one line of text + """ + log_timestamp = time.time() log_entry = {'log_type' : LogType, 'log_timestamp' : log_timestamp, 'log_line' : log_line, '_future' : None} - self.Log.append(log_entry) - - def log_to_file(self, LogToFileAttr, file_name): - """ Class will log to file current log entries. - Note: you should be able to see log file like this: - tail -f log_file.txt - """ - pass + # Store log in memory + if self.store_log: + self.log.append(log_entry) + return log_entry class CLITestLogger(TestLogger): - pass + """ Logger used with CLI (Command line interface) test suite. Logs on screen and to file if needed + """ + def __init__(self, store_log=True, file_name=None): + TestLogger.__init__(self) + self.log_file_name = file_name + self.TIMESTAMP_FORMAT = '%y-%m-%d %H:%M:%S' + + def log_print(self, log_entry, timestamp=True): + """ Prints on screen formatted log entry + """ + ts = log_entry['log_timestamp'] + timestamp_str = datetime.datetime.fromtimestamp(ts).strftime("[%s] "% self.TIMESTAMP_FORMAT) if timestamp else '' + log_line_str = "%(log_type)s: %(log_line)s"% (log_entry) + return timestamp_str + log_line_str + + def log_line(self, LogType, log_line, timestamp=True, line_delim='\n'): + log_entry = TestLogger.log_line(self, LogType, log_line) + log_line_str = self.log_print(log_entry, timestamp) + print log_line_str + if self.log_file_name is not None: + try: + with open(self.log_file_name, 'a') as file: + file.write(log_line_str + line_delim) + except IOError: + pass def get_default_test_options_parser(): From 8cc7678c4bd0cf52ef368dd7c1e273a9d06d5858 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 16:11:22 +0100 Subject: [PATCH 31/41] Small comment indent in test web api file --- workspace_tools/test_webapi.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/workspace_tools/test_webapi.py b/workspace_tools/test_webapi.py index 0a70b0c4b2f..59273e80d2e 100644 --- a/workspace_tools/test_webapi.py +++ b/workspace_tools/test_webapi.py @@ -74,8 +74,7 @@ def rest_api_config(self): pass def rest_api_log(self): - """ Returns current test log - """ + """ Returns current test log """ with self.resource_lock: pass From 61f028f0508be21d510229a1dfdd2402b66f0274 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Tue, 12 Aug 2014 16:15:33 +0100 Subject: [PATCH 32/41] Fixed commit issues regarding logging mechanism - missed during previous commits --- workspace_tools/singletest.py | 1 + workspace_tools/test_api.py | 36 +++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/workspace_tools/singletest.py b/workspace_tools/singletest.py index 608f23ce0f3..3301f569019 100644 --- a/workspace_tools/singletest.py +++ b/workspace_tools/singletest.py @@ -169,6 +169,7 @@ def get_version(): single_test = SingleTestRunner(_global_loops_count=opts.test_global_loops_value, _test_loops_list=opts.test_loops_list, _muts=MUTs, + _opts_log_file_name=opts.log_file_name, _test_spec=test_spec, _opts_goanna_for_mbed_sdk=opts.goanna_for_mbed_sdk, _opts_goanna_for_tests=opts.goanna_for_tests, diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 866d3437909..1e0d1153187 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -25,6 +25,7 @@ import pprint import random import optparse +import datetime import threading from types import ListType from prettytable import PrettyTable @@ -131,6 +132,7 @@ def __init__(self, _global_loops_count=1, _test_loops_list=None, _muts={}, + _opts_log_file_name=None, _test_spec={}, _opts_goanna_for_mbed_sdk=None, _opts_goanna_for_tests=None, @@ -173,6 +175,7 @@ def __init__(self, self.test_spec = _test_spec # Settings passed e.g. from command line + self.opts_log_file_name = _opts_log_file_name self.opts_goanna_for_mbed_sdk = _opts_goanna_for_mbed_sdk self.opts_goanna_for_tests = _opts_goanna_for_tests self.opts_shuffle_test_order = _opts_shuffle_test_order @@ -192,7 +195,7 @@ def __init__(self, self.opts_jobs = _opts_jobs if _opts_jobs is not None else 1 self.opts_extend_test_timeout = _opts_extend_test_timeout - self.logger = CLITestLogger() # Default test logger + self.logger = CLITestLogger(file_name=self.opts_log_file_name) # Default test logger def shuffle_random_func(self): return self.shuffle_random_seed @@ -223,7 +226,7 @@ def execute(self): # print '=== %s::%s ===' % (target, toolchain) # Let's build our test if target not in TARGET_MAP: - print 'Skipped tests for %s target. Target platform not found' % (target) + print self.logger.log_line(self.logger.LogType.NOTIF, 'Skipped tests for %s target. Target platform not found' % (target)) continue T = TARGET_MAP[target] @@ -236,7 +239,7 @@ def execute(self): clean=clean_mbed_libs_options, jobs=self.opts_jobs) if not build_mbed_libs_result: - print 'Skipped tests for %s target. Toolchain %s is not yet supported for this target' % (T.name, toolchain) + print self.logger.log_line(self.logger.LogType.NOTIF, 'Skipped tests for %s target. Toolchain %s is not yet supported for this target' % (T.name, toolchain)) continue build_dir = join(BUILD_DIR, "test", target, toolchain) @@ -256,19 +259,19 @@ def execute(self): if self.opts_test_only_peripheral and not test.peripherals: if self.opts_verbose_skipped_tests: - print "TargetTest::%s::NotPeripheralTestSkipped()" % (target) + print self.logger.log_line(self.logger.LogType.INFO, 'Common test skipped for target %s'% (target)) continue if self.opts_test_only_common and test.peripherals: if self.opts_verbose_skipped_tests: - print "TargetTest::%s::PeripheralTestSkipped()" % (target) + print self.logger.log_line(self.logger.LogType.INFO, 'Peripheral test skipped for target %s'% (target)) continue if test.automated and test.is_supported(target, toolchain): if not self.is_peripherals_available(target, test.peripherals): if self.opts_verbose_skipped_tests: test_peripherals = test.peripherals if test.peripherals else [] - print "TargetTest::%s::TestSkipped(%s)" % (target, ",".join(test_peripherals)) + print self.logger.log_line(self.logger.LogType.INFO, 'Peripheral %s test skipped for target %s'% (",".join(test_peripherals), target)) continue build_project_options = ["analyze"] if self.opts_goanna_for_tests else None @@ -567,7 +570,7 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): # base network folder base path: join(NETWORK_BASE_PATH, ) image_path = image if not exists(image_path): - print "Error: Image file does not exist: %s" % image_path + print self.logger.log_line(self.logger.LogType.ERROR, 'Image file does not exist: %s' % image_path) elapsed_time = 0 test_result = self.TEST_RESULT_NO_IMAGE return (test_result, target_name, toolchain_name, @@ -593,7 +596,7 @@ def handle(self, test_spec, target_name, toolchain_name, test_loops=1): single_test_result = self.TEST_RESULT_UNDEF # singe test run result if not _copy_res: # Serial port copy error single_test_result = self.TEST_RESULT_IOERR_COPY - print "Error: Copy method '%s'. %s"% (_copy_method, _err_msg) + print self.logger.log_line(self.logger.LogType.ERROR, "Copy method '%s' failed. Reason: %s"% (_copy_method, _err_msg)) else: # Copy Extra Files if not target_by_mcu.is_disk_virtual and test.extra_files: @@ -808,7 +811,7 @@ def get_json_data_from_file(json_spec_filename, verbose=False): result = json.load(data_file) except ValueError as json_error_msg: result = None - print "Error in '%s' file. %s" % (json_spec_filename, json_error_msg) + print self.logger.log_line(self.logger.LogType.ERROR, 'JSON file %s parsing failed. Reason: %s' % (json_spec_filename, json_error_msg)) # We can print where error occurred inside JSON file if we can parse exception msg json_format_defect_pos = json_format_error_defect_pos(str(json_error_msg)) if json_format_defect_pos is not None: @@ -818,7 +821,8 @@ def get_json_data_from_file(json_spec_filename, verbose=False): show_json_file_format_error(json_spec_filename, line, column) except IOError as fileopen_error_msg: - print "Error: %s" % (fileopen_error_msg) + print self.logger.log_line(self.logger.LogType.ERROR, 'JSON file %s not opened. Reason: %s'% (json_spec_filename, fileopen_error_msg)) + print if verbose and result: pp = pprint.PrettyPrinter(indent=4) pp.pprint(result) @@ -1121,7 +1125,7 @@ def __init__(self, store_log=True): def log_line(self, LogType, log_line): """ Log one line of text """ - log_timestamp = time.time() + log_timestamp = time() log_entry = {'log_type' : LogType, 'log_timestamp' : log_timestamp, 'log_line' : log_line, @@ -1138,7 +1142,8 @@ class CLITestLogger(TestLogger): def __init__(self, store_log=True, file_name=None): TestLogger.__init__(self) self.log_file_name = file_name - self.TIMESTAMP_FORMAT = '%y-%m-%d %H:%M:%S' + #self.TIMESTAMP_FORMAT = '%y-%m-%d %H:%M:%S' # Full date and time + self.TIMESTAMP_FORMAT = '%H:%M:%S' # Time only def log_print(self, log_entry, timestamp=True): """ Prints on screen formatted log entry @@ -1151,14 +1156,13 @@ def log_print(self, log_entry, timestamp=True): def log_line(self, LogType, log_line, timestamp=True, line_delim='\n'): log_entry = TestLogger.log_line(self, LogType, log_line) log_line_str = self.log_print(log_entry, timestamp) - print log_line_str if self.log_file_name is not None: try: with open(self.log_file_name, 'a') as file: file.write(log_line_str + line_delim) except IOError: pass - + return log_line_str def get_default_test_options_parser(): """ Get common test script options used by CLI, webservices etc. @@ -1293,6 +1297,10 @@ def get_default_test_options_parser(): type="int", help='You can increase global timeout for each test by specifying additional test timeout in seconds') + parser.add_option('-l', '--log', + dest='log_file_name', + help='Log events to external file (note not all console entries may be visible in log file)') + parser.add_option('', '--verbose-skipped', dest='verbose_skipped_tests', default=False, From d076c510609d047f287bc16645c1dd644fc66649 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Wed, 13 Aug 2014 09:43:49 +0100 Subject: [PATCH 33/41] Changed short description for --firmware-name switch --- workspace_tools/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 1e0d1153187..16e8b748014 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -1268,7 +1268,7 @@ def get_default_test_options_parser(): parser.add_option('', '--firmware-name', dest='firmware_global_name', - help='Set global name for all produced projects. E.g. you can call all test binaries firmware.bin') + help='Set global name for all produced projects. Note, proper file extension will be added by buid scripts.') parser.add_option('-u', '--shuffle', dest='shuffle_test_order', From 005c3a7b87a0208f2c8ec12815f7d606e61487d1 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Wed, 13 Aug 2014 11:11:51 +0100 Subject: [PATCH 34/41] Host test: wrapped timeout for MUTs serial port access to handle IO_SERIAL error while accessing serial port --- workspace_tools/host_tests/host_test.py | 9 +++++++++ workspace_tools/host_tests/rtc_auto.py | 4 +++- workspace_tools/host_tests/wait_us_auto.py | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/workspace_tools/host_tests/host_test.py b/workspace_tools/host_tests/host_test.py index 09a477357e8..6503d174f94 100644 --- a/workspace_tools/host_tests/host_test.py +++ b/workspace_tools/host_tests/host_test.py @@ -86,6 +86,7 @@ def __init__(self): print 'Mbed: "%s" "%s"' % (self.port, self.disk) def init_serial(self, baud=9600, extra_baud=9600): + """ Initialize serial port. Function will return error is port can't be opened or initialized """ result = True try: self.serial = Serial(self.port, timeout=1) @@ -100,6 +101,14 @@ def init_serial(self, baud=9600, extra_baud=9600): self.flush() return result + def serial_timeout(self, timeout): + """ Wraps self.mbed.serial object timeout property """ + result = None + if self.serial: + self.serial.timeout = timeout + result = True + return result + def serial_read(self, count=1): """ Wraps self.mbed.serial object read method """ result = None diff --git a/workspace_tools/host_tests/rtc_auto.py b/workspace_tools/host_tests/rtc_auto.py index 3e4d5f7a09e..5a6e4c6c584 100644 --- a/workspace_tools/host_tests/rtc_auto.py +++ b/workspace_tools/host_tests/rtc_auto.py @@ -26,7 +26,9 @@ class RTCTest(DefaultTest): def run(self): test_result = True - c = self.mbed.serial.timeout = None + if self.mbed.serial_timeout(None) is None: + self.print_result("ioerr_serial") + return for i in range(0, 5): c = self.mbed.serial_read(38) # 38 len("[1256729742] [2009-10-28 11:35:42 AM]\n" if c is None: diff --git a/workspace_tools/host_tests/wait_us_auto.py b/workspace_tools/host_tests/wait_us_auto.py index 982b5719a80..9171bdb2e8d 100644 --- a/workspace_tools/host_tests/wait_us_auto.py +++ b/workspace_tools/host_tests/wait_us_auto.py @@ -23,7 +23,9 @@ class WaitusTest(DefaultTest): def run(self): test_result = True # First character to start test (to know after reset when test starts) - self.mbed.serial.timeout = None + if self.mbed.serial_timeout(None) is None: + self.print_result("ioerr_serial") + return c = self.mbed.serial_read(1) if c is None: self.print_result("ioerr_serial") From a5bdd4a8bba57d2d519b81d25131910829bc2ff0 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Wed, 13 Aug 2014 11:29:06 +0100 Subject: [PATCH 35/41] More comments added to methods in host_test.py --- workspace_tools/host_tests/host_test.py | 61 ++++++++++++++++++------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/workspace_tools/host_tests/host_test.py b/workspace_tools/host_tests/host_test.py index 6503d174f94..3045928fc84 100644 --- a/workspace_tools/host_tests/host_test.py +++ b/workspace_tools/host_tests/host_test.py @@ -28,8 +28,7 @@ from sys import stdout class Mbed: - """ - Base class for a host driven test + """ Base class for a host driven test """ def __init__(self): parser = OptionParser() @@ -83,10 +82,11 @@ def __init__(self): self.extra_serial = None self.serial = None self.timeout = self.DEFAULT_TOUT if self.options.timeout is None else self.options.timeout - print 'Mbed: "%s" "%s"' % (self.port, self.disk) + print 'Host test instrumentation on port: "%s" with serial: "%s"' % (self.port, self.disk) def init_serial(self, baud=9600, extra_baud=9600): - """ Initialize serial port. Function will return error is port can't be opened or initialized """ + """ Initialize serial port. Function will return error is port can't be opened or initialized + """ result = True try: self.serial = Serial(self.port, timeout=1) @@ -102,7 +102,8 @@ def init_serial(self, baud=9600, extra_baud=9600): return result def serial_timeout(self, timeout): - """ Wraps self.mbed.serial object timeout property """ + """ Wraps self.mbed.serial object timeout property + """ result = None if self.serial: self.serial.timeout = timeout @@ -110,7 +111,8 @@ def serial_timeout(self, timeout): return result def serial_read(self, count=1): - """ Wraps self.mbed.serial object read method """ + """ Wraps self.mbed.serial object read method + """ result = None if self.serial: try: @@ -120,7 +122,8 @@ def serial_read(self, count=1): return result def serial_write(self, write_buffer): - """ Wraps self.mbed.serial object write method """ + """ Wraps self.mbed.serial object write method + """ result = -1 if self.serial: try: @@ -131,12 +134,12 @@ def serial_write(self, write_buffer): def safe_sendBreak(self, serial): """ Wraps serial.sendBreak() to avoid serial::serialposix.py exception on Linux - Traceback (most recent call last): - File "make.py", line 189, in - serial.sendBreak() - File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 511, in sendBreak - termios.tcsendbreak(self.fd, int(duration/0.25)) - error: (32, 'Broken pipe') + Traceback (most recent call last): + File "make.py", line 189, in + serial.sendBreak() + File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 511, in sendBreak + termios.tcsendbreak(self.fd, int(duration/0.25)) + error: (32, 'Broken pipe') """ result = True try: @@ -151,15 +154,22 @@ def safe_sendBreak(self, serial): return result def touch_file(self, path): + """ Touch file and set timestamp to items + """ with open(path, 'a'): os.utime(path, None) def reset_timeout(self, timeout): + """ Timeout executed just after reset command is issued + """ for n in range(0, timeout): sleep(1) def reset(self): - """ reboot.txt - startup from standby state, reboots when in run mode. + """ Reset function. Supports 'standard' send break command via Mbed's CDC, + also handles other reset modes. + E.g. reset by touching file with specific file name: + reboot.txt - startup from standby state, reboots when in run mode. shutdown.txt - shutdown from run mode reset.txt - reset FPGA during run mode """ @@ -173,6 +183,8 @@ def reset(self): self.reset_timeout(reset_tout_s) def flush(self): + """ Flush serial ports + """ self.serial.flushInput() self.serial.flushOutput() if self.extra_serial: @@ -181,10 +193,15 @@ def flush(self): class Test: + """ Baseclass for host test's test runner + """ def __init__(self): self.mbed = Mbed() def run(self): + """ Test runner for host test. This function will start executing + test and forward test result via serial port to test suite + """ try: result = self.test() self.print_result("success" if result else "failure") @@ -193,7 +210,8 @@ def run(self): self.print_result("error") def setup(self): - """ Setup and check if configuration for test is correct. E.g. if serial port can be opened """ + """ Setup and check if configuration for test is correct. E.g. if serial port can be opened + """ result = True if not self.mbed.serial: result = False @@ -201,16 +219,20 @@ def setup(self): return result def notify(self, message): - """ On screen notification function """ + """ On screen notification function + """ print message stdout.flush() def print_result(self, result): - """ Test result unified printing function """ + """ Test result unified printing function + """ self.notify("\n{%s}\n{end}" % result) class DefaultTest(Test): + """ Test class with serial port initialization + """ def __init__(self): Test.__init__(self) serial_init_res = self.mbed.init_serial() @@ -218,6 +240,10 @@ def __init__(self): class Simple(DefaultTest): + """ Simple, basic host test's test runner waiting for serial port + output from MUT, no supervision over test running in MUT is executed. + Just waiting for result + """ def run(self): try: while True: @@ -230,5 +256,6 @@ def run(self): except KeyboardInterrupt, _: print "\n[CTRL+c] exit" + if __name__ == '__main__': Simple().run() From 278acbec5d5c375ca50e1c38d8c9550820d0e0ae Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Thu, 14 Aug 2014 11:29:56 +0100 Subject: [PATCH 36/41] Host test: wrapped mbed.serial.timeout into separate function to avoid traceback and send proper IO_SERIAL error from host test(s) --- workspace_tools/host_tests/echo.py | 2 +- workspace_tools/host_tests/host_test.py | 4 ++-- workspace_tools/host_tests/stdio_auto.py | 2 +- workspace_tools/host_tests/tcpecho_client_auto.py | 2 +- workspace_tools/host_tests/udpecho_client_auto.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/workspace_tools/host_tests/echo.py b/workspace_tools/host_tests/echo.py index f5f8300ba64..ad0f7303a8d 100644 --- a/workspace_tools/host_tests/echo.py +++ b/workspace_tools/host_tests/echo.py @@ -29,7 +29,7 @@ def test(self): TEST="longer serial test" check = True for i in range(1, 100): - self.mbed.serial.write(TEST + "\n") + self.mbed.serial_write(TEST + "\n") l = self.mbed.serial.readline().strip() if not l: continue diff --git a/workspace_tools/host_tests/host_test.py b/workspace_tools/host_tests/host_test.py index 3045928fc84..d6aa1bd8a50 100644 --- a/workspace_tools/host_tests/host_test.py +++ b/workspace_tools/host_tests/host_test.py @@ -124,12 +124,12 @@ def serial_read(self, count=1): def serial_write(self, write_buffer): """ Wraps self.mbed.serial object write method """ - result = -1 + result = None if self.serial: try: result = self.serial.write(write_buffer) except: - result = -1 + result = None return result def safe_sendBreak(self, serial): diff --git a/workspace_tools/host_tests/stdio_auto.py b/workspace_tools/host_tests/stdio_auto.py index 65fd272b9fb..b262e065ba5 100644 --- a/workspace_tools/host_tests/stdio_auto.py +++ b/workspace_tools/host_tests/stdio_auto.py @@ -31,7 +31,7 @@ def run(self): for i in range(1, 5): random_integer = random.randint(-10000, 10000) print "Generated number: " + str(random_integer) - self.mbed.serial.write(str(random_integer) + "\n") + self.mbed.serial_write(str(random_integer) + "\n") serial_stdio_msg = "" ip_msg_timeout = self.mbed.options.timeout diff --git a/workspace_tools/host_tests/tcpecho_client_auto.py b/workspace_tools/host_tests/tcpecho_client_auto.py index 9f2f26bb8c2..1d8b6b0f820 100644 --- a/workspace_tools/host_tests/tcpecho_client_auto.py +++ b/workspace_tools/host_tests/tcpecho_client_auto.py @@ -33,7 +33,7 @@ def send_server_ip_port(self, ip_address, port_no): self.mbed.reset() print "Sending server IP Address to target..." connection_str = ip_address + ":" + str(port_no) + "\n" - self.mbed.serial.write(connection_str) + self.mbed.serial_write(connection_str) class TCPEchoClient_Handler(BaseRequestHandler): diff --git a/workspace_tools/host_tests/udpecho_client_auto.py b/workspace_tools/host_tests/udpecho_client_auto.py index e03d2c59ff3..9d65bac3a81 100644 --- a/workspace_tools/host_tests/udpecho_client_auto.py +++ b/workspace_tools/host_tests/udpecho_client_auto.py @@ -32,7 +32,7 @@ def send_server_ip_port(self, ip_address, port_no): self.mbed.reset() print "Sending server IP Address to target..." connection_str = ip_address + ":" + str(port_no) + "\n" - self.mbed.serial.write(connection_str) + self.mbed.serial_write(connection_str) class UDPEchoClient_Handler(BaseRequestHandler): From a09f3dd605f18c1b8ca85be3781304e98cf09110 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Thu, 14 Aug 2014 11:30:50 +0100 Subject: [PATCH 37/41] Bugfix: when displaying extra summary using -t option some indexes are not found and dictionary must be checked against key --- workspace_tools/test_api.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 16e8b748014..54754958d70 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -370,12 +370,14 @@ def generate_test_summary_by_target(self, test_summary, shuffle_seed=None): pt.padding_width = 1 # One space between column edges and contents (default) for test in unique_tests: - test_results = result_dict[test] - row = [target, test, unique_test_desc[test]] - for toolchain in unique_toolchains: - if toolchain in test_results: - row.append(test_results[toolchain]) - pt.add_row(row) + if test in result_dict: + test_results = result_dict[test] + if test in unique_test_desc: + row = [target, test, unique_test_desc[test]] + for toolchain in unique_toolchains: + if toolchain in test_results: + row.append(test_results[toolchain]) + pt.add_row(row) result += pt.get_string() shuffle_seed_text = "Shuffle Seed: %.*f"% (self.SHUFFLE_SEED_ROUND, shuffle_seed if shuffle_seed else self.shuffle_random_seed) From 8c28ed250a774ce9ef91901e7c00b0187d10e85f Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 14 Aug 2014 11:38:11 +0100 Subject: [PATCH 38/41] Removed DISCO_F407VG from the official build It was basically useless, since there's no corresponding target on mbed.org --- workspace_tools/build_release.py | 1 - 1 file changed, 1 deletion(-) diff --git a/workspace_tools/build_release.py b/workspace_tools/build_release.py index 4867e579f7e..e1394626c5d 100755 --- a/workspace_tools/build_release.py +++ b/workspace_tools/build_release.py @@ -65,7 +65,6 @@ ('LPC11U68', ('uARM','GCC_ARM','GCC_CR')), ('GHI_MBUINO', ('ARM', 'uARM', 'GCC_ARM')), - ('DISCO_F407VG', ('ARM', 'GCC_ARM')), ) From 7d3ce4d65f72a92b88cb1a68a48dff990d02bbb3 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Thu, 14 Aug 2014 14:29:02 +0100 Subject: [PATCH 39/41] Fixed toolchain colummn order when using --config option --- workspace_tools/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 54754958d70..8dd4cc154d9 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -893,7 +893,7 @@ def print_test_configuration_from_json(json_data, join_delim=", "): target_name = target if target in TARGET_MAP else "%s*"% target row = [target_name] toolchains = targets[target] - for toolchain in toolchains_info_cols: + for toolchain in sorted(toolchains_info_cols): # Check for conflicts conflict = False if toolchain in toolchains: @@ -911,7 +911,7 @@ def print_test_configuration_from_json(json_data, join_delim=", "): # generate result string result = pt.get_string() # Test specification table - if toolchain_conflicts: # Print conflicts if the exist + if toolchain_conflicts: # Print conflicts if exist result += "\n" result += "Toolchain conflicts:\n" for target in toolchain_conflicts: From 4bc1944973a8c5667067d42a731126f7e75f3cf1 Mon Sep 17 00:00:00 2001 From: Przemek Wirkus Date: Thu, 14 Aug 2014 14:39:52 +0100 Subject: [PATCH 40/41] Removed two logger entries in global test api functions (JSON parser prompters) --- workspace_tools/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace_tools/test_api.py b/workspace_tools/test_api.py index 8dd4cc154d9..c1504b2b4b6 100644 --- a/workspace_tools/test_api.py +++ b/workspace_tools/test_api.py @@ -813,7 +813,7 @@ def get_json_data_from_file(json_spec_filename, verbose=False): result = json.load(data_file) except ValueError as json_error_msg: result = None - print self.logger.log_line(self.logger.LogType.ERROR, 'JSON file %s parsing failed. Reason: %s' % (json_spec_filename, json_error_msg)) + print 'JSON file %s parsing failed. Reason: %s' % (json_spec_filename, json_error_msg) # We can print where error occurred inside JSON file if we can parse exception msg json_format_defect_pos = json_format_error_defect_pos(str(json_error_msg)) if json_format_defect_pos is not None: @@ -823,7 +823,7 @@ def get_json_data_from_file(json_spec_filename, verbose=False): show_json_file_format_error(json_spec_filename, line, column) except IOError as fileopen_error_msg: - print self.logger.log_line(self.logger.LogType.ERROR, 'JSON file %s not opened. Reason: %s'% (json_spec_filename, fileopen_error_msg)) + print 'JSON file %s not opened. Reason: %s'% (json_spec_filename, fileopen_error_msg) print if verbose and result: pp = pprint.PrettyPrinter(indent=4) From 939725575dbe3b7670aec4ac573eec9ae4a66742 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 14 Aug 2014 17:08:56 +0100 Subject: [PATCH 41/41] Switched XADOW_M0 to uARM for correct compilation --- workspace_tools/targets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 074b5f4b086..d49e7f757c6 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -531,6 +531,7 @@ def __init__(self): self.core = "Cortex-M0" self.extra_labels = ['NXP', 'LPC11UXX', 'MCU_LPC11U35_501'] self.supported_toolchains = ["ARM", "uARM", "GCC_ARM", "GCC_CR"] + self.default_toolchain = "uARM" class ARCH_BLE(NRF51822):