Commit Graph

690 Commits

Author SHA1 Message Date
Andrew Boie a470ba1999 kernel: remove z_fatal_print()
Use LOG_ERR instead.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-09-12 05:17:39 -04:00
Ioannis Glaropoulos eddf058e1e arch: arm: be able to infer Z_ARCH_EXCEPT() for baseline SOCs
This commit makes it possible to infer Z_ARCH_EXCEPT()
calls in SVCs that escalate to HardFault due to being
invoked from priority level equal or higher to the
interrupt priority level of the SVC Handler.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-08-29 11:29:50 +02:00
Peter Bigot ce3f07954a arch/arm: rearrange for standard use of extern "C"
Consistently place C++ use of extern "C" after all include directives,
within the negative branch of _ASMLANGUAGE if used.

In arch.h the extern "C" in the including context is left active during
include of target-specific mpu headers to avoid more complex
restructuring.

Background from issue #17997:

Declarations that use C linkage should be placed within extern "C"
so the language linkage is correct when the header is included by
a C++ compiler.

Similarly #include directives should be outside the extern "C" to
ensure the language-specific default linkage is applied to any
declarations provided by the included header.

See: https://en.cppreference.com/w/cpp/language/language_linkage
Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
2019-08-20 00:49:15 +02:00
Ioannis Glaropoulos b8cd6fe626 arch: arm: fault: fix check on recoverable fault flag
'recoverable' is a value passed by reference and we
should be dereferencing the pointer, to check if the
fault has been classified as recoverable.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-08-19 09:46:24 +02:00
Bradley Bolen 8080a84887 arch: arm: Add Cortex-R5 support
Pass the correct -mcpu flags to the compiler when building for the
Cortex-R5.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-09 22:50:50 +02:00
Bradley Bolen e439cfdf38 arch: arm: Add Cortex-R4 support
Pass the correct -march and -mcpu flags to the compiler when building
for the Cortex-R4.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-09 22:50:50 +02:00
Bradley Bolen c30a71df95 arch: arm: Add Cortex-R support
This adds initial Cortex-R support for interrupts and context switching.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-09 22:50:50 +02:00
Ioannis Glaropoulos a3ee56f9a1 arch: arm: BusFault, NMI, and HardFault in Secure state when in test
This commit enables the option to route the BusFault,
HardFault, and NMI exceptions in Secure state, when
building for Cortex-M CPUs with ARM_SECURE_FIRMWARE=y.
This allows the various test to utilize BusFault,
HardFault and NMI exceptions during testing.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-08-09 16:14:16 +02:00
Bradley Bolen 06a79cc82e arch: arm: cpu_idle: Remove unused functions
Since commit c535300539 ("drivers/timer: New ARM SysTick driver"),
_NanoIdleValGet and _NanoIdleValClear have been unused.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-08 09:10:09 +02:00
Andrew Boie 8915e41b7b userspace: adjust arch memory domain interface
The current API was assuming too much, in that it expected that
arch-specific memory domain configuration is only maintained
in some global area, and updates to domains that are not currently
active have no effect.

This was true when all memory domain state was tracked in page
tables or MPU registers, but no longer works when arch-specific
memory management information is stored in thread-specific areas.

This is needed for: #13441 #13074 #15135

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-08-05 13:25:50 +02:00
Bradley Bolen e788290522 arch: arm: Move prep_c.c to common location
This file provides functionality that will be common to Cortex-R.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-02 23:37:03 +03:00
Bradley Bolen 505aebf5c9 arch: arm: Move nmi code for Cortex-R support
This code can start out being common between Cortex-R and Cortex-M.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-02 23:37:03 +03:00
Bradley Bolen 808b953ee3 arch: arm: Move fault.c to cortex_m directory
This fault handling code is specific to Cortex-M so move it to prepare
for Cortex-R support.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-02 23:37:03 +03:00
Bradley Bolen eb9f23fdb1 arch: arm: Move thread_abort.c to cortex_m specific directory
The ARM specific _impl_k_thread_abort function only applies to Cortex-M
so move it to the cortex_m specific directory.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-02 23:37:03 +03:00
Bradley Bolen 3015e7b780 arch: arm: Move irq_init.c to cortex_m specific directory
The NVIC is Cortex M specific.  Move in order to add Cortex R support.

Signed-off-by: Bradley Bolen <bbolen@lexmark.com>
2019-08-02 23:37:03 +03:00
Ioannis Glaropoulos e78b61b187 arch: arm: only allow OOPS and STACK_CHK_FAIL from nPRIV mode
User mode is only allowed to induce oopses and stack check
failures via software-triggered system fatal exceptions. This
commit forces a kernel oops if any other fatal exception reason
is enforced.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-07-29 11:08:49 -07:00
Andrew Boie 96571a8c40 kernel: rename NANO_ESF
This is now called z_arch_esf_t, conforming to our naming
convention.

This needs to remain a typedef due to how our offset generation
header mechanism works.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Andrew Boie c9a4bd47a7 arm: dump registers on fatal exceptions
We had a function that did this, but it was dead code.
Move to fatal.c and call from z_arm_fatal_error().

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Andrew Boie fe8d75acbf arm: fix exception reason code for bad syscall
ARM was reporting as a CPU exception and not a kernel
oops.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Andrew Boie 8a9e8e0cd7 kernel: support log system for fatal errors
We introduce a new z_fatal_print() API and replace all
occurrences of exception handling code to use it.
This routes messages to the logging subsystem if enabled.
Otherwise, messages are sent to printk().

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Andrew Boie 71ce8ceb18 kernel: consolidate error handling code
* z_NanoFatalErrorHandler() is now moved to common kernel code
  and renamed z_fatal_error(). Arches dump arch-specific info
  before calling.
* z_SysFatalErrorHandler() is now moved to common kernel code
  and renamed k_sys_fatal_error_handler(). It is now much simpler;
  the default policy is simply to lock interrupts and halt the system.
  If an implementation of this function returns, then the currently
  running thread is aborted.
* New arch-specific APIs introduced:
  - z_arch_system_halt() simply powers off or halts the system.
* We now have a standard set of fatal exception reason codes,
  namespaced under K_ERR_*
* CONFIG_SIMPLE_FATAL_ERROR_HANDLER deleted
* LOG_PANIC() calls moved to k_sys_fatal_error_handler()

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Andrew Boie 81245a0193 arm: don't use exc reason codes for internal state
We are standardizing to a arch-independent set of exception
reason codes, don't overload it with internal state of
the ARM fault handling code.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2019-07-25 15:06:58 -07:00
Ioannis Glaropoulos da735b9c73 arch: arm: userspace: don't use the default stack in z_arm_do_syscall
z_arm_do_syscall is executing in privileged mode. This implies
that we shall not be allowed to use the thread's default
unprivileged stack, (i.e push to or pop from it), to avoid any
possible stack corruptions.

Note that since we execute in PRIV mode and no MPU guard or
PSPLIM register is guarding the end of the default stack, we
won't be able to detect any stack overflows.

This commit implement the above change, by forcing
z_arm_do_syscall() to FIRST switch to privileged
stack and then do all the preparations to execute
the system call.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-07-02 19:18:48 -04:00
Ioannis Glaropoulos f3a1270f85 arch: arm: userspace: correct inline comment for bad syscalls
We need to correct the inline comment in swap_helper.S,
which is suggesting that system call attempts with
invalid syscall IDs (i.e. above the limit) do not force
the CPU to elevate privileges. This is in fact not true,
since the execution flow moves into valid syscall ID
handling.

In other words, all we do for system calls with invalid
ID numbers is to treat them as valid syscalls with the
K_SYSCALL_BAD ID value.

We fix the inline documentation to reflect the actual
execution flow.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-07-02 19:18:48 -04:00
Ioannis Glaropoulos 5d423b8078 userspace: minor typo fixes in various places
System call arguments are indexed from 1 to 6, so arg0
is corrected to arg1 in two occasions. In addition, the
ARM function for system calls is now called z_arm_do_syscall,
so we update the inline comment in __svc handler.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-07-02 19:18:48 -04:00
Ioannis Glaropoulos 9b03cd8bdc arch: arm: allow user to fall-back to MPU-based guards in ARMv8-M
ARMv8-M architecture supports the built-in stack overflow
detection mechanisms via the SPLIM registers. However, the
user might still wish to use the traditional MPU-based stack
overflow detection mechanism (for testing or other reasons).
We now allow the user to enable HW stack protection, but
manually turn off BUILTIN_STACK_GUARD option. This will force
the MPU_STACK_GUARD option to be selected.

It is still not allowed for the user to not select any stack
guard mechanisms, if HW_STACK_PROTECTION is selected.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-07-01 12:54:20 -07:00
Ioannis Glaropoulos e82004e211 arch: arm: mpu: minor fix to the start of the guard
Fix the start of the guard to take into account the
configurable size of the guard.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-28 12:25:08 -07:00
Anas Nashif 5b0aa794b2 cleanup: include/: move misc/reboot.h to power/reboot.h
move misc/reboot.h to power/reboot.h and
create a shim for backward-compatibility.

No functional changes to the headers.
A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES.

Related to #16539

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-27 22:55:49 -04:00
Anas Nashif a2fd7d70ec cleanup: include/: move misc/util.h to sys/util.h
move misc/util.h to sys/util.h and
create a shim for backward-compatibility.

No functional changes to the headers.
A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES.

Related to #16539

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-27 22:55:49 -04:00
Anas Nashif 9ab2a56751 cleanup: include/: move misc/printk.h to sys/printk.h
move misc/printk.h to sys/printk.h and
create a shim for backward-compatibility.

No functional changes to the headers.
A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES.

Related to #16539

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-27 22:55:49 -04:00
Anas Nashif 5eb90ec169 cleanup: include/: move misc/__assert.h to sys/__assert.h
move misc/__assert.h to sys/__assert.h and
create a shim for backward-compatibility.

No functional changes to the headers.
A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES.

Related to #16539

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-27 22:55:49 -04:00
Anas Nashif 10291a0789 cleanup: include/: move tracing.h to debug/tracing.h
move tracing.h to debug/tracing.h and
create a shim for backward-compatibility.

No functional changes to the headers.
A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES.

Related to #16539

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-27 22:55:49 -04:00
Ioannis Glaropoulos 171272cf31 arch: arm: update thread options flag and CONTROL atomically
Under FP shared registers mode (CONFIG_FP_SHARING=y),
a thread's user_options flag is checked during swap and
during stack fail check. Therefore, in k_float_disable()
we want to ensure that a thread won't be swapped-out with
K_FP_REGS flag cleared but still FP-active (CONTROL.FPCA
being not zero). To ensure that we temporarily disable
interrupts.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-27 18:07:03 -07:00
Ioannis Glaropoulos f70093afb8 arch: arm: rework stack fail checking for FP capable threads
This commit reworks the ARM stack fail checking, under FP
Sharing registers mode, to account for the right width of
the MPU stack guard.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-27 18:07:03 -07:00
Ioannis Glaropoulos 360ad9e277 arch: arm: mpu: program a wide MPU stack guard for FP capable threads
For threads that appear to be FP-capable (i.e. with K_FP_REGS
option flag set), we configure a wide MPU stack guard, if we
build with stack protection enabled (CONFIG_MPU_STACK_GUARD=y).

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-27 18:07:03 -07:00
Ioannis Glaropoulos 6a9b3f5ddd arch: arm: allocate a wide priv stack guard for FP-capable threads
When an FP capable thread (i.e. with K_FP_REGS option)
transitions into user mode, we want to allocate a wider
MPU stack guard region, to be able to successfully detect
overflows of the privilege stack during system calls. For
that we also need to re-adjust the .priv_stack_start pointer,
which denotes the start of the writable area of the privilege
stack buffer.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-27 18:07:03 -07:00
Ioannis Glaropoulos 1ef7a858a0 arch: arm: allocate a wide stack guard for FP-capable threads
When an FP capable thread is created (i.e. with K_FP_REGS
option) we want to allocate a wider MPU stack guard region,
to be able to successfully detect stack overflows. For that
we also need to re-adjust the values that will be passed to
the thread's stack_info .start and .size parameters.

applicable) for a thread which intends to use the FP services.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-27 18:07:03 -07:00
Nicolas Pitre f32330b22c stdint.h: streamline type definitions
Compilers (at least gcc and clang) already provide definitions to
create standard types and their range. For example, __INT16_TYPE__ is
normally defined as a short to be used with the int16_t typedef, and
__INT16_MAX__ is defined as 32767. So it makes sense to rely on them
rather than hardcoding our own, especially for the fast types where
the compiler itself knows what basic type is best.

Using compiler provided definitions makes even more sense when dealing
with 64-bit targets where some types such as intptr_t and size_t must
have a different size and range. Those definitions are then adjusted
by the compiler directly.

However there are two cases for which we should override those
definitions:

* The __INT32_TYPE__ definition on 32-bit targets vary between an int
  and a long int depending on the architecture and configuration.
  Notably, all compilers shipped with the Zephyr SDK, except for the
  i586-zephyr-elfiamcu variant, define __INT32_TYPE__ to a long int.
  Whereas, all Linux configurations for gcc, both 32-bit and 64-bit,
  always define __INT32_TYPE__ as an int. Having variability here is
  not welcome as pointers to a long int and to an int are not deemed
  compatible by the compiler, and printing an int32_t defined with a
  long using %d makes the compiler to complain, even if they're the
  same size on 32-bit targets. Given that an int is always 32 bits
  on all targets we might care about, and given that Zephyr hardcoded
  int32_t to an int before, then we just redefine __INT32_TYPE__ and
  derrivatives to an int to keep the peace in the code.

* The confusion also exists with __INTPTR_TYPE__. Looking again at the
  Zephyr SDK, it is defined as an int, even even when __INT32_TYPE__ is
  initially a long int. One notable exception is i586-zephyr-elf where
  __INTPTR_TYPE__ is a long int even when using -m32. On 64-bit targets
  this is always a long int. So let's redefine __INTPTR_TYPE__ to always
  be a long int on Zephyr which simplifies the code, works for both
  32-bit and 64-bit targets, and mimics what the Linux kernel does.
  Only a few print format strings needed adjustment.

In those two cases, there is a safeguard to ensure the type we're
enforcing has the right size and fail the build otherwise.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2019-06-25 23:29:22 -04:00
Ioannis Glaropoulos 639eb76729 arch: arm: make priv stack guard programming similar to normal guard
This commit aligns the programming of the privileged stack MPU
guard with that of the default stack guard (i.e of supervisor
threads). In particular:
- the guard is programmed BELOW the address indicated in
  arch.priv_stack_start; it is, therefore, similar to the
  default guard that is programmed BELOW stack_info.start.
  An ASSERT is added to confirm that the guard is programmed
  inside the thread privilege stack area.
- the stack fail check is updated accordningly
- arch.priv_stack_start is adjusted in arch_userspace_enter(),
  to make sure we account for a (possible) guard requirement,
  that is, if building with CONFIG_MPU_STACK_GUARD=y.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-24 10:16:57 -07:00
Ioannis Glaropoulos e0db39447b arch: arm: re-organize thread stack macro defines in arch.h
This commit re-organizes the macro definitions in arch.h for
the ARM architecture. In particular, the commit:
- defines the minimum alignment requirement for thread stacks,
  that is, excluding alignment requirement for (possible)
  MPU stack guards.
- defines convenience macros for the MPU stack guard align and
  size for threads using the FP services under Shared registers
  mode (CONFIG_FP_SHARING=y). For that, a hidden Kconfig option
  is defined in arch/arm/core/cortex_m/mpu/Kconfig.
- enforces stack alignment with a wide MPU stack guard (128
  bytes) under CONFIG_FP_SHARING=y for the ARMv7-M architecture,
  which requires start address alignment with power-of-two and
  region size.

The commit does not change the amount of stack that is reserved
with K_THREAD_STACK_DEFINE; it only determines the stack buffer
alignment as explained above.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-24 10:16:57 -07:00
Anas Nashif f2cb20c772 docs: fix misspelling across the tree
Found a few annoying typos and figured I better run script and
fix anything it can find, here are the results...

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2019-06-19 15:34:13 -05:00
Ioannis Glaropoulos d840d1cbb5 arch: implement arch-specific float disable routines
This commit adds the architecture-specific implementation
of k_float_disable() for ARM and x86.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-12 09:17:45 -07:00
Ioannis Glaropoulos d2c724f4c9 arch: arm: fix start of MPU guard in stack-fail check (no user mode)
When building without support for user mode (CONFIG_USERSPACE=n)
we need to correct the starting address of the MPU Guard, before
passing it to the function that evaluates whether a stack
corruption has occurred. The bug was introduced by commit
(60bae5de38) in
PR-13619, where the start address of the MPU guard was properly
corrected, but the guard start at the corresponding stack-fail
check was not adjusted accordingly.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-12 09:16:16 -07:00
Ioannis Glaropoulos b3114efc5a arch: arm: userspace: don't subtract MPU guard from top of stack
ip register holds the stack_info.size (it is passed as argument
into z_arch_user_mode_enter(.)). We trust that the value of
stack_info.size contains the accurate size of the writable
stack buffer, above stack_info.start (as specified in kernel.h).
Therefore, we do not need to subtract any bytes for the MPU
stack guard. This allows us to clean-up one more occurrence of
CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT in userspace.S.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-06-03 12:37:33 -07:00
Ioannis Glaropoulos 18e80aeb4a arch: arm: mpu: remove arm_core_mpu_enable/disable internal API
arm_core_mpu_enable() and arm_core_mpu_disable() functions are
effectively static functions, only used in the drivers for ARM
and NXP MPU, therefore, we do not need to expose them in the
arm_core_mpu_dev.h header.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-05-30 09:00:05 -05:00
Ioannis Glaropoulos 45a147c271 arch: arm: mpu: move internal API inside arch/arm/cortex_m/mpu
arm_core_mpu_dev.h is an internal API, and is not supposed to
be directly called by kernel / application functions, therefore,
we can move it inside arch/arm/core/cortex_m/mpu directory.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-05-30 09:00:05 -05:00
Øyvind Rønningstad f032729c91 arch: arm: core: tz: Linking of secure entry functions into NS firmware
Add Kconfig options:
 - ARM_FIRMWARE_USES_SECURE_ENTRY_FUNCS
 - ARM_ENTRY_VENEERS_LIB_NAME

Use these to link the veneers lib into the Non-Secure Firmware when
needed.

Also, make the path passed to the linker absolute to make it work with
makefiles.

Signed-off-by: Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>
2019-05-30 13:18:04 +02:00
Ioannis Glaropoulos 1ba8c3402c arch: arm: add z_ prefix to _PlatformInit
Rename function _PlatformInit() to z_platform_init() to
comply with naming conventions.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-05-27 09:20:50 -04:00
Ioannis Glaropoulos 4f4b23b449 arch: arm: fp sharing: save & restore FP registers in context-switch
When in Sharing Floating Point Services mode we want to
dynamically save and restore the FP registers in thread
context switch, depending on whether the swapped-in and
swapped-out threads are currently using the FP registers.
This commit adds this functionality to the ARM context
switch mechanism. The logic consists of inspecting the
corresponding status flag (present in thread.arch.mode)
to decide whether to save or restore the FP registers.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-05-21 15:29:44 -04:00
Ioannis Glaropoulos 358d389c54 arch: arm: extend use of arch.mode variable in FP sharing mode
Only a single bit of the 4-byte internal (thread.arch) status
variable 'mode' is currently used, when we build with User mode
support (CONFIG_USERSPACE=y). In this commit we extend the usage
of 'mode' variable, adding an additional bit-flag to track the
status of the floating point context in a particular thread,
i.e. to track whether FP context is active or not. The status
bit is meant to be used in context-switch, to restore the FP
register context when required.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
2019-05-21 15:29:44 -04:00