Compare commits
No commits in common. "master" and "e5087fadb859695a050179a6ff8d836d2c34ee84" have entirely different histories.
master
...
e5087fadb8
46
.murdock
46
.murdock
@ -1,9 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# uncomment and change this to limit builds, e.g.,
|
||||
#export BOARDS="samr21-xpro native"
|
||||
export BOARDS="samr21-xpro native"
|
||||
# and / or
|
||||
#export APPS="examples/hello-world tests/unittests"
|
||||
#export APPS="examples/hello-world tests/unittests tests/pkg_heatshrink"
|
||||
|
||||
#
|
||||
: ${TEST_BOARDS_AVAILABLE:="esp32-wroom-32 samr21-xpro"}
|
||||
@ -105,28 +105,18 @@ tests/ieee802154_hal
|
||||
# As a rule of thumb, only add boards here if there are not differences in
|
||||
# modules or packages.
|
||||
# Eventually this list will be removed...
|
||||
#
|
||||
# msbiot and pyboard are on the list as kconfig tunes the pll due to different
|
||||
# HSE values from the standard, this is not the case in makefile.
|
||||
: ${TEST_KCONFIG_BOARD_BLOCKLIST:="
|
||||
6lowpan-clicker
|
||||
esp32-wrover-kit
|
||||
esp8266-esp-12x
|
||||
esp8266-olimex-mod
|
||||
esp8266-sparkfun-thing
|
||||
limifrog-v1
|
||||
lora-e5-dev
|
||||
msbiot
|
||||
msb-430h
|
||||
nucleo-l011k4
|
||||
nucleo-wl55jc
|
||||
omote
|
||||
openmote-b
|
||||
pic32-wifire
|
||||
|
||||
esp32-wrover-kit
|
||||
esp8266-olimex-mod
|
||||
|
||||
msbiot
|
||||
pyboard
|
||||
remote-pa
|
||||
samd10-xmini
|
||||
stk3200
|
||||
stm32f030f4-demo
|
||||
stm32f3discovery
|
||||
stm32mp157c-dk2
|
||||
"}
|
||||
|
||||
# This list will force all boards that are not in the TEST_KCONFIG_BOARD_BLOCKLIST
|
||||
@ -184,6 +174,20 @@ get_supported_kconfig_board_app() {
|
||||
if is_in_list "${board}" "${TEST_KCONFIG_BOARD_BLOCKLIST}"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# On nightlies run all possible kconfig tests on all boards
|
||||
# Normally we don't want to do this as it adds quite a bit to build time
|
||||
# and the subset of boards we are testing for are pretty good at catching
|
||||
# any bugs...
|
||||
# This will be over one day, I promise.
|
||||
if [ ${NIGHTLY} -eq 1 ]; then
|
||||
if is_in_list "${appdir}" "${TEST_KCONFIG_ENFORCE_APP_GROUPS}"; then
|
||||
return 0
|
||||
fi
|
||||
if [ -f "${appdir}/app.config.test" ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if is_in_list "${appdir}" "${TEST_KCONFIG_TEST_ALLOWLIST}"; then
|
||||
return 0
|
||||
fi
|
||||
@ -382,7 +386,7 @@ get_compile_jobs() {
|
||||
|
||||
get_apps | \
|
||||
maybe_filter_changed_apps | \
|
||||
dwqc ${DWQ_ENV} -s \
|
||||
dwqc ${DWQ_ENV} --queue default-first -s \
|
||||
${DWQ_JOBID:+--subjob} \
|
||||
"$0 get_app_board_toolchain_pairs \${1} $0 compile"
|
||||
}
|
||||
|
||||
6
Kconfig
6
Kconfig
@ -34,9 +34,13 @@ rsource "sys/Kconfig"
|
||||
rsource "pkg/Kconfig"
|
||||
|
||||
menu "External Modules"
|
||||
osource "$(KCONFIG_EXTERNAL_CONFIGS)"
|
||||
osource "$(KCONFIG_EXTERNAL_MODULE_CONFIGS)"
|
||||
endmenu # External Modules
|
||||
|
||||
menu "External Packages"
|
||||
osource "$(KCONFIG_EXTERNAL_PKG_CONFIGS)"
|
||||
endmenu # External Packages
|
||||
|
||||
comment "RIOT is in a migration phase."
|
||||
comment "Some configuration options may not be here. Use CFLAGS instead."
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
# include external modules dependencies
|
||||
# processed before RIOT ones to be evaluated before the 'default' rules.
|
||||
-include $(EXTERNAL_MODULE_PATHS:%=%/Makefile.dep)
|
||||
-include $(EXTERNAL_MODULE_PATHS:%=%Makefile.dep)
|
||||
|
||||
# pull dependencies from sys and drivers
|
||||
include $(RIOTBASE)/sys/Makefile.dep
|
||||
|
||||
@ -49,6 +49,7 @@ EXTERNAL_BOARD_DIRS ?=
|
||||
RIOTMAKE ?= $(RIOTBASE)/makefiles
|
||||
RIOTKCONFIG ?= $(RIOTBASE)/kconfigs
|
||||
RIOTPKG ?= $(RIOTBASE)/pkg
|
||||
EXTERNAL_PKG_DIRS ?=
|
||||
RIOTTOOLS ?= $(RIOTBASE)/dist/tools
|
||||
RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd)
|
||||
BUILD_DIR ?= $(RIOTBASE)/build
|
||||
@ -98,6 +99,9 @@ ifeq ($(INSIDE_DOCKER),0)
|
||||
ifeq ($(origin EXTERNAL_MODULE_DIRS),command line)
|
||||
$(error EXTERNAL_MODULE_DIRS must be passed as environment variable, and not as command line argument)
|
||||
endif
|
||||
ifeq ($(origin EXTERNAL_PKG_DIRS),command line)
|
||||
$(error EXTERNAL_PKG_DIRS must be passed as environment variable, and not as command line argument)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Deprecation of configuring 'RIOTBOARD'
|
||||
@ -142,6 +146,9 @@ EXTERNAL_BOARD_DIRS := $(foreach dir,\
|
||||
EXTERNAL_MODULE_DIRS := $(foreach dir,\
|
||||
$(EXTERNAL_MODULE_DIRS),\
|
||||
$(abspath $(dir)))
|
||||
EXTERNAL_PKG_DIRS := $(foreach dir,\
|
||||
$(EXTERNAL_PKG_DIRS),\
|
||||
$(abspath $(dir)))
|
||||
|
||||
# Ensure that all directories are set and don't contain spaces.
|
||||
ifneq (, $(filter-out 1, $(foreach v,$(__DIRECTORY_VARIABLES),$(words $($(v))))))
|
||||
@ -428,9 +435,12 @@ ifeq (1,$(TEST_KCONFIG))
|
||||
KCONFIG_PACKAGES := $(call lowercase,$(patsubst CONFIG_PACKAGE_%,%,$(filter CONFIG_PACKAGE_%,$(.VARIABLES))))
|
||||
USEPKG := $(KCONFIG_PACKAGES)
|
||||
|
||||
# Locate used packages in $(RIOTPKG).
|
||||
PKG_PATHS := $(sort $(foreach dir,$(RIOTPKG),\
|
||||
# Locate used packages in $(RIOTPKG) or $(EXTERNAL_PKG_DIRS).
|
||||
PKGDIRS := $(RIOTPKG) $(EXTERNAL_PKG_DIRS)
|
||||
PKG_PATHS := $(sort $(foreach dir,$(PKGDIRS),\
|
||||
$(foreach pkg,$(USEPKG),$(dir $(wildcard $(dir)/$(pkg)/Makefile)))))
|
||||
|
||||
EXTERNAL_MODULE_PATHS := $(dir $(EXTERNAL_MODULE_KCONFIGS))
|
||||
else
|
||||
# always select provided architecture features
|
||||
FEATURES_REQUIRED += $(filter arch_%,$(FEATURES_PROVIDED))
|
||||
@ -578,7 +588,7 @@ include $(RIOTBASE)/sys/Makefile.include
|
||||
-include $(PKG_PATHS:%=%Makefile.include)
|
||||
|
||||
# include external modules configuration
|
||||
-include $(EXTERNAL_MODULE_PATHS:%=%/Makefile.include)
|
||||
-include $(EXTERNAL_MODULE_PATHS:%=%Makefile.include)
|
||||
|
||||
# Deduplicate includes without sorting them
|
||||
# see https://stackoverflow.com/questions/16144115/makefile-remove-duplicate-words-without-sorting
|
||||
|
||||
@ -40,7 +40,6 @@ static const mtd_spi_nor_params_t _samd51_nor_params = {
|
||||
.cs = SAM0_QSPI_PIN_CS,
|
||||
.wp = SAM0_QSPI_PIN_DATA_2,
|
||||
.hold = SAM0_QSPI_PIN_DATA_3,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t samd51_nor_dev = {
|
||||
|
||||
@ -40,7 +40,6 @@ static const mtd_spi_nor_params_t _weact_nor_params = {
|
||||
.cs = WEACT_4X1CX_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t weact_nor_dev = {
|
||||
|
||||
@ -19,5 +19,5 @@ FEATURES_PROVIDED += arduino
|
||||
# This configuration enables modules that are only available when using Kconfig
|
||||
# module modelling
|
||||
ifeq (1, $(TEST_KCONFIG))
|
||||
KCONFIG_ADD_CONFIG += $(BOARDDIR)/esp32-wrover-kit.config
|
||||
KCONFIG_BOARD_CONFIG += $(BOARDDIR)/esp32-wrover-kit.config
|
||||
endif
|
||||
|
||||
@ -59,9 +59,11 @@ extern "C" {
|
||||
* @{
|
||||
**/
|
||||
#define SX127X_PARAM_SPI SPI_DEV(0)
|
||||
#if defined(BOARD_FEATHER_M0_LORA)
|
||||
#define SX127X_PARAM_SPI_NSS GPIO_PIN(PA, 6)
|
||||
#define SX127X_PARAM_RESET GPIO_PIN(PA, 8)
|
||||
#define SX127X_PARAM_DIO0 GPIO_PIN(PA, 9)
|
||||
#endif
|
||||
#define SX127X_PARAM_DIO1 GPIO_UNDEF
|
||||
#define SX127X_PARAM_DIO2 GPIO_UNDEF
|
||||
#define SX127X_PARAM_DIO3 GPIO_UNDEF
|
||||
|
||||
@ -38,7 +38,6 @@ static const mtd_spi_nor_params_t _ikea_tradfri_nor_params = {
|
||||
.cs = IKEA_TRADFRI_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t ikea_tradfri_nor_dev = {
|
||||
|
||||
@ -40,7 +40,6 @@ static const mtd_spi_nor_params_t _mtd_nor_params = {
|
||||
.cs = GPIO_PIN(PORT_A, 11),
|
||||
.wp = GPIO_PIN(PORT_C, 6),
|
||||
.hold = GPIO_PIN(PORT_C, 9),
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t mtd_nor_dev = {
|
||||
|
||||
@ -19,4 +19,6 @@ config BOARD_LIMIFROG_V1
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
select HAVE_LIS3MDL
|
||||
|
||||
source "$(RIOTBOARD)/common/stm32/Kconfig"
|
||||
|
||||
@ -25,6 +25,10 @@ config BOARD_LORA_E5_DEV
|
||||
# Put other features for this board (in alphabetical order)
|
||||
select HAS_RIOTBOOT
|
||||
|
||||
# Clock configuration
|
||||
select BOARD_HAS_HSE
|
||||
select BOARD_HAS_LSE
|
||||
|
||||
select HAVE_SAUL_GPIO
|
||||
select HAVE_LM75A
|
||||
|
||||
@ -35,3 +39,5 @@ config LORA_E5_DEV_ENABLE_3P3V
|
||||
config LORA_E5_DEV_ENABLE_5V
|
||||
bool "LoRa-E5 Development Kit - Enable 5V output"
|
||||
default y
|
||||
|
||||
source "$(RIOTBOARD)/common/stm32/Kconfig"
|
||||
|
||||
@ -16,5 +16,6 @@ config BOARD_MSB_430H
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
select BOARD_COMMON_MSB_430
|
||||
select HAVE_SHT11
|
||||
|
||||
source "$(RIOTBOARD)/common/msb-430/Kconfig"
|
||||
|
||||
@ -27,4 +27,7 @@ config BOARD_MSBIOT
|
||||
select BOARD_HAS_HSE
|
||||
select BOARD_HAS_LSE
|
||||
|
||||
select HAVE_MPU9150
|
||||
select HAVE_SAUL_GPIO
|
||||
|
||||
source "$(RIOTBOARD)/common/stm32/Kconfig"
|
||||
|
||||
@ -56,7 +56,6 @@ static const mtd_spi_nor_params_t mulle_nor_params = {
|
||||
.wait_32k_erase = 20LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.spi = MULLE_NOR_SPI_DEV,
|
||||
.addr_width = 3,
|
||||
.mode = SPI_MODE_3,
|
||||
.cs = MULLE_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
|
||||
@ -40,7 +40,6 @@ static const mtd_spi_nor_params_t _nrf52840dk_nor_params = {
|
||||
.cs = NRF52840DK_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t nrf52840dk_nor_dev = {
|
||||
|
||||
@ -18,3 +18,7 @@ config BOARD_OMOTE
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
select HAS_RIOTBOOT
|
||||
|
||||
select HAVE_SAUL_GPIO
|
||||
select HAVE_BMP180
|
||||
select HAVE_ADXL345
|
||||
|
||||
@ -18,3 +18,6 @@ config BOARD_OPENMOTE_B
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
select HAS_RIOTBOOT
|
||||
|
||||
select HAVE_SI7006
|
||||
select HAVE_SAUL_GPIO
|
||||
|
||||
@ -43,7 +43,6 @@ static const mtd_spi_nor_params_t _pinetime_nor_params = {
|
||||
.cs = PINETIME_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t pinetime_nor_dev = {
|
||||
|
||||
@ -43,7 +43,6 @@ static const mtd_spi_nor_params_t _mtd_nor_params = {
|
||||
.cs = SPI_HWCS(0), /* GPIO(PORT_A, 3) is used for HWCS(0) on FC2 */
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3, /* 24-bit addresses */
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t mtd_nor_dev = {
|
||||
|
||||
@ -11,5 +11,7 @@ config BOARD_REMOTE_PA
|
||||
bool
|
||||
default y
|
||||
select BOARD_COMMON_REMOTE
|
||||
select HAVE_SAUL_GPIO
|
||||
select HAVE_SAUL_ADC
|
||||
|
||||
source "$(RIOTBOARD)/common/remote/Kconfig"
|
||||
|
||||
@ -20,3 +20,9 @@ config BOARD_SAMD10_XMINI
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
select HAVE_SAUL_GPIO
|
||||
|
||||
choice LIBC_IMPLEMENTATION
|
||||
# Use Picolibc to reduce ROM usage
|
||||
default MODULE_PICOLIBC
|
||||
endchoice
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
#include "timex.h"
|
||||
|
||||
#ifdef MODULE_MTD
|
||||
/* N25Q256A */
|
||||
/* N25Q256A or SST26VF064B */
|
||||
static const mtd_spi_nor_params_t _same54_nor_params = {
|
||||
.opcode = &mtd_spi_nor_opcode_default,
|
||||
.wait_chip_erase = 240 * US_PER_SEC,
|
||||
@ -38,7 +38,6 @@ static const mtd_spi_nor_params_t _same54_nor_params = {
|
||||
.cs = SAM0_QSPI_PIN_CS,
|
||||
.wp = SAM0_QSPI_PIN_DATA_2,
|
||||
.hold = SAM0_QSPI_PIN_DATA_3,
|
||||
.addr_width = 4,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t same54_nor_dev = {
|
||||
|
||||
@ -41,7 +41,6 @@ static const mtd_spi_nor_params_t _serpente_nor_params = {
|
||||
.cs = SERPENTE_NOR_SPI_CS,
|
||||
.wp = GPIO_UNDEF,
|
||||
.hold = GPIO_UNDEF,
|
||||
.addr_width = 3,
|
||||
};
|
||||
|
||||
static mtd_spi_nor_t serpente_nor_dev = {
|
||||
|
||||
@ -3,9 +3,6 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
endif
|
||||
|
||||
# limit the stack size so most tests and examples compile
|
||||
CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=512
|
||||
|
||||
# add board common drivers
|
||||
USEMODULE += boards_common_silabs
|
||||
USEMODULE += silabs_bc
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
# setup JLink for flashing
|
||||
JLINK_PRE_FLASH = r
|
||||
|
||||
# limit the stack size so most tests and examples compile
|
||||
CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=512
|
||||
|
||||
# include board common
|
||||
include $(RIOTBOARD)/common/silabs/Makefile.include
|
||||
|
||||
@ -15,3 +15,9 @@ config BOARD_STM32MP157C_DK2
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
# Clock configuration
|
||||
select BOARD_HAS_HSE
|
||||
select BOARD_HAS_LSE
|
||||
|
||||
source "$(RIOTBOARD)/common/stm32/Kconfig"
|
||||
|
||||
@ -4,7 +4,3 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
# USEMODULE += si7034 # TODO: add when si70xx driver is updated
|
||||
endif
|
||||
|
||||
ifneq (,$(filter vfs,$(USEMODULE)))
|
||||
USEMODULE += mtd_sdcard
|
||||
endif
|
||||
|
||||
@ -24,11 +24,6 @@
|
||||
#define RMUTEX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
#include "c11_atomics_compat.hpp"
|
||||
#else
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#include "mutex.h"
|
||||
#include "sched.h"
|
||||
@ -62,14 +57,14 @@ typedef struct rmutex_t {
|
||||
* atomic_int_least16_t is used. Note @ref kernel_pid_t is an int16
|
||||
* @internal
|
||||
*/
|
||||
atomic_int_least16_t owner;
|
||||
kernel_pid_t owner;
|
||||
} rmutex_t;
|
||||
|
||||
/**
|
||||
* @brief Static initializer for rmutex_t.
|
||||
* @details This initializer is preferable to rmutex_init().
|
||||
*/
|
||||
#define RMUTEX_INIT { MUTEX_INIT, 0, ATOMIC_VAR_INIT(KERNEL_PID_UNDEF) }
|
||||
#define RMUTEX_INIT { MUTEX_INIT, 0, KERNEL_PID_UNDEF }
|
||||
|
||||
/**
|
||||
* @brief Initializes a recursive mutex object.
|
||||
|
||||
@ -24,9 +24,10 @@
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "atomic_utils.h"
|
||||
#include "rmutex.h"
|
||||
#include "thread.h"
|
||||
#include "assert.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -78,7 +79,7 @@ static int _lock(rmutex_t *rmutex, int trylock)
|
||||
*/
|
||||
|
||||
/* ensure that owner is read atomically, since I need a consistent value */
|
||||
owner = atomic_load_explicit(&rmutex->owner, memory_order_relaxed);
|
||||
owner = atomic_load_kernel_pid(&rmutex->owner);
|
||||
DEBUG("rmutex %" PRIi16 " : mutex held by %" PRIi16 " \n",
|
||||
thread_getpid(), owner);
|
||||
|
||||
@ -104,8 +105,7 @@ static int _lock(rmutex_t *rmutex, int trylock)
|
||||
DEBUG("rmutex %" PRIi16 " : setting the owner\n", thread_getpid());
|
||||
|
||||
/* ensure that owner is written atomically, since others need a consistent value */
|
||||
atomic_store_explicit(&rmutex->owner, thread_getpid(),
|
||||
memory_order_relaxed);
|
||||
atomic_store_kernel_pid(&rmutex->owner, thread_getpid());
|
||||
|
||||
DEBUG("rmutex %" PRIi16 " : increasing refs\n", thread_getpid());
|
||||
|
||||
@ -127,8 +127,8 @@ int rmutex_trylock(rmutex_t *rmutex)
|
||||
|
||||
void rmutex_unlock(rmutex_t *rmutex)
|
||||
{
|
||||
assert(atomic_load_explicit(&rmutex->owner,
|
||||
memory_order_relaxed) == thread_getpid());
|
||||
/* ensure that owner is read atomically, since I need a consistent value */
|
||||
assert(atomic_load_kernel_pid(&rmutex->owner) == thread_getpid());
|
||||
assert(rmutex->refcount > 0);
|
||||
|
||||
DEBUG("rmutex %" PRIi16 " : decrementing refs refs\n", thread_getpid());
|
||||
@ -143,8 +143,7 @@ void rmutex_unlock(rmutex_t *rmutex)
|
||||
DEBUG("rmutex %" PRIi16 " : resetting owner\n", thread_getpid());
|
||||
|
||||
/* ensure that owner is written only once */
|
||||
atomic_store_explicit(&rmutex->owner, KERNEL_PID_UNDEF,
|
||||
memory_order_relaxed);
|
||||
atomic_store_kernel_pid(&rmutex->owner, KERNEL_PID_UNDEF);
|
||||
|
||||
DEBUG("rmutex %" PRIi16 " : releasing mutex\n", thread_getpid());
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ config USE_CLOCK_PLL
|
||||
|
||||
config USE_CLOCK_MSI
|
||||
bool "Use direct multi-speed frequency internal oscillator (MSI)"
|
||||
depends on CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
depends on CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config USE_CLOCK_HSE
|
||||
bool "Direct High frequency external oscillator (HSE)"
|
||||
@ -33,7 +33,7 @@ config USE_CLOCK_HSI
|
||||
|
||||
endchoice
|
||||
|
||||
if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
choice
|
||||
bool "Source clock for PLL" if USE_CLOCK_PLL
|
||||
default CLOCK_PLL_SRC_HSE if BOARD_HAS_HSE
|
||||
@ -50,23 +50,23 @@ config CLOCK_PLL_SRC_HSI
|
||||
bool "Use HSI16 source clock"
|
||||
endchoice
|
||||
|
||||
endif # CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
endif # CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CUSTOM_PLL_PARAMS
|
||||
bool "Configure PLL parameters"
|
||||
depends on USE_CLOCK_PLL
|
||||
|
||||
if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_MP1
|
||||
config CLOCK_PLL_M
|
||||
int "M: PLLIN division factor" if CUSTOM_PLL_PARAMS
|
||||
default 4 if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7
|
||||
default 1 if CPU_FAM_G0
|
||||
default 6 if CPU_FAM_G4 && BOARD_HAS_HSE
|
||||
default 4 if CPU_FAM_G4
|
||||
default 6 if (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB) && CLOCK_PLL_SRC_MSI
|
||||
default 4 if CPU_FAM_WB && CLOCK_PLL_SRC_HSE
|
||||
default 2 if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
range 1 8 if CPU_FAM_G0 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
default 6 if (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL) && CLOCK_PLL_SRC_MSI
|
||||
default 4 if (CPU_FAM_WB || CPU_FAM_WL) && CLOCK_PLL_SRC_HSE
|
||||
default 2 if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL || CPU_FAM_MP1
|
||||
range 1 8 if CPU_FAM_G0 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
range 1 16 if CPU_FAM_G4
|
||||
|
||||
config CLOCK_PLL_N
|
||||
@ -85,17 +85,21 @@ config CLOCK_PLL_N
|
||||
default 90 if CPU_FAM_F4 && CLOCK_MAX_180MHZ
|
||||
default 216 if CPU_FAM_F7 && BOARD_HAS_HSE
|
||||
default 108 if CPU_FAM_F7
|
||||
default 12 if CPU_FAM_WL
|
||||
default 16 if CPU_FAM_WB
|
||||
default 30 if CPU_LINE_STM32L4A6XX || CPU_LINE_STM32L4P5XX || CPU_LINE_STM32L4Q5XX || CPU_LINE_STM32L4R5XX || CPU_LINE_STM32L4R7XX || CPU_LINE_STM32L4R9XX || CPU_LINE_STM32L4S5XX || CPU_LINE_STM32L4S7XX || CPU_LINE_STM32L4S9XX
|
||||
default 27 if CPU_FAM_L5
|
||||
default 20 if CPU_FAM_G0 || CPU_FAM_L4
|
||||
default 85 if CPU_FAM_G4
|
||||
default 52 if CPU_FAM_MP1 && BOARD_HAS_HSE
|
||||
default 78 if CPU_FAM_MP1
|
||||
range 8 86 if CPU_FAM_G0 || CPU_FAM_L4 || CPU_FAM_L5
|
||||
range 50 432 if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7
|
||||
range 8 127 if CPU_FAM_G4
|
||||
range 6 127 if CPU_FAM_WB
|
||||
range 6 127 if CPU_FAM_WB || CPU_FAM_WL
|
||||
range 4 512 if CPU_FAM_MP1
|
||||
|
||||
if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7
|
||||
if CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_MP1
|
||||
choice
|
||||
bool "Main PLL division factor (PLLP) for main system clock" if CUSTOM_PLL_PARAMS
|
||||
default PLL_P_DIV_4 if CPU_FAM_F4 && CLOCK_MAX_84MHZ
|
||||
@ -117,6 +121,7 @@ endchoice
|
||||
|
||||
config CLOCK_PLL_P
|
||||
int
|
||||
default 3 if CPU_FAM_MP1
|
||||
default 2 if PLL_P_DIV_2
|
||||
default 4 if PLL_P_DIV_4
|
||||
default 6 if PLL_P_DIV_6
|
||||
@ -129,18 +134,20 @@ config CLOCK_PLL_Q
|
||||
default 4 if CPU_FAM_F4 && CLOCK_MAX_100MHZ
|
||||
default 7 if CPU_FAM_F4 && CLOCK_MAX_180MHZ && (MODULE_PERIPH_USBDEV || USEMODULE_PERIPH_USBDEV)
|
||||
default 9 if CPU_FAM_F7
|
||||
default 13 if CPU_FAM_MP1
|
||||
default 8
|
||||
range 2 15
|
||||
endif # CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7
|
||||
endif # CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_MP1
|
||||
|
||||
if CPU_FAM_G0 || CPU_FAM_WB
|
||||
if CPU_FAM_G0 || CPU_FAM_WB || CPU_FAM_WL || CPU_FAM_MP1
|
||||
config CLOCK_PLL_R
|
||||
int "Q: VCO division factor" if CUSTOM_PLL_PARAMS
|
||||
default 2 if CPU_FAM_WB
|
||||
default 2 if CPU_FAM_WB || CPU_FAM_WL
|
||||
default 3 if CPU_FAM_MP1
|
||||
default 6 if BOARD_HAS_HSE
|
||||
default 5
|
||||
range 2 8
|
||||
endif # CPU_FAM_G0 || CPU_FAM_WB
|
||||
endif # CPU_FAM_G0 || CPU_FAM_WB || CPU_FAM_WL || CPU_FAM_MP1
|
||||
|
||||
if CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5
|
||||
choice
|
||||
@ -169,12 +176,12 @@ config CLOCK_PLL_R
|
||||
default 8 if PLL_R_DIV_8
|
||||
endif # CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5
|
||||
|
||||
endif # CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
endif # CPU_FAM_F2 || CPU_FAM_F4 || CPU_FAM_F7 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL || CPU_FAM_MP1
|
||||
|
||||
if CPU_FAM_F0 || CPU_FAM_F1 || CPU_FAM_F3
|
||||
config CLOCK_PLL_PREDIV
|
||||
int "PLLIN division factor" if CUSTOM_PLL_PARAMS && !CPU_LINE_STM32F031X6 && !CPU_LINE_STM32F042X6 && !CPU_LINE_STM32F303X8
|
||||
default 2 if CPU_LINE_STM32F031X6 || CPU_LINE_STM32F042X6 || CPU_LINE_STM32F303X8
|
||||
default 2 if CPU_LINE_STM32F031X6 || CPU_LINE_STM32F042X6 || CPU_LINE_STM32F303X8 || CPU_LINE_STM32F303XC
|
||||
default 1
|
||||
range 1 16
|
||||
|
||||
@ -282,35 +289,35 @@ config CLOCK_HSISYS_DIV
|
||||
default 128 if CLOCK_HSISYS_DIV_128
|
||||
endif # CPU_FAM_G0
|
||||
|
||||
if CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
if CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
choice
|
||||
bool "Desired MSI clock frequency" if USE_CLOCK_MSI || (USE_CLOCK_PLL && CLOCK_PLL_SRC_MSI)
|
||||
default CLOCK_MSI_48MHZ if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
default CLOCK_MSI_48MHZ if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
default CLOCK_MSI_4MHZ
|
||||
|
||||
config CLOCK_MSI_65KHZ
|
||||
bool "65.536kHz" if CPU_FAM_L0 || CPU_FAM_L1
|
||||
|
||||
config CLOCK_MSI_100KHZ
|
||||
bool "100kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "100kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_130KHZ
|
||||
bool "131.072kHz" if CPU_FAM_L0 || CPU_FAM_L1
|
||||
|
||||
config CLOCK_MSI_200KHZ
|
||||
bool "200kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "200kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_260KHZ
|
||||
bool "262.144kHz" if CPU_FAM_L0 || CPU_FAM_L1
|
||||
|
||||
config CLOCK_MSI_400KHZ
|
||||
bool "400kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "400kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_520KHZ
|
||||
bool "524.288kHz" if CPU_FAM_L0 || CPU_FAM_L1
|
||||
|
||||
config CLOCK_MSI_800KHZ
|
||||
bool "800kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "800kHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_1MHZ
|
||||
bool
|
||||
@ -325,19 +332,19 @@ config CLOCK_MSI_4MHZ
|
||||
prompt "4MHz"
|
||||
|
||||
config CLOCK_MSI_8MHZ
|
||||
bool "8MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "8MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_16MHZ
|
||||
bool "16MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "16MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_24MHZ
|
||||
bool "24MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "24MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_32MHZ
|
||||
bool "32MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "32MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MSI_48MHZ
|
||||
bool "48MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
bool "48MHz" if CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
endchoice
|
||||
|
||||
@ -351,11 +358,11 @@ config CLOCK_MSI
|
||||
default 200000 if CLOCK_MSI_200KHZ
|
||||
default 400000 if CLOCK_MSI_400KHZ
|
||||
default 800000 if CLOCK_MSI_800KHZ
|
||||
default 1000000 if CLOCK_MSI_1MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB)
|
||||
default 1000000 if CLOCK_MSI_1MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL)
|
||||
default 1048000 if CLOCK_MSI_1MHZ && (CPU_FAM_L0 || CPU_FAM_L1)
|
||||
default 2000000 if CLOCK_MSI_2MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB)
|
||||
default 2000000 if CLOCK_MSI_2MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL)
|
||||
default 2097000 if CLOCK_MSI_2MHZ && (CPU_FAM_L0 || CPU_FAM_L1)
|
||||
default 4000000 if CLOCK_MSI_4MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB)
|
||||
default 4000000 if CLOCK_MSI_4MHZ && (CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL)
|
||||
default 4194000 if CLOCK_MSI_4MHZ && (CPU_FAM_L0 || CPU_FAM_L1)
|
||||
default 8000000 if CLOCK_MSI_8MHZ
|
||||
default 16000000 if CLOCK_MSI_16MHZ
|
||||
@ -363,12 +370,12 @@ config CLOCK_MSI
|
||||
default 32000000 if CLOCK_MSI_32MHZ
|
||||
default 48000000 if CLOCK_MSI_48MHZ
|
||||
|
||||
endif # CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB
|
||||
endif # CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
choice
|
||||
bool "APB1 prescaler (division factor of HCLK to produce PCLK1)"
|
||||
default CLOCK_APB1_DIV_4 if CPU_FAM_F2 || (CPU_FAM_F4 && CLOCK_MAX_180MHZ) || CPU_FAM_F7 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_U5 || CPU_FAM_WB
|
||||
default CLOCK_APB1_DIV_2 if CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_F4
|
||||
default CLOCK_APB1_DIV_4 if CPU_FAM_F2 || (CPU_FAM_F4 && CLOCK_MAX_180MHZ) || CPU_FAM_F7 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_U5 || CPU_FAM_WB || CPU_FAM_WL
|
||||
default CLOCK_APB1_DIV_2 if CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_F4 || CPU_FAM_MP1
|
||||
default CLOCK_APB1_DIV_1
|
||||
|
||||
config CLOCK_APB1_DIV_1
|
||||
@ -399,7 +406,7 @@ config CLOCK_APB1_DIV
|
||||
choice
|
||||
bool "APB2 prescaler (division factor of HCLK to produce PCLK2)"
|
||||
depends on !CPU_FAM_G0 && !CPU_FAM_F0
|
||||
default CLOCK_APB2_DIV_2 if CPU_FAM_F2 || (CPU_FAM_F4 && CLOCK_MAX_180MHZ) || CPU_FAM_F7 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_U5 || CPU_FAM_WB
|
||||
default CLOCK_APB2_DIV_2 if CPU_FAM_F2 || (CPU_FAM_F4 && CLOCK_MAX_180MHZ) || CPU_FAM_F7 || CPU_FAM_L4 || CPU_FAM_L5 || CPU_FAM_U5 || CPU_FAM_WB || CPU_FAM_WL || CPU_FAM_MP1
|
||||
default CLOCK_APB2_DIV_1
|
||||
|
||||
config CLOCK_APB2_DIV_1
|
||||
@ -427,7 +434,7 @@ config CLOCK_APB2_DIV
|
||||
default 8 if CLOCK_APB2_DIV_8
|
||||
default 16 if CLOCK_APB2_DIV_16
|
||||
|
||||
if CPU_FAM_F0 || CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB
|
||||
if CPU_FAM_F0 || CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB || CPU_FAM_WL
|
||||
config CLOCK_ENABLE_MCO
|
||||
bool "Enable MCU Clock Output (MCO) on PA8"
|
||||
|
||||
@ -447,15 +454,15 @@ config CLOCK_MCO_USE_HSI
|
||||
|
||||
config CLOCK_MCO_USE_LSE
|
||||
bool "Use LSE as MCO source"
|
||||
depends on CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB
|
||||
depends on CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MCO_USE_LSI
|
||||
bool "Use LSI as MCO source"
|
||||
depends on CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB
|
||||
depends on CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MCO_USE_MSI
|
||||
bool "Use MSI as MCO source"
|
||||
depends on CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB
|
||||
depends on CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
config CLOCK_MCO_USE_SYSCLK
|
||||
bool "Use SYSCLK as MCO source"
|
||||
@ -484,15 +491,15 @@ config CLOCK_MCO_PRE_16
|
||||
|
||||
config CLOCK_MCO_PRE_32
|
||||
bool "Divide MCO by 32"
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB && !CPU_FAM_WL
|
||||
|
||||
config CLOCK_MCO_PRE_64
|
||||
bool "Divide MCO by 64"
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB && !CPU_FAM_WL
|
||||
|
||||
config CLOCK_MCO_PRE_128
|
||||
bool "Divide MCO by 128"
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB
|
||||
depends on !CPU_FAM_G4 && !CPU_FAM_L0 && !CPU_FAM_L1 && !CPU_FAM_L4 && !CPU_FAM_WB && !CPU_FAM_WL
|
||||
|
||||
endchoice
|
||||
|
||||
@ -507,6 +514,6 @@ config CLOCK_MCO_PRE
|
||||
default 128 if CLOCK_MCO_PRE_128
|
||||
default 1
|
||||
|
||||
endif # CPU_FAM_F0 || CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB
|
||||
endif # CPU_FAM_F0 || CPU_FAM_F1 || CPU_FAM_F3 || CPU_FAM_G0 || CPU_FAM_G4 || CPU_FAM_L0 || CPU_FAM_L1 || CPU_FAM_L4 || CPU_FAM_WB || CPU_FAM_WL
|
||||
|
||||
endmenu
|
||||
|
||||
11
dist/pythonlibs/testrunner/spawn.py
vendored
11
dist/pythonlibs/testrunner/spawn.py
vendored
@ -39,7 +39,13 @@ TEST_INTERACTIVE_DELAY = int(os.environ.get('TEST_INTERACTIVE_DELAY') or 1)
|
||||
# By default never reset after the terminal is open unless explicitly requested
|
||||
# through an environment variable.
|
||||
TESTRUNNER_RESET_AFTER_TERM = int(os.environ.get('TESTRUNNER_RESET_AFTER_TERM')
|
||||
or '0')
|
||||
or 0)
|
||||
|
||||
# When running e.g. tests/shell_ble we don't want to reset the board, because
|
||||
# then ble-serial would terminate and the created virtual serial port would get
|
||||
# lost. By default the board is reset before the test starts.
|
||||
TESTRUNNER_RESET_BOARD_ON_STARTUP = \
|
||||
int(os.environ.get('TESTRUNNER_RESET_BOARD_ON_STARTUP') or 1)
|
||||
|
||||
MAKE = os.environ.get('MAKE', 'make')
|
||||
|
||||
@ -70,7 +76,8 @@ def find_exc_origin(exc_info):
|
||||
def setup_child(timeout=10, spawnclass=pexpect.spawnu, env=None, logfile=None):
|
||||
# Some boards can't be reset after a terminal is open. Therefore reset
|
||||
# before `cleanterm`.
|
||||
_reset_board(env)
|
||||
if TESTRUNNER_RESET_BOARD_ON_STARTUP:
|
||||
_reset_board(env)
|
||||
|
||||
# on platforms exposing UART over USB, wait a little before connecting to
|
||||
# the serial terminal. This gives time for stdio to be ready.
|
||||
|
||||
@ -10,3 +10,9 @@ config MODULE_ADXL345
|
||||
depends on HAS_PERIPH_I2C
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_PERIPH_I2C
|
||||
|
||||
config HAVE_ADXL345
|
||||
bool
|
||||
select MODULE_ADXL345 if MODULE_SAUL_DEFAULT
|
||||
help
|
||||
Indicates that a adxl345 sensor is present.
|
||||
|
||||
@ -12,3 +12,9 @@ config MODULE_BMP180
|
||||
select MODULE_PERIPH_I2C
|
||||
select MODULE_ZTIMER
|
||||
select MODULE_ZTIMER_MSEC
|
||||
|
||||
config HAVE_BMP180
|
||||
bool
|
||||
select MODULE_BMP180 if MODULE_SAUL_DEFAULT
|
||||
help
|
||||
Indicates that a bmp180 sensor is present.
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "dose.h"
|
||||
#include "random.h"
|
||||
#include "irq.h"
|
||||
@ -33,6 +34,10 @@
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(DOSE_TIMER_DEV) && IS_ACTIVE(MODULE_DOSE_WATCHDOG)
|
||||
#error "DOSE_TIMER_DEV needs to be set by the board"
|
||||
#endif
|
||||
|
||||
static uint16_t crc16_update(uint16_t crc, uint8_t octet);
|
||||
static dose_signal_t state_transit_blocked(dose_t *ctx, dose_signal_t signal);
|
||||
static dose_signal_t state_transit_idle(dose_t *ctx, dose_signal_t signal);
|
||||
|
||||
@ -170,8 +170,6 @@ typedef enum {
|
||||
*/
|
||||
#if DOXYGEN
|
||||
#define DOSE_TIMER_DEV TIMER_DEV(…)
|
||||
#elif !defined(DOSE_TIMER_DEV) && IS_ACTIVE(MODULE_DOSE_WATCHDOG)
|
||||
#error "DOSE_TIMER_DEV needs to be set by the board"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -113,7 +113,6 @@ typedef struct {
|
||||
gpio_t cs; /**< CS pin GPIO handle */
|
||||
gpio_t wp; /**< Write Protect pin GPIO handle */
|
||||
gpio_t hold; /**< HOLD pin GPIO handle */
|
||||
uint8_t addr_width; /**< Number of bytes in addresses, usually 3 for small devices */
|
||||
} mtd_spi_nor_params_t;
|
||||
|
||||
/**
|
||||
@ -150,6 +149,12 @@ typedef struct {
|
||||
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
|
||||
*/
|
||||
uint8_t sec_addr_shift;
|
||||
/**
|
||||
* @brief number of address bytes
|
||||
*
|
||||
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
|
||||
*/
|
||||
uint8_t addr_width;
|
||||
} mtd_spi_nor_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -5,30 +5,46 @@
|
||||
# directory for more details.
|
||||
#
|
||||
|
||||
if TEST_KCONFIG
|
||||
|
||||
choice
|
||||
bool "MPU-9X50 accelerometer/magnetometer/gyroscope"
|
||||
optional
|
||||
depends on HAS_PERIPH_I2C
|
||||
help
|
||||
This driver supports both MPU9150 and MPU9250. Choose one model.
|
||||
|
||||
config MODULE_MPU9150
|
||||
bool "MPU-9150"
|
||||
select MODULE_MPU9X50
|
||||
|
||||
config MODULE_MPU9250
|
||||
bool "MPU-9250"
|
||||
select MODULE_MPU9X50
|
||||
|
||||
endchoice
|
||||
|
||||
config MODULE_MPU9X50
|
||||
menuconfig MODULE_MPU9X50
|
||||
bool
|
||||
prompt "MPU-9X50 accelerometer/magnetometer/gyroscope" if !(MODULE_SAUL_DEFAULT && HAVE_MPU9X50)
|
||||
default y if (MODULE_SAUL_DEFAULT && HAVE_MPU9X50)
|
||||
depends on TEST_KCONFIG
|
||||
depends on HAS_PERIPH_I2C
|
||||
select MODULE_PERIPH_I2C
|
||||
select MODULE_ZTIMER
|
||||
select MODULE_ZTIMER_MSEC
|
||||
|
||||
endif # TEST_KCONFIG
|
||||
choice
|
||||
bool "Sensor variant"
|
||||
default MODULE_MPU9150 if HAVE_MPU9150
|
||||
default MODULE_MPU9250 if HAVE_MPU9250
|
||||
depends on MODULE_MPU9X50
|
||||
help
|
||||
This driver supports both MPU9150 and MPU9250. Choose one model.
|
||||
|
||||
config MODULE_MPU9150
|
||||
bool "MPU-9150"
|
||||
|
||||
config MODULE_MPU9250
|
||||
bool "MPU-9250"
|
||||
|
||||
endchoice
|
||||
|
||||
config HAVE_MPU9150
|
||||
bool
|
||||
select HAVE_MPU9X50
|
||||
help
|
||||
Indicates that a mpu9150 sensor is present.
|
||||
|
||||
config HAVE_MPU9250
|
||||
bool
|
||||
select HAVE_MPU9X50
|
||||
help
|
||||
Indicates that a mpu9250 sensor is present.
|
||||
|
||||
config HAVE_MPU9X50
|
||||
bool
|
||||
help
|
||||
Indicates that a mpu9X50 sensor is present.
|
||||
|
||||
@ -45,6 +45,8 @@
|
||||
#define SFLASH_CMD_4_BYTE_ADDR (0xB7) /**< enable 32 bit addressing */
|
||||
#define SFLASH_CMD_3_BYTE_ADDR (0xE9) /**< enable 24 bit addressing */
|
||||
|
||||
#define SFLASH_CMD_ULBPR (0x98) /**< Global Block Protection Unlock */
|
||||
|
||||
#define MTD_64K (65536ul)
|
||||
#define MTD_64K_ADDR_MASK (0xFFFF)
|
||||
#define MTD_32K (32768ul)
|
||||
@ -66,6 +68,7 @@
|
||||
|
||||
typedef enum {
|
||||
SPI_NOR_JEDEC_ATMEL = 0x1F | JEDEC_BANK(1),
|
||||
SPI_NOR_JEDEC_MICROCHIP = 0xBF | JEDEC_BANK(1),
|
||||
} jedec_manuf_t;
|
||||
/** @} */
|
||||
|
||||
@ -88,7 +91,7 @@ static void mtd_spi_release(const mtd_spi_nor_t *dev)
|
||||
static inline uint8_t* _be_addr(const mtd_spi_nor_t *dev, uint32_t *addr)
|
||||
{
|
||||
*addr = htonl(*addr);
|
||||
return &((uint8_t*)addr)[4 - dev->params->addr_width];
|
||||
return &((uint8_t*)addr)[4 - dev->addr_width];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,7 +114,7 @@ static void mtd_spi_cmd_addr_read(const mtd_spi_nor_t *dev, uint8_t opcode,
|
||||
|
||||
if (IS_ACTIVE(ENABLE_TRACE)) {
|
||||
TRACE("mtd_spi_cmd_addr_read: addr:");
|
||||
for (unsigned int i = 0; i < dev->params->addr_width; ++i) {
|
||||
for (unsigned int i = 0; i < dev->addr_width; ++i) {
|
||||
TRACE(" %02x", addr_buf[i]);
|
||||
}
|
||||
TRACE("\n");
|
||||
@ -120,7 +123,7 @@ static void mtd_spi_cmd_addr_read(const mtd_spi_nor_t *dev, uint8_t opcode,
|
||||
/* Send opcode followed by address */
|
||||
spi_transfer_byte(_get_spi(dev), dev->params->cs, true, opcode);
|
||||
spi_transfer_bytes(_get_spi(dev), dev->params->cs, true,
|
||||
(char *)addr_buf, NULL, dev->params->addr_width);
|
||||
(char *)addr_buf, NULL, dev->addr_width);
|
||||
|
||||
/* Read data */
|
||||
spi_transfer_bytes(_get_spi(dev), dev->params->cs, false,
|
||||
@ -147,7 +150,7 @@ static void mtd_spi_cmd_addr_write(const mtd_spi_nor_t *dev, uint8_t opcode,
|
||||
|
||||
if (IS_ACTIVE(ENABLE_TRACE)) {
|
||||
TRACE("mtd_spi_cmd_addr_write: addr:");
|
||||
for (unsigned int i = 0; i < dev->params->addr_width; ++i) {
|
||||
for (unsigned int i = 0; i < dev->addr_width; ++i) {
|
||||
TRACE(" %02x", addr_buf[i]);
|
||||
}
|
||||
TRACE("\n");
|
||||
@ -159,7 +162,7 @@ static void mtd_spi_cmd_addr_write(const mtd_spi_nor_t *dev, uint8_t opcode,
|
||||
/* only keep CS asserted when there is data that follows */
|
||||
bool cont = (count > 0);
|
||||
spi_transfer_bytes(_get_spi(dev), dev->params->cs, cont,
|
||||
(char *)addr_buf, NULL, dev->params->addr_width);
|
||||
(char *)addr_buf, NULL, dev->addr_width);
|
||||
|
||||
/* Write data */
|
||||
if (cont) {
|
||||
@ -303,6 +306,28 @@ static uint32_t mtd_spi_nor_get_size(const mtd_jedec_id_t *id)
|
||||
(id->device[1] & ~0x3) == 0) {
|
||||
return (0x1F & id->device[0]) * MBIT_AS_BYTES;
|
||||
}
|
||||
if (mtd_spi_manuf_match(id, SPI_NOR_JEDEC_MICROCHIP)) {
|
||||
switch (id->device[1]) {
|
||||
case 0x12: /* SST26VF020A */
|
||||
case 0x8c: /* SST25VF020B */
|
||||
return 2 * MBIT_AS_BYTES;
|
||||
case 0x54: /* SST26WF040B */
|
||||
case 0x8d: /* SST25VF040B */
|
||||
return 4 * MBIT_AS_BYTES;
|
||||
case 0x58: /* SST26WF080B */
|
||||
case 0x8e: /* SST25VF080B */
|
||||
return 8 * MBIT_AS_BYTES;
|
||||
case 0x1: /* SST26VF016 */
|
||||
case 0x41: /* SST26VF016B */
|
||||
return 16 * MBIT_AS_BYTES;
|
||||
case 0x2: /* SST26VF032 */
|
||||
case 0x42: /* SST26VF032B */
|
||||
return 32 * MBIT_AS_BYTES;
|
||||
case 0x43: /* SST26VF064B */
|
||||
case 0x53: /* SST26WF064C */
|
||||
return 64 * MBIT_AS_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
/* everyone else seems to use device ID 2 for density */
|
||||
return 1 << id->device[1];
|
||||
@ -376,6 +401,12 @@ static void _init_pins(mtd_spi_nor_t *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void _enable_32bit_addr(mtd_spi_nor_t *dev)
|
||||
{
|
||||
mtd_spi_cmd(dev, dev->params->opcode->wren);
|
||||
mtd_spi_cmd(dev, SFLASH_CMD_4_BYTE_ADDR);
|
||||
}
|
||||
|
||||
static int mtd_spi_nor_power(mtd_dev_t *mtd, enum mtd_power_state power)
|
||||
{
|
||||
mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
|
||||
@ -399,9 +430,8 @@ static int mtd_spi_nor_power(mtd_dev_t *mtd, enum mtd_power_state power)
|
||||
}
|
||||
#endif
|
||||
/* enable 32 bit address mode */
|
||||
if (dev->params->addr_width == 4) {
|
||||
mtd_spi_cmd(dev, dev->params->opcode->wren);
|
||||
mtd_spi_cmd(dev, SFLASH_CMD_4_BYTE_ADDR);
|
||||
if (dev->addr_width == 4) {
|
||||
_enable_32bit_addr(dev);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -414,6 +444,20 @@ static int mtd_spi_nor_power(mtd_dev_t *mtd, enum mtd_power_state power)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _set_addr_width(mtd_dev_t *mtd)
|
||||
{
|
||||
mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
|
||||
|
||||
uint32_t flash_size = mtd->pages_per_sector * mtd->page_size
|
||||
* mtd->sector_count;
|
||||
|
||||
if (flash_size > 0xFFFFFF) {
|
||||
dev->addr_width = 4;
|
||||
} else {
|
||||
dev->addr_width = 3;
|
||||
}
|
||||
}
|
||||
|
||||
static int mtd_spi_nor_init(mtd_dev_t *mtd)
|
||||
{
|
||||
DEBUG("mtd_spi_nor_init: %p\n", (void *)mtd);
|
||||
@ -422,10 +466,6 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
|
||||
DEBUG("mtd_spi_nor_init: -> spi: %lx, cs: %lx, opcodes: %p\n",
|
||||
(unsigned long)_get_spi(dev), (unsigned long)dev->params->cs, (void *)dev->params->opcode);
|
||||
|
||||
/* verify configuration */
|
||||
assert(dev->params->addr_width > 0);
|
||||
assert(dev->params->addr_width <= 4);
|
||||
|
||||
/* CS, WP, Hold */
|
||||
_init_pins(dev);
|
||||
|
||||
@ -450,6 +490,7 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
|
||||
mtd->sector_count = mtd_spi_nor_get_size(&dev->jedec_id)
|
||||
/ (mtd->pages_per_sector * mtd->page_size);
|
||||
}
|
||||
_set_addr_width(mtd);
|
||||
|
||||
DEBUG("mtd_spi_nor_init: %" PRIu32 " bytes "
|
||||
"(%" PRIu32 " sectors, %" PRIu32 " bytes/sector, "
|
||||
@ -459,14 +500,23 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
|
||||
mtd->sector_count, mtd->pages_per_sector * mtd->page_size,
|
||||
mtd->pages_per_sector * mtd->sector_count,
|
||||
mtd->pages_per_sector, mtd->page_size);
|
||||
DEBUG("mtd_spi_nor_init: Using %u byte addresses\n", dev->params->addr_width);
|
||||
DEBUG("mtd_spi_nor_init: Using %u byte addresses\n", dev->addr_width);
|
||||
|
||||
uint8_t status;
|
||||
mtd_spi_cmd_read(dev, dev->params->opcode->rdsr, &status, sizeof(status));
|
||||
mtd_spi_release(dev);
|
||||
|
||||
DEBUG("mtd_spi_nor_init: device status = 0x%02x\n", (unsigned int)status);
|
||||
|
||||
/* enable 32 bit address mode */
|
||||
if (dev->addr_width == 4) {
|
||||
_enable_32bit_addr(dev);
|
||||
}
|
||||
|
||||
/* Global Block-Protection Unlock */
|
||||
mtd_spi_cmd(dev, dev->params->opcode->wren);
|
||||
mtd_spi_cmd(dev, SFLASH_CMD_ULBPR);
|
||||
|
||||
mtd_spi_release(dev);
|
||||
|
||||
/* check whether page size and sector size are powers of two (most chips' are)
|
||||
* and compute the number of shifts needed to get the page and sector addresses
|
||||
* from a byte address */
|
||||
|
||||
@ -6,8 +6,9 @@
|
||||
EXTERNAL_MODULE_PATHS := $(sort $(foreach dir,$(EXTERNAL_MODULE_DIRS),\
|
||||
$(foreach mod,$(USEMODULE),$(dir $(wildcard $(dir)/$(mod)/Makefile)))))
|
||||
|
||||
# Locate used packages in $(RIOTPKG).
|
||||
PKG_PATHS := $(sort $(foreach dir,$(RIOTPKG),\
|
||||
# Locate used packages in $(RIOTPKG) or $(EXTERNAL_PKG_DIRS).
|
||||
PKGDIRS := $(RIOTPKG) $(EXTERNAL_PKG_DIRS)
|
||||
PKG_PATHS := $(sort $(foreach dir,$(PKGDIRS),\
|
||||
$(foreach pkg,$(USEPKG),$(dir $(wildcard $(dir)/$(pkg)/Makefile)))))
|
||||
|
||||
# Back up current state to detect changes
|
||||
|
||||
@ -27,7 +27,10 @@ export KCONFIG_AUTOHEADER_HEADER
|
||||
export KCONFIG_GENERATED_DEPENDENCIES = $(GENERATED_DIR)/Kconfig.dep
|
||||
|
||||
# This file will contain external module configurations
|
||||
export KCONFIG_EXTERNAL_CONFIGS = $(GENERATED_DIR)/Kconfig.external_modules
|
||||
export KCONFIG_EXTERNAL_MODULE_CONFIGS = $(GENERATED_DIR)/Kconfig.external_modules
|
||||
|
||||
# This file will contain external package configurations
|
||||
export KCONFIG_EXTERNAL_PKG_CONFIGS = $(GENERATED_DIR)/Kconfig.external_pkgs
|
||||
|
||||
# Add configurations that only work when running the Kconfig test so far,
|
||||
# because they activate modules.
|
||||
@ -179,12 +182,12 @@ $(KCONFIG_GENERATED_ENV_CONFIG): FORCE | $(GENERATED_DIR)
|
||||
| $(LAZYSPONGE) $(LAZYSPONGE_FLAGS) $@
|
||||
|
||||
# All directories in EXTERNAL_MODULES_PATHS which have a Kconfig file
|
||||
EXTERNAL_MODULE_KCONFIGS ?= $(sort $(foreach dir,$(EXTERNAL_MODULE_PATHS),\
|
||||
$(wildcard $(dir)/Kconfig)))
|
||||
EXTERNAL_MODULE_KCONFIGS ?= $(sort $(foreach dir,$(EXTERNAL_MODULE_DIRS),\
|
||||
$(wildcard $(dir)/*/Kconfig)))
|
||||
# Build a Kconfig file that source all external modules configuration
|
||||
# files. Every EXTERNAL_MODULE_DIRS with a Kconfig file is written to
|
||||
# KCONFIG_EXTERNAL_CONFIGS as 'osource dir/Kconfig'
|
||||
$(KCONFIG_EXTERNAL_CONFIGS): FORCE | $(GENERATED_DIR)
|
||||
# KCONFIG_EXTERNAL_MODULE_CONFIGS as 'osource dir/Kconfig'
|
||||
$(KCONFIG_EXTERNAL_MODULE_CONFIGS): FORCE | $(GENERATED_DIR)
|
||||
$(Q)\
|
||||
if [ -n "$(EXTERNAL_MODULE_KCONFIGS)" ] ; then \
|
||||
printf "%s\n" $(EXTERNAL_MODULE_KCONFIGS) \
|
||||
@ -195,6 +198,24 @@ $(KCONFIG_EXTERNAL_CONFIGS): FORCE | $(GENERATED_DIR)
|
||||
| $(LAZYSPONGE) $(LAZYSPONGE_FLAGS) $@ ; \
|
||||
fi
|
||||
|
||||
# All directories in EXTERNAL_PKG_DIRS which have a subdirectory containing a
|
||||
# Kconfig file.
|
||||
EXTERNAL_PKG_KCONFIGS ?= $(sort $(foreach dir,$(EXTERNAL_PKG_DIRS),\
|
||||
$(wildcard $(dir)/*/Kconfig)))
|
||||
# Build a Kconfig file that sources all external packages configuration
|
||||
# files. Every directory with a Kconfig file is written to KCONFIG_PKG_CONFIGS
|
||||
# as 'osource dir/Kconfig'
|
||||
$(KCONFIG_EXTERNAL_PKG_CONFIGS): FORCE | $(GENERATED_DIR)
|
||||
$(Q)\
|
||||
if [ -n "$(EXTERNAL_PKG_KCONFIGS)" ] ; then \
|
||||
printf "%s\n" $(EXTERNAL_PKG_KCONFIGS) \
|
||||
| awk '{ printf "osource \"%s\"\n", $$0 }' \
|
||||
| $(LAZYSPONGE) $(LAZYSPONGE_FLAGS) $@ ; \
|
||||
else \
|
||||
printf "# no external packages" \
|
||||
| $(LAZYSPONGE) $(LAZYSPONGE_FLAGS) $@ ; \
|
||||
fi
|
||||
|
||||
# When the 'clean' target is called, the files inside GENERATED_DIR should be
|
||||
# regenerated. For that, we conditionally change GENERATED_DIR from an 'order
|
||||
# only' requisite to a normal one.
|
||||
@ -211,7 +232,7 @@ GENERATED_DIR_DEP := $(if $(CLEAN),,|) $(GENERATED_DIR)
|
||||
# Generates a .config file by merging multiple sources specified in
|
||||
# MERGE_SOURCES. This will also generate KCONFIG_OUT_DEP with the list of used
|
||||
# Kconfig files.
|
||||
$(KCONFIG_OUT_CONFIG): $(KCONFIG_EXTERNAL_CONFIGS)
|
||||
$(KCONFIG_OUT_CONFIG): $(KCONFIG_EXTERNAL_MODULE_CONFIGS) $(KCONFIG_EXTERNAL_PKG_CONFIGS)
|
||||
$(KCONFIG_OUT_CONFIG): $(GENERATED_DEPENDENCIES_DEP) $(GENCONFIG) $(MERGE_SOURCES) $(GENERATED_DIR_DEP)
|
||||
$(Q) $(GENCONFIG) \
|
||||
--config-out=$(KCONFIG_OUT_CONFIG) \
|
||||
|
||||
@ -154,8 +154,11 @@ PSEUDOMODULES += netstats_rpl
|
||||
PSEUDOMODULES += nimble
|
||||
PSEUDOMODULES += nimble_adv_ext
|
||||
PSEUDOMODULES += nimble_autoconn_%
|
||||
PSEUDOMODULES += nimble_netif_ext
|
||||
PSEUDOMODULES += nimble_phy_coded
|
||||
PSEUDOMODULES += nimble_phy_2mbit
|
||||
PSEUDOMODULES += nimble_rpble_ext
|
||||
PSEUDOMODULES += nimble_statconn_ext
|
||||
PSEUDOMODULES += newlib
|
||||
PSEUDOMODULES += newlib_gnu_source
|
||||
PSEUDOMODULES += newlib_nano
|
||||
@ -201,6 +204,7 @@ PSEUDOMODULES += stdin
|
||||
PSEUDOMODULES += stdio_available
|
||||
PSEUDOMODULES += stdio_cdc_acm
|
||||
PSEUDOMODULES += stdio_ethos
|
||||
PSEUDOMODULES += stdio_nimble_debug
|
||||
PSEUDOMODULES += stdio_uart_rx
|
||||
PSEUDOMODULES += stm32_eth
|
||||
PSEUDOMODULES += stm32_eth_auto
|
||||
|
||||
@ -2,6 +2,7 @@ STDIO_MODULES = \
|
||||
slipdev_stdio \
|
||||
stdio_cdc_acm \
|
||||
stdio_ethos \
|
||||
stdio_nimble \
|
||||
stdio_null \
|
||||
stdio_rtt \
|
||||
stdio_semihosting \
|
||||
@ -29,6 +30,18 @@ ifneq (,$(filter stdio_ethos,$(USEMODULE)))
|
||||
USEMODULE += stdin
|
||||
endif
|
||||
|
||||
ifneq (,$(filter stdio_nimble,$(USEMODULE)))
|
||||
USEMODULE += stdio_available
|
||||
USEPKG += nimble
|
||||
USEMODULE += tsrb
|
||||
USEMODULE += isrpipe
|
||||
USEMODULE += nimble_svc_gap
|
||||
USEMODULE += nimble_svc_gatt
|
||||
ifneq (,$(filter stdio_nimble_debug,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_uart
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter stdin,$(USEMODULE)))
|
||||
ifneq (,$(filter stdio_uart,$(USEMODULE)))
|
||||
USEMODULE += stdio_uart_rx
|
||||
|
||||
@ -21,6 +21,7 @@ rsource "esp32_sdk/Kconfig"
|
||||
rsource "esp32_sdk_libs/Kconfig"
|
||||
rsource "esp8266_sdk/Kconfig"
|
||||
rsource "fff/Kconfig"
|
||||
rsource "fido2_tests/Kconfig"
|
||||
rsource "gecko_sdk/Kconfig"
|
||||
rsource "gemmlowp/Kconfig"
|
||||
rsource "hacl/Kconfig"
|
||||
|
||||
29
pkg/doc.txt
29
pkg/doc.txt
@ -72,5 +72,34 @@
|
||||
* * commit your changes using `git commit`
|
||||
* * create the patch files using `git format-patch -n riot-port`
|
||||
* * move the resulting patch files to the patches directory of your package.
|
||||
*
|
||||
* Packages outside of RIOTPKG
|
||||
* ---------------------------
|
||||
* It can be beneficial to create packages outside of the RIOT tree. For example
|
||||
* if one is working on new packages that aren't ready to be committed to
|
||||
* upstream or if an application needs its own unique packages. For this, one
|
||||
* can use the `EXTERNAL_PKG_DIRS` make variable. It works similar to the way
|
||||
* [external modules](src/creating-modules.html#modules-outside-of-riotbase) are
|
||||
* handled. In your application's Makefile, in addition to adding the package
|
||||
* name to `USEPKG` as shown above, add the path to a folder that contains your
|
||||
* external packages:
|
||||
*
|
||||
* ~~~~~~~~ {.mk}
|
||||
* EXTERNAL_PKG_DIRS += <PATH_TO_FOLDER_CONTAINING_PACKAGES>
|
||||
* ~~~~~~~~
|
||||
*
|
||||
* The path is allowed to be relative to the application's directory.
|
||||
*
|
||||
* ***NOTE:*** The name of an external package must be unique (both in regard to
|
||||
* other external packages, as well to native RIOT packages). Additionally, the
|
||||
* directory containing the packages must match the package name, e.g. package
|
||||
* `foo`must be located in `<PATH_IN_EXTERNAL_PKG_DIRS>/foo`.
|
||||
*
|
||||
* An example can be found in
|
||||
* [`tests/external_pkg_dirs`](https://github.com/RIOT-OS/RIOT/tree/master/tests/external_pkg_dirs)
|
||||
*
|
||||
* RIOT welcomes new and useful packages. If you'd like to share your work,
|
||||
* consider [contributing](https://github.com/RIOT-OS/RIOT/tree/master/CONTRIBUTING.md).
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -219,6 +219,19 @@ static ssize_t _write(vfs_file_t *filp, const void *src, size_t nbytes)
|
||||
return (ssize_t)bw;
|
||||
}
|
||||
|
||||
static int _fsync(vfs_file_t *filp)
|
||||
{
|
||||
fatfs_file_desc_t *fd = _get_fatfs_file_desc(filp);
|
||||
|
||||
FRESULT res = f_sync(&fd->file);
|
||||
|
||||
if (res != FR_OK) {
|
||||
return fatfs_err_to_errno(res);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _read(vfs_file_t *filp, void *dest, size_t nbytes)
|
||||
{
|
||||
fatfs_file_desc_t *fd = _get_fatfs_file_desc(filp);
|
||||
@ -469,6 +482,7 @@ static const vfs_file_ops_t fatfs_file_ops = {
|
||||
.write = _write,
|
||||
.lseek = _lseek,
|
||||
.fstat = _fstat,
|
||||
.fsync = _fsync,
|
||||
};
|
||||
|
||||
static const vfs_dir_ops_t fatfs_dir_ops = {
|
||||
|
||||
4
pkg/fido2_tests/Kconfig
Normal file
4
pkg/fido2_tests/Kconfig
Normal file
@ -0,0 +1,4 @@
|
||||
config PACKAGE_FIDO2_TESTS
|
||||
bool "FIDO2 tests"
|
||||
help
|
||||
Test suite for FIDO2, U2F, and other security key functions.
|
||||
@ -377,6 +377,22 @@ static off_t _lseek(vfs_file_t *filp, off_t off, int whence)
|
||||
return littlefs_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int _fsync(vfs_file_t *filp)
|
||||
{
|
||||
littlefs_desc_t *fs = filp->mp->private_data;
|
||||
lfs_file_t *fp = _get_lfs_file(filp);
|
||||
|
||||
mutex_lock(&fs->lock);
|
||||
|
||||
DEBUG("littlefs: fsync: filp=%p, fp=%p\n",
|
||||
(void *)filp, (void *)fp);
|
||||
|
||||
int ret = lfs_file_sync(&fs->fs, fp);
|
||||
mutex_unlock(&fs->lock);
|
||||
|
||||
return littlefs_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int _stat(vfs_mount_t *mountp, const char *restrict path, struct stat *restrict buf)
|
||||
{
|
||||
littlefs_desc_t *fs = mountp->private_data;
|
||||
@ -519,6 +535,7 @@ static const vfs_file_ops_t littlefs_file_ops = {
|
||||
.read = _read,
|
||||
.write = _write,
|
||||
.lseek = _lseek,
|
||||
.fsync = _fsync,
|
||||
};
|
||||
|
||||
static const vfs_dir_ops_t littlefs_dir_ops = {
|
||||
|
||||
@ -383,6 +383,22 @@ static off_t _lseek(vfs_file_t *filp, off_t off, int whence)
|
||||
return littlefs_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int _fsync(vfs_file_t *filp)
|
||||
{
|
||||
littlefs2_desc_t *fs = filp->mp->private_data;
|
||||
lfs_file_t *fp = _get_lfs_file(filp);
|
||||
|
||||
mutex_lock(&fs->lock);
|
||||
|
||||
DEBUG("littlefs: fsync: filp=%p, fp=%p\n",
|
||||
(void *)filp, (void *)fp);
|
||||
|
||||
int ret = lfs_file_sync(&fs->fs, fp);
|
||||
mutex_unlock(&fs->lock);
|
||||
|
||||
return littlefs_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int _stat(vfs_mount_t *mountp, const char *restrict path, struct stat *restrict buf)
|
||||
{
|
||||
littlefs2_desc_t *fs = mountp->private_data;
|
||||
@ -525,6 +541,7 @@ static const vfs_file_ops_t littlefs_file_ops = {
|
||||
.read = _read,
|
||||
.write = _write,
|
||||
.lseek = _lseek,
|
||||
.fsync = _fsync,
|
||||
};
|
||||
|
||||
static const vfs_dir_ops_t littlefs_dir_ops = {
|
||||
|
||||
@ -23,7 +23,7 @@ else
|
||||
CFLAGS += -Wno-unused-but-set-variable
|
||||
endif
|
||||
|
||||
IGNORE := nimble_autoconn_% nimble_phy_% nimble_adv_ext
|
||||
IGNORE := nimble_autoconn_% nimble_phy_% nimble_%_ext
|
||||
SUBMODS := $(filter-out $(IGNORE),$(filter nimble_%,$(USEMODULE)))
|
||||
|
||||
.PHONY: all
|
||||
|
||||
@ -12,6 +12,15 @@ USEMODULE += nimble_riot_contrib
|
||||
# RIOT port
|
||||
USEMODULE += nimble_porting_nimble
|
||||
|
||||
# Pull in dependencies based on used features
|
||||
ifneq (,$(filter ble_phy_coded,$(FEATURES_USED)))
|
||||
USEMODULE += nimble_phy_coded
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ble_phy_2mbit,$(FEATURES_USED)))
|
||||
USEMODULE += nimble_phy_2mbit
|
||||
endif
|
||||
|
||||
# NOTE: this dependency depends on inclusion order, for it to work properly
|
||||
# mynewt-core should be selected as nimble backend as early as possible,
|
||||
# i.e. at the application level.
|
||||
@ -56,6 +65,10 @@ ifneq (,$(filter nimble_autoadv,$(USEMODULE)))
|
||||
USEMODULE += bluetil_ad
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_autoconn_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_autoconn_%,$(USEMODULE)))
|
||||
USEMODULE += nimble_autoconn
|
||||
endif
|
||||
@ -67,10 +80,6 @@ ifneq (,$(filter nimble_autoconn,$(USEMODULE)))
|
||||
USEMODULE += bluetil_ad
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_%,$(USEMODULE)))
|
||||
USEMODULE += nimble_adv_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_2mbit,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_phy_2mbit
|
||||
endif
|
||||
@ -79,6 +88,11 @@ ifneq (,$(filter nimble_phy_coded,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_phy_coded
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_rpble_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_rpble
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_rpble,$(USEMODULE)))
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += nimble_netif
|
||||
@ -92,12 +106,22 @@ ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
|
||||
USEMODULE += ztimer_usec
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_statconn_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_statconn
|
||||
USEMODULE += nimble_netif_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_statconn,$(USEMODULE)))
|
||||
USEMODULE += random
|
||||
USEMODULE += nimble_netif
|
||||
USEMODULE += nimble_addr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif_ext,$(USEMODULE)))
|
||||
USEMODULE += nimble_netif
|
||||
USEMODULE += nimble_adv_ext
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_nimble_netif
|
||||
USEMODULE += random
|
||||
|
||||
@ -26,6 +26,14 @@ ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_drivers_nrf5x,$(USEMODULE)))
|
||||
INCLUDES += $(NIMIBASE)/nimble/drivers/$(CPU_FAM)/include
|
||||
endif
|
||||
|
||||
# Enable additional PHY modes if requested by the build
|
||||
ifneq (,$(filter ble_phy_2mbit,$(FEATURES_USED)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY=1
|
||||
endif
|
||||
ifneq (,$(filter ble_phy_coded,$(FEATURES_USED)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
# include nimble host headers
|
||||
@ -94,18 +102,6 @@ ifneq (,$(filter nimble_adv_ext,$(USEMODULE)))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_2mbit,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_phy_coded,$(USEMODULE)))
|
||||
ifneq (,$(filter nimble_controller,$(USEMODULE)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTPKG)/nimble/netif/include
|
||||
|
||||
@ -135,6 +131,17 @@ ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS=1
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT=1
|
||||
endif
|
||||
else
|
||||
ifneq (,$(filter stdio_nimble,$(USEMODULE)))
|
||||
# the maximum fragment size that we can receive. For maximum efficiency this
|
||||
# should be equal to the maximum configured link layer packet size.
|
||||
# WARNING: this value MUST never be larger than MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE
|
||||
CFLAGS += -DMYNEWT_VAL_BLE_L2CAP_COC_MPS=251
|
||||
|
||||
# in order to fit a 251 byte COC data segment into a single mbuf buffer, the
|
||||
# used block size must be at least 297 byte (251 data + 48 overhead)
|
||||
CFLAGS += -DMYNEWT_VAL_MSYS_1_BLOCK_SIZE="(MYNEWT_VAL_BLE_L2CAP_COC_MPS + 48)"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nimble_rpble,$(USEMODULE)))
|
||||
|
||||
@ -131,29 +131,31 @@ enum {
|
||||
*/
|
||||
typedef struct {
|
||||
/** amount of time spend in scanning mode [in ms] */
|
||||
uint32_t period_scan;
|
||||
uint32_t period_scan_ms;
|
||||
/** amount of time spend in advertising mode [in ms] */
|
||||
uint32_t period_adv;
|
||||
uint32_t period_adv_ms;
|
||||
/** a random value from 0 to this value is added to the duration of each
|
||||
* scanning and advertising period [in ms] */
|
||||
uint32_t period_jitter;
|
||||
uint32_t period_jitter_ms;
|
||||
/** advertising interval used when in advertising mode [in ms] */
|
||||
uint32_t adv_itvl;
|
||||
uint32_t adv_itvl_ms;
|
||||
/** scan interval applied while in scanning state [in ms] */
|
||||
uint32_t scan_itvl;
|
||||
uint32_t scan_itvl_ms;
|
||||
/** scan window applied while in scanning state [in ms] */
|
||||
uint32_t scan_win;
|
||||
uint32_t scan_win_ms;
|
||||
/** opening a new connection is aborted after this time [in ms] */
|
||||
uint32_t conn_timeout;
|
||||
uint32_t conn_timeout_ms;
|
||||
/** connection interval used when opening a new connection, lower bound.
|
||||
* [in ms] */
|
||||
uint32_t conn_itvl_min;
|
||||
uint32_t conn_itvl_min_ms;
|
||||
/** connection interval, upper bound [in ms] */
|
||||
uint32_t conn_itvl_max;
|
||||
/** slave latency used for new connections [in ms] */
|
||||
uint32_t conn_itvl_max_ms;
|
||||
/** slave latency used for new connections */
|
||||
uint16_t conn_latency;
|
||||
/** supervision timeout used for new connections [in ms] */
|
||||
uint32_t conn_super_to;
|
||||
uint32_t conn_super_to_ms;
|
||||
/** BLE PHY mode to use */
|
||||
nimble_phy_t phy_mode;
|
||||
/** node ID included in the advertising data, may be NULL */
|
||||
const char *node_id;
|
||||
} nimble_autoconn_params_t;
|
||||
|
||||
@ -64,24 +64,32 @@ extern "C" {
|
||||
#define NIMBLE_AUTOCONN_CONN_SVTO_MS (2500U) /* 2.5s */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default BLE PHY mode used by autoconn
|
||||
*/
|
||||
#ifndef NIMBLE_AUTOCONN_PHY_MODE
|
||||
#define NIMBLE_AUTOCONN_PHY_MODE NIMBLE_PHY_1M
|
||||
#endif
|
||||
|
||||
#ifndef NIMBLE_AUTOCONN_NODE_ID
|
||||
#define NIMBLE_AUTOCONN_NODE_ID "RIOT-autoconn"
|
||||
#endif
|
||||
|
||||
#ifndef NIMBLE_AUTOCONN_PARAMS
|
||||
#define NIMBLE_AUTOCONN_PARAMS \
|
||||
{ .period_scan = NIMBLE_AUTOCONN_PERIOD_SCAN_MS, \
|
||||
.period_adv = NIMBLE_AUTOCONN_PERIOD_ADV_MS, \
|
||||
.period_jitter = NIMBLE_AUTOCONN_PERIOD_JITTER_MS, \
|
||||
.adv_itvl = NIMBLE_AUTOCONN_ADV_ITVL_MS, \
|
||||
.scan_itvl = NIMBLE_AUTOCONN_SCAN_ITVL_MS, \
|
||||
.scan_win = NIMBLE_AUTOCONN_SCAN_WIN_MS, \
|
||||
.conn_timeout = NIMBLE_AUTOCONN_CONN_TIMEOUT_MS, \
|
||||
.conn_itvl_min = NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS, \
|
||||
.conn_itvl_max = NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
|
||||
.conn_super_to = NIMBLE_AUTOCONN_CONN_SVTO_MS, \
|
||||
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
|
||||
{ .period_scan_ms = NIMBLE_AUTOCONN_PERIOD_SCAN_MS, \
|
||||
.period_adv_ms = NIMBLE_AUTOCONN_PERIOD_ADV_MS, \
|
||||
.period_jitter_ms = NIMBLE_AUTOCONN_PERIOD_JITTER_MS, \
|
||||
.adv_itvl_ms = NIMBLE_AUTOCONN_ADV_ITVL_MS, \
|
||||
.scan_itvl_ms = NIMBLE_AUTOCONN_SCAN_ITVL_MS, \
|
||||
.scan_win_ms = NIMBLE_AUTOCONN_SCAN_WIN_MS, \
|
||||
.conn_timeout_ms = NIMBLE_AUTOCONN_CONN_TIMEOUT_MS, \
|
||||
.conn_itvl_min_ms = NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS, \
|
||||
.conn_itvl_max_ms = NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
|
||||
.conn_super_to_ms = NIMBLE_AUTOCONN_CONN_SVTO_MS, \
|
||||
.phy_mode = NIMBLE_AUTOCONN_PHY_MODE, \
|
||||
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
|
||||
@ -55,9 +55,8 @@ static volatile uint8_t _enabled = 0;
|
||||
static bluetil_ad_t _ad;
|
||||
static uint8_t _ad_buf[BLE_HS_ADV_MAX_SZ];
|
||||
|
||||
static struct ble_gap_adv_params _adv_params;
|
||||
static struct ble_gap_conn_params _conn_params;
|
||||
static uint32_t _conn_timeout;
|
||||
static nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
static struct ble_npl_callout _state_evt;
|
||||
static ble_npl_time_t _timeout_adv_period;
|
||||
@ -77,7 +76,7 @@ static void _on_state_change(struct ble_npl_event *ev)
|
||||
/* stop scanning */
|
||||
nimble_scanner_stop();
|
||||
/* start advertising/accepting */
|
||||
int res = nimble_netif_accept(_ad.buf, _ad.pos, &_adv_params);
|
||||
int res = nimble_netif_accept(_ad.buf, _ad.pos, &_accept_params);
|
||||
assert((res == 0) || (res == -ENOMEM));
|
||||
(void)res;
|
||||
|
||||
@ -137,11 +136,18 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
{
|
||||
(void)info;
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
if ((type != (NIMBLE_SCANNER_EXT_ADV | BLE_HCI_ADV_CONN_MASK)) ||
|
||||
(info->status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* we are only interested in ADV_IND packets, the rest can be dropped right
|
||||
* away */
|
||||
if (type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bluetil_ad_t ad = {
|
||||
.buf = (uint8_t *)ad_buf,
|
||||
@ -157,7 +163,7 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
nimble_scanner_stop();
|
||||
DEBUG("[autoconn] SCAN success, initiating connection\n");
|
||||
_state = STATE_CONN;
|
||||
int res = nimble_netif_connect(addr, &_conn_params, _conn_timeout);
|
||||
int res = nimble_netif_connect(addr, &_conn_params);
|
||||
assert(res >= 0);
|
||||
(void)res;
|
||||
}
|
||||
@ -271,47 +277,66 @@ int nimble_autoconn_update(const nimble_autoconn_params_t *params,
|
||||
}
|
||||
|
||||
/* scan and advertising period configuration */
|
||||
ble_npl_time_ms_to_ticks(params->period_adv, &_timeout_adv_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_scan, &_timeout_scan_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_jitter, &_period_jitter);
|
||||
ble_npl_time_ms_to_ticks(params->period_adv_ms, &_timeout_adv_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_scan_ms, &_timeout_scan_period);
|
||||
ble_npl_time_ms_to_ticks(params->period_jitter_ms, &_period_jitter);
|
||||
|
||||
/* populate the connection parameters */
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(params->scan_win);
|
||||
_conn_params.scan_window = _conn_params.scan_itvl;
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_min);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_max);
|
||||
_conn_params.latency = 0;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
params->conn_super_to);
|
||||
_conn_params.min_ce_len = 0;
|
||||
_conn_params.max_ce_len = 0;
|
||||
_conn_timeout = params->conn_timeout;
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
_conn_params.scan_itvl_ms = params->scan_itvl_ms;
|
||||
_conn_params.scan_window_ms = params->scan_win_ms;
|
||||
_conn_params.conn_itvl_min_ms = params->conn_itvl_min_ms;
|
||||
_conn_params.conn_itvl_max_ms = params->conn_itvl_max_ms;
|
||||
_conn_params.conn_supervision_timeout_ms = params->conn_super_to_ms;
|
||||
_conn_params.conn_slave_latency = params->conn_latency;
|
||||
_conn_params.timeout_ms = params->conn_timeout_ms;
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_conn_params.phy_mode = params->phy_mode;
|
||||
#else
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* we use the same values to updated existing connections */
|
||||
struct ble_gap_upd_params conn_update_params;
|
||||
conn_update_params.itvl_min = _conn_params.itvl_min;
|
||||
conn_update_params.itvl_max = _conn_params.itvl_max;
|
||||
conn_update_params.latency = _conn_params.latency;
|
||||
conn_update_params.supervision_timeout = _conn_params.supervision_timeout;
|
||||
conn_update_params.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_min_ms);
|
||||
conn_update_params.itvl_max = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_max_ms);
|
||||
conn_update_params.latency = params->conn_latency;
|
||||
conn_update_params.supervision_timeout =
|
||||
BLE_GAP_SUPERVISION_TIMEOUT_MS(params->conn_super_to_ms);
|
||||
conn_update_params.min_ce_len = 0;
|
||||
conn_update_params.max_ce_len = 0;
|
||||
|
||||
/* calculate the used scan parameters */
|
||||
nimble_scanner_cfg_t scan_params;
|
||||
scan_params.itvl_ms = params->scan_itvl;
|
||||
scan_params.win_ms = params->scan_win;
|
||||
scan_params.flags = NIMBLE_SCANNER_PASSIVE
|
||||
| NIMBLE_SCANNER_FILTER_DUPS
|
||||
| NIMBLE_SCANNER_PHY_1M;
|
||||
scan_params.itvl_ms = params->scan_itvl_ms;
|
||||
scan_params.win_ms = params->scan_win_ms;
|
||||
scan_params.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_FILTER_DUPS);
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT) && IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
if (params->phy_mode == NIMBLE_PHY_CODED) {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_CODED;
|
||||
}
|
||||
else {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
}
|
||||
#else
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
#endif
|
||||
|
||||
/* set the advertising parameters used */
|
||||
_adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
_adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
_adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(params->adv_itvl);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
_adv_params.channel_map = 0;
|
||||
_adv_params.filter_policy = 0;
|
||||
_adv_params.high_duty_cycle = 0;
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_accept_params.flags = 0;
|
||||
_accept_params.primary_phy = params->phy_mode;
|
||||
_accept_params.secondary_phy = params->phy_mode;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = params->adv_itvl_ms;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* initialize the advertising data that will be used */
|
||||
if (adlen > 0) {
|
||||
|
||||
@ -69,6 +69,20 @@ extern "C" {
|
||||
#define NIMBLE_HOST_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief BLE PHY modes
|
||||
*/
|
||||
typedef enum {
|
||||
NIMBLE_PHY_INVALID, /**< PHY mode invalid */
|
||||
NIMBLE_PHY_1M, /**< legacy 1Mbit PHY mode (always supported) */
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
NIMBLE_PHY_2M, /**< 2Mbit PHY mode */
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
NIMBLE_PHY_CODED, /**< Coded (long range) PHY mode */
|
||||
#endif
|
||||
} nimble_phy_t;
|
||||
|
||||
/**
|
||||
* @brief Export our own address type for later usage
|
||||
*/
|
||||
|
||||
@ -176,6 +176,13 @@ void nimble_riot_init(void)
|
||||
nimble_autoconn_enable();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_STDIO_NIMBLE
|
||||
extern void stdio_nimble_init(void);
|
||||
/* stdio_nimble_init() needs to be called after nimble stack initialization
|
||||
* and before nimble_autoadv_init() */
|
||||
stdio_nimble_init();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NIMBLE_AUTOADV
|
||||
extern void nimble_autoadv_init(void);
|
||||
nimble_autoadv_init();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Freie Universität Berlin
|
||||
* Copyright (C) 2018-2021 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
|
||||
@ -70,6 +70,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "net/ble.h"
|
||||
#include "nimble_riot.h"
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
@ -103,6 +104,46 @@ extern "C" {
|
||||
#define NIMBLE_NETIF_MTU (1280U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Flags for enabling legacy advertisement and high-duty cycle mode
|
||||
* when accepting incoming connections
|
||||
*/
|
||||
enum {
|
||||
NIMBLE_NETIF_FLAG_LEGACY = 0x01, /**< use legacy advertising mode */
|
||||
NIMBLE_NETIF_FLAG_HD_MODE = 0x02, /**< use high duty cycle mode, only
|
||||
* valid for direct advertising */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parameter set used to configure accepting connections (advertising)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t flags; /**< flags */
|
||||
uint8_t channel_map; /**< specify custom channel map */
|
||||
uint8_t own_addr_type; /**< specify our own address type to use */
|
||||
int8_t tx_power; /**< specify TX power to be used */
|
||||
uint32_t adv_itvl_ms; /**< advertising interval [ms] */
|
||||
uint32_t timeout_ms; /**< stop accepting after this time [ms] */
|
||||
nimble_phy_t primary_phy; /**< primary PHY mode */
|
||||
nimble_phy_t secondary_phy; /**< secondary PHY mode */
|
||||
} nimble_netif_accept_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Parameter set used to configure connection initiation
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t scan_itvl_ms; /**< scan interval [ms] */
|
||||
uint16_t scan_window_ms; /**< scan window [ms] */
|
||||
uint16_t conn_itvl_min_ms; /**< connection interval, lower bound [ms] */
|
||||
uint16_t conn_itvl_max_ms; /**< connection interval, upper bound [ms] */
|
||||
uint16_t conn_supervision_timeout_ms; /**< supervision timeout [ms] */
|
||||
uint16_t conn_slave_latency;/**< slave latency */
|
||||
uint32_t timeout_ms; /**< abort connection initiation after this time
|
||||
* [ms] */
|
||||
uint8_t phy_mode; /**< PHY mode used for the connection */
|
||||
uint8_t own_addr_type; /**< specify our own address type to use */
|
||||
} nimble_netif_connect_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Set to > 0 to enforce different connection intervals for each of the
|
||||
* nodes BLE connections
|
||||
@ -197,19 +238,18 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb);
|
||||
*
|
||||
* @param[in] addr address of the advertising BLE slave, in the NimBLE
|
||||
* addr format (little endian)
|
||||
* @param[in] conn_params connection (timing) parameters, set to NULL to use
|
||||
* NimBLEs default parameters
|
||||
* @param[in] timeout connect timeout [in ms]
|
||||
* @param[in] cfg connection parameters
|
||||
*
|
||||
* @return the used connection handle on success
|
||||
* @return -EBUSY if already connected to the given address or if
|
||||
* a connection setup procedure is in progress
|
||||
* @return -EBUSY if already connected to the given address or if a connection
|
||||
* setup procedure is in progress
|
||||
* @return -ENOMEM if no connection context memory is available
|
||||
* @return -ECANCELED if unable to find valid connection interval
|
||||
* @return -EINVAL if unable to apply given PHY mode
|
||||
* @return -EIO on all other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout);
|
||||
const nimble_netif_connect_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Close the connection with the given handle
|
||||
@ -219,6 +259,7 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
||||
* @return 0 on success
|
||||
* @return -EINVAL if the handle is invalid
|
||||
* @return -ENOTCONN if context for given handle is not connected
|
||||
* @return -EIO on all other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_close(int handle);
|
||||
|
||||
@ -227,36 +268,39 @@ int nimble_netif_close(int handle);
|
||||
*
|
||||
* @param[in] ad advertising data (in BLE AD format)
|
||||
* @param[in] ad_len length of @p ad in bytes
|
||||
* @param[in] adv_params advertising (timing) parameters to use
|
||||
* @param[in] cfg advertising parameters to use
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if already advertising
|
||||
* @return -ENOMEM on insufficient connection memory
|
||||
* @return -EINVAL on invalid configuration parameters
|
||||
* @return -ECANCELED on other errors
|
||||
*/
|
||||
int nimble_netif_accept(const uint8_t *ad, size_t ad_len,
|
||||
const struct ble_gap_adv_params *adv_params);
|
||||
const nimble_netif_accept_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Wait for an incoming connection from a specific peer, sending
|
||||
* directed advertisements (IND_DIR)
|
||||
* directed advertisements
|
||||
*
|
||||
* @param[in] addr BLE address of the target peer
|
||||
* @param[in] timeout_ms stop advertising after this time (in ms), set to
|
||||
* BLE_HS_FOREVER to disable timeout
|
||||
* @param[in] adv_params advertising (timing) parameters to use
|
||||
* @param[in] cfg advertising parameters to use
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if already advertising
|
||||
* @return -ENOMEM on insufficient connection memory
|
||||
* @return -EINVAL on invalid configuration parameters
|
||||
* @return -ECANCELED on other errors
|
||||
*/
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr, uint32_t timeout_ms,
|
||||
const struct ble_gap_adv_params *adv_params);
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Stop accepting incoming connections (stop advertising)
|
||||
* *
|
||||
* @return 0 on success
|
||||
* @return -EALREADY if not currently advertising
|
||||
* @return -EIO on other NimBLE errors
|
||||
*/
|
||||
int nimble_netif_accept_stop(void);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Freie Universität Berlin
|
||||
* Copyright (C) 2018-2021 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
|
||||
@ -55,6 +55,8 @@
|
||||
#define NIMBLE_NETIF_PRIO GNRC_NETIF_PRIO
|
||||
#endif
|
||||
|
||||
#define EXT_ADV_INST 0
|
||||
|
||||
/* thread flag used for signaling transmit readiness */
|
||||
#define FLAG_TX_UNSTALLED (1u << 13)
|
||||
#define FLAG_TX_NOTCONN (1u << 12)
|
||||
@ -543,10 +545,14 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg)
|
||||
/* nothing to do here */
|
||||
break;
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
nimble_netif_conn_free(handle, addr);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, addr);
|
||||
if (conn->state == NIMBLE_NETIF_ADV) {
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
nimble_netif_conn_free(handle, addr);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, addr);
|
||||
}
|
||||
}
|
||||
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -577,14 +583,10 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb)
|
||||
}
|
||||
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout)
|
||||
const nimble_netif_connect_cfg_t *params)
|
||||
{
|
||||
assert(addr);
|
||||
assert(_eventcb);
|
||||
|
||||
uint16_t itvl_min = 0;
|
||||
uint16_t itvl_max = 0;
|
||||
assert(params);
|
||||
|
||||
/* the netif_conn module expects addresses in network byte order */
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
@ -602,33 +604,63 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((conn_params != NULL)
|
||||
&& (conn_params->itvl_min != conn_params->itvl_max)) {
|
||||
/* we need to save the min/max intervals in order to restore them
|
||||
* later on */
|
||||
itvl_min = conn_params->itvl_min;
|
||||
itvl_max = conn_params->itvl_max;
|
||||
|
||||
uint16_t itvl = nimble_netif_conn_gen_itvl(itvl_min, itvl_max);
|
||||
if (itvl == 0) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
conn_params->itvl_min = itvl;
|
||||
conn_params->itvl_max = itvl;
|
||||
/* generate connection interval */
|
||||
uint16_t itvl = params->conn_itvl_min_ms;
|
||||
if (params->conn_itvl_min_ms < params->conn_itvl_max_ms) {
|
||||
itvl = nimble_netif_conn_gen_itvl(params->conn_itvl_min_ms,
|
||||
params->conn_itvl_max_ms);
|
||||
}
|
||||
if (itvl == 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
int res = ble_gap_connect(nimble_riot_own_addr_type, addr, timeout,
|
||||
conn_params, _on_gap_master_evt, (void *)handle);
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
struct ble_gap_conn_params p = {
|
||||
.scan_itvl = BLE_GAP_SCAN_ITVL_MS(params->scan_itvl_ms),
|
||||
.scan_window = BLE_GAP_SCAN_WIN_MS(params->scan_window_ms),
|
||||
.itvl_min = BLE_GAP_CONN_ITVL_MS(itvl),
|
||||
.itvl_max = BLE_GAP_CONN_ITVL_MS(itvl),
|
||||
.latency = params->conn_slave_latency,
|
||||
.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
params->conn_supervision_timeout_ms),
|
||||
.min_ce_len = 0,
|
||||
.max_ce_len = 0,
|
||||
};
|
||||
|
||||
if (itvl_min != itvl_max) {
|
||||
conn_params->itvl_min = itvl_min;
|
||||
conn_params->itvl_max = itvl_max;
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
uint8_t phy_mask;
|
||||
if (params->phy_mode == NIMBLE_PHY_1M) {
|
||||
phy_mask = BLE_GAP_LE_PHY_1M_MASK;
|
||||
}
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (params->phy_mode == NIMBLE_PHY_2M) {
|
||||
phy_mask = (BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK);
|
||||
}
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (params->phy_mode == NIMBLE_PHY_CODED) {
|
||||
phy_mask = BLE_GAP_LE_PHY_CODED_MASK;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int res = ble_gap_ext_connect(params->own_addr_type, addr,
|
||||
params->timeout_ms, phy_mask, &p, &p, &p,
|
||||
_on_gap_master_evt, (void *)handle);
|
||||
#else
|
||||
uint32_t timeout = (params->timeout_ms == 0) ? BLE_HS_FOREVER
|
||||
: params->timeout_ms;
|
||||
int res = ble_gap_connect(params->own_addr_type, addr,
|
||||
timeout, &p,
|
||||
_on_gap_master_evt, (void *)handle);
|
||||
#endif
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_notify(handle, NIMBLE_NETIF_INIT_MASTER, addrn);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@ -642,63 +674,168 @@ int nimble_netif_close(int handle)
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
int res = ble_gap_terminate(ble_l2cap_get_conn_handle(conn->coc),
|
||||
BLE_ERR_REM_USER_CONN_TERM);
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
int res = ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM);
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _accept(const uint8_t *ad, size_t ad_len, const ble_addr_t *addr,
|
||||
uint32_t timeout,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
static int _get_phy_hci(uint8_t mode)
|
||||
{
|
||||
assert(adv_params);
|
||||
switch (mode) {
|
||||
case NIMBLE_PHY_1M:
|
||||
return BLE_HCI_LE_PHY_1M;
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
case NIMBLE_PHY_2M:
|
||||
return BLE_HCI_LE_PHY_2M;
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
case NIMBLE_PHY_CODED:
|
||||
return BLE_HCI_LE_PHY_CODED;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _accept(const uint8_t *ad, size_t ad_len, const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
int handle;
|
||||
int res;
|
||||
(void)res;
|
||||
|
||||
assert(params);
|
||||
|
||||
/* allocate a connection context for incoming connections */
|
||||
handle = nimble_netif_conn_start_adv();
|
||||
if (handle < 0) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
/* set advertisement data */
|
||||
if (ad != NULL) {
|
||||
res = ble_gap_adv_set_data(ad, (int)ad_len);
|
||||
assert(res == 0);
|
||||
}
|
||||
/* remember address if applicable */
|
||||
if (addr) {
|
||||
nimble_netif_conn_t *conn = nimble_netif_conn_get(handle);
|
||||
bluetil_addr_swapped_cp(addr->val, conn->addr);
|
||||
}
|
||||
|
||||
/* remember context and start advertising */
|
||||
res = ble_gap_adv_start(nimble_riot_own_addr_type, addr, timeout,
|
||||
adv_params, _on_gap_slave_evt, (void *)handle);
|
||||
assert(res == 0);
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
struct ble_gap_ext_adv_params p;
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
/* figure out PHY modes */
|
||||
int phy_pri = _get_phy_hci(params->primary_phy);
|
||||
int phy_sec = _get_phy_hci(params->secondary_phy);
|
||||
if ((phy_pri < 0) || (phy_sec < 0)) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* the 2M PHY is not allowed as primary phy, we need to used the 1M PHY
|
||||
* instead. This is for convenience so uses may define 2M as primary PHY */
|
||||
if (phy_pri == BLE_HCI_LE_PHY_2M) {
|
||||
phy_pri = BLE_HCI_LE_PHY_1M;
|
||||
}
|
||||
|
||||
if (addr != NULL) {
|
||||
p.directed = 1;
|
||||
memcpy(&p.peer, addr, sizeof(p.peer));
|
||||
if (params->flags & NIMBLE_NETIF_FLAG_HD_MODE) {
|
||||
p.high_duty_directed = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.connectable = 1;
|
||||
}
|
||||
if (params->flags & NIMBLE_NETIF_FLAG_LEGACY) {
|
||||
p.legacy_pdu = 1;
|
||||
/* legacy connectable PDUs are always scannable */
|
||||
p.scannable = 1;
|
||||
}
|
||||
p.itvl_min = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms);
|
||||
p.itvl_max = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms);
|
||||
p.channel_map = params->channel_map;
|
||||
p.own_addr_type = params->own_addr_type;
|
||||
p.primary_phy = (uint8_t)phy_pri;
|
||||
p.secondary_phy = (uint8_t)phy_sec;
|
||||
p.tx_power = params->tx_power;
|
||||
|
||||
res = ble_gap_ext_adv_configure(EXT_ADV_INST, &p, NULL,
|
||||
_on_gap_slave_evt, (void *)handle);
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ad != NULL) {
|
||||
struct os_mbuf *data = os_msys_get_pkthdr(ad_len, 0);
|
||||
if (data == NULL) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = os_mbuf_append(data, ad, ad_len);
|
||||
if (res != 0) {
|
||||
os_mbuf_free_chain(data);
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = ble_gap_ext_adv_set_data(EXT_ADV_INST, data);
|
||||
assert(res == 0);
|
||||
}
|
||||
res = ble_gap_ext_adv_start(EXT_ADV_INST, params->timeout_ms / 10, 0);
|
||||
#else
|
||||
uint8_t mode = (addr != NULL) ? BLE_GAP_CONN_MODE_DIR
|
||||
: BLE_GAP_CONN_MODE_UND;
|
||||
struct ble_gap_adv_params p = {
|
||||
.conn_mode = mode,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_GEN,
|
||||
.itvl_min = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms),
|
||||
.itvl_max = BLE_GAP_ADV_ITVL_MS(params->adv_itvl_ms),
|
||||
.channel_map = params->channel_map,
|
||||
.filter_policy = 0,
|
||||
.high_duty_cycle = (params->flags & NIMBLE_NETIF_FLAG_HD_MODE) ? 1 : 0,
|
||||
};
|
||||
|
||||
/* set advertisement data, if applicable */
|
||||
if (ad != NULL) {
|
||||
res = ble_gap_adv_set_data(ad, (int)ad_len);
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* start advertising */
|
||||
uint32_t timeout = (params->timeout_ms == 0) ? BLE_HS_FOREVER
|
||||
: params->timeout_ms;
|
||||
res = ble_gap_adv_start(params->own_addr_type, addr, timeout,
|
||||
&p, _on_gap_slave_evt, (void *)handle);
|
||||
#endif
|
||||
if (res != 0) {
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPTING, _netif.l2addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_netif_accept(const uint8_t *ad, size_t ad_len,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
assert(ad != NULL);
|
||||
assert(ad_len > 0);
|
||||
return _accept(ad, ad_len, NULL, BLE_HS_FOREVER, adv_params);
|
||||
return _accept(ad, ad_len, NULL, params);
|
||||
}
|
||||
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr, uint32_t timeout,
|
||||
const struct ble_gap_adv_params *adv_params)
|
||||
int nimble_netif_accept_direct(const ble_addr_t *addr,
|
||||
const nimble_netif_accept_cfg_t *params)
|
||||
{
|
||||
return _accept(NULL, 0, addr, timeout, adv_params);
|
||||
assert(addr);
|
||||
return _accept(NULL, 0, addr, params);
|
||||
}
|
||||
|
||||
int nimble_netif_accept_stop(void)
|
||||
@ -708,9 +845,15 @@ int nimble_netif_accept_stop(void)
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
int res = ble_gap_adv_stop();
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
int res;
|
||||
#if MYNEWT_VAL_BLE_EXT_ADV
|
||||
res = ble_gap_ext_adv_stop(EXT_ADV_INST);
|
||||
#else
|
||||
res = ble_gap_adv_stop();
|
||||
#endif
|
||||
if (res != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
nimble_netif_conn_free(handle, NULL);
|
||||
_notify(handle, NIMBLE_NETIF_ACCEPT_STOP, _netif.l2addr);
|
||||
|
||||
|
||||
@ -113,6 +113,7 @@ typedef struct {
|
||||
uint16_t conn_latency; /**< used slave latency for parent connection */
|
||||
uint32_t conn_super_to_ms; /**< used supervision timeout for parent
|
||||
* connection, in ms */
|
||||
nimble_phy_t phy_mode; /**< BLE PHY mode to use */
|
||||
uint32_t eval_itvl_min_ms; /**< amount of time a node searches for
|
||||
* potential parents, lower bound in ms */
|
||||
uint32_t eval_itvl_max_ms; /**< amount of time a node searches for
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Freie Universität Berlin
|
||||
* Copyright (C) 2019-2021 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
|
||||
@ -69,6 +69,13 @@ extern "C" {
|
||||
#define NIMBLE_RPBLE_EVAL_ITVL_MAX_MS 13000U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default BLE PHY mode used by rpble
|
||||
*/
|
||||
#ifndef NIMBLE_RPBLE_PHY_MODE
|
||||
#define NIMBLE_RPBLE_PHY_MODE NIMBLE_PHY_1M
|
||||
#endif
|
||||
|
||||
#ifndef NIMBLE_RPBLE_PARAMS
|
||||
#define NIMBLE_RPBLE_PARAMS \
|
||||
{ .scan_itvl_ms = NIMBLE_RPBLE_SCAN_ITVL_MS, \
|
||||
@ -81,6 +88,7 @@ extern "C" {
|
||||
.conn_itvl_max_ms = NIMBLE_RPBLE_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_RPBLE_CONN_LATENCY, \
|
||||
.conn_super_to_ms = NIMBLE_RPBLE_CONN_SUPER_TO_MS, \
|
||||
.phy_mode = NIMBLE_RPBLE_PHY_MODE, \
|
||||
.eval_itvl_min_ms = NIMBLE_RPBLE_EVAL_ITVL_MIN_MS, \
|
||||
.eval_itvl_max_ms = NIMBLE_RPBLE_EVAL_ITVL_MAX_MS }
|
||||
#endif
|
||||
|
||||
@ -50,9 +50,8 @@
|
||||
#define POS_FREE_SLOTS 22
|
||||
|
||||
/* keep the timing parameters for connections and advertisements */
|
||||
static struct ble_gap_adv_params _adv_params = { 0 };
|
||||
static struct ble_gap_conn_params _conn_params = { 0 };
|
||||
static uint32_t _conn_scan_to; /* in ms */
|
||||
static nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
/* local RPL context */
|
||||
static nimble_rpble_ctx_t _local_rpl_ctx;
|
||||
@ -107,7 +106,7 @@ static void _children_accept(void)
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
|
||||
/* start advertising this node */
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_adv_params);
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_accept_params);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
@ -118,10 +117,17 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
|
||||
int res;
|
||||
(void)info;
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
if ((type != (NIMBLE_SCANNER_EXT_ADV | BLE_HCI_ADV_CONN_MASK)) ||
|
||||
(info->status != BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE)) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* filter out all non-connectible advertisements */
|
||||
if (type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if scanned node does actually speak rpble */
|
||||
bluetil_ad_data_t sd_field;
|
||||
@ -199,7 +205,7 @@ static void _parent_connect(struct ble_npl_event *ev)
|
||||
}
|
||||
|
||||
/* try to connect to parent */
|
||||
int res = nimble_netif_connect(&_psel.addr, &_conn_params, _conn_scan_to);
|
||||
int res = nimble_netif_connect(&_psel.addr, &_conn_params);
|
||||
if (res < 0) {
|
||||
_parent_find();
|
||||
return;
|
||||
@ -283,19 +289,36 @@ int nimble_rpble_param_update(const nimble_rpble_cfg_t *cfg)
|
||||
cfg->eval_itvl_max_ms);
|
||||
ble_npl_time_ms_to_ticks(itvl, &_eval_itvl);
|
||||
|
||||
_adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
_adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
_adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(cfg->adv_itvl_ms);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
/* accept parameter extraction */
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
_accept_params.flags = 0;
|
||||
_accept_params.primary_phy = cfg->phy_mode;
|
||||
_accept_params.secondary_phy = cfg->phy_mode;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = cfg->adv_itvl_ms;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(cfg->conn_scan_itvl_ms);
|
||||
_conn_params.scan_window = BLE_GAP_SCAN_WIN_MS(cfg->conn_scan_win_ms);
|
||||
_conn_params.latency = cfg->conn_latency;
|
||||
_conn_params.supervision_timeout =
|
||||
BLE_GAP_SUPERVISION_TIMEOUT_MS(cfg->conn_super_to_ms);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(cfg->conn_itvl_min_ms);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(cfg->conn_itvl_max_ms);
|
||||
_conn_scan_to = cfg->conn_scan_to_ms;
|
||||
/* connection parameter extraction */
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
_conn_params.scan_itvl_ms = cfg->conn_scan_itvl_ms;
|
||||
_conn_params.scan_window_ms = cfg->conn_scan_win_ms;
|
||||
_conn_params.conn_itvl_min_ms = cfg->conn_itvl_min_ms;
|
||||
_conn_params.conn_itvl_max_ms = cfg->conn_itvl_max_ms;
|
||||
_conn_params.conn_supervision_timeout_ms = cfg->conn_super_to_ms;
|
||||
_conn_params.conn_slave_latency = cfg->conn_latency;
|
||||
_conn_params.timeout_ms = cfg->conn_scan_to_ms;
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT)
|
||||
_conn_params.phy_mode = cfg->phy_mode;
|
||||
#else
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* register event callback */
|
||||
nimble_netif_eventcb(_on_netif_evt);
|
||||
@ -304,9 +327,18 @@ int nimble_rpble_param_update(const nimble_rpble_cfg_t *cfg)
|
||||
nimble_scanner_cfg_t scan_params = { 0 };
|
||||
scan_params.itvl_ms = cfg->scan_itvl_ms;
|
||||
scan_params.win_ms = cfg->scan_win_ms;
|
||||
scan_params.flags = NIMBLE_SCANNER_PASSIVE
|
||||
| NIMBLE_SCANNER_FILTER_DUPS
|
||||
| NIMBLE_SCANNER_PHY_1M;
|
||||
scan_params.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_FILTER_DUPS);
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_RPBLE_EXT) && IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
if (cfg->phy_mode == NIMBLE_PHY_CODED) {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_CODED;
|
||||
}
|
||||
else {
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
}
|
||||
#else
|
||||
scan_params.flags |= NIMBLE_SCANNER_PHY_1M;
|
||||
#endif
|
||||
nimble_scanner_init(&scan_params, _on_scan_evt);
|
||||
|
||||
/* start to look for parents */
|
||||
|
||||
@ -44,7 +44,9 @@ enum {
|
||||
NIMBLE_SCANNER_LIMITED = 0x02, /**< do limited discovery */
|
||||
NIMBLE_SCANNER_FILTER_DUPS = 0x04, /**< filter duplicates */
|
||||
NIMBLE_SCANNER_PHY_1M = 0x10, /**< scan on 1Mbit PHY */
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
NIMBLE_SCANNER_PHY_CODED = 0x20, /**< scan on CODED PHY */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -100,9 +100,12 @@ int nimble_scanner_start(void)
|
||||
uint8_t limited = (_scan_flags & NIMBLE_SCANNER_LIMITED) ? 1 : 0;
|
||||
const struct ble_gap_ext_disc_params *uncoded =
|
||||
(_scan_flags & NIMBLE_SCANNER_PHY_1M) ? &_scan_params : NULL;
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
const struct ble_gap_ext_disc_params *coded =
|
||||
(_scan_flags & NIMBLE_SCANNER_PHY_CODED) ? &_scan_params : NULL;
|
||||
|
||||
#else
|
||||
const struct ble_gap_ext_disc_params *coded = NULL;
|
||||
#endif
|
||||
int32_t dur = (_scan_duration == BLE_HS_FOREVER) ? 0
|
||||
: _scan_duration / 10;
|
||||
|
||||
|
||||
@ -113,6 +113,21 @@ extern "C" {
|
||||
#define NIMBLE_STATCONN_CONN_SUPERTO_MS (2500U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief BLE PHY mode used by statconn. This value is only used if statconn
|
||||
* is used in its extended mode (module `nimble_statconn_ext`)
|
||||
*/
|
||||
#ifndef NIMBLE_STATCONN_PHY_MODE
|
||||
#define NIMBLE_STATCONN_PHY_MODE NIMBLE_PHY_1M
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Statconn connection parameters
|
||||
*/
|
||||
typedef struct {
|
||||
nimble_phy_t phy_mode; /**< BLE PHY mode used for the connection */
|
||||
} nimble_statconn_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the statconn module
|
||||
*
|
||||
@ -138,23 +153,31 @@ void nimble_statconn_eventcb(nimble_netif_eventcb_t cb);
|
||||
* connection by that master.
|
||||
*
|
||||
* @param[in] addr BLE address of the peer
|
||||
* @param[in] cfg additional connection parameters, set to NULL to apply
|
||||
* default values
|
||||
*
|
||||
* @return 0 if peer was successfully added
|
||||
* @return -EALREADY if the peer address is already in use
|
||||
* @return -ENOMEM if no empty connection slot is available
|
||||
* @return -EINVAL if invalid configuration parameters are given
|
||||
*/
|
||||
int nimble_statconn_add_master(const uint8_t *addr);
|
||||
int nimble_statconn_add_master(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Connect to a peer (slave) with a given address as master
|
||||
*
|
||||
* @param[in] addr BLE address of the peer
|
||||
* @param[in] cfg additional connection parameters, set to NULL to apply
|
||||
* default values
|
||||
*
|
||||
* @return 0 if peer was successfully added
|
||||
* @return -EALREADY if the peer address is already in use
|
||||
* @return -ENOMEM if no empty connection slot is available
|
||||
* @return -EINVAL if invalid configuration parameters are given
|
||||
*/
|
||||
int nimble_statconn_add_slave(const uint8_t *addr);
|
||||
int nimble_statconn_add_slave(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Remove the connection to the given peer
|
||||
|
||||
@ -44,6 +44,9 @@
|
||||
typedef struct {
|
||||
uint8_t addr[BLE_ADDR_LEN]; /**< peer addr, network byte order */
|
||||
uint8_t state; /**< internal state */
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
nimble_phy_t phy_mode; /**< PHY mode used by this slot */
|
||||
#endif
|
||||
} slot_t;
|
||||
|
||||
static const uint8_t _ad[2] = { BLE_GAP_AD_FLAGS, BLUETIL_AD_FLAGS_DEFAULT };
|
||||
@ -51,9 +54,8 @@ static const uint8_t _ad[2] = { BLE_GAP_AD_FLAGS, BLUETIL_AD_FLAGS_DEFAULT };
|
||||
static mutex_t _lock = MUTEX_INIT;
|
||||
static slot_t _slots[NIMBLE_NETIF_MAX_CONN];
|
||||
|
||||
static struct ble_gap_adv_params _adv_params;
|
||||
static struct ble_gap_conn_params _conn_params;
|
||||
static uint32_t _conn_timeout;
|
||||
static nimble_netif_accept_cfg_t _accept_params;
|
||||
static nimble_netif_connect_cfg_t _conn_params;
|
||||
|
||||
static nimble_netif_eventcb_t _eventcb = NULL;
|
||||
|
||||
@ -87,10 +89,17 @@ static void _activate(uint8_t role)
|
||||
peer.type = BLE_ADDR_RANDOM;
|
||||
bluetil_addr_swapped_cp(slot->addr, peer.val);
|
||||
/* try to (re)open the connection */
|
||||
nimble_netif_connect(&peer, &_conn_params, _conn_timeout);
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_conn_params.phy_mode = slot->phy_mode;
|
||||
#endif
|
||||
nimble_netif_connect(&peer, &_conn_params);
|
||||
}
|
||||
else if (slot && (role == ROLE_S)) {
|
||||
nimble_netif_accept(_ad, sizeof(_ad), &_adv_params);
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_accept_params.primary_phy = slot->phy_mode;
|
||||
_accept_params.secondary_phy = slot->phy_mode;
|
||||
#endif
|
||||
nimble_netif_accept(_ad, sizeof(_ad), &_accept_params);
|
||||
}
|
||||
mutex_unlock(&_lock);
|
||||
}
|
||||
@ -153,7 +162,8 @@ static void _on_netif_evt(int handle, nimble_netif_event_t event,
|
||||
}
|
||||
}
|
||||
|
||||
static int _be(uint8_t role, const uint8_t *addr)
|
||||
static int _be(uint8_t role, const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
mutex_lock(&_lock);
|
||||
slot_t *s = _get_addr(addr);
|
||||
@ -170,6 +180,18 @@ static int _be(uint8_t role, const uint8_t *addr)
|
||||
s->state = (role | PENDING);
|
||||
memcpy(s->addr, addr, BLE_ADDR_LEN);
|
||||
mutex_unlock(&_lock);
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
if (cfg != NULL) {
|
||||
s->phy_mode = cfg->phy_mode;
|
||||
}
|
||||
else {
|
||||
s->phy_mode = NIMBLE_STATCONN_PHY_MODE;
|
||||
}
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif
|
||||
|
||||
_activate(role);
|
||||
return 0;
|
||||
}
|
||||
@ -179,27 +201,31 @@ void nimble_statconn_init(void)
|
||||
memset(_slots, 0, sizeof(_slots));
|
||||
|
||||
/* set the advertising parameters used */
|
||||
_adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
_adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
_adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(NIMBLE_STATCONN_ADV_ITVL_MS);
|
||||
_adv_params.itvl_max = _adv_params.itvl_min;
|
||||
_adv_params.channel_map = 0;
|
||||
_adv_params.filter_policy = 0;
|
||||
_adv_params.high_duty_cycle = 0;
|
||||
memset(&_accept_params, 0, sizeof(_accept_params));
|
||||
#if IS_USED(MODULE_NIMBLE_STATCONN_EXT)
|
||||
_accept_params.flags = 0;
|
||||
#else
|
||||
_accept_params.flags = NIMBLE_NETIF_FLAG_LEGACY;
|
||||
_accept_params.primary_phy = NIMBLE_PHY_1M;
|
||||
_accept_params.secondary_phy = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_accept_params.adv_itvl_ms = NIMBLE_STATCONN_ADV_ITVL_MS;
|
||||
_accept_params.timeout_ms = BLE_HS_FOREVER;
|
||||
_accept_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* set connection parameters */
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(NIMBLE_STATCONN_CONN_WIN_MS);
|
||||
_conn_params.scan_window = _conn_params.scan_itvl;
|
||||
_conn_params.latency = NIMBLE_STATCONN_CONN_LATENCY;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
NIMBLE_STATCONN_CONN_SUPERTO_MS);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MIN_MS);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MAX_MS);
|
||||
_conn_params.min_ce_len = 0;
|
||||
_conn_params.max_ce_len = 0;
|
||||
_conn_timeout = NIMBLE_STATCONN_CONN_TIMEOUT_MS;
|
||||
memset(&_conn_params, 0, sizeof(_conn_params));
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN_EXT)
|
||||
_conn_params.phy_mode = NIMBLE_PHY_1M;
|
||||
#endif
|
||||
_conn_params.scan_itvl_ms = NIMBLE_STATCONN_CONN_WIN_MS;
|
||||
_conn_params.scan_window_ms = NIMBLE_STATCONN_CONN_WIN_MS;
|
||||
_conn_params.conn_itvl_min_ms = NIMBLE_STATCONN_CONN_ITVL_MIN_MS;
|
||||
_conn_params.conn_itvl_max_ms = NIMBLE_STATCONN_CONN_ITVL_MAX_MS;
|
||||
_conn_params.conn_supervision_timeout_ms = NIMBLE_STATCONN_CONN_SUPERTO_MS;
|
||||
_conn_params.conn_slave_latency = NIMBLE_STATCONN_CONN_LATENCY;
|
||||
_conn_params.timeout_ms = NIMBLE_STATCONN_CONN_TIMEOUT_MS;
|
||||
_conn_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* register our event callback */
|
||||
nimble_netif_eventcb(_on_netif_evt);
|
||||
@ -210,14 +236,16 @@ void nimble_statconn_eventcb(nimble_netif_eventcb_t cb)
|
||||
_eventcb = cb;
|
||||
}
|
||||
|
||||
int nimble_statconn_add_master(const uint8_t *addr)
|
||||
int nimble_statconn_add_master(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
return _be(ROLE_S, addr);
|
||||
return _be(ROLE_S, addr, cfg);
|
||||
}
|
||||
|
||||
int nimble_statconn_add_slave(const uint8_t *addr)
|
||||
int nimble_statconn_add_slave(const uint8_t *addr,
|
||||
const nimble_statconn_cfg_t *cfg)
|
||||
{
|
||||
return _be(ROLE_M, addr);
|
||||
return _be(ROLE_M, addr, cfg);
|
||||
}
|
||||
|
||||
int nimble_statconn_rm(const uint8_t *addr)
|
||||
|
||||
@ -115,7 +115,9 @@ $(PKG_PATCHED): $(PKG_PATCHED_PREREQUISITES)
|
||||
$(call gen_dependency_files,$@.d,$(PKG_PATCHED_PREREQUISITES))
|
||||
$(Q)$(GIT_IN_PKG) clean $(GIT_QUIET) -xdff '**' -e $(PKG_STATE:$(PKG_SOURCE_DIR)/%='%*')
|
||||
$(Q)$(GIT_IN_PKG) checkout $(GIT_QUIET) -f $(PKG_VERSION)
|
||||
$(Q)$(GIT_IN_PKG) $(GITFLAGS) am $(GITAMFLAGS) $(PKG_PATCHES) </dev/null
|
||||
$(Q) if test -n "$(PKG_PATCHES)" ; then \
|
||||
$(GIT_IN_PKG) $(GITFLAGS) am $(GITAMFLAGS) $(PKG_PATCHES) </dev/null ; \
|
||||
fi
|
||||
@touch $@
|
||||
|
||||
$(PKG_DOWNLOADED): $(MAKEFILE_LIST) | $(PKG_SOURCE_DIR)/.git
|
||||
|
||||
@ -332,6 +332,15 @@ static off_t _lseek(vfs_file_t *filp, off_t off, int whence)
|
||||
return spiffs_err_to_errno(SPIFFS_lseek(&fs_desc->fs, filp->private_data.value, off, s_whence));
|
||||
}
|
||||
|
||||
static int _fsync(vfs_file_t *filp)
|
||||
{
|
||||
spiffs_desc_t *fs_desc = filp->mp->private_data;
|
||||
|
||||
int ret = SPIFFS_fflush(&fs_desc->fs, filp->private_data.value);
|
||||
|
||||
return spiffs_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int _fstat(vfs_file_t *filp, struct stat *buf)
|
||||
{
|
||||
spiffs_desc_t *fs_desc = filp->mp->private_data;
|
||||
@ -514,6 +523,7 @@ static const vfs_file_ops_t spiffs_file_ops = {
|
||||
.write = _write,
|
||||
.lseek = _lseek,
|
||||
.fstat = _fstat,
|
||||
.fsync = _fsync,
|
||||
};
|
||||
|
||||
static const vfs_dir_ops_t spiffs_dir_ops = {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
PKG_NAME=tinycbor
|
||||
PKG_URL=https://github.com/intel/tinycbor
|
||||
# Tinycbor v0.5.3
|
||||
PKG_VERSION=755f9ef932f9830a63a712fd2ac971d838b131f1
|
||||
# Tinycbor v0.6.0
|
||||
PKG_VERSION=d393c16f3eb30d0c47e6f9d92db62272f0ec4dc7
|
||||
PKG_LICENSE=MIT
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
||||
@ -843,7 +843,6 @@ ifneq (,$(filter fido2_ctap,$(USEMODULE)))
|
||||
USEMODULE += ztimer_msec
|
||||
USEMODULE += event
|
||||
USEMODULE += event_timeout
|
||||
USEMODULE += prng_sha256prng
|
||||
USEMODULE += cipher_modes
|
||||
USEMODULE += crypto_aes_256
|
||||
USEMODULE += hashes
|
||||
|
||||
@ -4,4 +4,17 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig MODULE_FIDO2
|
||||
bool "FIDO2"
|
||||
help
|
||||
FIDO2 is an authentication standard that seeks to solve the password
|
||||
problem by enabling passwordless authentication. FIDO2 consists of the
|
||||
W3C Web Authentication specification (WebAuthn) and the Client to
|
||||
Authenticator Protocol (CTAP). For more information visit
|
||||
https://fidoalliance.org/fido2.
|
||||
|
||||
if MODULE_FIDO2
|
||||
|
||||
rsource "ctap/Kconfig"
|
||||
|
||||
endif # MODULE_FIDO2
|
||||
|
||||
@ -4,13 +4,37 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig KCONFIG_USEMODULE_FIDO2_CTAP
|
||||
menuconfig MODULE_FIDO2_CTAP
|
||||
bool "FIDO2 CTAP"
|
||||
depends on USEMODULE_FIDO2_CTAP
|
||||
depends on HAS_PERIPH_FLASHPAGE
|
||||
depends on HAS_PERIPH_GPIO
|
||||
depends on HAS_PERIPH_GPIO_IRQ
|
||||
depends on MODULE_FIDO2
|
||||
depends on TEST_KCONFIG
|
||||
select PACKAGE_TINYCBOR
|
||||
select PACKAGE_MICRO-ECC
|
||||
select PACKAGE_TINY-ASN1
|
||||
select MODULE_PERIPH_GPIO
|
||||
select MODULE_PERIPH_GPIO_IRQ
|
||||
select MODULE_EVENT
|
||||
select MODULE_EVENT_TIMEOUT
|
||||
select MODULE_ZTIMER
|
||||
select MODULE_ZTIMER_MSEC
|
||||
select MODULE_MTD
|
||||
select MODULE_MTD_FLASHPAGE
|
||||
select MODULE_MTD_WRITE_PAGE
|
||||
select MODULE_RANDOM
|
||||
select MODULE_CRYPTO_AES_256
|
||||
select MODULE_CIPHER_MODES
|
||||
select MODULE_HASHES
|
||||
help
|
||||
Configure a FIDO2 CTAP authenticator via KConfig.
|
||||
Y to enable CTAP protocol support. The Client-to-Authenticator
|
||||
Protocol (CTAP) is an application layer protocol for the communication
|
||||
between an authenticator and a host. CTAP is part of the FIDO2 Project.
|
||||
For more information visit https://fidoalliance.org/fido2.
|
||||
|
||||
if KCONFIG_USEMODULE_FIDO2_CTAP
|
||||
|
||||
if MODULE_FIDO2_CTAP
|
||||
|
||||
config FIDO2_CTAP_STACK_SIZE
|
||||
int "CTAP thread stack size"
|
||||
@ -93,4 +117,4 @@ config FIDO2_CTAP_FLASH_START_PAGE
|
||||
|
||||
rsource "transport/Kconfig"
|
||||
|
||||
endif # KCONFIG_USEMODULE_FIDO2_CTAP
|
||||
endif # MODULE_FIDO2_CTAP
|
||||
|
||||
@ -4,4 +4,9 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig MODULE_FIDO2_CTAP_TRANSPORT
|
||||
bool "FIDO2 CTAP transport"
|
||||
depends on MODULE_FIDO2_CTAP
|
||||
depends on TEST_KCONFIG
|
||||
|
||||
rsource "hid/Kconfig"
|
||||
|
||||
@ -4,13 +4,16 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig KCONFIG_USEMODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
bool "FIDO2 CTAP TRANSPORT HID"
|
||||
depends on USEMODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
menuconfig MODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
bool "FIDO2 CTAP transport HID"
|
||||
depends on MODULE_FIDO2_CTAP_TRANSPORT
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_ISRPIPE
|
||||
select MODULE_USBUS_HID
|
||||
help
|
||||
Configure a FIDO2 CTAP authenticator via KConfig.
|
||||
|
||||
if KCONFIG_USEMODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
if MODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
|
||||
config FIDO2_CTAP_TRANSPORT_HID_TRANSACTION_TIMEOUT
|
||||
int "CTAPHID Transaction timeout in milliseconds"
|
||||
@ -20,4 +23,4 @@ config FIDO2_CTAP_TRANSPORT_HID_TRANSACTION_TIMEOUT
|
||||
of time to prevent the authenticator from being locked by a
|
||||
stalling application.
|
||||
|
||||
endif # KCONFIG_USEMODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
endif # MODULE_FIDO2_CTAP_TRANSPORT_HID
|
||||
|
||||
@ -139,6 +139,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "sched.h"
|
||||
|
||||
#include "atomic_utils_arch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -263,6 +265,16 @@ static inline uintptr_t atomic_load_uintptr(const volatile uintptr_t *var) {
|
||||
static inline void * atomic_load_ptr(void **ptr_addr) {
|
||||
return (void *)atomic_load_uintptr((const volatile uintptr_t *)ptr_addr);
|
||||
}
|
||||
/**
|
||||
* @brief Load an `kernel_pid_t` atomically
|
||||
*
|
||||
* @param[in] var Variable to load atomically
|
||||
* @return The value stored in @p var
|
||||
*/
|
||||
static inline kernel_pid_t atomic_load_kernel_pid(const volatile kernel_pid_t *var)
|
||||
{
|
||||
return atomic_load_u16((const volatile uint16_t *)var);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -321,6 +333,17 @@ static inline void atomic_store_uintptr(volatile uintptr_t *dest, uintptr_t val)
|
||||
static inline void atomic_store_ptr(void **dest, const void *val) {
|
||||
atomic_store_uintptr((volatile uintptr_t *)dest, (uintptr_t)val);
|
||||
}
|
||||
/**
|
||||
* @brief Store an `kernel_pid_t` atomically
|
||||
*
|
||||
* @param[out] dest Location to atomically write the new value to
|
||||
* @param[in] val Value to write
|
||||
*/
|
||||
static inline void atomic_store_kernel_pid(volatile kernel_pid_t *dest,
|
||||
kernel_pid_t val)
|
||||
{
|
||||
atomic_store_u16((volatile uint16_t *)dest, (uint16_t)val);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
69
sys/include/stdio_nimble.h
Normal file
69
sys/include/stdio_nimble.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_stdio_nimble STDIO over NimBLE
|
||||
* @ingroup sys
|
||||
*
|
||||
* @experimental This feature is experimental as some use-cases, such as examples/twr_aloha, show
|
||||
* unexpected behaviour.
|
||||
*
|
||||
* @brief Standard input/output backend using NimBLE.
|
||||
*
|
||||
* @note 'stdio_read' blocks until at least one character was read.
|
||||
*
|
||||
* @note 'stdio_write' is considered non-blocking even though it uses a mutex to protect the
|
||||
* write buffer since only 'stdio_write' uses this mutex. Characters will be written
|
||||
* in FIFO mode. Characters that do not fit in the buffer will be dropped.
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
*
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef STDIO_NIMBLE_H
|
||||
#define STDIO_NIMBLE_H
|
||||
|
||||
#include "stdio_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Whether to clear the buffers when establishing a new connection or
|
||||
* not. Defaults to true.
|
||||
*/
|
||||
#ifndef CONFIG_STDIO_NIMBLE_CLEAR_BUFFER_ON_CONNECT
|
||||
#define CONFIG_STDIO_NIMBLE_CLEAR_BUFFER_ON_CONNECT 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of buffer for stdin in bytes
|
||||
*
|
||||
* @note Must be a power of two!
|
||||
*/
|
||||
#ifndef CONFIG_STDIO_NIMBLE_STDIN_BUFSIZE
|
||||
#define CONFIG_STDIO_NIMBLE_STDIN_BUFSIZE 1024
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of buffer for stdout in bytes
|
||||
*
|
||||
* @note Must be a power of two!
|
||||
*/
|
||||
#ifndef CONFIG_STDIO_NIMBLE_STDOUT_BUFSIZE
|
||||
#define CONFIG_STDIO_NIMBLE_STDOUT_BUFSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif /* STDIO_NIMBLE_H */
|
||||
@ -440,6 +440,17 @@ struct vfs_file_ops {
|
||||
* @return <0 on error
|
||||
*/
|
||||
ssize_t (*write) (vfs_file_t *filp, const void *src, size_t nbytes);
|
||||
|
||||
/**
|
||||
* @brief Synchronize a file on storage
|
||||
* Any pending writes are written out to storage.
|
||||
*
|
||||
* @param[in] filp pointer to open file
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int (*fsync) (vfs_file_t *filp);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -739,6 +750,17 @@ ssize_t vfs_read(int fd, void *dest, size_t count);
|
||||
*/
|
||||
ssize_t vfs_write(int fd, const void *src, size_t count);
|
||||
|
||||
/**
|
||||
* @brief Synchronize a file on storage
|
||||
* Any pending writes are written out to storage.
|
||||
*
|
||||
* @param[in] fd fd number obtained from vfs_open
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int vfs_fsync(int fd);
|
||||
|
||||
/**
|
||||
* @brief Open a directory for reading with readdir
|
||||
*
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "fmt.h"
|
||||
#include "ztimer.h"
|
||||
@ -30,17 +31,37 @@
|
||||
#include "net/bluetil/ad.h"
|
||||
#include "net/bluetil/addr.h"
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
#define FULL_CONTROL !IS_USED(MODULE_NIMBLE_AUTOCONN) && \
|
||||
!IS_USED(MODULE_NIMBLE_STATCONN) && \
|
||||
!IS_USED(MODULE_NIMBLE_RPBLE)
|
||||
|
||||
#if FULL_CONTROL
|
||||
#include "nimble_scanlist.h"
|
||||
#include "nimble_scanner.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_NODE_NAME "bleRIOT"
|
||||
#define DEFAULT_SCAN_DURATION (500U) /* 500ms */
|
||||
#define DEFAULT_CONN_TIMEOUT (500U) /* 500ms */
|
||||
#define DEFAULT_SCAN_DURATION_MS 500U
|
||||
#define DEFAULT_CONN_TIMEOUT_MS 500U
|
||||
#define DEFAULT_SCAN_ITVL_MS 100U
|
||||
#define DEFAULT_CONN_ITVL_MS 75U
|
||||
#define DEFAULT_TX_POWER 0 /* 0dBm */
|
||||
#define DEFAULT_ADV_ITVL_MS 75U
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
static const char *_phystr[] = { "N/A", "1M", "2M", "CODED" };
|
||||
|
||||
#if FULL_CONTROL
|
||||
static const char *_name_to_connect = NULL;
|
||||
static nimble_netif_connect_cfg_t _connect_params = {
|
||||
.scan_itvl_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.scan_window_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.conn_itvl_min_ms = DEFAULT_CONN_ITVL_MS,
|
||||
.conn_itvl_max_ms = DEFAULT_CONN_ITVL_MS,
|
||||
.conn_supervision_timeout_ms = DEFAULT_CONN_ITVL_MS * 20,
|
||||
.conn_slave_latency = 0,
|
||||
.timeout_ms = 0, /* will be filled later */
|
||||
.phy_mode = 0, /* will be filled later */
|
||||
.own_addr_type = 0 /* will be filled later */,
|
||||
};
|
||||
|
||||
static void _scan_for_name(uint8_t type, const ble_addr_t *addr,
|
||||
const nimble_scanner_info_t *info,
|
||||
@ -56,7 +77,7 @@ static void _scan_for_name(uint8_t type, const ble_addr_t *addr,
|
||||
_name_to_connect, strlen(_name_to_connect));
|
||||
if (res) {
|
||||
nimble_scanner_stop();
|
||||
nimble_netif_connect(addr, NULL, DEFAULT_CONN_TIMEOUT);
|
||||
nimble_netif_connect(addr, &_connect_params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,12 +111,34 @@ static void _on_ble_evt(int handle, nimble_netif_event_t event,
|
||||
case NIMBLE_NETIF_ABORT_SLAVE:
|
||||
_print_evt("CONNECTION ABORT", handle, addr);
|
||||
break;
|
||||
case NIMBLE_NETIF_ACCEPT_STOP:
|
||||
_print_evt("ACCEPT STOP", handle, addr);
|
||||
case NIMBLE_NETIF_CONN_UPDATED:
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t _parsephy(const char *phy_str)
|
||||
{
|
||||
if (memcmp(phy_str, "1M", 2) == 0) {
|
||||
return NIMBLE_PHY_1M;
|
||||
}
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (memcmp(phy_str, "2M", 2) == 0) {
|
||||
return NIMBLE_PHY_2M;
|
||||
}
|
||||
#endif
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (memcmp(phy_str, "CODED", 5) == 0) {
|
||||
return NIMBLE_PHY_CODED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return NIMBLE_PHY_INVALID;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _conn_dump(nimble_netif_conn_t *conn, int handle, void *arg)
|
||||
@ -117,8 +160,20 @@ static int _conn_dump(nimble_netif_conn_t *conn, int handle, void *arg)
|
||||
printf(" ");
|
||||
bluetil_addr_ipv6_l2ll_print(conn->addr);
|
||||
#endif
|
||||
printf(" (%c,%ums,%ums,%i)", role, itvl, sto, (int)desc.conn_latency);
|
||||
puts("");
|
||||
|
||||
#if IS_USED(MODULE_NIMBLE_NETIF_EXT)
|
||||
uint8_t phy_rx, phy_tx;
|
||||
(void)phy_tx;
|
||||
res = ble_gap_read_le_phy(conn->gaphandle, &phy_tx, &phy_rx);
|
||||
if (res != 0) {
|
||||
phy_rx = 1;
|
||||
}
|
||||
#else
|
||||
/* when not using extended advertisements we always use the 1M phy mode */
|
||||
uint8_t phy_rx = 1;
|
||||
#endif
|
||||
printf(" (%c,%ums,%ums,%i,%s)\n",
|
||||
role, itvl, sto, (int)desc.conn_latency, _phystr[phy_rx]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -159,7 +214,7 @@ static void _conn_list(void)
|
||||
if (active > 0) {
|
||||
nimble_netif_conn_foreach(NIMBLE_NETIF_L2CAP_CONNECTED,
|
||||
_conn_dump, NULL);
|
||||
puts(" (role, conn itvl, superv. timeout, slave latency)");
|
||||
puts(" (role, conn itvl, superv. timeout, slave latency, PHY)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +234,15 @@ static void _cmd_info(void)
|
||||
#endif
|
||||
puts("");
|
||||
|
||||
printf("Supported PHY modes: 1M");
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_2MBIT)
|
||||
printf(" 2M");
|
||||
#endif
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
printf(" CODED");
|
||||
#endif
|
||||
puts("");
|
||||
|
||||
printf(" Free slots: %u/%u\n", free, NIMBLE_NETIF_MAX_CONN);
|
||||
printf("Advertising: ");
|
||||
if (nimble_netif_conn_get_adv() != NIMBLE_NETIF_CONN_INVALID) {
|
||||
@ -196,99 +260,107 @@ static void _cmd_info(void)
|
||||
puts("");
|
||||
}
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
static void _cmd_adv(const char *name)
|
||||
#if FULL_CONTROL
|
||||
static int _cmd_adv(int argc, char **argv, bool legacy)
|
||||
{
|
||||
int res;
|
||||
(void)res;
|
||||
uint8_t buf[BLE_HS_ADV_MAX_SZ];
|
||||
bluetil_ad_t ad;
|
||||
const struct ble_gap_adv_params _adv_params = {
|
||||
.conn_mode = BLE_GAP_CONN_MODE_UND,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_LTD,
|
||||
.itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN,
|
||||
.itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX,
|
||||
};
|
||||
const char *name = NULL;
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
ble_addr_t addr = { .type = nimble_riot_own_addr_type };
|
||||
|
||||
/* stop sub-command: stop advertising */
|
||||
if (memcmp(argv[2], "stop", 4) == 0) {
|
||||
res = nimble_netif_accept_stop();
|
||||
if (res == 0) {
|
||||
puts("advertising stopped");
|
||||
}
|
||||
else if (res == -EALREADY) {
|
||||
puts("no advertising in progress");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure no advertising is in progress */
|
||||
if (nimble_netif_conn_is_adv()) {
|
||||
puts("err: advertising already in progress");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* build advertising data */
|
||||
res = bluetil_ad_init_with_flags(&ad, buf, BLE_HS_ADV_MAX_SZ,
|
||||
BLUETIL_AD_FLAGS_DEFAULT);
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
uint16_t ipss = BLE_GATT_SVC_IPSS;
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_UUID16_INCOMP, &ipss, sizeof(ipss));
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
if (name == NULL) {
|
||||
name = DEFAULT_NODE_NAME;
|
||||
/* try if first parameter is a BLE address, if so, use directed
|
||||
* advertisement */
|
||||
if (bluetil_addr_from_str(addrn, argv[2]) != NULL) {
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
puts("Found BLE address: sending directed advertisements");
|
||||
}
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_NAME, name, strlen(name));
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
puts("err: the given name is too long");
|
||||
return;
|
||||
else {
|
||||
name = argv[2];
|
||||
}
|
||||
|
||||
uint32_t timeout = 0;
|
||||
if (argc >= 4) {
|
||||
timeout = (uint32_t)atoi(argv[3]);
|
||||
}
|
||||
|
||||
uint8_t phy_sec = BLE_GAP_LE_PHY_1M;
|
||||
if (argc >= 5) {
|
||||
phy_sec = _parsephy(argv[4]);
|
||||
if (phy_sec == 0) {
|
||||
puts("err: PHY mode not supported\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
uint8_t phy_pri = (phy_sec == BLE_HCI_LE_PHY_2M) ? BLE_HCI_LE_PHY_1M
|
||||
: phy_sec;
|
||||
|
||||
nimble_netif_accept_cfg_t p = {
|
||||
.flags = (legacy) ? NIMBLE_NETIF_FLAG_LEGACY : 0,
|
||||
.adv_itvl_ms = DEFAULT_ADV_ITVL_MS,
|
||||
.primary_phy = phy_pri,
|
||||
.secondary_phy = phy_sec,
|
||||
.tx_power = DEFAULT_TX_POWER,
|
||||
.channel_map = 0,
|
||||
.timeout_ms = timeout,
|
||||
.own_addr_type = nimble_riot_own_addr_type,
|
||||
};
|
||||
|
||||
if (name != NULL) {
|
||||
uint8_t buf[BLE_HS_ADV_MAX_SZ];
|
||||
bluetil_ad_t ad;
|
||||
/* build advertising data */
|
||||
res = bluetil_ad_init_with_flags(&ad, buf, BLE_HS_ADV_MAX_SZ,
|
||||
BLUETIL_AD_FLAGS_DEFAULT);
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
uint16_t ipss = BLE_GATT_SVC_IPSS;
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_UUID16_INCOMP, &ipss, sizeof(ipss));
|
||||
assert(res == BLUETIL_AD_OK);
|
||||
res = bluetil_ad_add(&ad, BLE_GAP_AD_NAME, name, strlen(name));
|
||||
if (res != BLUETIL_AD_OK) {
|
||||
puts("err: the given name is too long");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &p);
|
||||
}
|
||||
else {
|
||||
res = nimble_netif_accept_direct(&addr, &p);
|
||||
}
|
||||
|
||||
/* start listening for incoming connections */
|
||||
res = nimble_netif_accept(ad.buf, ad.pos, &_adv_params);
|
||||
if (res != 0) {
|
||||
printf("err: unable to start advertising (%i)\n", res);
|
||||
}
|
||||
else {
|
||||
printf("success: advertising this node as '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_adv_direct(const char *addr_str)
|
||||
{
|
||||
int res;
|
||||
(void)res;
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
ble_addr_t addr;
|
||||
const struct ble_gap_adv_params _adv_params = {
|
||||
.conn_mode = BLE_GAP_CONN_MODE_DIR,
|
||||
.disc_mode = BLE_GAP_DISC_MODE_GEN,
|
||||
.itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN,
|
||||
.itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX,
|
||||
};
|
||||
|
||||
/* make sure no advertising is in progress */
|
||||
if (nimble_netif_conn_is_adv()) {
|
||||
puts("err: advertising already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse and convert address -> RIOT uses big endian notation, NimBLE
|
||||
* expects little endian... */
|
||||
if (bluetil_addr_from_str(addrn, addr_str) == NULL) {
|
||||
puts("err: unable to parse BLE address");
|
||||
return;
|
||||
}
|
||||
addr.type = nimble_riot_own_addr_type;
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
|
||||
/* start advertising directed advertising with the given BLE address */
|
||||
res = nimble_netif_accept_direct(&addr, BLE_HS_FOREVER, &_adv_params);
|
||||
if (res != 0) {
|
||||
printf("err: unable to start directed advertising (%i)\n", res);
|
||||
}
|
||||
else {
|
||||
puts("success: started to send directed advertisements");
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_adv_stop(void)
|
||||
{
|
||||
int res = nimble_netif_accept_stop();
|
||||
if (res == 0) {
|
||||
puts("canceled advertising");
|
||||
}
|
||||
else {
|
||||
puts("no advertising in progress");
|
||||
if (name != NULL) {
|
||||
printf("success: advertising this node as '%s'\n", name);
|
||||
}
|
||||
else {
|
||||
printf("success: sending direct advertisements to ");
|
||||
bluetil_addr_print(addrn);
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _do_scan(nimble_scanner_cb cb, unsigned duration)
|
||||
@ -301,7 +373,19 @@ static void _do_scan(nimble_scanner_cb cb, unsigned duration)
|
||||
printf("err: scanner already active\n");
|
||||
return;
|
||||
}
|
||||
nimble_scanner_init(NULL, cb);
|
||||
|
||||
nimble_scanner_cfg_t p = {
|
||||
.itvl_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
.win_ms = DEFAULT_SCAN_ITVL_MS,
|
||||
#if IS_USED(MODULE_NIMBLE_PHY_CODED)
|
||||
.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_PHY_1M |
|
||||
NIMBLE_SCANNER_PHY_CODED),
|
||||
#else
|
||||
.flags = (NIMBLE_SCANNER_PASSIVE | NIMBLE_SCANNER_PHY_1M),
|
||||
#endif
|
||||
};
|
||||
|
||||
nimble_scanner_init(&p, cb);
|
||||
nimble_scanlist_clear();
|
||||
nimble_scanner_start();
|
||||
ztimer_sleep(ZTIMER_MSEC, duration);
|
||||
@ -316,58 +400,73 @@ static void _cmd_scan(unsigned duration)
|
||||
nimble_scanlist_print();
|
||||
}
|
||||
|
||||
static void _cmd_connect_addr(ble_addr_t *addr)
|
||||
static void _cmd_connect(int argc, char **argv)
|
||||
{
|
||||
/* simply use NimBLEs default connection parameters */
|
||||
int res = nimble_netif_connect(addr, NULL, DEFAULT_CONN_TIMEOUT);
|
||||
if (res < 0) {
|
||||
printf("err: unable to trigger connection sequence (%i)\n", res);
|
||||
return;
|
||||
}
|
||||
ble_addr_t addr;
|
||||
int proceed = 0;
|
||||
|
||||
printf("initiated connection procedure with ");
|
||||
/* populate connection parameters */
|
||||
_connect_params.timeout_ms = DEFAULT_CONN_TIMEOUT_MS;
|
||||
if (argc >= 4) {
|
||||
_connect_params.timeout_ms = (uint32_t)atoi(argv[3]);
|
||||
}
|
||||
_connect_params.phy_mode = NIMBLE_PHY_1M;
|
||||
if (argc >= 5) {
|
||||
_connect_params.phy_mode = _parsephy(argv[4]);
|
||||
if (_connect_params.phy_mode == 0) {
|
||||
puts("err: PHY mode not supported\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
_connect_params.own_addr_type = nimble_riot_own_addr_type;
|
||||
|
||||
/* try to parse address directly */
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
bluetil_addr_swapped_cp(addr->val, addrn);
|
||||
bluetil_addr_print(addrn);
|
||||
puts("");
|
||||
|
||||
}
|
||||
|
||||
static void _cmd_connect_addr_raw(const uint8_t *addr_in)
|
||||
{
|
||||
/* RANDOM is the most common type, has no noticeable effect when connecting
|
||||
anyhow... */
|
||||
ble_addr_t addr = { .type = BLE_ADDR_RANDOM };
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addr_in, addr.val);
|
||||
_cmd_connect_addr(&addr);
|
||||
}
|
||||
|
||||
static void _cmd_connect_name(const char *name, unsigned duration)
|
||||
{
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("err: already trying to connect to '%s'\n", _name_to_connect);
|
||||
if (bluetil_addr_from_str(addrn, argv[2]) != NULL) {
|
||||
addr.type = nimble_riot_own_addr_type;
|
||||
/* NimBLE expects address in little endian, so swap */
|
||||
bluetil_addr_swapped_cp(addrn, addr.val);
|
||||
proceed = 1;
|
||||
}
|
||||
/* try if param is a number, if so use it as scanlist entry number */
|
||||
else if (fmt_is_number(argv[2])) {
|
||||
unsigned pos = atoi(argv[2]);
|
||||
nimble_scanlist_entry_t *sle = nimble_scanlist_get_by_pos(pos);
|
||||
if (sle == NULL) {
|
||||
puts("err: unable to find given entry in scanlist");
|
||||
return;
|
||||
}
|
||||
_connect_params.phy_mode = sle->phy_sec;
|
||||
memcpy(&addr, &sle->addr, sizeof(addr));
|
||||
proceed = 1;
|
||||
}
|
||||
/* else interpret value as name and search for that peer */
|
||||
else {
|
||||
unsigned duration = DEFAULT_SCAN_DURATION_MS;
|
||||
if (argc > 3) {
|
||||
duration = atoi(argv[3]);
|
||||
}
|
||||
_name_to_connect = argv[2];
|
||||
printf("trying to find and connect to a node with name '%s'\n", argv[2]);
|
||||
_do_scan(_scan_for_name, duration);
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("fail: unable to connect to '%s'\n", _name_to_connect);
|
||||
_name_to_connect = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
_name_to_connect = name;
|
||||
printf("trying to find and connect to a node with name '%s'\n", name);
|
||||
_do_scan(_scan_for_name, duration);
|
||||
if (_name_to_connect != NULL) {
|
||||
printf("fail: unable to connect to '%s'\n", _name_to_connect);
|
||||
_name_to_connect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void _cmd_connect_scanlist(unsigned pos)
|
||||
{
|
||||
nimble_scanlist_entry_t *sle = nimble_scanlist_get_by_pos(pos);
|
||||
if (sle == NULL) {
|
||||
puts("err: unable to find given entry in scanlist");
|
||||
return;
|
||||
if (proceed == 1) {
|
||||
int res = nimble_netif_connect(&addr, &_connect_params);
|
||||
if (res == 0) {
|
||||
puts("Successfully connected 123");
|
||||
}
|
||||
else {
|
||||
puts("err: unable to connect");
|
||||
}
|
||||
}
|
||||
_cmd_connect_addr(&sle->addr);
|
||||
}
|
||||
#endif /* MODULE_NIMBLE_AUTOCONN */
|
||||
#endif
|
||||
|
||||
static void _cmd_close(int handle)
|
||||
{
|
||||
@ -406,7 +505,7 @@ static int _ishelp(char *argv)
|
||||
|
||||
void sc_nimble_netif_init(void)
|
||||
{
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
#if FULL_CONTROL
|
||||
/* setup the scanning environment */
|
||||
nimble_scanlist_init();
|
||||
|
||||
@ -418,8 +517,9 @@ void sc_nimble_netif_init(void)
|
||||
int _nimble_netif_handler(int argc, char **argv)
|
||||
{
|
||||
if ((argc == 1) || _ishelp(argv[1])) {
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
printf("usage: %s [help|info|adv|scan|connect|close|update|chanmap]\n", argv[0]);
|
||||
#if FULL_CONTROL
|
||||
printf("usage: %s [help|info|adv|adv_ext|adv_dir|"
|
||||
"scan|connect|close|update|chanmap]\n", argv[0]);
|
||||
#else
|
||||
printf("usage: %s [help|info|close|update|chanmap]\n", argv[0]);
|
||||
#endif
|
||||
@ -429,34 +529,26 @@ int _nimble_netif_handler(int argc, char **argv)
|
||||
_cmd_info();
|
||||
}
|
||||
|
||||
#if !IS_USED(MODULE_NIMBLE_AUTOCONN) && !IS_USED(MODULE_NIMBLE_STATCONN)
|
||||
else if (memcmp(argv[1], "adv", 3) == 0) {
|
||||
char *name = NULL;
|
||||
if (argc > 2) {
|
||||
if (_ishelp(argv[2])) {
|
||||
printf("usage: %s adv [help|stop|direct <addr>|<name>]\n",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "stop", 4) == 0) {
|
||||
_cmd_adv_stop();
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "direct", 6) == 0) {
|
||||
puts("DBG: direct adv");
|
||||
if (argc < 4) {
|
||||
printf("error, no BLE address given\n");
|
||||
return 0;
|
||||
}
|
||||
_cmd_adv_direct(argv[3]);
|
||||
return 0;
|
||||
}
|
||||
name = argv[2];
|
||||
#if FULL_CONTROL
|
||||
else if (memcmp(argv[1], "adv_ext", 7) == 0) {
|
||||
if (argc <= 2 || _ishelp(argv[2])) {
|
||||
printf("usage: %s adv_ext <help|stop|addr|name> [timeout] [phy mode]\n"
|
||||
" timeout in ms, 0 for no timeout\n"
|
||||
" phy mode: [1M|2M|CODED]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
_cmd_adv(name);
|
||||
return _cmd_adv(argc, argv, false);
|
||||
}
|
||||
else if (memcmp(argv[1], "adv", 3) == 0) {
|
||||
if (argc <= 2 || _ishelp(argv[2])) {
|
||||
printf("usage: %s adv <help|stop|addr|name> [timeout]\n"
|
||||
" timeout in ms, 0 for no timeout\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
return _cmd_adv(argc, argv, true);
|
||||
}
|
||||
else if (memcmp(argv[1], "scan", 4) == 0) {
|
||||
uint32_t duration = DEFAULT_SCAN_DURATION;
|
||||
uint32_t duration = DEFAULT_SCAN_DURATION_MS;
|
||||
if (argc > 2) {
|
||||
if (_ishelp(argv[2])) {
|
||||
printf("usage: %s scan [help|list|[duration in ms]]\n", argv[0]);
|
||||
@ -472,32 +564,16 @@ int _nimble_netif_handler(int argc, char **argv)
|
||||
}
|
||||
else if (memcmp(argv[1], "connect", 7) == 0) {
|
||||
if ((argc < 3) || _ishelp(argv[2])) {
|
||||
printf("usage: %s connect [help|list|<scanlist entry #>|<BLE addr>|<name>]\n",
|
||||
argv[0]);
|
||||
printf("usage: %s %s [help|list|<scanlist #>|<BLE addr>|<name>] "
|
||||
"[timeout ms] [phy mode]\n"
|
||||
" phy mode: [1M|2M|CODED]\n", argv[0], argv[1]);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(argv[2], "list", 4) == 0) {
|
||||
_conn_list();
|
||||
return 0;
|
||||
}
|
||||
/* try if param is an BLE address */
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
if (bluetil_addr_from_str(addr, argv[2]) != NULL) {
|
||||
_cmd_connect_addr_raw(addr);
|
||||
return 0;
|
||||
}
|
||||
/* try if param is a name (contains non-number chars) */
|
||||
if (!fmt_is_number(argv[2])) {
|
||||
unsigned duration = DEFAULT_SCAN_DURATION;
|
||||
if (argc > 3) {
|
||||
duration = atoi(argv[3]);
|
||||
}
|
||||
_cmd_connect_name(argv[2], duration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned pos = atoi(argv[2]);
|
||||
_cmd_connect_scanlist(pos);
|
||||
_cmd_connect(argc, argv);
|
||||
}
|
||||
#endif
|
||||
else if (memcmp(argv[1], "close", 5) == 0) {
|
||||
|
||||
@ -24,13 +24,48 @@
|
||||
#include "net/bluetil/addr.h"
|
||||
#include "nimble_statconn.h"
|
||||
|
||||
|
||||
static uint8_t _parsephy(const char *phy_str)
|
||||
{
|
||||
if (memcmp(phy_str, "1M", 2) == 0) {
|
||||
return NIMBLE_PHY_1M;
|
||||
}
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_2MBIT)
|
||||
else if (memcmp(phy_str, "2M", 2) == 0) {
|
||||
return NIMBLE_PHY_2M;
|
||||
}
|
||||
#endif
|
||||
#if IS_ACTIVE(MODULE_NIMBLE_PHY_CODED)
|
||||
else if (memcmp(phy_str, "CODED", 5) == 0) {
|
||||
return NIMBLE_PHY_CODED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return NIMBLE_PHY_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
int _nimble_statconn_handler(int argc, char **argv)
|
||||
{
|
||||
nimble_statconn_cfg_t cfg;
|
||||
|
||||
if ((argc < 3)) {
|
||||
printf("usage: %s <addm|adds|rm> <BLE addr>\n", argv[0]);
|
||||
printf("usage: %s <addm|adds|rm> <BLE addr> [phy mode]\n"
|
||||
" phy_mode := [1M, 2M, CODED]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc >= 4) {
|
||||
cfg.phy_mode = _parsephy(argv[3]);
|
||||
if (cfg.phy_mode == NIMBLE_PHY_INVALID) {
|
||||
puts("err: PHY mode not supported");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cfg.phy_mode = NIMBLE_STATCONN_PHY_MODE;
|
||||
}
|
||||
|
||||
/* parse address */
|
||||
uint8_t addr[BLE_ADDR_LEN];
|
||||
if (bluetil_addr_from_str(addr, argv[2]) == NULL) {
|
||||
@ -39,7 +74,7 @@ int _nimble_statconn_handler(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (strncmp(argv[1], "addm", 4) == 0) {
|
||||
if (nimble_statconn_add_master(addr) == 0) {
|
||||
if (nimble_statconn_add_master(addr, &cfg) == 0) {
|
||||
puts("success: connecting to peer as slave");
|
||||
}
|
||||
else {
|
||||
@ -47,7 +82,7 @@ int _nimble_statconn_handler(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
else if (strncmp(argv[1], "adds", 4) == 0) {
|
||||
if (nimble_statconn_add_slave(addr) == 0) {
|
||||
if (nimble_statconn_add_slave(addr, &cfg) == 0) {
|
||||
puts("success: connecting to peer as master");
|
||||
}
|
||||
else {
|
||||
|
||||
1
sys/stdio_nimble/Makefile
Normal file
1
sys/stdio_nimble/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
110
sys/stdio_nimble/README.md
Normal file
110
sys/stdio_nimble/README.md
Normal file
@ -0,0 +1,110 @@
|
||||
# STDIO NimBLE
|
||||
|
||||
This module uses NimBLE for stdio. The bluetooth characteristic for
|
||||
stdin is writable and the characteristic for stdout uses the indicate
|
||||
mechanism to publish the system's output to a connected device. Data will be
|
||||
sent out asynchronously via callout functions.
|
||||
|
||||
To use this module, add
|
||||
```
|
||||
USEMODULE += stdio_nimble
|
||||
```
|
||||
to your makefile.
|
||||
|
||||
You can change the default buffer sizes by adding
|
||||
```
|
||||
CFLAGS += -DCONFIG_STDIO_NIMBLE_STDIN_BUFSIZE=1024
|
||||
CFLAGS += -DCONFIG_STDIO_NIMBLE_STDOUT_BUFSIZE=2048
|
||||
```
|
||||
to your makefile. \
|
||||
**NOTE:** These values must be a power of two!
|
||||
|
||||
By default, stdin and stdout buffers are cleared on a connect event. To keep the
|
||||
content add the following to your makefile:
|
||||
```
|
||||
CFLAGS += -DCONFIG_STDIO_NIMBLE_CLEAR_BUFFER_ON_CONNECT=0
|
||||
```
|
||||
|
||||
For automatic bluetooth advertising a module is provided: *nimble_autoadv*.
|
||||
It will take care of enabling advertising on disconnect events and
|
||||
disabling advertising on connect events. It can be enabled by adding
|
||||
```
|
||||
USEMODULE += nimble_autoadv
|
||||
```
|
||||
to your makefile.
|
||||
|
||||
The advertised device name can then optionally be configured with
|
||||
```
|
||||
CFLAGS += -DNIMBLE_AUTOADV_DEVICE_NAME='"Riot OS device"'
|
||||
```
|
||||
Otherwise the device will appear as "*RIOT OS device*".
|
||||
|
||||
## Instructions to connect to the bluetooth shell via ble-serial
|
||||
|
||||
- Configure and compile shell app for nrf52840dongle target in `tests/shell`.\
|
||||
|
||||
Add following to Makefile:
|
||||
```
|
||||
BOARD = nrf52840dongle
|
||||
USEMODULE += nimble_autoadv
|
||||
USEMODULE += stdio_nimble
|
||||
```
|
||||
|
||||
**NOTE:** You can also have a look at `tests/shell_ble`.
|
||||
|
||||
- Flash
|
||||
|
||||
`$ make -C tests/shell -j clean all flash`
|
||||
|
||||
- Install the ble-serial tool
|
||||
|
||||
`$ pip install ble-serial`
|
||||
|
||||
- Scan for your device (device name `Riot OS device`) and note its BLE address.\
|
||||
When you get `ble-scan: command not found` you can also run
|
||||
`python -m ble_serial.scan` instead.
|
||||
```
|
||||
$ ble-scan
|
||||
Started BLE scan
|
||||
|
||||
6BE8174C-A0F8-4479-AFA6-9828372CAFE9 (RSSI=-40): Riot OS device
|
||||
A2862DCB-D382-4C0B-95BF-FA9A961F8D88 (RSSI=-48): Unknown
|
||||
F2C75C08-7DD7-4F43-BEF0-151C92068FE5 (RSSI=-66): Unknown
|
||||
69400683-FBE5-4B45-8CFE-98594076E5F4 (RSSI=-89): Unknown
|
||||
```
|
||||
|
||||
- Discover characteristics (check the one advertised by the gatt server stdin/stdout)
|
||||
```
|
||||
$ ble-scan -d 6BE8174C-A0F8-4479-AFA6-9828372CAFE9
|
||||
Started deep scan of 6BE8174C-A0F8-4479-AFA6-9828372CAFE9
|
||||
|
||||
SERVICE e6d54866-0292-4779-b8f8-c52bbec91e71 (Handle: 10): Unknown
|
||||
CHARACTERISTIC 35f28386-3070-4f3b-ba38-27507e991762 (Handle: 11): Unknown ['indicate']
|
||||
DESCRIPTOR 00002902-0000-1000-8000-00805f9b34fb (Handle: 13): Client Characteristic Configuration
|
||||
CHARACTERISTIC ccdd113f-40d5-4d68-86ac-a728dd82f4aa (Handle: 14): Unknown ['write']
|
||||
|
||||
Completed deep scan of 6BE8174C-A0F8-4479-AFA6-9828372CAFE9
|
||||
```
|
||||
|
||||
- Create a virtual port and mount it on /tmp/dev_riot_ble
|
||||
```
|
||||
$ ble-serial -d 6BE8174C-A0F8-4479-AFA6-9828372CAFE9 -p /tmp/dev_riot_ble --write-uuid ccdd113f-40d5-4d68-86ac-a728dd82f4aa --read-uuid 35f28386-3070-4f3b-ba38-27507e991762
|
||||
17:44:18.765 | INFO | linux_pty.py: Slave created on /tmp/dev_riot_ble -> /dev/ttys006
|
||||
17:44:18.766 | INFO | ble_interface.py: Receiver set up
|
||||
17:44:18.766 | INFO | ble_interface.py: Trying to connect with 6BE8174C-A0F8-4479-AFA6-9828372CAFE9
|
||||
17:44:19.861 | INFO | ble_interface.py: Device 6BE8174C-A0F8-4479-AFA6-9828372CAFE9 connected
|
||||
17:44:19.862 | INFO | ble_interface.py: Found write characteristic ccdd113f-40d5-4d68-86ac-a728dd82f4aa (H. 14)
|
||||
17:44:19.862 | INFO | ble_interface.py: Found notify characteristic 35f28386-3070-4f3b-ba38-27507e991762 (H. 11)
|
||||
17:44:19.883 | INFO | main.py: Running main loop!
|
||||
```
|
||||
|
||||
- Open the virtual com port (the port name is from the logs in previous steps)
|
||||
```
|
||||
$ picocom -q -b 115200 --imap lfcrlf /tmp/dev_riot_ble
|
||||
ps
|
||||
pid | state Q | pri
|
||||
1 | running Q | 7
|
||||
2 | bl anyfl _ | 5
|
||||
3 | bl anyfl _ | 0
|
||||
>
|
||||
```
|
||||
387
sys/stdio_nimble/stdio_nimble.c
Normal file
387
sys/stdio_nimble/stdio_nimble.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup sys
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief STDIO over NimBLE implementation
|
||||
*
|
||||
*
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nimble_riot.h"
|
||||
#include "nimble/nimble_port.h"
|
||||
#include "net/bluetil/ad.h"
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/util/util.h"
|
||||
#include "host/ble_gatt.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
#include <stdarg.h>
|
||||
#include "stdio_uart.h"
|
||||
#include "periph/uart.h"
|
||||
#endif /* IS_USED(MODULE_STDIO_NIMBLE_DEBUG) */
|
||||
|
||||
#if IS_USED(MODULE_VFS)
|
||||
#include "vfs.h"
|
||||
#endif
|
||||
|
||||
#include "tsrb.h"
|
||||
#include "isrpipe.h"
|
||||
#include "stdio_nimble.h"
|
||||
|
||||
#define NIMBLE_MAX_PAYLOAD MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE)
|
||||
|
||||
/* Nimble uses ZTIMER_MSEC => 1 tick equals 1 ms */
|
||||
#define CALLOUT_TICKS_MS 1
|
||||
|
||||
enum {
|
||||
STDIO_NIMBLE_DISCONNECTED,
|
||||
STDIO_NIMBLE_CONNECTED,
|
||||
STDIO_NIMBLE_SUBSCRIBED,
|
||||
STDIO_NIMBLE_SENDING,
|
||||
};
|
||||
|
||||
/* isrpipe for stdin */
|
||||
static uint8_t _isrpipe_stdin_mem[CONFIG_STDIO_NIMBLE_STDIN_BUFSIZE];
|
||||
static isrpipe_t _isrpipe_stdin = ISRPIPE_INIT(_isrpipe_stdin_mem);
|
||||
|
||||
/* tsrb for stdout */
|
||||
static uint8_t _tsrb_stdout_mem[CONFIG_STDIO_NIMBLE_STDOUT_BUFSIZE];
|
||||
static tsrb_t _tsrb_stdout = TSRB_INIT(_tsrb_stdout_mem);
|
||||
|
||||
/* intermediate buffer to transfer data between tsrb and nimble functions,
|
||||
* which are all based on os_mbuf implementation */
|
||||
static uint8_t _stdin_read_buf[NIMBLE_MAX_PAYLOAD];
|
||||
static uint8_t _stdout_write_buf[NIMBLE_MAX_PAYLOAD];
|
||||
|
||||
/* information about bluetooth connection */
|
||||
static uint16_t _conn_handle;
|
||||
static uint16_t _val_handle_stdout;
|
||||
static volatile uint8_t _status = STDIO_NIMBLE_DISCONNECTED;
|
||||
|
||||
/* nimble related structs */
|
||||
static struct ble_npl_callout _send_stdout_callout;
|
||||
static struct ble_gap_event_listener _gap_event_listener;
|
||||
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
#define DEBUG_PRINTF_BUFSIZE 512
|
||||
#define PREFIX_STDIN "\nSTDIN: "
|
||||
#define PREFIX_STDOUT "STDOUT: "
|
||||
|
||||
static char _debug_printf_buf[DEBUG_PRINTF_BUFSIZE];
|
||||
#endif /* IS_USED(MODULE_STDIO_NIMBLE_DEBUG) */
|
||||
|
||||
static int _debug_printf(const char *format, ...)
|
||||
{
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
unsigned state = irq_disable();
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
int rc = vsnprintf(_debug_printf_buf, DEBUG_PRINTF_BUFSIZE, format, va);
|
||||
va_end(va);
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)_debug_printf_buf, rc);
|
||||
irq_restore(state);
|
||||
|
||||
return rc;
|
||||
#else
|
||||
(void)format;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UUID for stdio service (value: e6d54866-0292-4779-b8f8-c52bbec91e71)
|
||||
*/
|
||||
static const ble_uuid128_t gatt_svr_svc_stdio_uuid
|
||||
= BLE_UUID128_INIT(0x71, 0x1e, 0xc9, 0xbe, 0x2b, 0xc5, 0xf8, 0xb8,
|
||||
0x79, 0x47, 0x92, 0x02, 0x66, 0x48, 0xd5, 0xe6);
|
||||
|
||||
/**
|
||||
* @brief UUID for stdout characteristic (value: 35f28386-3070-4f3b-ba38-27507e991762)
|
||||
*/
|
||||
static const ble_uuid128_t gatt_svr_chr_stdout_uuid
|
||||
= BLE_UUID128_INIT(0x62, 0x17, 0x99, 0x7e, 0x50, 0x27, 0x38, 0xba,
|
||||
0x3b, 0x4f, 0x70, 0x30, 0x86, 0x83, 0xf2, 0x35);
|
||||
|
||||
/**
|
||||
* @brief UUID for stdin characteristic (value: ccdd113f-40d5-4d68-86ac-a728dd82f4aa)
|
||||
*/
|
||||
static const ble_uuid128_t gatt_svr_chr_stdin_uuid
|
||||
= BLE_UUID128_INIT(0xaa, 0xf4, 0x82, 0xdd, 0x28, 0xa7, 0xac, 0x86,
|
||||
0x68, 0x4d, 0xd5, 0x40, 0x3f, 0x11, 0xdd, 0xcc);
|
||||
|
||||
/**
|
||||
* @brief Nimble access callback for stdin characteristic
|
||||
*/
|
||||
static int gatt_svr_chr_access_stdin(
|
||||
uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Dummy access callback, because nimble requires one
|
||||
*/
|
||||
static int gatt_svr_chr_access_noop(
|
||||
uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
|
||||
(void)conn_handle;
|
||||
(void)attr_handle;
|
||||
(void)ctxt;
|
||||
(void)arg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Struct to define the stdio bluetooth service with its characteristics
|
||||
*/
|
||||
static const struct ble_gatt_svc_def _gatt_svr_svcs[] =
|
||||
{
|
||||
/*
|
||||
* access_cb defines a callback for read and write access events on
|
||||
* given characteristics
|
||||
*/
|
||||
{
|
||||
/* Service: stdio */
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = (ble_uuid_t *)&gatt_svr_svc_stdio_uuid.u,
|
||||
.characteristics = (struct ble_gatt_chr_def[]) { {
|
||||
/* Characteristic: stdout */
|
||||
.uuid = (ble_uuid_t *)&gatt_svr_chr_stdout_uuid.u,
|
||||
.access_cb = gatt_svr_chr_access_noop,
|
||||
.val_handle = &_val_handle_stdout,
|
||||
.flags = BLE_GATT_CHR_F_INDICATE,
|
||||
}, {
|
||||
/* Characteristic: stdin */
|
||||
.uuid = (ble_uuid_t *)&gatt_svr_chr_stdin_uuid.u,
|
||||
.access_cb = gatt_svr_chr_access_stdin,
|
||||
.flags = BLE_GATT_CHR_F_WRITE,
|
||||
}, {
|
||||
0, /* No more characteristics in this service */
|
||||
}, }
|
||||
},
|
||||
{
|
||||
0, /* No more services */
|
||||
},
|
||||
};
|
||||
|
||||
static void _purge_buffer(void)
|
||||
{
|
||||
tsrb_clear(&_isrpipe_stdin.tsrb);
|
||||
|
||||
#if IS_USED(MODULE_SHELL)
|
||||
/* send Ctrl-C to the shell to reset the input */
|
||||
isrpipe_write_one(&_isrpipe_stdin, '\x03');
|
||||
#endif
|
||||
|
||||
tsrb_clear(&_tsrb_stdout);
|
||||
}
|
||||
|
||||
static void _send_stdout(struct ble_npl_event *ev)
|
||||
{
|
||||
(void)ev;
|
||||
|
||||
/* rearm callout */
|
||||
ble_npl_callout_reset(&_send_stdout_callout, CALLOUT_TICKS_MS);
|
||||
|
||||
if (_status == STDIO_NIMBLE_SUBSCRIBED) {
|
||||
_status = STDIO_NIMBLE_SENDING;
|
||||
int to_send = tsrb_peek(&_tsrb_stdout, _stdout_write_buf, NIMBLE_MAX_PAYLOAD);
|
||||
|
||||
if (to_send > 0) {
|
||||
struct os_mbuf *om = ble_hs_mbuf_from_flat(_stdout_write_buf, to_send);
|
||||
if (om != NULL) {
|
||||
int rc = ble_gattc_indicate_custom(_conn_handle, _val_handle_stdout, om);
|
||||
if (rc == 0) {
|
||||
/* bytes were successfully sent, so drop them from the buffer */
|
||||
tsrb_drop(&_tsrb_stdout, to_send);
|
||||
_debug_printf("%d bytes sent successfully\n", to_send);
|
||||
}
|
||||
else {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int _gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
switch (event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
_debug_printf("BLE_GAP_EVENT_CONNECT\n");
|
||||
if (event->connect.status == 0) {
|
||||
_status = STDIO_NIMBLE_CONNECTED;
|
||||
if (CONFIG_STDIO_NIMBLE_CLEAR_BUFFER_ON_CONNECT) {
|
||||
_purge_buffer();
|
||||
}
|
||||
_conn_handle = event->connect.conn_handle;
|
||||
}
|
||||
else {
|
||||
_status = STDIO_NIMBLE_DISCONNECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
_debug_printf("BLE_GAP_EVENT_DISCONNECT\n");
|
||||
_status = STDIO_NIMBLE_DISCONNECTED;
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
||||
_debug_printf("BLE_GAP_EVENT_SUBSCRIBE\n");
|
||||
if (event->subscribe.attr_handle == _val_handle_stdout) {
|
||||
if (event->subscribe.cur_indicate == 1) {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
else {
|
||||
_status = STDIO_NIMBLE_CONNECTED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX:
|
||||
_debug_printf("BLE_GAP_EVENT_NOTIFY_TX\n");
|
||||
if (event->notify_tx.indication == 1) {
|
||||
if (event->notify_tx.status == BLE_HS_EDONE) {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
else if (event->notify_tx.status != 0) {
|
||||
_status = STDIO_NIMBLE_SUBSCRIBED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_MTU:
|
||||
_debug_printf("BLE_GAP_EVENT_MTU: mtu = %d\n", event->mtu.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gatt_svr_chr_access_stdin(
|
||||
uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||
{
|
||||
(void)conn_handle;
|
||||
(void)attr_handle;
|
||||
(void)arg;
|
||||
|
||||
uint16_t om_len = OS_MBUF_PKTLEN(ctxt->om);
|
||||
|
||||
/* read sent data */
|
||||
int rc = ble_hs_mbuf_to_flat(ctxt->om, _stdin_read_buf, sizeof(_stdin_read_buf), &om_len);
|
||||
|
||||
isrpipe_write(&_isrpipe_stdin, _stdin_read_buf, om_len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void stdio_init(void)
|
||||
{
|
||||
#if IS_USED(MODULE_VFS)
|
||||
vfs_bind_stdio();
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
uart_init(STDIO_UART_DEV, STDIO_UART_BAUDRATE, NULL, NULL);
|
||||
#endif
|
||||
|
||||
ble_npl_callout_init(&_send_stdout_callout, nimble_port_get_dflt_eventq(),
|
||||
_send_stdout, NULL);
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_STDIO_AVAILABLE)
|
||||
int stdio_available(void)
|
||||
{
|
||||
return tsrb_avail(&_isrpipe_stdin.tsrb);
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t stdio_read(void *buffer, size_t count)
|
||||
{
|
||||
/* blocks until at least one character was read */
|
||||
ssize_t res = isrpipe_read(&_isrpipe_stdin, buffer, count);
|
||||
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
unsigned state = irq_disable();
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)PREFIX_STDIN, strlen(PREFIX_STDIN));
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, res);
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)"\n", 1);
|
||||
irq_restore(state);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t stdio_write(const void *buffer, size_t len)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
|
||||
#if IS_USED(MODULE_STDIO_NIMBLE_DEBUG)
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)PREFIX_STDOUT, strlen(PREFIX_STDOUT));
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len);
|
||||
uart_write(STDIO_UART_DEV, (const uint8_t *)"\n", 1);
|
||||
#endif
|
||||
|
||||
irq_restore(state);
|
||||
|
||||
unsigned int consumed = tsrb_add(&_tsrb_stdout, buffer, len);
|
||||
|
||||
if (!ble_npl_callout_is_active(&_send_stdout_callout)) {
|
||||
/* bootstrap callout */
|
||||
ble_npl_callout_reset(&_send_stdout_callout, CALLOUT_TICKS_MS);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/* is going to be called by auto_init */
|
||||
void stdio_nimble_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* verify and add our custom services */
|
||||
rc = ble_gatts_count_cfg(_gatt_svr_svcs);
|
||||
assert(rc == 0);
|
||||
rc = ble_gatts_add_svcs(_gatt_svr_svcs);
|
||||
assert(rc == 0);
|
||||
|
||||
/* reload the GATT server to link our added services */
|
||||
ble_gatts_start();
|
||||
|
||||
/* register gap event listener */
|
||||
rc = ble_gap_event_listener_register(&_gap_event_listener, _gap_event_cb, NULL);
|
||||
assert(rc == 0);
|
||||
|
||||
/* fix compilation error when using DEVELHELP=0 */
|
||||
(void)rc;
|
||||
}
|
||||
@ -333,6 +333,25 @@ ssize_t vfs_write(int fd, const void *src, size_t count)
|
||||
return filp->f_op->write(filp, src, count);
|
||||
}
|
||||
|
||||
int vfs_fsync(int fd)
|
||||
{
|
||||
DEBUG_NOT_STDOUT(fd, "vfs_fsync: %d\n", fd);
|
||||
int res = _fd_is_valid(fd);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
vfs_file_t *filp = &_vfs_open_files[fd];
|
||||
if (((filp->flags & O_ACCMODE) != O_WRONLY) & ((filp->flags & O_ACCMODE) != O_RDWR)) {
|
||||
/* File not open for writing */
|
||||
return -EBADF;
|
||||
}
|
||||
if (filp->f_op->fsync == NULL) {
|
||||
/* driver does not implement fsync() */
|
||||
return -EINVAL;
|
||||
}
|
||||
return filp->f_op->fsync(filp);
|
||||
}
|
||||
|
||||
int vfs_opendir(vfs_DIR *dirp, const char *dirname)
|
||||
{
|
||||
DEBUG("vfs_opendir: %p, \"%s\"\n", (void *)dirp, dirname);
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "atomic_utils.h"
|
||||
#include "msg.h"
|
||||
#include "mutex.h"
|
||||
#include "rmutex.h"
|
||||
@ -224,8 +225,7 @@ int xtimer_rmutex_lock_timeout(rmutex_t *rmutex, uint64_t timeout)
|
||||
return 0;
|
||||
}
|
||||
if (xtimer_mutex_lock_timeout(&rmutex->mutex, timeout) == 0) {
|
||||
atomic_store_explicit(&rmutex->owner,
|
||||
thread_getpid(), memory_order_relaxed);
|
||||
atomic_store_kernel_pid(&rmutex->owner, thread_getpid());
|
||||
rmutex->refcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "atomic_utils.h"
|
||||
#include "irq.h"
|
||||
#include "mutex.h"
|
||||
#include "rmutex.h"
|
||||
@ -190,8 +191,7 @@ int ztimer_rmutex_lock_timeout(ztimer_clock_t *clock, rmutex_t *rmutex,
|
||||
return 0;
|
||||
}
|
||||
if (ztimer_mutex_lock_timeout(clock, &rmutex->mutex, timeout) == 0) {
|
||||
atomic_store_explicit(&rmutex->owner,
|
||||
thread_getpid(), memory_order_relaxed);
|
||||
atomic_store_kernel_pid(&rmutex->owner, thread_getpid());
|
||||
rmutex->refcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "atomic_utils.h"
|
||||
#include "irq.h"
|
||||
#include "mutex.h"
|
||||
#include "rmutex.h"
|
||||
@ -183,8 +184,7 @@ int ztimer64_rmutex_lock_until(ztimer64_clock_t *clock, rmutex_t *rmutex,
|
||||
return 0;
|
||||
}
|
||||
if (ztimer64_mutex_lock_until(clock, &rmutex->mutex, target) == 0) {
|
||||
atomic_store_explicit(&rmutex->owner,
|
||||
thread_getpid(), memory_order_relaxed);
|
||||
atomic_store_kernel_pid(&rmutex->owner, thread_getpid());
|
||||
rmutex->refcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
This is a test application for the ON Semiconductor lc709203F Battery Fuel Gauge
|
||||
# Usage
|
||||
Just enter the `make BOARD=??? flash` command in the `tests/driver_lc709203F/` folder.
|
||||
Make sure the `LC709203F_INT_PIN` is set in your boards periph_conf.h
|
||||
Make sure the `LC709203F_PARAMS_ALARM_PIN` is set in your boards `board.h`
|
||||
# Results
|
||||
The sensor will first test the low RSOC interrupt by setting the threshold limit to 100%. Therefore a low RSOC interrupt should be triggered and the message "ALARM low RSOC" should be printed to the terminal. After that all major measurements will be printed and refreshed every 5s.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# this file enables modules defined in Kconfig. Do not use this file for
|
||||
# application configuration. This is only needed during migration.
|
||||
CONFIG_MODULE_MPU9150=y
|
||||
CONFIG_MODULE_MPU9X50=y
|
||||
CONFIG_MODULE_ZTIMER=y
|
||||
CONFIG_MODULE_ZTIMER_MSEC=y
|
||||
|
||||
6
tests/external_pkg_dirs/Makefile
Normal file
6
tests/external_pkg_dirs/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
EXTERNAL_PKG_DIRS += external_pkgs
|
||||
USEPKG += external_pkg
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
16
tests/external_pkg_dirs/README.md
Normal file
16
tests/external_pkg_dirs/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
external_pkg_dirs
|
||||
=================
|
||||
|
||||
Test application for the EXTERNAL_PKG_DIRS feature of the buildsystem.
|
||||
Two external packages are provided in `external_pkgs/`: `external_pkg` and
|
||||
`external_pkg_not_used`. If the first package is not properly included, a define
|
||||
from `CFLAGS` is missing and a precompiler error is triggered. If the second
|
||||
package somehow ends up included it triggers a makefile error.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Set `EXTERNAL_PKG_DIRS` inside Makefile to point to other paths where the
|
||||
buildsystem can look for packages. Similar functionality to `EXTERNAL_PKG_DIRS`.
|
||||
Be careful to not name these externally provided packages the same as existing
|
||||
packages in `$(RIOTBASE)/pkg/`.
|
||||
1
tests/external_pkg_dirs/app.config.test
Normal file
1
tests/external_pkg_dirs/app.config.test
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_PACKAGE_EXTERNAL_PKG=y
|
||||
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2022 Niklaus Leuenberger
|
||||
#
|
||||
# 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.
|
||||
|
||||
config PACKAGE_EXTERNAL_PKG
|
||||
bool "external_pkg package"
|
||||
depends on TEST_KCONFIG
|
||||
16
tests/external_pkg_dirs/external_pkgs/external_pkg/Makefile
Normal file
16
tests/external_pkg_dirs/external_pkgs/external_pkg/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
PKG_NAME = external_pkg
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
||||
.PHONY: all prepare clean distclean
|
||||
|
||||
all: prepare
|
||||
|
||||
prepare:
|
||||
@:
|
||||
|
||||
clean::
|
||||
rm -rf $(BINDIR)/pkg/$(PKG_NAME)
|
||||
|
||||
distclean::
|
||||
rm -rf $(BINDIR)/pkg/$(PKG_NAME)
|
||||
@ -0,0 +1 @@
|
||||
CFLAGS += -DTEST_EXTERNAL_PKG
|
||||
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2022 Niklaus Leuenberger
|
||||
#
|
||||
# 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.
|
||||
|
||||
config PACKAGE_EXTERNAL_PKG_NOT_USED
|
||||
bool "external_pkg_not_used package"
|
||||
depends on TEST_KCONFIG
|
||||
@ -0,0 +1,19 @@
|
||||
PKG_NAME = external_pkg_not_used
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
||||
.PHONY: all prepare clean distclean
|
||||
|
||||
all:
|
||||
$(error target all for external_pkg_not_used executed)
|
||||
|
||||
prepare:
|
||||
$(error target prepare for external_pkg_not_used executed)
|
||||
|
||||
clean::
|
||||
rm -rf $(BINDIR)/pkg/$(PKG_NAME)
|
||||
$(error target clean for external_pkg_not_used executed)
|
||||
|
||||
distclean::
|
||||
rm -rf $(BINDIR)/pkg/$(PKG_NAME)
|
||||
$(error target distclean for external_pkg_not_used executed)
|
||||
@ -0,0 +1 @@
|
||||
CFLAGS += -DTEST_EXTERNAL_PKG_NOT_USED
|
||||
35
tests/external_pkg_dirs/main.c
Normal file
35
tests/external_pkg_dirs/main.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Niklaus Leuenberger
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief This is a test for the EXTERNAL_PKG_DIRS variable.
|
||||
*
|
||||
* @author Niklaus Leuenberger <niklaus.leuenb@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef TEST_EXTERNAL_PKG
|
||||
#error "Required external package not included."
|
||||
#endif
|
||||
|
||||
#ifdef TEST_EXTERNAL_PKG_NOT_USED
|
||||
#error "External package included that shouldn't be."
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("If it compiles, it works!");
|
||||
return 0;
|
||||
}
|
||||
@ -4,4 +4,12 @@ USEMODULE += external_module_1
|
||||
USEMODULE += external_module_2
|
||||
EXTERNAL_MODULE_DIRS += external_modules
|
||||
|
||||
USEPKG += external_pkg_1
|
||||
USEPKG += external_pkg_2
|
||||
EXTERNAL_PKG_DIRS += external_pkgs
|
||||
|
||||
ifeq (1, $(TEST_KCONFIG))
|
||||
KCONFIG_ADD_CONFIG += $(APPDIR)/app.config
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
@ -9,3 +9,7 @@ CONFIG_APP_MSG_2=y
|
||||
# enable configuration of external modules via kconfig
|
||||
CONFIG_KCONFIG_EXTERNAL_MODULE_1=y
|
||||
CONFIG_KCONFIG_EXTERNAL_MODULE_2=y
|
||||
|
||||
# enable configuration of external packages via kconfig
|
||||
CONFIG_KCONFIG_EXTERNAL_PKG_1=y
|
||||
CONFIG_KCONFIG_EXTERNAL_PKG_2=y
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user