diff --git a/configure.ac b/configure.ac index 94736639b..ee338c90b 100644 --- a/configure.ac +++ b/configure.ac @@ -957,11 +957,11 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_RAW_LINK_API],[${OPENTHREAD_ENABLE_RAW_LIN AC_ARG_WITH(examples, [AS_HELP_STRING([--with-examples=TARGET], - [Specify the examples from one of: none, posix, cc2538, cc2650, da15000, nrf52840 @<:@default=none@:>@.])], + [Specify the examples from one of: none, posix, cc2538, cc2650, da15000, efr32, nrf52840 @<:@default=none@:>@.])], [ case "${with_examples}" in - none|posix|cc2538|cc2650|da15000|nrf52840) + none|posix|cc2538|cc2650|da15000|efr32|nrf52840) ;; *) AC_MSG_ERROR([Invalid value ${with_examples} for --with-examples]) @@ -994,6 +994,11 @@ case ${with_examples} in AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_DA15000],[${OPENTHREAD_EXAMPLES_DA15000}],[Define to 1 if you want to use da15000 examples]) ;; + efr32) + OPENTHREAD_EXAMPLES_EFR32=1 + AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_EFR32],[${OPENTHREAD_EXAMPLES_EFR32}],[Define to 1 if you want to use efr32 examples]) + ;; + nrf52840) OPENTHREAD_EXAMPLES_NRF52840=1 AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_NRF52840],[${OPENTHREAD_EXAMPLES_NRF52840}],[Define to 1 if you want to use nrf52840 examples]) @@ -1020,6 +1025,9 @@ AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC2650], [test "${OPENTHREAD_EXAMPLES}" = "c AC_SUBST(OPENTHREAD_EXAMPLES_DA15000) AM_CONDITIONAL([OPENTHREAD_EXAMPLES_DA15000], [test "${OPENTHREAD_EXAMPLES}" = "da15000"]) +AC_SUBST(OPENTHREAD_EXAMPLES_EFR32) +AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32], [test "${OPENTHREAD_EXAMPLES}" = "efr32"]) + AC_SUBST(OPENTHREAD_EXAMPLES_NRF52840) AM_CONDITIONAL([OPENTHREAD_EXAMPLES_NRF52840], [test "${OPENTHREAD_EXAMPLES}" = "nrf52840"]) @@ -1180,6 +1188,7 @@ examples/platforms/Makefile examples/platforms/cc2538/Makefile examples/platforms/cc2650/Makefile examples/platforms/da15000/Makefile +examples/platforms/efr32/Makefile examples/platforms/nrf52840/Makefile examples/platforms/posix/Makefile examples/platforms/utils/Makefile diff --git a/examples/Makefile-efr32 b/examples/Makefile-efr32 new file mode 100644 index 000000000..19c7dfc9f --- /dev/null +++ b/examples/Makefile-efr32 @@ -0,0 +1,303 @@ +# +# Copyright (c) 2017, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +.NOTPARALLEL: + +AR = arm-none-eabi-ar +CCAS = arm-none-eabi-as +CPP = arm-none-eabi-cpp +CC = arm-none-eabi-gcc +CXX = arm-none-eabi-g++ +LD = arm-none-eabi-ld +STRIP = arm-none-eabi-strip +NM = arm-none-eabi-nm +RANLIB = arm-none-eabi-ranlib +OBJCOPY = arm-none-eabi-objcopy + +BuildJobs ?= 10 + +configure_OPTIONS = \ + --enable-cli-app=all \ + --enable-ncp-app=all \ + --with-ncp-bus=uart \ + --enable-diag \ + --enable-default-logging \ + --with-examples=efr32 \ + --with-platform-info=EFR32 \ + MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)" \ + $(NULL) + +ifeq ($(CERT_LOG),1) +configure_OPTIONS += --enable-cert-log +endif + +ifeq ($(COMMISSIONER),1) +configure_OPTIONS += --enable-commissioner +endif + +ifeq ($(JOINER),1) +configure_OPTIONS += --enable-joiner +endif + +ifeq ($(DHCP6_SERVER),1) +configure_OPTIONS += --enable-dhcp6-server +endif + +ifeq ($(DHCP6_CLIENT),1) +configure_OPTIONS += --enable-dhcp6-client +endif + +ifeq ($(JAM_DETECTION),1) +configure_OPTIONS += --enable-jam-detection +endif + +ifeq ($(DNS_CLIENT),1) +configure_OPTIONS += --enable-dns-client +endif + +TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST)))).. +AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))).. + +EFR32_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"' +EFR32_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"efr32-mbedtls-config.h\"' +EFR32_MBEDTLS_CPPFLAGS += -DEFR32MG12P432F1024GL125 +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/crypto +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v1.0/util/third_party/mbedtls/configs +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/CMSIS/Include +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v1.0/util/third_party/mbedtls/sl_crypto/include +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Include +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/inc +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/mbedtls +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/mbedtls/repo/include +EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/mbedtls/repo/include/mbedtls + +CONFIG_FILE = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-efr32-config.h\"' +CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/efr32/ + +COMMONCFLAGS := \ + -fdata-sections \ + -ffunction-sections \ + -Os \ + -g \ + -D$(CONFIG_FILE) \ + -I$(CONFIG_FILE_PATH) \ + $(NULL) + +CPPFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CPPFLAGS) \ + $(NULL) + +CFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CFLAGS) \ + $(NULL) + +CXXFLAGS += \ + $(COMMONCFLAGS) \ + $(target_CXXFLAGS) \ + -fno-exceptions \ + -fno-rtti \ + $(NULL) + +LDFLAGS += \ + $(COMMONCFLAGS) \ + $(target_LDFLAGS) \ + -nostartfiles \ + -specs=nano.specs \ + -specs=nosys.specs \ + -Wl,--gc-sections \ + -Wl,-Map=map.map \ + $(NULL) + +ECHO := @echo +MAKE := make +MKDIR_P := mkdir -p +LN_S := ln -s +RM_F := rm -f + +INSTALL := /usr/bin/install +INSTALLFLAGS := -p + +BuildPath = build +TopBuildDir = $(BuildPath) +AbsTopBuildDir = $(PWD)/$(TopBuildDir) + +ResultPath = output +TopResultDir = $(ResultPath) +AbsTopResultDir = $(PWD)/$(TopResultDir) + +TargetTuple = efr32 + +ARCHS = cortex-m4 + +TopTargetLibDir = $(TopResultDir)/$(TargetTuple)/lib + +ifndef BuildJobs +BuildJobs := $(shell getconf _NPROCESSORS_ONLN) +endif +JOBSFLAG := -j$(BuildJobs) + +# +# configure-arch +# +# Configure OpenThread for the specified architecture. +# +# arch - The architecture to configure. +# +define configure-arch +$(ECHO) " CONFIG $(TargetTuple)..." +(cd $(BuildPath)/$(TargetTuple) && $(AbsTopSourceDir)/configure \ +INSTALL="$(INSTALL) $(INSTALLFLAGS)" \ +CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" \ +--host=arm-none-eabi \ +--prefix=/ \ +--exec-prefix=/$(TargetTuple) \ +$(configure_OPTIONS)) +endef # configure-arch + +# +# build-arch +# +# Build the OpenThread intermediate build products for the specified +# architecture. +# +# arch - The architecture to build. +# +define build-arch +$(ECHO) " BUILD $(TargetTuple)" +$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \ +all +endef # build-arch + +# +# stage-arch +# +# Stage (install) the OpenThread final build products for the specified +# architecture. +# +# arch - The architecture to stage. +# +define stage-arch +$(ECHO) " STAGE $(TargetTuple)" +$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \ +DESTDIR=$(AbsTopResultDir) \ +install +endef # stage-arch + +# +# ARCH_template +# +# Define macros, targets and rules to configure, build, and stage the +# OpenThread for a single architecture. +# +# arch - The architecture to instantiate the template for. +# +define ARCH_template +CONFIGURE_TARGETS += configure-$(1) +BUILD_TARGETS += do-build-$(1) +STAGE_TARGETS += stage-$(1) +BUILD_DIRS += $(BuildPath)/$(TargetTuple) +DIRECTORIES += $(BuildPath)/$(TargetTuple) + +configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS) +configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS) +configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS) +configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS) + +configure-$(1): $(BuildPath)/$(TargetTuple)/config.status + +$(BuildPath)/$(TargetTuple)/config.status: | $(BuildPath)/$(TargetTuple) + $$(call configure-arch,$(1)) + +do-build-$(1): configure-$(1) + +do-build-$(1): + +$$(call build-arch,$(1)) + +stage-$(1): do-build-$(1) + +stage-$(1): | $(TopResultDir) + $$(call stage-arch,$(1)) + +$(1): stage-$(1) +endef # ARCH_template + +.DEFAULT_GOAL := all + +all: stage + +# +# cortex-m4 +# + +cortex-m4_target_ABI = cortex-m4 +cortex-m4_target_CPPFLAGS = -mcpu=cortex-m4 -mfloat-abi=soft -mthumb +cortex-m4_target_CFLAGS = -mcpu=cortex-m4 -mfloat-abi=soft -mthumb +cortex-m4_target_CXXFLAGS = -mcpu=cortex-m4 -mfloat-abi=soft -mthumb +cortex-m4_target_LDFLAGS = -mcpu=cortex-m4 -mfloat-abi=soft -mthumb + +# Instantiate an architecture-specific build template for each target +# architecture. + +$(foreach arch,$(ARCHS),$(eval $(call ARCH_template,$(arch)))) + +# +# Common / Finalization +# + +configure: $(CONFIGURE_TARGETS) + +build: $(BUILD_TARGETS) + +stage: $(STAGE_TARGETS) + +DIRECTORIES = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS) + +CLEAN_DIRS = $(TopResultDir) $(BUILD_DIRS) + +all: stage + +$(DIRECTORIES): + $(ECHO) " MKDIR $@" + @$(MKDIR_P) "$@" + +clean: + $(ECHO) " CLEAN" + @$(RM_F) -r $(CLEAN_DIRS) + +help: + $(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following " + $(ECHO) "architectures: " + $(ECHO) "" + $(ECHO) " $(ARCHS)" + $(ECHO) "" + $(ECHO) "To build only a particular architecture, specify: " + $(ECHO) "" + $(ECHO) " make -f $(firstword $(MAKEFILE_LIST)) " + $(ECHO) "" diff --git a/examples/apps/cli/Makefile.am b/examples/apps/cli/Makefile.am index d2ea4e038..e710ae2b3 100644 --- a/examples/apps/cli/Makefile.am +++ b/examples/apps/cli/Makefile.am @@ -102,6 +102,17 @@ LDFLAGS_COMMON += \ $(NULL) endif # OPENTHREAD_EXAMPLES_DA15000 +if OPENTHREAD_EXAMPLES_EFR32 + LDADD_COMMON += \ + $(top_builddir)/examples/platforms/efr32/libopenthread-efr32.a \ + $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/radio/rail_lib/autogen/librail_release/librail_efr32xg12_gcc_release.a \ + $(NULL) + +LDFLAGS_COMMON += \ + -T $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/efr32mg12p.ld \ + $(NULL) +endif # OPENTHREAD_EXAMPLES_EFR32 + if OPENTHREAD_EXAMPLES_NRF52840 LDADD_COMMON += \ $(top_builddir)/examples/platforms/nrf52840/libopenthread-nrf52840.a \ diff --git a/examples/apps/ncp/Makefile.am b/examples/apps/ncp/Makefile.am index 4ee5a55d2..afb621304 100644 --- a/examples/apps/ncp/Makefile.am +++ b/examples/apps/ncp/Makefile.am @@ -102,6 +102,17 @@ LDFLAGS_COMMON += \ $(NULL) endif # OPENTHREAD_EXAMPLES_DA15000 +if OPENTHREAD_EXAMPLES_EFR32 +LDADD_COMMON += \ + $(top_builddir)/examples/platforms/efr32/libopenthread-efr32.a \ + $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/radio/rail_lib/autogen/librail_release/librail_efr32xg12_gcc_release.a \ + $(NULL) + +LDFLAGS_COMMON += \ + -T $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/efr32mg12p.ld \ + $(NULL) +endif # OPENTHREAD_EXAMPLES_EFR32 + if OPENTHREAD_EXAMPLES_NRF52840 LDADD_COMMON += \ $(top_builddir)/examples/platforms/nrf52840/libopenthread-nrf52840.a \ diff --git a/examples/platforms/Makefile.am b/examples/platforms/Makefile.am index 21cd7639f..2a5a08616 100644 --- a/examples/platforms/Makefile.am +++ b/examples/platforms/Makefile.am @@ -34,6 +34,7 @@ DIST_SUBDIRS = \ cc2538 \ cc2650 \ da15000 \ + efr32 \ nrf52840 \ posix \ utils \ @@ -57,6 +58,10 @@ if OPENTHREAD_EXAMPLES_DA15000 SUBDIRS += da15000 endif +if OPENTHREAD_EXAMPLES_EFR32 +SUBDIRS += efr32 +endif + if OPENTHREAD_EXAMPLES_NRF52840 SUBDIRS += nrf52840 endif @@ -71,6 +76,7 @@ PRETTY_SUBDIRS = \ cc2538 \ cc2650 \ da15000 \ + efr32 \ nrf52840 \ posix \ utils \ diff --git a/examples/platforms/efr32/Makefile.am b/examples/platforms/efr32/Makefile.am new file mode 100644 index 000000000..227c1b3cf --- /dev/null +++ b/examples/platforms/efr32/Makefile.am @@ -0,0 +1,123 @@ +# +# Copyright (c) 2017, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +include $(abs_top_nlbuild_autotools_dir)/automake/pre.am + +lib_LIBRARIES = libopenthread-efr32.a + +# Do not enable -Wconversion for rail +override CFLAGS := $(filter-out -Wconversion,$(CFLAGS)) +override CXXFLAGS := $(filter-out -Wconversion,$(CXXFLAGS)) + +# Do not enable -pedantic-errors for rail +override CFLAGS := $(filter-out -pedantic-errors,$(CFLAGS)) +override CXXFLAGS := $(filter-out -pedantic-errors,$(CXXFLAGS)) + +EFR32MG_SDK_SRCDIR = $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0 + +libopenthread_efr32_a_CPPFLAGS = \ + -DEFR32MG12P432F1024GL125 \ + -D__START=main \ + -D__STARTUP_CLEAR_BSS \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/examples/platforms \ + -I$(top_srcdir)/src/core \ + -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/common \ + -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/chip/efr32 \ + -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/protocol/ieee802154 \ + -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/chip/efr32/rf/common/cortex \ + -I$(EFR32MG_SDK_SRCDIR)/platform/radio/rail_lib/hal/efr32 \ + -I$(EFR32MG_SDK_SRCDIR)/hardware/kit/common/bsp \ + -I$(EFR32MG_SDK_SRCDIR)/hardware/kit/EFR32MG12_BRD4161A/config \ + -I$(EFR32MG_SDK_SRCDIR)/platform/CMSIS/Include \ + -I$(EFR32MG_SDK_SRCDIR)/platform/Device/SiliconLabs/EFR32MG12P/Include \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emdrv/common/inc \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emdrv/uartdrv/inc \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emdrv/ustimer/inc \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emdrv/dmadrv/inc \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emdrv/rtcdrv/inc \ + -I$(EFR32MG_SDK_SRCDIR)/platform/emlib/inc \ + -Wno-unused-parameter \ + $(NULL) + +PLATFORM_SOURCES = \ + alarm.c \ + flash.c \ + logging.c \ + misc.c \ + platform.c \ + radio.c \ + random.c \ + startup-gcc.c \ + uart.c \ + $(NULL) + +if OPENTHREAD_ENABLE_DIAG +PLATFORM_SOURCES += \ + diag.c \ + $(NULL) +endif + +nodist_libopenthread_efr32_a_SOURCES = \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/hardware/kit/common/bsp/bsp_bcc.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/hardware/kit/common/bsp/bsp_stk.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/system_efr32mg12p.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/startup_efr32mg12p.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emdrv/rtcdrv/src/rtcdriver.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emdrv/ustimer/src/ustimer.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_adc.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_cmu.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_core.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_emu.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_gpio.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_rmu.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_rtcc.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_system.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_timer.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_usart.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_msc.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/emlib/src/em_crypto.c \ + $(NULL) + +noinst_HEADERS = \ + platform-efr32.h \ + $(NULL) + +libopenthread_efr32_a_SOURCES = \ + $(PLATFORM_SOURCES) \ + $(NULL) + +PRETTY_FILES = \ + $(PLATFORM_SOURCES) \ + $(NULL) + +Dash = - +libopenthread_efr32_a_LIBADD = \ + $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o") + +include $(abs_top_nlbuild_autotools_dir)/automake/post.am diff --git a/examples/platforms/efr32/README.md b/examples/platforms/efr32/README.md new file mode 100644 index 000000000..151b7cc09 --- /dev/null +++ b/examples/platforms/efr32/README.md @@ -0,0 +1,187 @@ +# OpenThread on EFR32 Example + +This directory contains example platform drivers for the [Silicon Labs EFR32][efr32mg] +based on [EFR32™ Mighty Gecko Wireless Starter Kit][SLWSTK6000B]. + +[efr32mg]: http://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc +[SLWSTK6000B]: http://www.silabs.com/products/development-tools/wireless/mesh-networking/mighty-gecko-starter-kit + +The example platform drivers are intended to present the minimal code +necessary to support OpenThread. [EFR32MG12P SoC][efr32mg12p] +has rich memory and peripheral resources which can support all OpenThread +capabilities. See the "Run the example with EFR32 boards" section below +for an example using basic OpenThread capabilities. + +[efr32mg12p]: http://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc/device.EFR32MG12P432F1024GL125 + +## Toolchain + +Download and install the [GNU toolchain for ARM Cortex-M][gnu-toolchain]. + +[gnu-toolchain]: https://launchpad.net/gcc-arm-embedded + +## Build Examples + +1. Download and install the [Simplicity Studio][simplicity_studio]. + +[simplicity_studio]: http://www.silabs.com/products/development-tools/software/simplicity-studio + +2. Install Flex (Gecko) SDK including RAIL Library from Simplicity Studio. + - Connect EFR32MG12P Wireless Starter Kit to Simplicity Studio. + - Find the latest Flex SDK in the Software Update page and click Install. + - Flex SDK will be installed in the path: `/SimplicityStudio_v4/developer/sdks/gecko_sdk_suite`. + +For more information on configuring, building, and installing applications for the Wireless Gecko (EFR32) +portfolio using RAIL, see [Getting Started with RAIL Library quick start guide][QSG121]. For more information +on RAIL, see [Radio Abstraction Interface Layer][rail]. + +[QSG121]: http://www.silabs.com/documents/public/quick-start-guides/QSG121-EFR32-RAIL.pdf +[rail]: http://www.silabs.com/products/development-tools/software/radio-abstraction-interface-layer-sdk + +3. Configure the path to Flex SDK source code. +```bash +$ cd /third_party +$ mkdir silabs +$ cd /developer/sdks +$ cp -rf gecko_sdk_suite /third_party/silabs/ +``` + +4. Build OpenThread Firmware (CLI example) on EFR32 platform. +```bash +$ cd +$ ./bootstrap +$ make -f examples/Makefile-efr32 +``` + +After a successful build, the `elf` files are found in +`/output/efr32/bin`. + +## Flash Binaries + +Compiled binaries may be flashed onto the EFR32 using [JLinkGDBServer][jlinkgdbserver]. +EFR32 Starter kit mainboard integrates an on-board SEGGER J-Link debugger. + +[jlinkgdbserver]: https://www.segger.com/jlink-gdb-server.html + +```bash +$ cd +$ sudo ./JLinkGDBServer -if swd -device EFR32MG1PxxxF256 +$ cd /output/efr32/bin +$ arm-none-eabi-gdb ot-cli-ftd +$ (gdb) target remote 127.0.0.1:2331 +$ (gdb) load +$ (gdb) monitor reset +$ (gdb) c +``` + +## Run the example with EFR32 boards +1. Flash two EFR32 boards with the `CLI example` firmware (as shown above). +2. Open terminal to first device `/dev/ttyACM0` (serial port settings: 115200 8-N-1). + Type `help` for a list of commands. + +```bash +> help +help +channel +childtimeout +contextreusedelay +extaddr +extpanid +ipaddr +keysequence +leaderweight +masterkey +mode +netdataregister +networkidtimeout +networkname +panid +ping +prefix +releaserouterid +rloc16 +route +routerupgradethreshold +scan +start +state +stop +whitelist +``` + +3. Start a Thread network as Leader. + +```bash +> panid 0xface +Done +> ifconfig up +Done +> thread start +Done + +wait a couple of seconds... + +> state +leader +Done +``` + +4. Open terminal to second device `/dev/ttyACM1` (serial port settings: 115200 8-N-1) + and attach it to the Thread network as a Router. + +```bash +> panid 0xface +Done +> routerselectionjitter 1 +Done +> ifconfig up +Done +> thread start +Done + +wait a couple of seconds... + +> state +router +Done +``` + +5. List all IPv6 addresses of Leader. + +```bash +> ipaddr +fdde:ad00:beef:0:0:ff:fe00:fc00 +fdde:ad00:beef:0:0:ff:fe00:800 +fdde:ad00:beef:0:5b:3bcd:deff:7786 +fe80:0:0:0:6447:6e10:cf7:ee29 +Done +``` + +6. Send an ICMPv6 ping to Leader's Mesh-EID IPv6 address. + +```bash +> ping fdde:ad00:beef:0:5b:3bcd:deff:7786 +8 bytes from fdde:ad00:beef:0:5b:3bcd:deff:7786: icmp_seq=1 hlim=64 time=24ms +``` + +The above example demonstrates basic OpenThread capabilities. Enable more features/roles (e.g. commissioner, +joiner, DHCPv6 Server/Client, etc.) by assigning compile-options before compiling. + +```bash +$ cd +$ ./bootstrap +$ make -f examples/Makefile-efr32 COMMISSIONER=1 JOINER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 +``` + +For a list of all available commands, visit [OpenThread CLI Reference README.md][CLI]. + +[CLI]: https://github.com/openthread/openthread/blob/master/src/cli/README.md + +## Verification + +The following toolchain has been used for testing and verification: + - gcc version 4.9.3 + +The EFR32 example has been verified with following Flex SDK/RAIL Library version: + - Flex SDK version 1.1.1.0 + - RAIL Library version 1.5.2.2 diff --git a/examples/platforms/efr32/alarm.c b/examples/platforms/efr32/alarm.c new file mode 100644 index 000000000..fc1bbe8bd --- /dev/null +++ b/examples/platforms/efr32/alarm.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for the alarm. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "rail.h" + +static uint32_t sTimerHi = 0; +static uint32_t sTimerLo = 0; +static uint32_t sAlarmT0 = 0; +static uint32_t sAlarmDt = 0; +static bool sIsRunning = false; + +void efr32AlarmInit(void) +{ +} + +uint32_t otPlatAlarmGetNow(void) +{ + uint32_t timer_lo; + + timer_lo = RAIL_GetTime(); + + if (timer_lo < sTimerLo) + { + sTimerHi++; + } + + sTimerLo = timer_lo; + + return (((uint64_t)sTimerHi << 32) | sTimerLo) / 1000; +} + +void otPlatAlarmStartAt(otInstance *aInstance, uint32_t t0, uint32_t dt) +{ + (void)aInstance; + sAlarmT0 = t0; + sAlarmDt = dt; + sIsRunning = true; +} + +void otPlatAlarmStop(otInstance *aInstance) +{ + (void)aInstance; + sIsRunning = false; +} + +void efr32AlarmProcess(otInstance *aInstance) +{ + uint32_t now = otPlatAlarmGetNow(); + uint32_t expires; + bool fire = false; + + otEXPECT(sIsRunning); + + expires = sAlarmT0 + sAlarmDt; + + if (sAlarmT0 <= now) + { + fire = (expires >= sAlarmT0 && expires <= now); + } + else + { + fire = (expires >= sAlarmT0 || expires <= now); + } + + if (fire) + { + sIsRunning = false; + +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagAlarmFired(aInstance); + } + else +#endif + { + otPlatAlarmFired(aInstance); + } + } + +exit: + return; +} + +void RAILCb_TimerExpired(void) +{ +} diff --git a/examples/platforms/efr32/crypto/efr32-mbedtls-config.h b/examples/platforms/efr32/crypto/efr32-mbedtls-config.h new file mode 100644 index 000000000..00093a047 --- /dev/null +++ b/examples/platforms/efr32/crypto/efr32-mbedtls-config.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EFR32_MBEDTLS_CONFIG_H +#define EFR32_MBEDTLS_CONFIG_H + +#include "em_device.h" + +/** + * \def MBEDTLS_AES_ALT + * + * Enable hardware acceleration for the AES block cipher + * + * Module: sl_crypto/src/sl_aes.c + * or + * sl_crypto/src/slcl_aes.c if MBEDTLS_SLCL_PLUGINS is defined. + * + * See MBEDTLS_AES_C for more information. + */ +#define MBEDTLS_AES_ALT + +/** + * \def MBEDTLS_ECP_DEVICE_ALT + * \def MBEDTLS_ECP_DEVICE_ALT + * \def MBEDTLS_ECP_DOUBLE_JAC_ALT + * \def MBEDTLS_ECP_DEVICE_ADD_MIXED_ALT + * \def MBEDTLS_ECP_NORMALIZE_JAC_ALT + * \def MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT + * \def MBEDTLS_MPI_MODULAR_DIVISION_ALT + * + * Enable hardware acceleration for the elliptic curve over GF(p) library. + * + * Module: sl_crypto/src/sl_ecp.c + * or + * sl_crypto/src/slcl_ecp.c if MBEDTLS_SLCL_PLUGINS is defined. + * Caller: library/ecp.c + * library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_ECP_C and at least one + * MBEDTLS_ECP_DP_XXX_ENABLED and (CRYPTO_COUNT > 0) + */ +#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) +#define MBEDTLS_ECP_DEVICE_ALT +#define MBEDTLS_ECP_DOUBLE_JAC_ALT +#define MBEDTLS_ECP_DEVICE_ADD_MIXED_ALT +#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +#define MBEDTLS_MPI_MODULAR_DIVISION_ALT +#endif + +/** + * \def MBEDTLS_SHA256_ALT + * + * Enable hardware acceleration for the SHA-224 and SHA-256 cryptographic + * hash algorithms. + * + * Module: sl_crypto/src/sl_sha256.c + * or + * sl_crypto/src/slcl_sha256.c if MBEDTLS_SLCL_PLUGINS is defined. + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_SHA256_C and (CRYPTO_COUNT > 0) + * See MBEDTLS_SHA256_C for more information. + */ +#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) +//#define MBEDTLS_SHA256_ALT +#endif + +#endif // EFR32_MBEDTLS_CONFIG_H diff --git a/examples/platforms/efr32/diag.c b/examples/platforms/efr32/diag.c new file mode 100644 index 000000000..6b28d5785 --- /dev/null +++ b/examples/platforms/efr32/diag.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for the diagnostics. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include "platform-efr32.h" + +/** + * Diagnostics mode variables. + * + */ +static bool sDiagMode = false; + +void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + // Add more plarform specific diagnostics features here. + snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]); + (void) argc; + (void) aInstance; +} + +void otPlatDiagModeSet(bool aMode) +{ + sDiagMode = aMode; +} + +bool otPlatDiagModeGet() +{ + return sDiagMode; +} + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + (void) aChannel; +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + (void) aTxPower; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError) +{ + (void) aInstance; + (void) aFrame; + (void) aError; +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + (void) aInstance; +} diff --git a/examples/platforms/efr32/flash.c b/examples/platforms/efr32/flash.c new file mode 100644 index 000000000..625ee5ff7 --- /dev/null +++ b/examples/platforms/efr32/flash.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for the non-volatile storage. + */ + +#include +#include +#include +#include + +#include "em_msc.h" + +#define FLASH_DATA_USED_PAGES 10 +#define FLASH_DATA_END_ADDR (FLASH_BASE + FLASH_SIZE) +#define FLASH_DATA_START_ADDR (FLASH_DATA_END_ADDR - (FLASH_PAGE_SIZE * FLASH_DATA_USED_PAGES)) + +static inline uint32_t mapAddress(uint32_t aAddress) +{ + return aAddress + FLASH_DATA_START_ADDR; +} + +static ThreadError returnTypeConvert(int32_t aStatus) +{ + ThreadError error = kThreadError_None; + + switch (aStatus) + { + case mscReturnOk: + error = kThreadError_None; + break; + + case mscReturnInvalidAddr: + case mscReturnUnaligned: + error = kThreadError_InvalidArgs; + break; + + default: + error = kThreadError_Failed; + } + + return error; +} + +ThreadError utilsFlashInit(void) +{ + MSC_Init(); + return kThreadError_None; +} + +uint32_t utilsFlashGetSize(void) +{ + return FLASH_DATA_END_ADDR - FLASH_DATA_START_ADDR; +} + +ThreadError utilsFlashErasePage(uint32_t aAddress) +{ + int32_t status; + + status = MSC_ErasePage((uint32_t *)mapAddress(aAddress)); + + return returnTypeConvert(status); +} + +ThreadError utilsFlashStatusWait(uint32_t aTimeout) +{ + ThreadError error = kThreadError_Busy; + uint32_t start = otPlatAlarmGetNow(); + + do + { + if (MSC->STATUS & MSC_STATUS_WDATAREADY) + { + error = kThreadError_None; + break; + } + } + while (aTimeout && ((otPlatAlarmGetNow() - start) < aTimeout)); + + return error; +} + +uint32_t utilsFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + uint32_t rval = aSize; + int32_t status; + + otEXPECT_ACTION(aData, rval = 0); + otEXPECT_ACTION(((aAddress + aSize) < utilsFlashGetSize()) && + (!(aAddress & 3)) && (!(aSize & 3)), rval = 0); + + status = MSC_WriteWord((uint32_t *)mapAddress(aAddress), aData, aSize); + otEXPECT_ACTION(returnTypeConvert(status) == kThreadError_None, rval = 0); + +exit: + return rval; +} + +uint32_t utilsFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + uint32_t rval = aSize; + uint32_t pAddress = mapAddress(aAddress); + uint8_t *byte = aData; + + otEXPECT_ACTION(aData, rval = 0); + otEXPECT_ACTION((aAddress + aSize) < utilsFlashGetSize(), rval = 0); + + while (aSize--) + { + *byte++ = (*(uint8_t *)(pAddress++)); + } + +exit: + return rval; +} diff --git a/examples/platforms/efr32/logging.c b/examples/platforms/efr32/logging.c new file mode 100644 index 000000000..64ba71222 --- /dev/null +++ b/examples/platforms/efr32/logging.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for logging. + * + */ + +#ifdef OPENTHREAD_CONFIG_FILE +#include OPENTHREAD_CONFIG_FILE +#else +#include +#endif + + +#include +#if OPENTHREAD_ENABLE_CLI_LOGGING +#include +#include +#include +#include +#include +#include + +#include +#include +#endif + +void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) +{ +#if OPENTHREAD_ENABLE_CLI_LOGGING + va_list args; + va_start(args, aFormat); + otCliLog(aLogLevel, aLogRegion, aFormat, args); + va_end(args); +#else + (void)aLogLevel; + (void)aLogRegion; + (void)aFormat; +#endif // OPENTHREAD_ENABLE_CLI_LOGGING +} diff --git a/examples/platforms/efr32/misc.c b/examples/platforms/efr32/misc.c new file mode 100644 index 000000000..8f84222c5 --- /dev/null +++ b/examples/platforms/efr32/misc.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for miscellaneous behaviors. + */ + +#include +#include + +#include "platform-efr32.h" +#include "em_rmu.h" + +static uint32_t sResetCause; + +void efr32MiscInit(void) +{ + // Read the cause of last reset. + sResetCause = RMU_ResetCauseGet(); + + // Clear the register, as the causes cumulate over resets. + RMU_ResetCauseClear(); +} + +void otPlatReset(otInstance *aInstance) +{ + (void)aInstance; + NVIC_SystemReset(); +} + +otPlatResetReason otPlatGetResetReason(otInstance *aInstance) +{ + (void)aInstance; + otPlatResetReason reason; + + if (sResetCause & RMU_RSTCAUSE_PORST) + { + reason = kPlatResetReason_PowerOn; + } + else if (sResetCause & RMU_RSTCAUSE_SYSREQRST) + { + reason = kPlatResetReason_Software; + } + else if (sResetCause & RMU_RSTCAUSE_WDOGRST) + { + reason = kPlatResetReason_Watchdog; + } + else if (sResetCause & RMU_RSTCAUSE_EXTRST) + { + reason = kPlatResetReason_External; + } + else if (sResetCause & RMU_RSTCAUSE_LOCKUPRST) + { + reason = kPlatResetReason_Fault; + } + else if ((sResetCause & RMU_RSTCAUSE_AVDDBOD) || + (sResetCause & RMU_RSTCAUSE_DECBOD) || + (sResetCause & RMU_RSTCAUSE_DVDDBOD) || + (sResetCause & RMU_RSTCAUSE_EM4RST)) + { + reason = kPlatResetReason_Assert; + } + else + { + reason = kPlatResetReason_Unknown; + } + + return reason; +} diff --git a/examples/platforms/efr32/openthread-core-efr32-config.h b/examples/platforms/efr32/openthread-core-efr32-config.h new file mode 100644 index 000000000..c9b31002f --- /dev/null +++ b/examples/platforms/efr32/openthread-core-efr32-config.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes efr32 compile-time configuration constants + * for OpenThread. + */ + +#ifndef OPENTHREAD_CORE_EFR32_CONFIG_H_ +#define OPENTHREAD_CORE_EFR32_CONFIG_H_ + +/** + * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT + * + * Define to 1 if you want to enable software ACK timeout logic. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT 1 + +/** + * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT + * + * Define to 1 if you want to enable software retransmission logic. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT 1 + +/** + * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN + * + * Define to 1 if you want to enable software energy scanning logic. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN 1 + +/** + * @def SETTINGS_CONFIG_BASE_ADDRESS + * + * The base address of settings. + * + */ +#define SETTINGS_CONFIG_BASE_ADDRESS 0 + +/** + * @def SETTINGS_CONFIG_PAGE_SIZE + * + * The page size of settings. + * + */ +#define SETTINGS_CONFIG_PAGE_SIZE 0x800 + +/** + * @def SETTINGS_CONFIG_PAGE_NUM + * + * The page number of settings. + * + */ +#define SETTINGS_CONFIG_PAGE_NUM 4 + +/** + * @def RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM + * + * The number of short source address table entries. + * + */ +#define RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM 6 + +/** + * @def RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM + * + * The number of extended source address table entries. + * + */ +#define RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM 6 + +/** + * @def RADIO_CONFIG_XXX + * + * The Radio configuration Auto-generated by Simplicity Studio (rail_config.h). + * + */ +#define RADIO_CONFIG_BASE_FREQUENCY 2450000000UL +#define RADIO_CONFIG_XTAL_FREQUENCY 38400000UL +#define RADIO_CONFIG_BITRATE "2.4kbps" +#define RADIO_CONFIG_MODULATION_TYPE "FSK2" +#define RADIO_CONFIG_DEVIATION "1.2kHz" + +#endif // OPENTHREAD_CORE_EFR32_CONFIG_H_ diff --git a/examples/platforms/efr32/platform-efr32.h b/examples/platforms/efr32/platform-efr32.h new file mode 100644 index 000000000..f1007101f --- /dev/null +++ b/examples/platforms/efr32/platform-efr32.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes the platform-specific initializers. + * + */ + +#ifndef PLATFORM_EFR32_H_ +#define PLATFORM_EFR32_H_ + +#include "em_device.h" +#include "em_system.h" +#include "core_cm4.h" + +// Global OpenThread instance structure +extern otInstance *sInstance; + +/** + * This function initializes the alarm service used by OpenThread. + * + */ +void efr32AlarmInit(void); + +/** + * This function performs alarm driver processing. + * + * @param[in] aInstance The OpenThread instance structure. + * + */ +void efr32AlarmProcess(otInstance *aInstance); + +/** + * This function initializes the radio service used by OpenThead. + * + */ +void efr32RadioInit(void); + +/** + * This function deinitializes the radio service used by OpenThead. + * + */ +void efr32RadioDeinit(void); + +/** + * This function performs radio driver processing. + * + * @param[in] aInstance The OpenThread instance structure. + * + */ +void efr32RadioProcess(otInstance *aInstance); + +/** + * This function performs UART driver processing. + * + */ +void efr32UartProcess(void); + +/** + * Initialization of Misc module. + * + */ +void efr32MiscInit(void); + +/** + * Initialization of ADC module for random number generator. + * + */ +void efr32RandomInit(void); + +/** + * Initialization of EFR32 Hardware Abstract Layer. + * + */ +void efr32HalInit(void); + +#endif // PLATFORM_EFR32_H_ diff --git a/examples/platforms/efr32/platform.c b/examples/platforms/efr32/platform.c new file mode 100644 index 000000000..1eca397a1 --- /dev/null +++ b/examples/platforms/efr32/platform.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file includes the platform-specific initializers. + */ + +#include + +#include +#include + +#include "pa.h" +#include "pti.h" +#include "bsp.h" +#include "em_emu.h" +#include "em_cmu.h" +#include "em_chip.h" +#include "platform-efr32.h" +#include "rail.h" +#include "rail_ieee802154.h" +#include "openthread-core-efr32-config.h" + +otInstance *sInstance; + +void PlatformInit(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + CHIP_Init(); + efr32HalInit(); + BSP_Init(BSP_INIT_BCC); + + otPlatUartEnable(); + + RAIL_Init_t railInitParams = + { + 128, // maxPacketLength: UNUSED + RADIO_CONFIG_XTAL_FREQUENCY, + 0 + }; + RAIL_RfInit(&railInitParams); + RAIL_RfIdle(); + + efr32AlarmInit(); + efr32RadioInit(); + efr32MiscInit(); + efr32RandomInit(); +} + +void PlatformDeinit(void) +{ + efr32RadioDeinit(); +} + +void PlatformProcessDrivers(otInstance *aInstance) +{ + sInstance = aInstance; + + // should sleep and wait for interrupts here + + efr32UartProcess(); + efr32RadioProcess(aInstance); + efr32AlarmProcess(aInstance); +} + +void halInitChipSpecific(void) +{ + CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_WSTK_DEFAULT; + RADIO_PTIInit_t ptiInit = RADIO_PTI_INIT; + RADIO_PAInit_t paInit; + + SYSTEM_ChipRevision_TypeDef chipRev; + SYSTEM_ChipRevisionGet(&chipRev); + + // Init DCDC regulator and HFXO with WSTK radio board specific parameters + // from s025_sw\kits\SLWSTK6100A_EFR32MG\config\bspconfig.h +#ifdef EMU_DCDCINIT_WSTK_DEFAULT + EMU_DCDCInit_TypeDef dcdcInit = EMU_DCDCINIT_WSTK_DEFAULT; + EMU_DCDCInit(&dcdcInit); +#else + EMU_DCDCPowerOff(); +#endif + CMU_HFXOInit(&hfxoInit); + SystemHFXOClockSet(RADIO_CONFIG_XTAL_FREQUENCY); + + // Initialize the Packet Trace Interface (PTI) to match the configuration in + // the board header + RADIO_PTI_Init(&ptiInit); + + /* Switch HFCLK to HFXO and disable HFRCO */ + CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); + CMU_OscillatorEnable(cmuOsc_HFRCO, false, false); + + // Initialize the PA now that the HFXO is up and the timing is correct +#if (RADIO_CONFIG_BASE_FREQUENCY < 1000000000UL) + paInit = (RADIO_PAInit_t) RADIO_PA_SUBGIG_INIT; +#else + paInit = (RADIO_PAInit_t) RADIO_PA_2P4_INIT; +#endif + + if (!RADIO_PA_Init(&paInit)) + { + // Error: The PA could not be initialized due to an improper configuration. + // Please ensure your configuration is valid for the selected part. + while (1); + } + + // Initialize other chip clocks + CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); + CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); + CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFRCO); + CMU_ClockEnable(cmuClock_CORELE, true); +} + +void efr32HalInit(void) +{ + halInitChipSpecific(); +} diff --git a/examples/platforms/efr32/radio.c b/examples/platforms/efr32/radio.c new file mode 100644 index 000000000..62c97971a --- /dev/null +++ b/examples/platforms/efr32/radio.c @@ -0,0 +1,844 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for radio communication. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "em_core.h" +#include "em_system.h" +#include "rail.h" +#include "rail_ieee802154.h" +#include "openthread-core-efr32-config.h" + +enum +{ + IEEE802154_MIN_LENGTH = 5, + IEEE802154_MAX_LENGTH = 127, + IEEE802154_ACK_LENGTH = 5, + IEEE802154_FRAME_TYPE_MASK = 0x7, + IEEE802154_FRAME_TYPE_ACK = 0x2, + IEEE802154_FRAME_PENDING = 1 << 4, + IEEE802154_ACK_REQUEST = 1 << 5, + IEEE802154_DSN_OFFSET = 2, +}; + +static uint16_t sPanId = 0; +static uint8_t sChannel = 0; +static bool sTransmitBusy = false; +static bool sPromiscuous = false; +static bool sIsReceiverEnabled = false; +static bool sIsSrcMatchEnabled = false; +static PhyState sState = kStateDisabled; + +static uint8_t sReceiveBuffer[IEEE802154_MAX_LENGTH + 1 + sizeof(RAIL_RxPacketInfo_t)]; +static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH]; +static RadioPacket sReceiveFrame; +static ThreadError sReceiveError; + +static RadioPacket sTransmitFrame; +static uint8_t sTransmitPsdu[IEEE802154_MAX_LENGTH]; +static ThreadError sTransmitError; + +typedef struct srcMatchEntry +{ + uint16_t checksum; + bool allocated; +} sSrcMatchEntry; + +static sSrcMatchEntry srcMatchShortEntry[RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM]; +static sSrcMatchEntry srcMatchExtEntry[RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM]; + +void efr32RadioInit(void) +{ + // Data Management + RAIL_DataConfig_t railDataConfig = + { + TX_PACKET_DATA, + RX_PACKET_DATA, + PACKET_MODE, + PACKET_MODE, + }; + + RAIL_DataConfig(&railDataConfig); + + // 802.15.4 configuration + RAIL_IEEE802154_Config_t config = + { + false, // promiscuousMode + false, // isPanCoordinator + RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES, // framesMask + RAIL_RF_STATE_RX, // defaultState + 100, // idleTime + 192, // turnaroundTime + 894, // ackTimeout + NULL // addresses + }; + + sReceiveFrame.mLength = 0; + sReceiveFrame.mPsdu = sReceivePsdu; + sTransmitFrame.mLength = 0; + sTransmitFrame.mPsdu = sTransmitPsdu; + + if (RAIL_IEEE802154_2p4GHzRadioConfig()) + { + assert(false); + } + + if (RAIL_IEEE802154_Init(&config)) + { + assert(false); + } + + RAIL_TxPowerSet(0); + + otLogInfoPlat(sInstance, "Initialized", NULL); +} + +void efr32RadioDeinit(void) +{ + RAIL_RfIdle(); + RAIL_IEEE802154_Deinit(); +} + +void setChannel(uint8_t channel) +{ + bool enabled = false; + + otEXPECT(sChannel != channel); + + if (sIsReceiverEnabled) + { + RAIL_RfIdle(); + enabled = true; + sIsReceiverEnabled = false; + } + + otLogInfoPlat(sInstance, "Channel=%d", channel); + + sChannel = channel; + + if (enabled) + { + if (RAIL_RxStart(channel)) + { + assert(false); + } + + sIsReceiverEnabled = true; + } + +exit: + return; +} + +void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) +{ + uint64_t eui64; + uint8_t *eui64Ptr = NULL; + (void)aInstance; + + eui64 = SYSTEM_GetUnique(); + eui64Ptr = (uint8_t *)&eui64; + + for (uint8_t i = 0; i < OT_EXT_ADDRESS_SIZE; i++) + { + aIeeeEui64[i] = eui64Ptr[(OT_EXT_ADDRESS_SIZE - 1) - i]; + } +} + +void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId) +{ + (void)aInstance; + + otLogInfoPlat(sInstance, "PANID=%X", aPanId); + + sPanId = aPanId; + RAIL_IEEE802154_SetPanId(aPanId); +} + +void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *aAddress) +{ + (void)aInstance; + + otLogInfoPlat(sInstance, "ExtAddr=%X%X%X%X%X%X%X%X", + aAddress[7], aAddress[6], aAddress[5], aAddress[4], + aAddress[3], aAddress[2], aAddress[1], aAddress[0]); + + RAIL_IEEE802154_SetLongAddress(aAddress); +} + +void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress) +{ + (void)aInstance; + + otLogInfoPlat(sInstance, "ShortAddr=%X", aAddress); + + RAIL_IEEE802154_SetShortAddress(aAddress); +} + +bool otPlatRadioIsEnabled(otInstance *aInstance) +{ + (void)aInstance; + return (sState != kStateDisabled); +} + +ThreadError otPlatRadioEnable(otInstance *aInstance) +{ + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + otEXPECT(!otPlatRadioIsEnabled(aInstance)); + + otLogInfoPlat(sInstance, "State=kStateSleep", NULL); + sState = kStateSleep; + +exit: + CORE_EXIT_CRITICAL(); + return kThreadError_None; +} + +ThreadError otPlatRadioDisable(otInstance *aInstance) +{ + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + otEXPECT(otPlatRadioIsEnabled(aInstance)); + + otLogInfoPlat(sInstance, "State=kStateDisabled", NULL); + sState = kStateDisabled; + +exit: + CORE_EXIT_CRITICAL(); + return kThreadError_None; +} + +ThreadError otPlatRadioSleep(otInstance *aInstance) +{ + ThreadError error = kThreadError_None; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + otEXPECT_ACTION((sState != kStateTransmit) && (sState != kStateDisabled), + error = kThreadError_InvalidState); + + otLogInfoPlat(sInstance, "State=kStateSleep", NULL); + sState = kStateSleep; + + if (sIsReceiverEnabled) + { + RAIL_RfIdleExt(RAIL_IDLE, true); + sIsReceiverEnabled = false; + } + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +ThreadError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) +{ + ThreadError error = kThreadError_None; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + otEXPECT_ACTION(sState != kStateDisabled, error = kThreadError_InvalidState); + + otLogInfoPlat(sInstance, "State=kStateReceive", NULL); + sState = kStateReceive; + setChannel(aChannel); + sReceiveFrame.mChannel = aChannel; + + if (!sIsReceiverEnabled) + { + if (RAIL_RxStart(aChannel)) + { + assert(false); + } + + sIsReceiverEnabled = true; + } + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket) +{ + ThreadError error = kThreadError_None; + RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA; + RAIL_TxData_t tx_data; + uint8_t frame[IEEE802154_MAX_LENGTH + 1]; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + otEXPECT_ACTION((sState != kStateDisabled) && (sState != kStateTransmit), + error = kThreadError_InvalidState); + + sState = kStateTransmit; + sTransmitError = kThreadError_None; + sTransmitBusy = true; + + frame[0] = aPacket->mLength; + memcpy(frame + 1, aPacket->mPsdu, aPacket->mLength); + + tx_data.dataPtr = frame; + tx_data.dataLength = aPacket->mLength - 1; + setChannel(aPacket->mChannel); + RAIL_RfIdleExt(RAIL_IDLE, true); + + if (RAIL_TxDataLoad(&tx_data)) + { + assert(false); + } + + if (RAIL_TxStart(aPacket->mChannel, RAIL_CcaCsma, &csmaConfig)) + { + assert(false); + } + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *aInstance) +{ + (void)aInstance; + return &sTransmitFrame; +} + +int8_t otPlatRadioGetRssi(otInstance *aInstance) +{ + (void)aInstance; + return (uint8_t)(RAIL_RxGetRSSI() >> 2); +} + +otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) +{ + (void)aInstance; + return kRadioCapsNone; +} + +bool otPlatRadioGetPromiscuous(otInstance *aInstance) +{ + (void)aInstance; + return sPromiscuous; +} + +void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) +{ + (void)aInstance; + + sPromiscuous = aEnable; + RAIL_IEEE802154_SetPromiscuousMode(aEnable); +} + +int8_t findSrcMatchAvailEntry(bool aShortAddress) +{ + int8_t entry = -1; + + if (aShortAddress) + { + for (uint8_t i = 0; i < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM; i++) + { + if (!srcMatchShortEntry[i].allocated) + { + entry = i; + break; + } + } + } + else + { + for (uint8_t i = 0; i < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM; i++) + { + if (!srcMatchExtEntry[i].allocated) + { + entry = i; + break; + } + } + } + + return entry; +} + +int8_t findSrcMatchShortEntry(const uint16_t aShortAddress) +{ + int8_t entry = -1; + uint16_t checksum = aShortAddress + sPanId; + + for (uint8_t i = 0; i < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM; i++) + { + if (checksum == srcMatchShortEntry[i].checksum && + srcMatchShortEntry[i].allocated) + { + entry = i; + break; + } + } + + return entry; +} + +int8_t findSrcMatchExtEntry(const uint8_t *aExtAddress) +{ + int8_t entry = -1; + uint16_t checksum = sPanId; + + checksum += (uint16_t)aExtAddress[0] | (uint16_t)(aExtAddress[1] << 8); + checksum += (uint16_t)aExtAddress[2] | (uint16_t)(aExtAddress[3] << 8); + checksum += (uint16_t)aExtAddress[4] | (uint16_t)(aExtAddress[5] << 8); + checksum += (uint16_t)aExtAddress[6] | (uint16_t)(aExtAddress[7] << 8); + + for (uint8_t i = 0; i < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM; i++) + { + if (checksum == srcMatchExtEntry[i].checksum && + srcMatchExtEntry[i].allocated) + { + entry = i; + break; + } + } + + return entry; +} + +void addToSrcMatchShortIndirect(uint8_t entry, const uint16_t aShortAddress) +{ + uint16_t checksum = aShortAddress + sPanId; + + srcMatchShortEntry[entry].checksum = checksum; + srcMatchShortEntry[entry].allocated = true; +} + +void addToSrcMatchExtIndirect(uint8_t entry, const uint8_t *aExtAddress) +{ + uint16_t checksum = sPanId; + + checksum += (uint16_t)aExtAddress[0] | (uint16_t)(aExtAddress[1] << 8); + checksum += (uint16_t)aExtAddress[2] | (uint16_t)(aExtAddress[3] << 8); + checksum += (uint16_t)aExtAddress[4] | (uint16_t)(aExtAddress[5] << 8); + checksum += (uint16_t)aExtAddress[6] | (uint16_t)(aExtAddress[7] << 8); + + srcMatchExtEntry[entry].checksum = checksum; + srcMatchExtEntry[entry].allocated = true; +} + +void removeFromSrcMatchShortIndirect(uint8_t entry) +{ + srcMatchShortEntry[entry].allocated = false; + memset(&srcMatchShortEntry[entry].checksum, 0, sizeof(uint16_t)); +} + +void removeFromSrcMatchExtIndirect(uint8_t entry) +{ + srcMatchExtEntry[entry].allocated = false; + memset(&srcMatchExtEntry[entry].checksum, 0, sizeof(uint16_t)); +} + +void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) +{ + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + // set Frame Pending bit for all outgoing ACKs if aEnable is false + sIsSrcMatchEnabled = aEnable; + + CORE_EXIT_CRITICAL(); +} + +ThreadError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + (void)aInstance; + ThreadError error = kThreadError_None; + int8_t entry = -1; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + entry = findSrcMatchAvailEntry(true); + otLogDebgPlat(sInstance, "Add ShortAddr entry: %d", entry); + + otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM, + error = kThreadError_NoBufs); + + addToSrcMatchShortIndirect(entry, aShortAddress); + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +ThreadError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +{ + ThreadError error = kThreadError_None; + int8_t entry = -1; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + entry = findSrcMatchAvailEntry(false); + otLogDebgPlat(sInstance, "Add ExtAddr entry: %d", entry); + + otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM, + error = kThreadError_NoBufs); + + addToSrcMatchExtIndirect(entry, aExtAddress); + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +ThreadError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +{ + ThreadError error = kThreadError_None; + int8_t entry = -1; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + entry = findSrcMatchShortEntry(aShortAddress); + otLogDebgPlat(sInstance, "Clear ShortAddr entry: %d", entry); + + otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM, + error = kThreadError_NoAddress); + + removeFromSrcMatchShortIndirect(entry); + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +ThreadError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +{ + ThreadError error = kThreadError_None; + int8_t entry = -1; + (void)aInstance; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + entry = findSrcMatchExtEntry(aExtAddress); + otLogDebgPlat(sInstance, "Clear ExtAddr entry: %d", entry); + + otEXPECT_ACTION(entry >= 0 && entry < RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM, + error = kThreadError_NoAddress); + + removeFromSrcMatchExtIndirect(entry); + +exit: + CORE_EXIT_CRITICAL(); + return error; +} + +void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) +{ + (void)aInstance; + + otLogDebgPlat(sInstance, "Clear ShortAddr entries", NULL); + + memset(srcMatchShortEntry, 0, sizeof(srcMatchShortEntry)); +} + +void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) +{ + (void)aInstance; + + otLogDebgPlat(sInstance, "Clear ExtAddr entries", NULL); + + memset(srcMatchExtEntry, 0, sizeof(srcMatchExtEntry)); +} + +void RAILCb_IEEE802154_DataRequestCommand(RAIL_IEEE802154_Address_t *aAddress) +{ + if (sIsSrcMatchEnabled) + { + if ((aAddress->length == RAIL_IEEE802154_LongAddress && + findSrcMatchExtEntry(aAddress->longAddress) >= 0) || + (aAddress->length == RAIL_IEEE802154_ShortAddress && + findSrcMatchShortEntry(aAddress->shortAddress) >= 0)) + { + RAIL_IEEE802154_SetFramePending(); + } + } + else + { + (void)aAddress; + RAIL_IEEE802154_SetFramePending(); + } +} + +ThreadError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) +{ + (void)aInstance; + (void)aScanChannel; + (void)aScanDuration; + return kThreadError_NotImplemented; +} + +void RAILCb_TxRadioStatus(uint8_t aStatus) +{ + switch (aStatus) + { + case RAIL_TX_CONFIG_CHANNEL_BUSY: + sTransmitError = kThreadError_ChannelAccessFailure; + sTransmitBusy = false; + break; + + case RAIL_TX_CONFIG_TX_ABORTED: + sTransmitError = kThreadError_Abort; + sTransmitBusy = false; + break; + + default: + break; + } +} + +void RAILCb_TxPacketSent(RAIL_TxPacketInfo_t *aTxPacketInfo) +{ + (void)aTxPacketInfo; + sTransmitError = kThreadError_None; + sTransmitBusy = false; +} + +void RAILCb_RxPacketReceived(void *aRxPacketHandle) +{ + RAIL_RxPacketInfo_t *rxPacketInfo; + uint8_t length; + + rxPacketInfo = (RAIL_RxPacketInfo_t *)aRxPacketHandle; + + // check recv packet appended info + otEXPECT(rxPacketInfo != NULL && + rxPacketInfo->appendedInfo.crcStatus && + rxPacketInfo->appendedInfo.frameCodingStatus); + + length = rxPacketInfo->dataLength + 1; + + // check the length in recv packet info structure + otEXPECT(length == rxPacketInfo->dataPtr[0]); + + // check the lenght validity of recv packet + otEXPECT(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH); + + memcpy(sReceiveFrame.mPsdu, rxPacketInfo->dataPtr + 1, rxPacketInfo->dataLength); + sReceiveFrame.mPower = rxPacketInfo->appendedInfo.rssiLatch; + sReceiveFrame.mLqi = rxPacketInfo->appendedInfo.lqi; + sReceiveFrame.mLength = length; + sReceiveError = kThreadError_None; + +exit: + return; +} + +void efr32RadioProcess(otInstance *aInstance) +{ + // ensure process would not be broken by + // the incoming interrupt with higher priority + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + + if ((sState == kStateReceive && sReceiveFrame.mLength > 0) || + (sState == kStateTransmit && sReceiveFrame.mLength > IEEE802154_ACK_LENGTH)) + { +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError); + } + else +#endif + { + // signal MAC layer for each received frame if promiscous is enabled + // otherwise only signal MAC layer for non-ACK frame + if (sPromiscuous || sReceiveFrame.mLength > IEEE802154_ACK_LENGTH) + { + otLogInfoPlat(sInstance, "Received %d bytes", sReceiveFrame.mLength); + otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError); + } + } + } + + if (sState == kStateTransmit && sTransmitBusy == false) + { + if (sTransmitError != kThreadError_None || (sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) + { + if (sTransmitError != kThreadError_None) + { + otLogDebgPlat(sInstance, "Transmit failed ErrorCode=%d", sTransmitError); + } + + sState = kStateReceive; + +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, false, sTransmitError); + } + else +#endif + { + otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, sTransmitError); + } + } + else if (sReceiveFrame.mLength == IEEE802154_ACK_LENGTH && + (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK && + (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])) + { + sState = kStateReceive; + +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, + (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, + sTransmitError); + } + else +#endif + { + otLogInfoPlat(sInstance, "Received ACK:%d", sReceiveFrame.mLength); + otPlatRadioTransmitDone(aInstance, &sTransmitFrame, + (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, + sTransmitError); + } + } + } + + sReceiveFrame.mLength = 0; + CORE_EXIT_CRITICAL(); +} + +void RAILCb_RfReady(void) +{ +} + +void RAILCb_CalNeeded(void) +{ +} + +void RAILCb_RxAckTimeout(void) +{ +} + +void RAILCb_RxRadioStatus(uint8_t aStatus) +{ + (void)aStatus; +} + +void RAILCb_RadioStateChanged(uint8_t aState) +{ + (void)aState; +} + +void RAILCb_RssiAverageDone(int16_t avgRssi) +{ + (void)avgRssi; +} + +void RAILCb_RxFifoAlmostFull(uint16_t bytesAvailable) +{ + (void)bytesAvailable; +} + +void RAILCb_TxFifoAlmostEmpty(uint16_t spaceAvailable) +{ + (void)spaceAvailable; +} + +void *RAILCb_AllocateMemory(uint32_t size) +{ + uint8_t *pointer = NULL; + CORE_DECLARE_IRQ_STATE; + + CORE_ENTER_CRITICAL(); + + otEXPECT(size <= (IEEE802154_MAX_LENGTH + 1 + sizeof(RAIL_RxPacketInfo_t))); + + pointer = sReceiveBuffer; + +exit: + CORE_EXIT_CRITICAL(); + return pointer; +} + +void *RAILCb_BeginWriteMemory(void *handle, uint32_t offset, + uint32_t *available) +{ + (void)available; + return ((uint8_t *)handle) + offset; +} + +void RAILCb_EndWriteMemory(void *handle, uint32_t offset, uint32_t size) +{ + (void)handle; + (void)offset; + (void)size; +} + +void RAILCb_FreeMemory(void *handle) +{ + (void)handle; +} + +void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) +{ + (void)aInstance; + RAIL_TxPowerSet(aPower); +} diff --git a/examples/platforms/efr32/random.c b/examples/platforms/efr32/random.c new file mode 100644 index 000000000..205999057 --- /dev/null +++ b/examples/platforms/efr32/random.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for random number generator. + * + */ + +#include +#include +#include + +#include "em_adc.h" +#include "em_cmu.h" + +enum +{ + EFR32_ADC_REF_CLOCK = 7000000, +}; + +void efr32RandomInit(void) +{ + /* Enable ADC Clock */ + CMU_ClockEnable(cmuClock_ADC0, true); + ADC_Init_TypeDef init = ADC_INIT_DEFAULT; + ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; + + /* Initialize the ADC with the required values */ + init.timebase = ADC_TimebaseCalc(0); + init.prescale = ADC_PrescaleCalc(EFR32_ADC_REF_CLOCK, 0); + ADC_Init(ADC0, &init); + + /* Initialize for single conversion specific to RNG */ + singleInit.reference = adcRefVEntropy; + singleInit.diff = true; + singleInit.posSel = adcPosSelVSS; + singleInit.negSel = adcNegSelVSS; + ADC_InitSingle(ADC0, &singleInit); + + /* Set VINATT to maximum value and clear FIFO */ + ADC0->SINGLECTRLX |= _ADC_SINGLECTRLX_VINATT_MASK; + ADC0->SINGLEFIFOCLEAR = ADC_SINGLEFIFOCLEAR_SINGLEFIFOCLEAR; +} + +uint32_t otPlatRandomGet(void) +{ + uint8_t tmp = 0; + uint32_t random = 0; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 3; j++) + { + ADC_Start(ADC0, adcStartSingle); + + while ((ADC0->IF & ADC_IF_SINGLE) == 0); + + tmp |= ((ADC_DataSingleGet(ADC0) & 0x07) << (j * 3)); + } + + random |= (tmp & 0xff) << (i * 8); + } + + return random; +} + +ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength) +{ + ThreadError error = kThreadError_None; + + otEXPECT_ACTION(aOutput && aOutputLength, error = kThreadError_InvalidArgs); + + for (uint16_t length = 0; length < aInputLength; length++) + { + aOutput[length] = (uint8_t)otPlatRandomGet(); + } + + *aOutputLength = aInputLength; + +exit: + return error; +} diff --git a/examples/platforms/efr32/startup-gcc.c b/examples/platforms/efr32/startup-gcc.c new file mode 100644 index 000000000..dc6073b56 --- /dev/null +++ b/examples/platforms/efr32/startup-gcc.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements gcc-specific startup code for the efr32. + */ + +__extension__ typedef int __guard __attribute__((mode(__DI__))); +int __cxa_guard_acquire(__guard *g) { return !*(char *)(g); } +void __cxa_guard_release(__guard *g) { *(char *)g = 1; } +void __cxa_guard_abort(__guard *g) { (void)g; } +void __cxa_pure_virtual(void) { while (1); } diff --git a/examples/platforms/efr32/uart.c b/examples/platforms/efr32/uart.c new file mode 100644 index 000000000..17066671e --- /dev/null +++ b/examples/platforms/efr32/uart.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the OpenThread platform abstraction for UART communication. + * + */ + +#include + +#include +#include +#include + +#include "bspconfig.h" +#include "em_cmu.h" +#include "em_gpio.h" +#include "em_usart.h" + +enum +{ + kPlatformClock = 32000000, + kBaudRate = 115200, + kReceiveBufferSize = 128, +}; + +static void processReceive(void); +static void processTransmit(void); + +static const uint8_t *sTransmitBuffer = NULL; +static uint16_t sTransmitLength = 0; + +typedef struct RecvBuffer +{ + // The data buffer + uint8_t mBuffer[kReceiveBufferSize]; + // The offset of the first item written to the list. + uint16_t mHead; + // The offset of the next item to be written to the list. + uint16_t mTail; +} RecvBuffer; + +static RecvBuffer sReceive; + +ThreadError otPlatUartEnable(void) +{ + USART_TypeDef *usart = USART0; + USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT; + + sReceive.mHead = 0; + sReceive.mTail = 0; + + /* Enable peripheral clocks */ + CMU_ClockEnable(cmuClock_HFPER, true); + /* Configure GPIO pins */ + CMU_ClockEnable(cmuClock_GPIO, true); + + /* Configure GPIO pin for UART TX */ + /* To avoid false start, configure output as high. */ + GPIO_PinModeSet(BSP_BCC_TXPORT, BSP_BCC_TXPIN, gpioModePushPull, 1u); + /* Configure GPIO pin for UART RX */ + GPIO_PinModeSet(BSP_BCC_RXPORT, BSP_BCC_RXPIN, gpioModeInput, 1u); + + /* Enable the switch that enables UART communication. */ + GPIO_PinModeSet(BSP_BCC_ENABLE_PORT, BSP_BCC_ENABLE_PIN, gpioModePushPull, 1u); + + CMU_ClockEnable(cmuClock_USART0, true); + + /* Configure USART for basic async operation */ + init.enable = usartDisable; + USART_InitAsync(usart, &init); + + /* Enable pins at correct UART/USART location. */ + usart->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN; + usart->ROUTELOC0 = (usart->ROUTELOC0 & ~(_USART_ROUTELOC0_TXLOC_MASK | _USART_ROUTELOC0_RXLOC_MASK)) + | (_USART_ROUTELOC0_TXLOC_LOC0 << _USART_ROUTELOC0_TXLOC_SHIFT) + | (_USART_ROUTELOC0_RXLOC_LOC0 << _USART_ROUTELOC0_RXLOC_SHIFT); + + /* Clear previous RX interrupts */ + USART_IntClear(usart, USART_IF_RXDATAV); + NVIC_ClearPendingIRQ(USART0_RX_IRQn); + + /* Enable RX interrupts */ + USART_IntEnable(usart, USART_IF_RXDATAV); + NVIC_EnableIRQ(USART0_RX_IRQn); + + /* Finally enable it */ + USART_Enable(usart, usartEnable); + + return kThreadError_None; +} + +void USART0_RX_IRQHandler(void) +{ + if (USART0->STATUS & USART_STATUS_RXDATAV) + { + uint8_t byte = USART_Rx(USART0); + + // We can only write if incrementing mTail doesn't equal mHead + if (sReceive.mHead != (sReceive.mTail + 1) % kReceiveBufferSize) + { + sReceive.mBuffer[sReceive.mTail] = byte; + sReceive.mTail = (sReceive.mTail + 1) % kReceiveBufferSize; + } + } +} + +ThreadError otPlatUartDisable(void) +{ + return kThreadError_NotImplemented; +} + +ThreadError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) +{ + ThreadError error = kThreadError_None; + + otEXPECT_ACTION(sTransmitBuffer == NULL, error = kThreadError_Busy); + + sTransmitBuffer = aBuf; + sTransmitLength = aBufLength; + +exit: + return error; +} + +void processReceive(void) +{ + // Copy tail to prevent multiple reads + uint16_t tail = sReceive.mTail; + + // If the data wraps around, process the first part + if (sReceive.mHead > tail) + { + otPlatUartReceived(sReceive.mBuffer + sReceive.mHead, kReceiveBufferSize - sReceive.mHead); + + // Reset the buffer mHead back to zero. + sReceive.mHead = 0; + } + + // For any data remaining, process it + if (sReceive.mHead != tail) + { + otPlatUartReceived(sReceive.mBuffer + sReceive.mHead, tail - sReceive.mHead); + + // Set mHead to the local tail we have cached + sReceive.mHead = tail; + } +} + +void processTransmit(void) +{ + otEXPECT(sTransmitBuffer != NULL); + + for (; sTransmitLength > 0; sTransmitLength--) + { + USART_Tx(USART0, *sTransmitBuffer++); + } + + sTransmitBuffer = NULL; + otPlatUartSendDone(); + +exit: + return; +} + +void efr32UartProcess(void) +{ + processReceive(); + processTransmit(); +} diff --git a/examples/platforms/posix/flash.c b/examples/platforms/posix/flash.c index 83d9ce284..eb23fa4e7 100644 --- a/examples/platforms/posix/flash.c +++ b/examples/platforms/posix/flash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Nest Labs, Inc. + * Copyright (c) 2016, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/third_party/Makefile.am b/third_party/Makefile.am index 71bbfb272..7f0706b2e 100644 --- a/third_party/Makefile.am +++ b/third_party/Makefile.am @@ -35,6 +35,12 @@ EXTRA_DIST = \ NordicSemiconductor \ $(NULL) +if OPENTHREAD_EXAMPLES_EFR32 +EXTRA_DIST += \ + silabs \ + $(NULL) +endif + # Always package (e.g. for 'make dist') these subdirectories. DIST_SUBDIRS = \ diff --git a/third_party/mbedtls/Makefile.am b/third_party/mbedtls/Makefile.am index 9777636d8..eac98d9ce 100644 --- a/third_party/mbedtls/Makefile.am +++ b/third_party/mbedtls/Makefile.am @@ -42,7 +42,6 @@ libmbedcrypto_a_CPPFLAGS = \ libmbedcrypto_a_SOURCES = \ hardware_entropy.c \ - repo/library/aes.c \ repo/library/md.c \ repo/library/md_wrap.c \ repo/library/memory_buffer_alloc.c \ @@ -50,6 +49,16 @@ libmbedcrypto_a_SOURCES = \ repo/library/sha256.c \ $(NULL) +if OPENTHREAD_EXAMPLES_EFR32 +nodist_libmbedcrypto_a_SOURCES = \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/util/third_party/mbedtls/sl_crypto/src/sl_aes.c \ + $(NULL) +else +libmbedcrypto_a_SOURCES += \ + repo/library/aes.c \ + $(NULL) +endif # OPENTHREAD_EXAMPLES_EFR32 + if OPENTHREAD_ENABLE_DTLS libmbedcrypto_a_SOURCES += \ repo/library/bignum.c \ @@ -60,7 +69,6 @@ libmbedcrypto_a_SOURCES += \ repo/library/ctr_drbg.c \ repo/library/debug.c \ repo/library/ecjpake.c \ - repo/library/ecp.c \ repo/library/ecp_curves.c \ repo/library/entropy.c \ repo/library/entropy_poll.c \ @@ -72,6 +80,17 @@ libmbedcrypto_a_SOURCES += \ repo/library/ssl_tls.c \ $(NULL) +if OPENTHREAD_EXAMPLES_EFR32 +nodist_libmbedcrypto_a_SOURCES += \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/util/third_party/mbedtls/library/ecp.c \ + @top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/util/third_party/mbedtls/sl_crypto/src/sl_ecp.c \ + $(NULL) +else +libmbedcrypto_a_SOURCES += \ + repo/library/ecp.c \ + $(NULL) +endif # OPENTHREAD_EXAMPLES_EFR32 + # # mbedtls patches # diff --git a/third_party/mbedtls/hardware_entropy.c b/third_party/mbedtls/hardware_entropy.c index f81fbfac0..aac174421 100644 --- a/third_party/mbedtls/hardware_entropy.c +++ b/third_party/mbedtls/hardware_entropy.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Nest Labs Inc. All Rights Reserved. + * Copyright 2016 The OpenThread Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.