mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
nrf52dk: add BLE/6lo support utilizing Nordic's SoftDevice
This commit is contained in:
parent
f45c7d4b9e
commit
e012df1bac
11
Makefile.dep
11
Makefile.dep
@ -31,6 +31,17 @@ ifneq (,$(filter gnrc_uhcpc,$(USEMODULE)))
|
||||
USEMODULE += fmt
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nordic_softdevice_ble,$(USEPKG)))
|
||||
USEMODULE += softdevice_handler
|
||||
USEMODULE += ble_common
|
||||
USEMODULE += ble_6lowpan
|
||||
USEMODULE += gnrc_sixlowpan
|
||||
USEMODULE += gnrc_sixlowpan_iphc
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += gnrc_netdev2
|
||||
USEMODULE += gnrc_ipv6_netif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_%,$(filter-out gnrc_netapi gnrc_netreg gnrc_netif% gnrc_pktbuf,$(USEMODULE))))
|
||||
USEMODULE += gnrc
|
||||
endif
|
||||
|
@ -1,3 +1,7 @@
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
|
||||
USEPKG += nordic_softdevice_ble
|
||||
endif
|
||||
|
@ -11,6 +11,13 @@ include $(RIOTBOARD)/$(BOARD)/Makefile.dep
|
||||
|
||||
# setup JLink for flashing
|
||||
export JLINK_DEVICE := nrf52
|
||||
|
||||
# special options when using SoftDevice
|
||||
ifneq (,$(filter nordic_softdevice_ble,$(USEPKG)))
|
||||
export JLINK_PRE_FLASH := loadfile $(BINDIR)/softdevice.hex
|
||||
export JLINK_FLASH_ADDR := 0x1f000
|
||||
export LINKER_SCRIPT ?= $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)_sd.ld
|
||||
endif
|
||||
include $(RIOTBOARD)/Makefile.include.jlink
|
||||
|
||||
# setup serial terminal
|
||||
|
@ -44,10 +44,10 @@ extern "C" {
|
||||
*/
|
||||
static const timer_conf_t timer_config[] = {
|
||||
/* dev, channels, width, IRQn */
|
||||
{ NRF_TIMER0, 3, TIMER_BITMODE_BITMODE_32Bit, TIMER0_IRQn }
|
||||
{ NRF_TIMER1, 3, TIMER_BITMODE_BITMODE_32Bit, TIMER1_IRQn }
|
||||
};
|
||||
|
||||
#define TIMER_0_ISR isr_timer0
|
||||
#define TIMER_0_ISR isr_timer1
|
||||
|
||||
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
@ -57,9 +57,9 @@ static const timer_conf_t timer_config[] = {
|
||||
* @{
|
||||
*/
|
||||
#define RTT_NUMOF (1U)
|
||||
#define RTT_DEV NRF_RTC0
|
||||
#define RTT_IRQ RTC0_IRQn
|
||||
#define RTT_ISR isr_rtc0
|
||||
#define RTT_DEV NRF_RTC1
|
||||
#define RTT_IRQ RTC1_IRQn
|
||||
#define RTT_ISR isr_rtc1
|
||||
#define RTT_MAX_VALUE (0xffffff)
|
||||
#define RTT_FREQUENCY (10) /* in Hz */
|
||||
#define RTT_PRESCALER (3275U) /* run with 10 Hz */
|
||||
|
@ -20,6 +20,8 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
#define DONT_OVERRIDE_NVIC
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
@ -28,14 +30,16 @@ static bool ftpan_32(void);
|
||||
static bool ftpan_37(void);
|
||||
static bool ftpan_36(void);
|
||||
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
#include "softdevice_handler.h"
|
||||
uint8_t _ble_evt_buffer[BLE_STACK_EVT_MSG_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the CPU, set IRQ priorities
|
||||
*/
|
||||
void cpu_init(void)
|
||||
{
|
||||
/* set pendSV interrupt to lowest possible priority */
|
||||
NVIC_SetPriority(PendSV_IRQn, 0xff);
|
||||
|
||||
/* Workaround for FTPAN-32
|
||||
* "DIF: Debug session automatically enables TracePort pins." */
|
||||
if (ftpan_32()) {
|
||||
@ -64,6 +68,20 @@ void cpu_init(void)
|
||||
|
||||
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
|
||||
#endif
|
||||
|
||||
/* softdevice needs to be enabled from ISR context */
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
softdevice_handler_init(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, &_ble_evt_buffer,
|
||||
BLE_STACK_EVT_MSG_BUF_SIZE, NULL);
|
||||
#endif
|
||||
/* call cortexm default initialization */
|
||||
cortexm_init();
|
||||
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
/* fixup swi0 (used as softdevice PendSV trampoline) */
|
||||
NVIC_EnableIRQ(SWI0_EGU0_IRQn);
|
||||
NVIC_SetPriority(SWI0_EGU0_IRQn, 6);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,11 +32,24 @@ extern "C" {
|
||||
* @brief ARM Cortex-M specific CPU configuration
|
||||
* @{
|
||||
*/
|
||||
#define CPU_DEFAULT_IRQ_PRIO (1U)
|
||||
#define CPU_IRQ_NUMOF (38)
|
||||
#define CPU_DEFAULT_IRQ_PRIO (2U)
|
||||
#define CPU_IRQ_NUMOF (38U)
|
||||
#define CPU_FLASH_BASE (0x00000000)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief SoftDevice settings
|
||||
* @{
|
||||
*/
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
#ifndef DONT_OVERRIDE_NVIC
|
||||
#include "nrf_soc.h"
|
||||
#undef NVIC_SetPriority
|
||||
#define NVIC_SetPriority sd_nvic_SetPriority
|
||||
#endif /* DONT_OVERRIDE_NVIC */
|
||||
#endif /* SOFTDEVICE_PRESENT */
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
27
cpu/nrf52/ldscripts/nrf52xxaa_sd.ld
Normal file
27
cpu/nrf52/ldscripts/nrf52xxaa_sd.ld
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup cpu_nrf52
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Memory definitions for the NRF52832XXAA
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000
|
||||
ram (rwx) : ORIGIN = 0x20002800, LENGTH = 0xD800
|
||||
}
|
||||
|
||||
INCLUDE cortexm_base.ld
|
@ -58,7 +58,21 @@ WEAK_DEFAULT void isr_wdt(void);
|
||||
WEAK_DEFAULT void isr_rtc1(void);
|
||||
WEAK_DEFAULT void isr_qdec(void);
|
||||
WEAK_DEFAULT void isr_lpcomp(void);
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
WEAK_DEFAULT void isr_swi0(void);
|
||||
#else
|
||||
/* For unknown reasons, setting PendSV pending within
|
||||
* the softdevice ISRs leads to a crash. This workaround
|
||||
* uses swi0 as trampoline.
|
||||
*/
|
||||
extern void thread_arch_yield(void);
|
||||
void isr_swi0(void)
|
||||
{
|
||||
thread_arch_yield();
|
||||
}
|
||||
#endif
|
||||
|
||||
WEAK_DEFAULT void isr_swi1(void);
|
||||
WEAK_DEFAULT void isr_swi2(void);
|
||||
WEAK_DEFAULT void isr_swi3(void);
|
||||
@ -76,6 +90,10 @@ WEAK_DEFAULT void isr_rtc2(void);
|
||||
WEAK_DEFAULT void isr_i2s(void);
|
||||
|
||||
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
extern void SWI2_EGU2_IRQHandler(void);
|
||||
#endif
|
||||
|
||||
/* interrupt vector table */
|
||||
ISR_VECTORS const void *interrupt_vector[] = {
|
||||
/* Exception stack pointer */
|
||||
@ -121,10 +139,14 @@ ISR_VECTORS const void *interrupt_vector[] = {
|
||||
(void *) isr_lpcomp, /* lpcomp */
|
||||
(void *) isr_swi0, /* swi0 */
|
||||
(void *) isr_swi1, /* swi1 */
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
(void *) SWI2_EGU2_IRQHandler, /* softdevice swi handler */
|
||||
#else
|
||||
(void *) isr_swi2, /* swi2 */
|
||||
(void *) isr_swi3, /* swi3 */
|
||||
(void *) isr_swi4, /* swi4 */
|
||||
(void *) isr_swi5, /* swi5 */
|
||||
#endif
|
||||
(void *) (0UL), /* swi3 */
|
||||
(void *) (0UL), /* swi4 */
|
||||
(void *) (0UL), /* swi5 */
|
||||
(void *) isr_timer3, /* timer 3 */
|
||||
(void *) isr_timer4, /* timer 4 */
|
||||
(void *) isr_pwm0, /* pwm 0 */
|
||||
|
49
pkg/nordic_softdevice_ble/Makefile
Normal file
49
pkg/nordic_softdevice_ble/Makefile
Normal file
@ -0,0 +1,49 @@
|
||||
PKG_NAME = nordic_softdevice_ble
|
||||
PKG_VERSION = 3288530
|
||||
PKG_FILE = nrf5_iot_sdk_$(PKG_VERSION).zip
|
||||
PKG_URL = https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/$(PKG_FILE)
|
||||
PKG_DIR=$(CURDIR)
|
||||
PKG_BUILDDIR=$(BINDIRBASE)/pkg/$(BOARD)/$(PKG_NAME)
|
||||
PKG_SRCDIR=$(PKG_BUILDDIR)/src
|
||||
|
||||
SOFTDEVICE := components/softdevice/s1xx_iot/s1xx-iot-prototype3_nrf52_softdevice.hex
|
||||
BLE_6LOWPAN_LIB := components/iot/ble_6lowpan/lib/ble_6lowpan.a
|
||||
MODULE_MAKEFILE := $(PKG_DIR)/Makefile.module
|
||||
|
||||
.PHONY: all clean distclean
|
||||
|
||||
all: $(BINDIR)/ble_6lowpan.a $(BINDIR)/softdevice.hex
|
||||
|
||||
$(BINDIR)/ble_6lowpan.a: $(PKG_SRCDIR)/.extracted
|
||||
cp $(PKG_SRCDIR)/$(BLE_6LOWPAN_LIB) $@
|
||||
|
||||
$(BINDIR)/softdevice.hex: $(PKG_SRCDIR)/.extracted
|
||||
cp $(PKG_SRCDIR)/$(SOFTDEVICE) $@
|
||||
|
||||
$(PKG_SRCDIR)/.extracted: $(PKG_BUILDDIR)/$(PKG_FILE)
|
||||
rm -rf $(@D)
|
||||
mkdir -p $(@D)
|
||||
$(AD)cd $(@D) && $(UNZIP_HERE) $(PKG_BUILDDIR)/$(PKG_FILE)
|
||||
|
||||
# this file doesn't compile with RIOT, but is not needed either
|
||||
rm $(PKG_BUILDDIR)/src/components/ble/common/ble_conn_params.c
|
||||
|
||||
# setup RIOT module makefiles for nordic SDK components
|
||||
cat $(MODULE_MAKEFILE) > $(PKG_SRCDIR)/components/softdevice/common/softdevice_handler/Makefile
|
||||
|
||||
echo "MODULE=ble_common" > $(PKG_SRCDIR)/components/ble/common/Makefile
|
||||
cat $(MODULE_MAKEFILE) >> $(PKG_SRCDIR)/components/ble/common/Makefile
|
||||
|
||||
cat $(MODULE_MAKEFILE) > $(PKG_SRCDIR)/components/iot/ble_ipsp/Makefile
|
||||
|
||||
touch $@
|
||||
|
||||
$(PKG_BUILDDIR)/$(PKG_FILE):
|
||||
@mkdir -p $(@D)
|
||||
$(AD)$(DOWNLOAD_TO_FILE) $@ $(PKG_URL)
|
||||
|
||||
clean::
|
||||
rm -rf $(PKG_SRCDIR)/
|
||||
|
||||
distclean::
|
||||
rm -rf $(PKG_BUILDDIR)/
|
32
pkg/nordic_softdevice_ble/Makefile.include
Normal file
32
pkg/nordic_softdevice_ble/Makefile.include
Normal file
@ -0,0 +1,32 @@
|
||||
NORDIC_SRCS := $(BINDIRBASE)/pkg/$(BOARD)/nordic_softdevice_ble/src
|
||||
|
||||
INCLUDES += \
|
||||
-I$(RIOTBASE)/pkg/nordic_softdevice_ble/src \
|
||||
-I$(NORDIC_SRCS)/components/ble/common \
|
||||
-I$(NORDIC_SRCS)/components/device \
|
||||
-I$(NORDIC_SRCS)/components/iot/ble_6lowpan \
|
||||
-I$(NORDIC_SRCS)/components/iot/ble_ipsp \
|
||||
-I$(NORDIC_SRCS)/components/iot/common \
|
||||
-I$(NORDIC_SRCS)/components/libraries/scheduler \
|
||||
-I$(NORDIC_SRCS)/components/libraries/util \
|
||||
-I$(NORDIC_SRCS)/components/softdevice/common/softdevice_handler \
|
||||
-I$(NORDIC_SRCS)/components/softdevice/s1xx_iot/headers \
|
||||
-I$(NORDIC_SRCS)/components/softdevice/s1xx_iot/headers/nrf52 \
|
||||
-I$(NORDIC_SRCS)/components/toolchain
|
||||
|
||||
CFLAGS += -DNRF52 \
|
||||
-DBLE_STACK_SUPPORT_REQD \
|
||||
-DISR_STACKSIZE=8192 \
|
||||
-DSOFTDEVICE_PRESENT \
|
||||
-DS132
|
||||
|
||||
# Nordic's ble_6lowpan.a is compiled with hard-float
|
||||
# so set this, otherwise linking fails
|
||||
CFLAGS_FPU := -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
|
||||
DIRS += \
|
||||
$(RIOTBASE)/pkg/nordic_softdevice_ble/src \
|
||||
$(NORDIC_SRCS)/components/softdevice/common/softdevice_handler \
|
||||
$(NORDIC_SRCS)/components/ble/common \
|
||||
$(NORDIC_SRCS)/components/iot/ble_ipsp
|
||||
|
1
pkg/nordic_softdevice_ble/Makefile.module
Normal file
1
pkg/nordic_softdevice_ble/Makefile.module
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
100
pkg/nordic_softdevice_ble/README-BLE-6LoWPAN.md
Normal file
100
pkg/nordic_softdevice_ble/README-BLE-6LoWPAN.md
Normal file
@ -0,0 +1,100 @@
|
||||
This README contains information how to establish an IPv6 connecton between
|
||||
Linux BLE router and an IPSP enabled BLE device.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
In general, any device capable of running Linux operating system, can be used
|
||||
as a BLE router provided the following conditions are met:
|
||||
|
||||
* Linux Kernel >3.18 is used
|
||||
* bluez, libcap-ng0, radvd tools are present.
|
||||
|
||||
If a built-in Bluetooth device is not available then Bluetooth 4.0 compatible
|
||||
USB dongle can be used.
|
||||
|
||||
The following procedures have been tested on Ubuntu 15.10.
|
||||
|
||||
Establishing an IPv6 connection
|
||||
===============================
|
||||
Use the following procedure to establish a connection between an nRF52 device
|
||||
and Linux router:
|
||||
|
||||
First enable 6LoWPAN module. This is neccessary only once per session:
|
||||
|
||||
# Log in as a root user.
|
||||
sudo su
|
||||
|
||||
# Mount debugfs file system.
|
||||
mount -t debugfs none /sys/kernel/debug
|
||||
|
||||
# Load 6LoWPAN module.
|
||||
modprobe bluetooth_6lowpan
|
||||
|
||||
# Enable the bluetooth 6lowpan module.
|
||||
echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable
|
||||
|
||||
# Look for available HCI devices.
|
||||
hciconfig
|
||||
|
||||
# Reset HCI device - for example hci0 device.
|
||||
hciconfig hci0 reset
|
||||
|
||||
# Read 00:AA:BB:XX:YY:ZZ address of the nRF5x device.
|
||||
hcitool lescan
|
||||
|
||||
If you see device name and address in lescan output then you can connect to the
|
||||
device:
|
||||
|
||||
echo "connect 00:AA:BB:XX:YY:ZZ 1" > /sys/kernel/debug/bluetooth/6lowpan_control
|
||||
|
||||
If above is successful then LED1 will stop blinking and LED2 will switch on.
|
||||
You can then check the connection using the following commands:
|
||||
|
||||
# Check if bt0 interface is present and up
|
||||
ifconfig
|
||||
|
||||
# Try to ping the device using its link-local address, for example, on bt0 interface.
|
||||
ping6 fe80::2aa:bbff:fexx:yyzz%bt0
|
||||
|
||||
If you'd like to learn more about the procedure please refer to
|
||||
[Connecting devices to the router].
|
||||
|
||||
Distributing routable IPv6 prefix
|
||||
=================================
|
||||
In Linux, Router Advertisement Daemon (RADVD) can be used to distribute prefixes
|
||||
in the network, hance configure routable IPv6 address.
|
||||
|
||||
To configure RADVD create `/etc/radvd.conf` file and paste the following contents:
|
||||
|
||||
interface bt0
|
||||
{
|
||||
AdvSendAdvert on;
|
||||
prefix 2001:db8::/64
|
||||
{
|
||||
AdvOnLink off;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr on;
|
||||
};
|
||||
};
|
||||
|
||||
Next, start RADVD daemon:
|
||||
|
||||
# Set IPv6 forwarding (must be present).
|
||||
sudo echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
|
||||
# Run radvd daemon.
|
||||
sudo service radvd restart
|
||||
|
||||
If successfull then all devices connected to the host will receive
|
||||
a routable `2001:db8` prefix.
|
||||
|
||||
This can be verified by sending echo request to the full address:
|
||||
|
||||
ping6 -I bt0 2001:db8::2aa:bbff:fexx:yyzz
|
||||
|
||||
where `aa:bbff:fexx:yyzz` is device Bluetooth address.
|
||||
|
||||
If you'd like to learn more about the procedure please refer to
|
||||
[Distributing a global IPv6 prefix].
|
||||
|
||||
* [Connecting devices to the router]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00089.html
|
||||
* [Distributing a global IPv6 prefix]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00090.html
|
30
pkg/nordic_softdevice_ble/README.md
Normal file
30
pkg/nordic_softdevice_ble/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Overview
|
||||
|
||||
This package provides necessary Makefiles and glue code to use the Nordic S132
|
||||
SoftDevice as Bluetooth BLE transport for RIOT's 6lowpan stack.
|
||||
|
||||
# Usage
|
||||
|
||||
"gnrc_netdev_default" has a dependency to "nordic_softdevice_ble", so all
|
||||
examples automatically download the SDK and compile / link / flash all needed
|
||||
code.
|
||||
|
||||
If you want to manually set up included modules, add "USEPKG +=
|
||||
nordic_softdevice_ble" to your application's Makefile.
|
||||
|
||||
See README-BLE-6LoWPAN.md for instructions on how to set up 6lowpan over BLE on
|
||||
Linux.
|
||||
|
||||
# Known issues
|
||||
|
||||
- floating point ABI mismatch
|
||||
|
||||
The Nordic binaries are compiled using hard float ABI, which RIOT currently
|
||||
doesn't support (RIOT's context switching code doesn't preserve the floating
|
||||
point registers). If the softdevice is compiled in, RIOT will be compiled with
|
||||
hard float ABI in order for the linking to succeed. This works for some
|
||||
application, but will lead to serious and hard-to-find bugs for code using
|
||||
floating point instructions.
|
||||
|
||||
Hopefully, either the RIOT community adds hard-float support, or Nordic
|
||||
releases a soft-float version of the used binaries.
|
2
pkg/nordic_softdevice_ble/src/Makefile
Normal file
2
pkg/nordic_softdevice_ble/src/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
MODULE = nordic_softdevice_ble
|
||||
include $(RIOTBASE)/Makefile.base
|
9
pkg/nordic_softdevice_ble/src/app_error.c
Normal file
9
pkg/nordic_softdevice_ble/src/app_error.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "app_error.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
|
||||
{
|
||||
puts("nordic softdevice app_error_handler()");
|
||||
}
|
235
pkg/nordic_softdevice_ble/src/ble-core.c
Normal file
235
pkg/nordic_softdevice_ble/src/ble-core.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @addtogroup cpu
|
||||
* @{
|
||||
*
|
||||
* @addtogroup nrf52832
|
||||
* @{
|
||||
*
|
||||
* @addtogroup nrf52832-ble Bluetooth Low Energy drivers
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* Basic BLE functions.
|
||||
* @author
|
||||
* Wojciech Bober <wojciech.bober@nordicsemi.no>
|
||||
* Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//#include "boards.h"
|
||||
//#include "nordic_common.h"
|
||||
//#include "nrf_delay.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "ble_advdata.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "ble_ipsp.h"
|
||||
#include "softdevice_handler.h"
|
||||
#include "app_error.h"
|
||||
#include "iot_defines.h"
|
||||
#include "ble-core.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define IS_SRVC_CHANGED_CHARACT_PRESENT 1
|
||||
#define APP_ADV_TIMEOUT 0 /**< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables timeout. */
|
||||
#define APP_ADV_ADV_INTERVAL MSEC_TO_UNITS(333, UNIT_0_625_MS) /**< The advertising interval. This value can vary between 100ms to 10.24s). */
|
||||
|
||||
static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */
|
||||
|
||||
static void
|
||||
ble_evt_dispatch(ble_evt_t * p_ble_evt);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize and enable the BLE stack.
|
||||
*/
|
||||
void
|
||||
ble_stack_init(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
// Enable BLE stack.
|
||||
ble_enable_params_t ble_enable_params;
|
||||
memset(&ble_enable_params, 0, sizeof(ble_enable_params));
|
||||
ble_enable_params.gatts_enable_params.attr_tab_size =
|
||||
BLE_GATTS_ATTR_TAB_SIZE_DEFAULT;
|
||||
ble_enable_params.gatts_enable_params.service_changed =
|
||||
IS_SRVC_CHANGED_CHARACT_PRESENT;
|
||||
err_code = sd_ble_enable(&ble_enable_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Register with the SoftDevice handler module for BLE events.
|
||||
err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Setup address
|
||||
ble_gap_addr_t ble_addr;
|
||||
err_code = sd_ble_gap_address_get(&ble_addr);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
ble_addr.addr[5] = 0x00;
|
||||
ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
|
||||
|
||||
err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &ble_addr);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Return device EUI64 MAC address
|
||||
* @param addr pointer to a buffer to store the address
|
||||
*/
|
||||
void
|
||||
ble_get_mac(uint8_t addr[8])
|
||||
{
|
||||
uint32_t err_code;
|
||||
ble_gap_addr_t ble_addr;
|
||||
|
||||
err_code = sd_ble_gap_address_get(&ble_addr);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
IPV6_EUI64_CREATE_FROM_EUI48(addr, ble_addr.addr, ble_addr.addr_type);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize BLE advertising data.
|
||||
* @param name Human readable device name that will be advertised
|
||||
*/
|
||||
void
|
||||
ble_advertising_init(const char *name)
|
||||
{
|
||||
uint32_t err_code;
|
||||
ble_advdata_t advdata;
|
||||
uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
|
||||
|
||||
err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)name,
|
||||
strlen(name));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
ble_uuid_t adv_uuids[] = {{BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}};
|
||||
|
||||
// Build and set advertising data.
|
||||
memset(&advdata, 0, sizeof(advdata));
|
||||
|
||||
advdata.name_type = BLE_ADVDATA_FULL_NAME;
|
||||
advdata.flags = flags;
|
||||
advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
|
||||
advdata.uuids_complete.p_uuids = adv_uuids;
|
||||
|
||||
err_code = ble_advdata_set(&advdata, NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Initialize advertising parameters (used when starting advertising).
|
||||
memset(&m_adv_params, 0, sizeof(m_adv_params));
|
||||
|
||||
m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
|
||||
m_adv_params.p_peer_addr = NULL; // Undirected advertisement.
|
||||
m_adv_params.fp = BLE_GAP_ADV_FP_ANY;
|
||||
m_adv_params.interval = APP_ADV_ADV_INTERVAL;
|
||||
m_adv_params.timeout = APP_ADV_TIMEOUT;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Start BLE advertising.
|
||||
*/
|
||||
void
|
||||
ble_advertising_start(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
err_code = sd_ble_gap_adv_start(&m_adv_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
DEBUG("ble-core: advertising started\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Print GAP address.
|
||||
* @param addr a pointer to address
|
||||
*/
|
||||
void
|
||||
ble_gap_addr_print(const ble_gap_addr_t *addr)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; i < sizeof(addr->addr); i++) {
|
||||
if(i > 0) {
|
||||
DEBUG(":");
|
||||
}DEBUG("%02x", addr->addr[i]);
|
||||
}DEBUG(" (%d)", addr->addr_type);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Function for handling the Application's BLE Stack events.
|
||||
* @param[in] p_ble_evt Bluetooth stack event.
|
||||
*/
|
||||
static void
|
||||
on_ble_evt(ble_evt_t *p_ble_evt)
|
||||
{
|
||||
switch(p_ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
DEBUG("ble-core: connected [handle:%d, peer: ", p_ble_evt->evt.gap_evt.conn_handle);
|
||||
ble_gap_addr_print(&(p_ble_evt->evt.gap_evt.params.connected.peer_addr));
|
||||
DEBUG("]\n");
|
||||
sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
BLE_GAP_RSSI_THRESHOLD_INVALID,
|
||||
0);
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
DEBUG("ble-core: disconnected [handle:%d]\n", p_ble_evt->evt.gap_evt.conn_handle);
|
||||
ble_advertising_start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief SoftDevice BLE event callback.
|
||||
* @param[in] p_ble_evt Bluetooth stack event.
|
||||
*/
|
||||
static void
|
||||
ble_evt_dispatch(ble_evt_t *p_ble_evt)
|
||||
{
|
||||
ble_ipsp_evt_handler(p_ble_evt);
|
||||
on_ble_evt(p_ble_evt);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
61
pkg/nordic_softdevice_ble/src/ble-core.h
Normal file
61
pkg/nordic_softdevice_ble/src/ble-core.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \addtogroup cpu
|
||||
* @{
|
||||
*
|
||||
* \addtogroup nrf52832
|
||||
* @{
|
||||
*
|
||||
* \addtogroup nrf52832-ble Bluetooth Low Energy drivers
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* Basic BLE functions.
|
||||
* \author
|
||||
* Wojciech Bober <wojciech.bober@nordicsemi.no>
|
||||
*/
|
||||
#ifndef DEV_BLE_H_
|
||||
#define DEV_BLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void ble_stack_init(void);
|
||||
void ble_advertising_init(const char *name);
|
||||
void ble_advertising_start(void);
|
||||
void ble_get_mac(uint8_t addr[8]);
|
||||
|
||||
#endif /* DEV_BLE_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
305
pkg/nordic_softdevice_ble/src/ble-mac.c
Normal file
305
pkg/nordic_softdevice_ble/src/ble-mac.c
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DONT_OVERRIDE_NVIC
|
||||
|
||||
#include "ble-core.h"
|
||||
#include "ble_ipsp.h"
|
||||
#include "ble_gap.h"
|
||||
|
||||
#include "ble-mac.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
#include "od.h"
|
||||
#endif
|
||||
|
||||
#ifndef BLE_MAC_MAX_INTERFACE_NUM
|
||||
#define BLE_MAC_MAX_INTERFACE_NUM (1U) /**< Maximum number of interfaces, i.e.,
|
||||
connection to master devices */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t peer_addr[8];
|
||||
ble_ipsp_handle_t handle;
|
||||
} ble_mac_interface_t;
|
||||
|
||||
static ble_mac_interface_t interfaces[BLE_MAC_MAX_INTERFACE_NUM];
|
||||
|
||||
volatile int ble_mac_busy_tx;
|
||||
volatile int ble_mac_busy_rx;
|
||||
|
||||
static ble_mac_inbuf_t inbuf;
|
||||
static ble_mac_callback_t _callback;
|
||||
|
||||
/**
|
||||
* @brief Lookup interface by IPSP connection.
|
||||
*
|
||||
* @param[in] handle a pointer to IPSP handle.
|
||||
* @return a pointer to interface structure
|
||||
* @return NULL if no interface has been found for a given handle
|
||||
*/
|
||||
static ble_mac_interface_t *ble_mac_interface_lookup(ble_ipsp_handle_t *handle)
|
||||
{
|
||||
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
|
||||
if (interfaces[i].handle.conn_handle == handle->conn_handle &&
|
||||
interfaces[i].handle.cid == handle->cid) {
|
||||
return &interfaces[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add IPSP connection to the interface table.
|
||||
*
|
||||
* This function binds IPSP connection with peer address.
|
||||
*
|
||||
* @param[in] peer a pointer to eui64 address
|
||||
* @param[in] handle a pointer to IPSP handle
|
||||
*
|
||||
* @return a pointer to an interface structure on success
|
||||
* @return NULL if interface table is full
|
||||
*/
|
||||
static ble_mac_interface_t *ble_mac_interface_add(uint8_t peer[8],
|
||||
ble_ipsp_handle_t *handle)
|
||||
{
|
||||
DEBUG("ble_mac_interface_add()");
|
||||
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
|
||||
if (interfaces[i].handle.conn_handle == 0 && interfaces[i].handle.cid == 0) {
|
||||
memcpy(&interfaces[i].handle, handle, sizeof(ble_ipsp_handle_t));
|
||||
memcpy(&interfaces[i].peer_addr, peer, 8);
|
||||
|
||||
/* notify handler thread */
|
||||
/* msg_t m = { .type = BLE_IFACE_ADDED, .content.ptr = &interfaces[i] }; */
|
||||
/* msg_send(&m, gnrc_nordic_ble_6lowpan_pid); */
|
||||
|
||||
return &interfaces[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove interface from the interface table.
|
||||
* @param[in] interface a pointer to interface
|
||||
*/
|
||||
static void ble_mac_interface_delete(ble_mac_interface_t *interface)
|
||||
{
|
||||
DEBUG("ble_mac_interface_delete()");
|
||||
memset(interface, 0, sizeof(ble_mac_interface_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lookup IPSP handle by peer address.
|
||||
*
|
||||
* @param[in] addr a pointer to eui64 address.
|
||||
* @retval a pointer to IPSP handle on success
|
||||
* @retval NULL if an IPSP handle for given address haven't been found
|
||||
*/
|
||||
static ble_ipsp_handle_t *_find_handle(const uint8_t *addr)
|
||||
{
|
||||
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
|
||||
if (memcmp(interfaces[i].peer_addr, addr, BLE_SIXLOWPAN_L2_ADDR_LEN) == 0) {
|
||||
return &interfaces[i].handle;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send packet on a given IPSP handle.
|
||||
*
|
||||
* @param[in] handle a pointer to IPSP handle.
|
||||
* @return 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _send_to_peer(ble_ipsp_handle_t *handle, void *data, size_t len)
|
||||
{
|
||||
DEBUG("ble-mac: sending packet[GAP handle:%d CID:0x%04X]\n",
|
||||
handle->conn_handle, handle->cid);
|
||||
return ble_ipsp_send(handle, data, len);
|
||||
}
|
||||
|
||||
static int _is_broadcast(uint8_t dest[8])
|
||||
{
|
||||
uint32_t *_dest = (uint32_t*)dest;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (_dest[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ble_mac_send(uint8_t dest[8], void *data, size_t len)
|
||||
{
|
||||
DEBUG("ble_mac_send(): sending pkt with len %u\n", (unsigned)len);
|
||||
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
od_hex_dump(dest, 8, OD_WIDTH_DEFAULT);
|
||||
od_hex_dump(data, len, OD_WIDTH_DEFAULT);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
ble_ipsp_handle_t *handle;
|
||||
int ret = -1;
|
||||
|
||||
if ((!dest) || _is_broadcast(dest)) {
|
||||
DEBUG("broadcast\n");
|
||||
for (i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
|
||||
if (interfaces[i].handle.cid != 0 && interfaces[i].handle.conn_handle != 0) {
|
||||
ret = _send_to_peer(&interfaces[i].handle, data, len);
|
||||
DEBUG("ret=%i\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((handle = _find_handle(dest)) != NULL) {
|
||||
DEBUG("unicast\n");
|
||||
ret = _send_to_peer(handle, data, len);
|
||||
}
|
||||
else {
|
||||
DEBUG("ble-mac: no connection found for peer\n");
|
||||
}
|
||||
|
||||
if (ret == NRF_SUCCESS) {
|
||||
ble_mac_busy_tx = 1;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DEBUG("ble-mac: send error: %i\n", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t ble_mac_ipsp_evt_handler_irq(ble_ipsp_handle_t *p_handle, ble_ipsp_evt_t *p_evt)
|
||||
{
|
||||
uint32_t retval = NRF_SUCCESS;
|
||||
|
||||
ble_mac_interface_t *p_instance = NULL;
|
||||
|
||||
p_instance = ble_mac_interface_lookup(p_handle);
|
||||
|
||||
if (p_handle) {
|
||||
DEBUG("ble-mac: IPSP event [handle:%d CID 0x%04X]\n", p_handle->conn_handle, p_handle->cid);
|
||||
}
|
||||
|
||||
switch (p_evt->evt_id) {
|
||||
case BLE_IPSP_EVT_CHANNEL_CONNECTED: {
|
||||
uint8_t peer_addr[8];
|
||||
|
||||
DEBUG("ble-mac: channel connected\n");
|
||||
ble_eui64_from_eui48(peer_addr, p_evt->evt_param->params.ch_conn_request.peer_addr.addr,
|
||||
p_evt->evt_param->params.ch_conn_request.peer_addr.addr_type ==
|
||||
BLE_GAP_ADDR_TYPE_PUBLIC);
|
||||
|
||||
p_instance = ble_mac_interface_add(peer_addr, p_handle);
|
||||
|
||||
if (p_instance != NULL) {
|
||||
DEBUG("ble-mac: added new IPSP interface\n");
|
||||
}
|
||||
else {
|
||||
DEBUG("ble-mac: cannot add new interface. Table is full\n");
|
||||
ble_ipsp_disconnect(p_handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_IPSP_EVT_CHANNEL_DISCONNECTED: {
|
||||
DEBUG("ble-mac: channel disconnected\n");
|
||||
if (p_instance != NULL) {
|
||||
DEBUG("ble-mac: removed IPSP interface\n");
|
||||
ble_mac_interface_delete(p_instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_IPSP_EVT_CHANNEL_DATA_RX: {
|
||||
DEBUG("ble-mac: data received\n");
|
||||
if (p_instance != NULL) {
|
||||
if (ble_mac_busy_rx) {
|
||||
DEBUG("ble-mac: packet dropped as input buffer is busy\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_evt->evt_param->params.ch_rx.len > BLE_SIXLOWPAN_MTU) {
|
||||
DEBUG("ble-mac: packet buffer is too small!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ble_mac_busy_rx = 1;
|
||||
|
||||
inbuf.len = p_evt->evt_param->params.ch_rx.len;
|
||||
memcpy(inbuf.payload, p_evt->evt_param->params.ch_rx.p_data, inbuf.len);
|
||||
memcpy(inbuf.src, p_instance->peer_addr, 8);
|
||||
sd_ble_gap_rssi_get(p_handle->conn_handle, &inbuf.rssi);
|
||||
|
||||
_callback(BLE_EVENT_RX_DONE, &inbuf);
|
||||
}
|
||||
else {
|
||||
DEBUG("ble-mac: got data to unknown interface!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE: {
|
||||
DEBUG("ble-mac: data transmitted\n");
|
||||
ble_mac_busy_tx = 0;
|
||||
//_callback(BLE_EVENT_TX_DONE, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sched_context_switch_request) {
|
||||
NVIC_SetPendingIRQ( SWI0_EGU0_IRQn );
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ble_mac_init(ble_mac_callback_t callback)
|
||||
{
|
||||
assert(callback);
|
||||
|
||||
uint32_t res;
|
||||
ble_ipsp_init_t ipsp_init_params = {
|
||||
.evt_handler = ble_mac_ipsp_evt_handler_irq
|
||||
};
|
||||
|
||||
_callback = callback;
|
||||
|
||||
res = ble_ipsp_init(&ipsp_init_params);
|
||||
DEBUG("ble_ipsp_init() res = %" PRIu32 "\n", res);
|
||||
(void)res;
|
||||
}
|
50
pkg/nordic_softdevice_ble/src/ble-mac.h
Normal file
50
pkg/nordic_softdevice_ble/src/ble-mac.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef BLE_MAC_H
|
||||
#define BLE_MAC_H
|
||||
|
||||
typedef enum {
|
||||
BLE_EVENT_RX_DONE = 20000,
|
||||
} ble_mac_event_enum_t;
|
||||
|
||||
#define BLE_IFACE_ADDED (10000)
|
||||
|
||||
#define BLE_SIXLOWPAN_MTU (1280U)
|
||||
#define BLE_SIXLOWPAN_L2_ADDR_LEN (8)
|
||||
|
||||
#define IPV6_IID_FLIP_VALUE (0x02)
|
||||
|
||||
#include "net/eui64.h"
|
||||
|
||||
static inline void ble_eui64_from_eui48(uint8_t eui64[8], uint8_t eui48[6], int _public)
|
||||
{
|
||||
eui64[0] = eui48[5];
|
||||
eui64[1] = eui48[4];
|
||||
eui64[2] = eui48[3];
|
||||
eui64[3] = 0xFF;
|
||||
eui64[4] = 0xFE;
|
||||
eui64[5] = eui48[2];
|
||||
eui64[6] = eui48[1];
|
||||
eui64[7] = eui48[0];
|
||||
if (_public) {
|
||||
eui64[0] &= ~(IPV6_IID_FLIP_VALUE);
|
||||
}
|
||||
else {
|
||||
eui64[0] |= IPV6_IID_FLIP_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t src[8];
|
||||
uint8_t payload[BLE_SIXLOWPAN_MTU];
|
||||
uint16_t len;
|
||||
int8_t rssi;
|
||||
} ble_mac_inbuf_t;
|
||||
|
||||
typedef void (*ble_mac_callback_t)(ble_mac_event_enum_t event, void*arg);
|
||||
void ble_mac_init(ble_mac_callback_t callback);
|
||||
int ble_mac_send(uint8_t dest[8], void *data, size_t len);
|
||||
|
||||
extern volatile int ble_mac_busy_tx; /**< Flag is set to 1 when the driver
|
||||
is busy transmitting a packet. */
|
||||
extern volatile int ble_mac_busy_rx; /**< Flag is set to 1 when there is a
|
||||
received packet pending. */
|
||||
#endif /* BLE_MAC_H */
|
318
pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.c
Normal file
318
pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @ingroup net
|
||||
* @file
|
||||
* @brief Glue for Nordic's SoftDevice BLE 6lowpan blob to netapi
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "msg.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
|
||||
#include "ble-core.h"
|
||||
#include "softdevice_handler.h"
|
||||
|
||||
#include "ble-mac.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
#include "od.h"
|
||||
#endif
|
||||
|
||||
#define BLE_NETAPI_MSG_QUEUE_SIZE (8U)
|
||||
#define BLE_PRIO (THREAD_PRIORITY_MAIN - 1)
|
||||
|
||||
kernel_pid_t gnrc_nordic_ble_6lowpan_pid;
|
||||
static char _stack[(THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE)];
|
||||
|
||||
static uint8_t _own_mac_addr[BLE_SIXLOWPAN_L2_ADDR_LEN];
|
||||
|
||||
static uint8_t _sendbuf[BLE_SIXLOWPAN_MTU];
|
||||
|
||||
static void _ble_mac_callback(ble_mac_event_enum_t event, void* arg)
|
||||
{
|
||||
msg_t m = { .type=event, .content.ptr=arg };
|
||||
|
||||
if (!msg_send_int(&m, gnrc_nordic_ble_6lowpan_pid)) {
|
||||
puts("_ble_mac_callback(): possibly lost interrupt");
|
||||
}
|
||||
}
|
||||
|
||||
static void _handle_raw_sixlowpan(ble_mac_inbuf_t *inbuf)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = NULL;
|
||||
|
||||
pkt = gnrc_pktbuf_add(NULL, inbuf->payload,
|
||||
inbuf->len,
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
|
||||
if(!pkt) {
|
||||
DEBUG("_handle_raw_sixlowpan(): no space left in packet buffer.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* create netif header */
|
||||
gnrc_pktsnip_t *netif_hdr;
|
||||
netif_hdr = gnrc_pktbuf_add(NULL, NULL,
|
||||
sizeof(gnrc_netif_hdr_t) + (2 * sizeof(eui64_t)),
|
||||
GNRC_NETTYPE_NETIF);
|
||||
|
||||
if (netif_hdr == NULL) {
|
||||
DEBUG("_handle_raw_sixlowpan(): no space left in packet buffer.\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
gnrc_netif_hdr_init(netif_hdr->data, BLE_SIXLOWPAN_L2_ADDR_LEN, BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
gnrc_netif_hdr_set_src_addr(netif_hdr->data, inbuf->src, BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
gnrc_netif_hdr_set_dst_addr(netif_hdr->data, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = gnrc_nordic_ble_6lowpan_pid;
|
||||
|
||||
DEBUG("_handle_raw_sixlowpan(): received packet from %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"of length %d\n",
|
||||
inbuf->src[0], inbuf->src[1], inbuf->src[2], inbuf->src[3], inbuf->src[4],
|
||||
inbuf->src[5], inbuf->src[6], inbuf->src[7], inbuf->len);
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
od_hex_dump(inbuf->payload, inbuf->len, OD_WIDTH_DEFAULT);
|
||||
#endif
|
||||
|
||||
LL_APPEND(pkt, netif_hdr);
|
||||
|
||||
/* throw away packet if no one is interested */
|
||||
if (!gnrc_netapi_dispatch_receive(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
|
||||
DEBUG("_handle_raw_sixlowpan: unable to forward packet of type %i\n", pkt->type);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static int _send(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
gnrc_netif_hdr_t *netif_hdr;
|
||||
gnrc_pktsnip_t *payload = pkt->next;
|
||||
uint8_t *dst;
|
||||
|
||||
if (ble_mac_busy_tx) {
|
||||
DEBUG("_send(): ble_mac_busy_tx\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
uint8_t *buf = _sendbuf;
|
||||
unsigned len = 0;
|
||||
|
||||
if (pkt == NULL) {
|
||||
DEBUG("_send_ble: pkt was NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pkt->type != GNRC_NETTYPE_NETIF) {
|
||||
DEBUG("_send_ble: first header is not generic netif header\n");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
netif_hdr = pkt->data;
|
||||
|
||||
/* prepare destination address */
|
||||
if (netif_hdr->flags &
|
||||
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
|
||||
dst = NULL;
|
||||
}
|
||||
else {
|
||||
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
|
||||
}
|
||||
|
||||
/* prepare packet for sending */
|
||||
while (payload) {
|
||||
memcpy(buf, payload->data, payload->size);
|
||||
len += payload->size;
|
||||
buf += payload->size;
|
||||
payload = payload->next;
|
||||
}
|
||||
|
||||
gnrc_pktbuf_release(pkt);
|
||||
|
||||
if (ble_mac_send(dst, _sendbuf, len) == -1) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int _handle_get(gnrc_netapi_opt_t *_opt)
|
||||
{
|
||||
int res = -ENOTSUP;
|
||||
uint8_t *value = _opt->data;
|
||||
|
||||
switch (_opt->opt) {
|
||||
case NETOPT_ACK_REQ:
|
||||
case NETOPT_CHANNEL:
|
||||
case NETOPT_NID:
|
||||
case NETOPT_ADDRESS:
|
||||
/* -ENOTSUP */
|
||||
break;
|
||||
case NETOPT_ADDRESS_LONG:
|
||||
assert(_opt->data_len >= BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
memcpy(value, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
value[0] = IPV6_IID_FLIP_VALUE;
|
||||
res = BLE_SIXLOWPAN_L2_ADDR_LEN;
|
||||
break;
|
||||
case NETOPT_ADDR_LEN:
|
||||
case NETOPT_SRC_LEN:
|
||||
assert(_opt->data_len == sizeof(uint16_t));
|
||||
*((uint16_t *)value) = BLE_SIXLOWPAN_L2_ADDR_LEN;
|
||||
res = sizeof(uint16_t);
|
||||
break;
|
||||
#ifdef MODULE_GNRC
|
||||
case NETOPT_PROTO:
|
||||
assert(_opt->data_len == sizeof(gnrc_nettype_t));
|
||||
*((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN;
|
||||
res = sizeof(gnrc_nettype_t);
|
||||
break;
|
||||
#endif
|
||||
/* case NETOPT_DEVICE_TYPE:
|
||||
assert(_opt->data_len == sizeof(uint16_t));
|
||||
*((uint16_t *)value) = NETDEV2_TYPE_IEEE802154;
|
||||
res = sizeof(uint16_t);
|
||||
break;*/
|
||||
case NETOPT_IPV6_IID:
|
||||
memcpy(value, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
|
||||
value[0] = IPV6_IID_FLIP_VALUE;
|
||||
res = BLE_SIXLOWPAN_L2_ADDR_LEN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Startup code and event loop of the gnrc_nordic_ble_6lowpan layer
|
||||
*
|
||||
* @return never returns
|
||||
*/
|
||||
static void *_gnrc_nordic_ble_6lowpan_thread(void *args)
|
||||
{
|
||||
(void)args;
|
||||
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: starting thread\n");
|
||||
|
||||
gnrc_nordic_ble_6lowpan_pid = thread_getpid();
|
||||
|
||||
gnrc_netapi_opt_t *opt;
|
||||
int res;
|
||||
msg_t msg, reply, msg_queue[BLE_NETAPI_MSG_QUEUE_SIZE];
|
||||
|
||||
/* setup the message queue */
|
||||
msg_init_queue(msg_queue, BLE_NETAPI_MSG_QUEUE_SIZE);
|
||||
|
||||
/* initialize BLE stack */
|
||||
assert((unsigned)softdevice_handler_isEnabled());
|
||||
|
||||
ble_stack_init();
|
||||
ble_get_mac(_own_mac_addr);
|
||||
|
||||
ble_mac_init(_ble_mac_callback);
|
||||
|
||||
ble_advertising_init("RIOT BLE");
|
||||
ble_advertising_start();
|
||||
|
||||
/* register the device to the network stack*/
|
||||
gnrc_netif_add(thread_getpid());
|
||||
|
||||
/* start the event loop */
|
||||
while (1) {
|
||||
// DEBUG("gnrc_nordic_ble_6lowpan: waiting for incoming messages\n");
|
||||
msg_receive(&msg);
|
||||
/* dispatch NETDEV and NETAPI messages */
|
||||
switch (msg.type) {
|
||||
case BLE_EVENT_RX_DONE:
|
||||
{
|
||||
DEBUG("ble rx:\n");
|
||||
_handle_raw_sixlowpan(msg.content.ptr);
|
||||
ble_mac_busy_rx = 0;
|
||||
break;
|
||||
}
|
||||
case GNRC_NETAPI_MSG_TYPE_SND:
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: GNRC_NETAPI_MSG_TYPE_SND received\n");
|
||||
_send(msg.content.ptr);
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_SET:
|
||||
/* read incoming options */
|
||||
opt = msg.content.ptr;
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n",
|
||||
netopt2str(opt->opt));
|
||||
/* set option for device driver */
|
||||
res = ENOTSUP;
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: response of netdev->set: %i\n", res);
|
||||
/* send reply to calling thread */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
reply.content.value = (uint32_t)res;
|
||||
msg_reply(&msg, &reply);
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_GET:
|
||||
/* read incoming options */
|
||||
opt = msg.content.ptr;
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n",
|
||||
netopt2str(opt->opt));
|
||||
res = _handle_get(opt);
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: response of netdev->get: %i\n", res);
|
||||
/* send reply to calling thread */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
reply.content.value = (uint32_t)res;
|
||||
msg_reply(&msg, &reply);
|
||||
break;
|
||||
default:
|
||||
DEBUG("gnrc_nordic_ble_6lowpan: Unknown command %" PRIu16 "\n", msg.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* never reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gnrc_nordic_ble_6lowpan_init(void)
|
||||
{
|
||||
kernel_pid_t res = thread_create(_stack, sizeof(_stack), BLE_PRIO,
|
||||
THREAD_CREATE_STACKTEST,
|
||||
_gnrc_nordic_ble_6lowpan_thread, NULL,
|
||||
"ble");
|
||||
assert(res > 0);
|
||||
(void)res;
|
||||
}
|
43
pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.h
Normal file
43
pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nordic Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef GNRC_NORDIC_BLE_6LOWPAN_H
|
||||
#define GNRC_NORDIC_BLE_6LOWPAN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void gnrc_nordic_ble_6lowpan_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NORDIC_BLE_6LOWPAN_H */
|
@ -225,6 +225,11 @@ void auto_init(void)
|
||||
auto_init_netdev2_tap();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
|
||||
extern void gnrc_nordic_ble_6lowpan_init(void);
|
||||
gnrc_nordic_ble_6lowpan_init();
|
||||
#endif
|
||||
|
||||
#endif /* MODULE_AUTO_INIT_GNRC_NETIF */
|
||||
|
||||
#ifdef MODULE_GNRC_IPV6_NETIF
|
||||
|
Loading…
Reference in New Issue
Block a user