[efr32] Silabs EFR32MG1 Platform Support (#5191)

This adds platform support for Silabs EFR32MG1 (series1 Mighty Gecko
with 32K RAM + 64K flash).

A few notes on this commit:

- MG1 cannot fit FTD builds with certain options enabled (like
  diagnostics). In testing, I simply removed FTD from build
  options. We may want to add this to README

- Most platform files are directly duplicated from MG12

- Only created BRD4151A reference. Suspect Silabs team will want to
  add other reference platforms like Thunderboard 1

- Should include latest crypto acceleration changes made by Silabs
  team

- This has been tested using RCP and CLI builds both on BRD4151A WSTK
  and a custom design based on MG1.
diff --git a/configure.ac b/configure.ac
index f91bea9..7ae375e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -780,7 +780,7 @@
 
 AC_ARG_WITH(examples,
     [AS_HELP_STRING([--with-examples=TARGET],
-        [Build example applications for one of: simulation, cc1352, cc2538, cc2650, cc2652, efr32mg12, efr32mg13, efr32mg21,
+        [Build example applications for one of: simulation, cc1352, cc2538, cc2650, cc2652, efr32mg1, efr32mg12, efr32mg13, efr32mg21,
          gp712, jn5189, k32w061, kw41z, nrf52811, nrf52833, nrf52840, qpg6095, samr21 @<:@default=no@:>@.
          Note that building example applications also builds the associated OpenThread platform libraries
          and any third_party libraries needed to support the examples.])],
@@ -788,7 +788,7 @@
         case "${with_examples}" in
         no)
             ;;
-        simulation|cc1352|cc2538|cc2650|cc2652|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|k32w061|kw41z|nrf52811|nrf52833|nrf52840|qpg6095|samr21)
+        simulation|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|k32w061|kw41z|nrf52811|nrf52833|nrf52840|qpg6095|samr21)
             ;;
         *)
             AC_MSG_RESULT(ERROR)
@@ -805,6 +805,7 @@
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC2538],    [test "${with_examples}" = "cc2538"])
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC2650],    [test "${with_examples}" = "cc2650"])
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_CC2652],    [test "${with_examples}" = "cc2652"])
+AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32MG1],  [test "${with_examples}" = "efr32mg1"])
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32MG12], [test "${with_examples}" = "efr32mg12"])
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32MG13], [test "${with_examples}" = "efr32mg13"])
 AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32MG21], [test "${with_examples}" = "efr32mg21"])
@@ -840,11 +841,11 @@
 AC_ARG_WITH(platform,
     [AS_HELP_STRING([--with-platform=TARGET],
         [Build OpenThread platform libraries for one of: cc1352, cc2538, cc2650, cc2652,
-         efr32mg12, efr32mg13, efr32mg21, gp712, jn5189, kw41z, nrf52811, nrf52833, nrf52840, posix, qpg6095, samr21, simulation @<:@default=simulation@:>@.])],
+         efr32mg1, efr32mg12, efr32mg13, efr32mg21, gp712, jn5189, kw41z, nrf52811, nrf52833, nrf52840, posix, qpg6095, samr21, simulation @<:@default=simulation@:>@.])],
     [
         # Make sure the given target is valid.
         case "${with_platform}" in
-        no|cc1352|cc2538|cc2650|cc2652|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|kw41z|nrf52811|nrf52833|nrf52840|posix|qpg6095|samr21|simulation)
+        no|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|kw41z|nrf52811|nrf52833|nrf52840|posix|qpg6095|samr21|simulation)
             ;;
         *)
             AC_MSG_RESULT(ERROR)
@@ -879,6 +880,7 @@
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_CC2538],    [test "${with_platform}" = "cc2538"])
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_CC2650],    [test "${with_platform}" = "cc2650"])
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_CC2652],    [test "${with_platform}" = "cc2652"])
+AM_CONDITIONAL([OPENTHREAD_PLATFORM_EFR32MG1],  [test "${with_platform}" = "efr32mg1"])
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_EFR32MG12], [test "${with_platform}" = "efr32mg12"])
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_EFR32MG13], [test "${with_platform}" = "efr32mg13"])
 AM_CONDITIONAL([OPENTHREAD_PLATFORM_EFR32MG21], [test "${with_platform}" = "efr32mg21"])
@@ -1038,6 +1040,7 @@
 examples/platforms/cc2538/Makefile
 examples/platforms/cc2650/Makefile
 examples/platforms/cc2652/Makefile
+examples/platforms/efr32mg1/Makefile
 examples/platforms/efr32mg12/Makefile
 examples/platforms/efr32mg12/sleepy-demo/Makefile
 examples/platforms/efr32mg12/sleepy-demo/sleepy-demo-ftd/Makefile
diff --git a/examples/Makefile-efr32mg1 b/examples/Makefile-efr32mg1
new file mode 100644
index 0000000..b46ca84
--- /dev/null
+++ b/examples/Makefile-efr32mg1
@@ -0,0 +1,309 @@
+#
+#  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-ncp                  \
+    --enable-radio-only           \
+    --enable-linker-map           \
+    --with-examples=efr32mg1      \
+    MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)" \
+    $(NULL)
+
+ifneq ($(DISABLE_BUILTIN_MBEDTLS), 1)
+configure_OPTIONS              += MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)"
+endif
+
+TopSourceDir                    := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
+AbsTopSourceDir                 := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
+
+
+#
+# Differentiate between boards
+#
+ifeq ($(BOARD),BRD4151A)
+MCU = EFR32MG1P232F256GM48
+else
+$(error Please provide a value for BOARD variable e.g BOARD= BRD4151A (currently supported BRD4151A))
+endif
+
+EFR32_MBEDTLS_CPPFLAGS  = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'
+EFR32_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"efr32-mbedtls-config.h\"'
+EFR32_MBEDTLS_CPPFLAGS += -D$(MCU)
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32mg1/crypto
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/util/third_party/mbedtls/configs
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/CMSIS/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/util/third_party/mbedtls/sl_crypto/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/Device/SiliconLabs/EFR32MG1P/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/emlib/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/radio/rail_lib/chip/efr32/efr32xg1x
+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_PATH = $(AbsTopSourceDir)/examples/platforms/efr32mg1/
+HAL_CONF_DIR     = $(CONFIG_FILE_PATH)/$(shell echo $(BOARD) | tr A-Z a-z)
+
+EFR32MG1_CONFIG_FILE_CPPFLAGS  = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-efr32-config.h\"'
+EFR32MG1_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-efr32-config-check.h\"'
+EFR32MG1_CONFIG_FILE_CPPFLAGS += -I$(CONFIG_FILE_PATH)
+
+COMMONCFLAGS                       := \
+    -fdata-sections                   \
+    -ffunction-sections               \
+    -Os                               \
+    -g                                \
+    -I$(HAL_CONF_DIR)                 \
+    -D__START=main                    \
+    -D$(MCU)                          \
+    $(EFR32MG1_CONFIG_FILE_CPPFLAGS)  \
+    $(NULL)
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
+
+#
+# Platform-Specific switches
+#
+
+DMP                            ?= 0
+RADIODEBUG                     ?= 0
+
+ifeq ($(DMP),1)
+COMMONCFLAGS                   += -DRADIO_CONFIG_DMP_SUPPORT=1
+endif
+
+ifeq ($(RADIODEBUG),1)
+COMMONCFLAGS                   += -DRADIO_CONFIG_DEBUG_COUNTERS_SUPPORT=1
+endif
+
+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             \
+    $(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                     = efr32mg1
+
+ARCHS                           = cortex-m4
+
+TopTargetLibDir                 = $(TopResultDir)/$(TargetTuple)/lib
+
+ifndef BuildJobs
+BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
+endif
+JOBSFLAG := -j$(BuildJobs)
+
+#
+# configure-arch <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 <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 <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 <arch>
+#
+# 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)) <architecture>"
+	$(ECHO) ""
diff --git a/examples/platforms/Makefile.am b/examples/platforms/Makefile.am
index 395c68a..a479ede 100644
--- a/examples/platforms/Makefile.am
+++ b/examples/platforms/Makefile.am
@@ -35,6 +35,7 @@
     cc2538                                \
     cc2650                                \
     cc2652                                \
+    efr32mg1    			  \
     efr32mg12                             \
     efr32mg13                             \
     efr32mg21                             \
@@ -70,6 +71,10 @@
 SUBDIRS                                += cc2652
 endif
 
+if OPENTHREAD_PLATFORM_EFR32MG1
+SUBDIRS                                += efr32mg1
+endif
+
 if OPENTHREAD_PLATFORM_EFR32MG12
 SUBDIRS                                += efr32mg12
 endif
diff --git a/examples/platforms/Makefile.platform.am b/examples/platforms/Makefile.platform.am
index a5f89be..4ced649 100644
--- a/examples/platforms/Makefile.platform.am
+++ b/examples/platforms/Makefile.platform.am
@@ -57,6 +57,10 @@
 include $(top_srcdir)/examples/platforms/cc2652/Makefile.platform.am
 endif
 
+if OPENTHREAD_EXAMPLES_EFR32MG1
+include $(top_srcdir)/examples/platforms/efr32mg1/Makefile.platform.am
+endif
+
 if OPENTHREAD_EXAMPLES_EFR32MG12
 include $(top_srcdir)/examples/platforms/efr32mg12/Makefile.platform.am
 endif
diff --git a/examples/platforms/efr32mg1/Makefile.am b/examples/platforms/efr32mg1/Makefile.am
new file mode 100644
index 0000000..c50b01a
--- /dev/null
+++ b/examples/platforms/efr32mg1/Makefile.am
@@ -0,0 +1,140 @@
+#
+#  Copyright (c) 2020, 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-efr32mg1.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))
+
+# Do not enable -Wundef for rail
+override CFLAGS   := $(filter-out -Wundef,$(CFLAGS))
+override CXXFLAGS := $(filter-out -Wundef,$(CXXFLAGS))
+
+EFR32_BOARD_DIR = $(shell echo $(BOARD) | tr A-Z a-z)
+
+SDK_SRC_DIR = $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v2.7
+
+libopenthread_efr32mg1_a_CPPFLAGS                                             = \
+    -DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\"       \
+    -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\"      \
+    -Wno-sign-compare                                                           \
+    -DCORTEXM3                                                                  \
+    -DPHY=EMBER_PHY_RAIL                                                        \
+    -DMICRO=EMBER_MICRO_CORTEXM3_EFR32                                          \
+    -DCORTEXM3_EFM32_MICRO                                                      \
+    -DPLAT=EMBER_PLATFORM_CORTEXM3                                              \
+    -I$(top_srcdir)/examples/platforms                                          \
+    -I$(top_srcdir)/examples/platforms/efr32mg1/$(EFR32_BOARD_DIR)              \
+    -I$(top_srcdir)/include                                                     \
+    -I$(top_srcdir)/src/core                                                    \
+    -I$(top_srcdir)/third_party/silabs/rail_config                              \
+    -I$(SDK_SRC_DIR)                                                            \
+    -I$(SDK_SRC_DIR)/hardware/kit/common/bsp                                    \
+    -I$(SDK_SRC_DIR)/hardware/kit/common/drivers                                \
+    -I$(SDK_SRC_DIR)/hardware/kit/EFR32MG1_$(BOARD)/config                      \
+    -I$(SDK_SRC_DIR)/platform/base/hal/micro/cortexm3/efm32                     \
+    -I$(SDK_SRC_DIR)/platform/base/hal/micro/cortexm3/efm32/config              \
+    -I$(SDK_SRC_DIR)/platform/bootloader/api                                    \
+    -I$(SDK_SRC_DIR)/platform/common/inc                                        \
+    -I$(SDK_SRC_DIR)/platform/CMSIS/Include                                     \
+    -I$(SDK_SRC_DIR)/platform/Device/SiliconLabs/EFR32MG1P/Include              \
+    -I$(SDK_SRC_DIR)/platform/emdrv/common/inc                                  \
+    -I$(SDK_SRC_DIR)/platform/emdrv/gpiointerrupt/inc                           \
+    -I$(SDK_SRC_DIR)/platform/emdrv/uartdrv/inc                                 \
+    -I$(SDK_SRC_DIR)/platform/emdrv/uartdrv/config                              \
+    -I$(SDK_SRC_DIR)/platform/emdrv/ustimer/inc                                 \
+    -I$(SDK_SRC_DIR)/platform/emdrv/dmadrv/inc                                  \
+    -I$(SDK_SRC_DIR)/platform/emdrv/dmadrv/config                               \
+    -I$(SDK_SRC_DIR)/platform/emdrv/nvm3/inc                                    \
+    -I$(SDK_SRC_DIR)/platform/emdrv/nvm3/config                                 \
+    -I$(SDK_SRC_DIR)/platform/emlib/inc                                         \
+    -I$(SDK_SRC_DIR)/platform/halconfig/inc/hal-config                          \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32                         \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32/efr32xg1x               \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32/rf/common/cortex        \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/common                             \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/hal                                \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/hal/efr32                          \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/protocol/ieee802154                \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/plugin/pa-conversions              \
+    -I$(SDK_SRC_DIR)/platform/service/mpu/inc                                   \
+    -I$(SDK_SRC_DIR)/platform/service/sleeptimer/config                         \
+    -I$(SDK_SRC_DIR)/platform/service/sleeptimer/inc                            \
+    -I$(SDK_SRC_DIR)/util/plugin/plugin-common/fem-control                      \
+    -I$(SDK_SRC_DIR)/util/third_party/mbedtls/sl_crypto/include                 \
+    -Wno-unused-parameter                                                       \
+    -Wno-missing-field-initializers                                             \
+    $(NULL)
+
+PLATFORM_SOURCES                                                              = \
+    alarm.c                                                                     \
+    diag.c                                                                      \
+    entropy.c                                                                   \
+    fem-control.c                                                               \
+    flash.c                                                                     \
+    logging.c                                                                   \
+    misc.c                                                                      \
+    openthread-core-efr32-config.h                                              \
+    openthread-core-efr32-config-check.h                                        \
+    platform-efr32.h                                                            \
+    platform-band.h                                                             \
+    radio.c                                                                     \
+    rail_config.h                                                               \
+    startup-gcc.c                                                               \
+    system.c                                                                    \
+    uart.c                                                                      \
+    $(NULL)
+
+noinst_HEADERS                                                                = \
+    platform-efr32.h                                                            \
+    platform-band.h                                                             \
+    $(NULL)
+
+libopenthread_efr32mg1_a_SOURCES                                              = \
+    $(PLATFORM_SOURCES)                                                         \
+    $(NULL)
+
+Dash = -
+libopenthread_efr32mg1_a_LIBADD                                                                      = \
+    $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")             \
+    $(shell find $(top_builddir)/third_party/jlink/SEGGER_RTT_V640/RTT $(Dash)type f $(Dash)name "*.o")
+
+DIST_SUBDIRS                                                                  = \
+    $(NULL)
+
+SUBDIRS                                                                       = \
+    $(NULL)
+
+include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/examples/platforms/efr32mg1/Makefile.platform.am b/examples/platforms/efr32mg1/Makefile.platform.am
new file mode 100644
index 0000000..d7920a8
--- /dev/null
+++ b/examples/platforms/efr32mg1/Makefile.platform.am
@@ -0,0 +1,49 @@
+#
+#  Copyright (c) 2020, 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.
+#
+
+#
+# efr32mg1 platform-specific Makefile
+#
+
+LIBRAIL = $(shell                                                                \
+if [ "$(DMP)" = "1" ]; then                                                      \
+    echo "librail_multiprotocol_efr32xg1_gcc_release.a";                         \
+else                                                                             \
+    echo "librail_efr32xg1_gcc_release.a";                                       \
+fi )
+
+LDADD_COMMON                                                                  += \
+    $(top_builddir)/examples/platforms/efr32mg1/libopenthread-efr32mg1.a         \
+    $(top_builddir)/third_party/silabs/libsilabs-efr32mg1-sdk.a                  \
+    $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/radio/rail_lib/autogen/librail_release/$(LIBRAIL) \
+    $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v2.7/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
+    $(NULL)
+
+LDFLAGS_COMMON                                                                += \
+    -T $(top_srcdir)/examples/platforms/efr32mg1/efr32mg1.ld                     \
+    $(NULL)
diff --git a/examples/platforms/efr32mg1/README.md b/examples/platforms/efr32mg1/README.md
new file mode 100644
index 0000000..4994495
--- /dev/null
+++ b/examples/platforms/efr32mg1/README.md
@@ -0,0 +1,242 @@
+# OpenThread on EFR32MG1P Example
+
+This directory contains example platform drivers for the [Silicon Labs EFR32MG1P][efr32mg1p] 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. [EFR32MG1P SoC][efr32mg1p] has rich memory and peripheral resources which can support all OpenThread capabilities. See the "Run the example with EFR32MG1 boards" section below for an example using basic OpenThread capabilities.
+
+## Toolchain
+
+Download and install the [GNU toolchain for ARM Cortex-M][gnu-toolchain].
+
+[gnu-toolchain]: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm
+
+In a Bash terminal, follow these instructions to install the GNU toolchain and other dependencies.
+
+```bash
+$ cd <path-to-openthread>
+$ ./script/bootstrap
+```
+
+## 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 EFR32MG1P Wireless Starter Kit to Simplicity Studio.
+   - Find Flex SDK v2.7 in the Software Update page and click Install.
+   - Flex SDK v2.7 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 FLEX, see [Getting Started with the Silicon Labs Flex Software Development Kit for the Wireless Gecko (EFR32™) Portfolio][qsg138]. For more information on RAIL, see [Radio Abstraction Interface Layer][rail].
+
+[qsg138]: https://www.silabs.com/documents/public/quick-start-guides/qsg138-flex-efr32.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 <path-to-openthread>/third_party
+$ mkdir silabs
+$ cd <path-to-Simplicity-Studio>/developer/sdks
+$ cp -rf gecko_sdk_suite <path-to-openthread>/third_party/silabs/
+```
+
+Alternatively create a symbolic link to the Flex SDK source code.
+
+```bash
+$ cd <path-to-openthread>/third_party
+$ mkdir silabs
+$ ln -s <path-to-Simplicity-Studio>/developer/sdks/gecko_sdk_suite silabs/gecko_sdk_suite
+```
+
+4. Build OpenThread Firmware (CLI example) on EFR32 platform.
+
+```bash
+$ cd <path-to-openthread>
+$ ./bootstrap
+```
+
+For EFR32MG1™ Mighty Gecko Wireless Starter Kit:
+
+```bash
+$ make -f examples/Makefile-efr32mg1 BOARD=BRD4151A
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/output/efr32mg1/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 <path-to-JLinkGDBServer>
+$ sudo ./JLinkGDBServer -if swd -device EFR32MG1PxxxF256
+$ cd <path-to-openthread>/output/efr32mg1/bin
+$ arm-none-eabi-gdb ot-cli-ftd
+$ (gdb) target remote 127.0.0.1:2331
+$ (gdb) load
+$ (gdb) monitor reset
+$ (gdb) c
+```
+
+Or Compiled binaries also may be flashed onto the specified EFR32 dev board using [J-Link Commander][j-link-commander].
+
+[j-link-commander]: https://www.segger.com/products/debug-probes/j-link/tools/j-link-commander/
+
+```bash
+$ cd <path-to-openthread>/output/efr32mg1/bin
+$ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex
+$ JLinkExe -device EFR32MG1PxxxF256 -speed 4000 -if SWD -autoconnect 1 -SelectEmuBySN <SerialNo>
+$ J-Link>loadfile ot-cli-ftd.hex
+$ J-Link>r
+$ J-Link>q
+```
+
+Note: SerialNo is J-Link serial number. Use the following command to get the serial number of the connected J-Link.
+
+```bash
+$ JLinkExe
+```
+
+Alternatively Simplicity Commander provides a graphical interface for J-Link Commander.
+
+```bash
+$ cd <path-to-openthread>/output/efr32mg1/bin
+$ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.ihex
+$ <path-to-simplicity-studio>/developer/adapter_packs/commander/commander
+```
+
+In the J-Link Device drop-down list select the serial number of the device to flash. Click the Adapter Connect button. Esnure the Debug Interface drop-down list is set to SWD and click the Target Connect button. Click on the Flash icon on the left side of the window to switch to the flash page. In the Flash MCU pane enter the path of the ot-cli-ftd.s37 file or choose the file with the Browse... button. Click the Flash button located under the Browse... button.
+
+## Run the example with EFR32MG1 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
+   > dataset init new
+   Done
+   > dataset
+   Active Timestamp: 1
+   Channel: 13
+   Channel Mask: 07fff800
+   Ext PAN ID: d63e8e3e495ebbc3
+   Mesh Local Prefix: fd3d:b50b:f96d:722d/64
+   Master Key: dfd34f0f05cad978ec4e32b0413038ff
+   Network Name: OpenThread-8f28
+   PAN ID: 0x8f28
+   PSKc: c23a76e98f1a6483639b1ac1271e2e27
+   Security Policy: 0, onrcb
+   Done
+   > dataset commit active
+   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
+   > dataset masterkey dfd34f0f05cad978ec4e32b0413038ff
+   Done
+   > dataset commit active
+   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
+   fd3d:b50b:f96d:722d:0:ff:fe00:fc00
+   fd3d:b50b:f96d:722d:0:ff:fe00:c00
+   fd3d:b50b:f96d:722d:7a73:bff6:9093:9117
+   fe80:0:0:0:6c41:9001:f3d6:4148
+   Done
+   ```
+
+6. Send an ICMPv6 ping to Leader's Mesh-EID IPv6 address.
+
+   ```bash
+   > ping fd3d:b50b:f96d:722d:7a73:bff6:9093:9117
+   16 bytes from fd3d:b50b:f96d:722d:558:f56b:d688:799: 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 <path-to-openthread>
+$ ./bootstrap
+$ make -f examples/Makefile-efr32mg1 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 7.3.1
+
+The EFR32 example has been verified with following Flex SDK/RAIL Library version:
+
+- Flex SDK version 2.7.0.0
diff --git a/examples/platforms/efr32mg1/alarm.c b/examples/platforms/efr32mg1/alarm.c
new file mode 100644
index 0000000..71a39c0
--- /dev/null
+++ b/examples/platforms/efr32mg1/alarm.c
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (c) 2020, 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 <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "openthread-system.h"
+#include <openthread/config.h>
+#include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/diag.h>
+#include "common/logging.hpp"
+
+#include "platform-efr32.h"
+#include "utils/code_utils.h"
+
+#include "em_core.h"
+#include "rail.h"
+#include "sl_sleeptimer.h"
+
+#define XTAL_ACCURACY 200
+
+static sl_sleeptimer_timer_handle_t sl_handle;
+static uint32_t                     sAlarm     = 0;
+static bool                         sIsRunning = false;
+
+static void AlarmCallback(sl_sleeptimer_timer_handle_t *aHandle, void *aData)
+{
+    otSysEventSignalPending();
+}
+
+void efr32AlarmInit(void)
+{
+    memset(&sl_handle, 0, sizeof sl_handle);
+}
+
+uint32_t otPlatAlarmMilliGetNow(void)
+{
+    uint64_t    ticks;
+    uint64_t    now;
+    sl_status_t status;
+
+    ticks  = sl_sleeptimer_get_tick_count64();
+    status = sl_sleeptimer_tick64_to_ms(ticks, &now);
+    assert(status == SL_STATUS_OK);
+    return (uint32_t)now;
+}
+
+uint32_t otPlatTimeGetXtalAccuracy(void)
+{
+    return XTAL_ACCURACY;
+}
+
+void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    sl_status_t status;
+    int32_t     remaining;
+    uint32_t    ticks;
+
+    sl_sleeptimer_stop_timer(&sl_handle);
+
+    sAlarm     = aT0 + aDt;
+    remaining  = (int32_t)(sAlarm - otPlatAlarmMilliGetNow());
+    sIsRunning = true;
+
+    if (remaining <= 0)
+    {
+        otSysEventSignalPending();
+    }
+    else
+    {
+        status = sl_sleeptimer_ms32_to_tick(remaining, &ticks);
+        assert(status == SL_STATUS_OK);
+
+        status = sl_sleeptimer_start_timer(&sl_handle, ticks, AlarmCallback, NULL, 0,
+                                           SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG);
+        assert(status == SL_STATUS_OK);
+    }
+}
+
+void otPlatAlarmMilliStop(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    sl_sleeptimer_stop_timer(&sl_handle);
+    sIsRunning = false;
+}
+
+void efr32AlarmProcess(otInstance *aInstance)
+{
+    int32_t remaining;
+
+    if (sIsRunning)
+    {
+        remaining = (int32_t)(sAlarm - otPlatAlarmMilliGetNow());
+
+        if (remaining <= 0)
+        {
+            sIsRunning = false;
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+            if (otPlatDiagModeGet())
+            {
+                otPlatDiagAlarmFired(aInstance);
+            }
+            else
+#endif
+            {
+                otPlatAlarmMilliFired(aInstance);
+            }
+        }
+    }
+}
diff --git a/examples/platforms/efr32mg1/brd4151a/board_config.h b/examples/platforms/efr32mg1/brd4151a/board_config.h
new file mode 100644
index 0000000..d798d52
--- /dev/null
+++ b/examples/platforms/efr32mg1/brd4151a/board_config.h
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2018, 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 dev borad compile-time configuration constants for efr32.
+ *
+ */
+
+#ifndef __BOARD_CONFIG_H__
+#define __BOARD_CONFIG_H__
+
+#define RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT 1 /// Dev board suppports OQPSK modulation in 2.4GHz band.
+#define RADIO_CONFIG_915MHZ_OQPSK_SUPPORT 0 /// Dev board doesn't support OQPSK modulation in 915MHz band.
+
+#ifndef RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+#define RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT 0 /// Set to 1 to enable debug counters in radio.c
+#endif
+
+#ifndef RADIO_CONFIG_DMP_SUPPORT
+#define RADIO_CONFIG_DMP_SUPPORT 0 /// Set to 1 to enable Dynamic Multi-Protocol support in radio.c
+#endif
+
+#define RADIO_CONFIG_PA_USES_DCDC 0 /// The PA(s) is(are) fed from VBAT
+
+#endif // __BOARD_CONFIG_H__
diff --git a/examples/platforms/efr32mg1/brd4151a/hal-config.h b/examples/platforms/efr32mg1/brd4151a/hal-config.h
new file mode 100644
index 0000000..24a9a5e
--- /dev/null
+++ b/examples/platforms/efr32mg1/brd4151a/hal-config.h
@@ -0,0 +1,407 @@
+#ifndef HAL_CONFIG_H
+#define HAL_CONFIG_H
+
+#include "em_device.h"
+#include "hal-config-types.h"
+
+// This file is auto-generated by Hardware Configurator in Simplicity Studio.
+// Any content between $[ and ]$ will be replaced whenever the file is regenerated.
+// Content outside these regions will be preserved.
+
+// $[ACMP0]
+// [ACMP0]$
+
+// $[ACMP1]
+// [ACMP1]$
+
+// $[ADC0]
+// [ADC0]$
+
+// $[ANTDIV]
+// [ANTDIV]$
+
+// $[BATTERYMON]
+// [BATTERYMON]$
+
+// $[BTL_BUTTON]
+// [BTL_BUTTON]$
+
+// $[BULBPWM]
+// [BULBPWM]$
+
+// $[BULBPWM_COLOR]
+// [BULBPWM_COLOR]$
+
+// $[BUTTON]
+#define BSP_BUTTON_PRESENT (1)
+
+#define BSP_BUTTON0_PIN (6U)
+#define BSP_BUTTON0_PORT (gpioPortF)
+
+#define BSP_BUTTON1_PIN (7U)
+#define BSP_BUTTON1_PORT (gpioPortF)
+
+#define BSP_BUTTON_COUNT (2U)
+#define BSP_BUTTON_INIT                                                            \
+    {                                                                              \
+        {BSP_BUTTON0_PORT, BSP_BUTTON0_PIN}, { BSP_BUTTON1_PORT, BSP_BUTTON1_PIN } \
+    }
+#define BSP_BUTTON_GPIO_DOUT (HAL_GPIO_DOUT_LOW)
+#define BSP_BUTTON_GPIO_MODE (HAL_GPIO_MODE_INPUT)
+// [BUTTON]$
+
+// $[CMU]
+#define HAL_CLK_HFCLK_SOURCE (HAL_CLK_HFCLK_SOURCE_HFXO)
+#define HAL_CLK_LFECLK_SOURCE (HAL_CLK_LFCLK_SOURCE_LFRCO)
+#define HAL_CLK_LFBCLK_SOURCE (HAL_CLK_LFCLK_SOURCE_LFRCO)
+#define BSP_CLK_LFXO_PRESENT (1)
+#define BSP_CLK_HFXO_PRESENT (1)
+#define BSP_CLK_LFXO_INIT CMU_LFXOINIT_DEFAULT
+#define BSP_CLK_LFXO_CTUNE (0)
+#define BSP_CLK_LFXO_FREQ (32768U)
+#define HAL_CLK_LFACLK_SOURCE (HAL_CLK_LFCLK_SOURCE_LFRCO)
+#define BSP_CLK_HFXO_FREQ (38400000UL)
+#define BSP_CLK_HFXO_CTUNE (338)
+#define BSP_CLK_HFXO_INIT CMU_HFXOINIT_DEFAULT
+#define BSP_CLK_HFXO_CTUNE_TOKEN (0)
+#define HAL_CLK_HFXO_AUTOSTART (HAL_CLK_HFXO_AUTOSTART_NONE)
+// [CMU]$
+
+// $[COEX]
+// [COEX]$
+
+// $[CS5463]
+// [CS5463]$
+
+// $[CSEN0]
+// [CSEN0]$
+
+// $[DCDC]
+#define BSP_DCDC_PRESENT (1)
+
+#define HAL_DCDC_BYPASS (0)
+#define BSP_DCDC_INIT EMU_DCDCINIT_DEFAULT
+// [DCDC]$
+
+// $[EMU]
+// [EMU]$
+
+// $[EXTFLASH]
+// [EXTFLASH]$
+
+// $[EZRADIOPRO]
+// [EZRADIOPRO]$
+
+// $[GPIO]
+#define PORTIO_GPIO_SWCLKTCK_PIN (0)
+#define PORTIO_GPIO_SWCLKTCK_PORT (gpioPortF)
+#define PORTIO_GPIO_DBGROUTE_LOC (0)
+
+#define PORTIO_GPIO_SWDIOTMS_PIN (1)
+#define PORTIO_GPIO_SWDIOTMS_PORT (gpioPortF)
+
+#define PORTIO_GPIO_SWV_PIN (2)
+#define PORTIO_GPIO_SWV_PORT (gpioPortF)
+#define PORTIO_GPIO_SWV_LOC (0)
+
+#define PORTIO_GPIO_TCLK_PIN (8)
+#define PORTIO_GPIO_TCLK_PORT (gpioPortF)
+#define PORTIO_GPIO_TCLK_LOC (0)
+
+#define PORTIO_GPIO_TD0_PIN (9)
+#define PORTIO_GPIO_TD0_PORT (gpioPortF)
+#define PORTIO_GPIO_TD0_LOC (0)
+
+#define PORTIO_GPIO_TD1_PIN (10)
+#define PORTIO_GPIO_TD1_PORT (gpioPortF)
+#define PORTIO_GPIO_TD1_LOC (0)
+
+#define PORTIO_GPIO_TD2_PIN (11)
+#define PORTIO_GPIO_TD2_PORT (gpioPortF)
+#define PORTIO_GPIO_TD2_LOC (0)
+
+#define PORTIO_GPIO_TD3_PIN (12)
+#define PORTIO_GPIO_TD3_PORT (gpioPortF)
+#define PORTIO_GPIO_TD3_LOC (0)
+
+// [GPIO]$
+
+// $[I2C0]
+#define PORTIO_I2C0_SCL_PIN (10)
+#define PORTIO_I2C0_SCL_PORT (gpioPortC)
+#define PORTIO_I2C0_SCL_LOC (14)
+
+#define PORTIO_I2C0_SDA_PIN (11)
+#define PORTIO_I2C0_SDA_PORT (gpioPortC)
+#define PORTIO_I2C0_SDA_LOC (16)
+
+// [I2C0]$
+
+// $[I2C1]
+// [I2C1]$
+
+// $[I2CSENSOR]
+// [I2CSENSOR]$
+
+// $[IDAC0]
+// [IDAC0]$
+
+// $[IOEXP]
+// [IOEXP]$
+
+// $[LED]
+#define BSP_LED_PRESENT (1)
+
+#define BSP_LED0_PIN (4)
+#define BSP_LED0_PORT (gpioPortF)
+
+#define BSP_LED1_PIN (5)
+#define BSP_LED1_PORT (gpioPortF)
+
+#define HAL_LED_ENABLE \
+    {                  \
+        0, 1           \
+    }
+#define HAL_LED_COUNT (2)
+#define BSP_LED_COUNT (2)
+#define BSP_LED_INIT                                                   \
+    {                                                                  \
+        {BSP_LED0_PORT, BSP_LED0_PIN}, { BSP_LED1_PORT, BSP_LED1_PIN } \
+    }
+// [LED]$
+
+// $[LESENSE]
+// [LESENSE]$
+
+// $[LETIMER0]
+// [LETIMER0]$
+
+// $[LEUART0]
+// [LEUART0]$
+
+// $[LFXO]
+// [LFXO]$
+
+// $[LNA]
+// [LNA]$
+
+// $[PA]
+#define HAL_PA_ENABLE (1)
+
+#define HAL_PA_RAMP (10)
+#define HAL_PA_2P4_LOWPOWER (0)
+#define HAL_PA_POWER (252)
+#define HAL_PA_VOLTAGE (3300)
+#define HAL_PA_CURVE_HEADER "pa_curves_efr32.h"
+// [PA]$
+
+// $[PCNT0]
+// [PCNT0]$
+
+// $[PCNT1]
+// [PCNT1]$
+
+// $[PCNT2]
+// [PCNT2]$
+
+// $[PORTIO]
+// [PORTIO]$
+
+// $[PRS]
+#define PORTIO_PRS_CH4_PIN (13)
+#define PORTIO_PRS_CH4_PORT (gpioPortD)
+#define PORTIO_PRS_CH4_LOC (4)
+
+// [PRS]$
+
+// $[PTI]
+#define PORTIO_PTI_DFRAME_PIN (13)
+#define PORTIO_PTI_DFRAME_PORT (gpioPortB)
+#define PORTIO_PTI_DFRAME_LOC (6)
+
+#define PORTIO_PTI_DOUT_PIN (12)
+#define PORTIO_PTI_DOUT_PORT (gpioPortB)
+#define PORTIO_PTI_DOUT_LOC (6)
+
+#define HAL_PTI_ENABLE (1)
+
+#define BSP_PTI_DFRAME_PIN (13)
+#define BSP_PTI_DFRAME_PORT (gpioPortB)
+#define BSP_PTI_DFRAME_LOC (6)
+
+#define BSP_PTI_DOUT_PIN (12)
+#define BSP_PTI_DOUT_PORT (gpioPortB)
+#define BSP_PTI_DOUT_LOC (6)
+
+#define HAL_PTI_MODE (HAL_PTI_MODE_UART)
+#define HAL_PTI_BAUD_RATE (1600000)
+// [PTI]$
+
+// $[PYD1698]
+// [PYD1698]$
+
+// $[SERIAL]
+#define HAL_SERIAL_USART0_ENABLE (0)
+#define HAL_SERIAL_LEUART0_ENABLE (0)
+#define HAL_SERIAL_USART1_ENABLE (0)
+#define HAL_SERIAL_USART2_ENABLE (0)
+#define HAL_SERIAL_USART3_ENABLE (0)
+#define HAL_SERIAL_RXWAKE_ENABLE (0)
+#define BSP_SERIAL_APP_CTS_PIN (2)
+#define BSP_SERIAL_APP_CTS_PORT (gpioPortA)
+#define BSP_SERIAL_APP_CTS_LOC (30)
+
+#define BSP_SERIAL_APP_RX_PIN (1)
+#define BSP_SERIAL_APP_RX_PORT (gpioPortA)
+#define BSP_SERIAL_APP_RX_LOC (0)
+
+#define BSP_SERIAL_APP_TX_PIN (0)
+#define BSP_SERIAL_APP_TX_PORT (gpioPortA)
+#define BSP_SERIAL_APP_TX_LOC (0)
+
+#define BSP_SERIAL_APP_RTS_PIN (3)
+#define BSP_SERIAL_APP_RTS_PORT (gpioPortA)
+#define BSP_SERIAL_APP_RTS_LOC (30)
+
+#define HAL_SERIAL_APP_RX_QUEUE_SIZE (128)
+#define HAL_SERIAL_APP_BAUD_RATE (115200)
+#define HAL_SERIAL_APP_RXSTOP (16)
+#define HAL_SERIAL_APP_RXSTART (16)
+#define HAL_SERIAL_APP_TX_QUEUE_SIZE (128)
+#define HAL_SERIAL_APP_FLOW_CONTROL (HAL_USART_FLOW_CONTROL_HWUART)
+// [SERIAL]$
+
+// $[SPIDISPLAY]
+// [SPIDISPLAY]$
+
+// $[SPINCP]
+// [SPINCP]$
+
+// $[TIMER0]
+// [TIMER0]$
+
+// $[TIMER1]
+// [TIMER1]$
+
+// $[UARTNCP]
+// [UARTNCP]$
+
+// $[USART0]
+#define PORTIO_USART0_CTS_PIN (2)
+#define PORTIO_USART0_CTS_PORT (gpioPortA)
+#define PORTIO_USART0_CTS_LOC (30)
+
+#define PORTIO_USART0_RTS_PIN (3)
+#define PORTIO_USART0_RTS_PORT (gpioPortA)
+#define PORTIO_USART0_RTS_LOC (30)
+
+#define PORTIO_USART0_RX_PIN (1)
+#define PORTIO_USART0_RX_PORT (gpioPortA)
+#define PORTIO_USART0_RX_LOC (0)
+
+#define PORTIO_USART0_TX_PIN (0)
+#define PORTIO_USART0_TX_PORT (gpioPortA)
+#define PORTIO_USART0_TX_LOC (0)
+
+#define HAL_USART0_ENABLE (1)
+
+#define BSP_USART0_CTS_PIN (2)
+#define BSP_USART0_CTS_PORT (gpioPortA)
+#define BSP_USART0_CTS_LOC (30)
+
+#define BSP_USART0_RX_PIN (1)
+#define BSP_USART0_RX_PORT (gpioPortA)
+#define BSP_USART0_RX_LOC (0)
+
+#define BSP_USART0_TX_PIN (0)
+#define BSP_USART0_TX_PORT (gpioPortA)
+#define BSP_USART0_TX_LOC (0)
+
+#define BSP_USART0_RTS_PIN (3)
+#define BSP_USART0_RTS_PORT (gpioPortA)
+#define BSP_USART0_RTS_LOC (30)
+
+#define HAL_USART0_RX_QUEUE_SIZE (128)
+#define HAL_USART0_BAUD_RATE (115200)
+#define HAL_USART0_RXSTOP (16)
+#define HAL_USART0_RXSTART (16)
+#define HAL_USART0_TX_QUEUE_SIZE (128)
+#define HAL_USART0_FLOW_CONTROL (HAL_USART_FLOW_CONTROL_NONE)
+// [USART0]$
+
+// $[USART1]
+#define PORTIO_USART1_CLK_PIN (8)
+#define PORTIO_USART1_CLK_PORT (gpioPortC)
+#define PORTIO_USART1_CLK_LOC (11)
+
+#define PORTIO_USART1_CS_PIN (9)
+#define PORTIO_USART1_CS_PORT (gpioPortC)
+#define PORTIO_USART1_CS_LOC (11)
+
+#define PORTIO_USART1_RX_PIN (7)
+#define PORTIO_USART1_RX_PORT (gpioPortC)
+#define PORTIO_USART1_RX_LOC (11)
+
+#define PORTIO_USART1_TX_PIN (6)
+#define PORTIO_USART1_TX_PORT (gpioPortC)
+#define PORTIO_USART1_TX_LOC (11)
+
+// [USART1]$
+
+// $[USART2]
+#define PORTIO_USART2_CLK_PIN (8)
+#define PORTIO_USART2_CLK_PORT (gpioPortA)
+#define PORTIO_USART2_CLK_LOC (1)
+
+#define PORTIO_USART2_CS_PIN (9)
+#define PORTIO_USART2_CS_PORT (gpioPortA)
+#define PORTIO_USART2_CS_LOC (1)
+
+#define PORTIO_USART2_RX_PIN (7)
+#define PORTIO_USART2_RX_PORT (gpioPortA)
+#define PORTIO_USART2_RX_LOC (1)
+
+#define PORTIO_USART2_TX_PIN (6)
+#define PORTIO_USART2_TX_PORT (gpioPortA)
+#define PORTIO_USART2_TX_LOC (1)
+
+// [USART2]$
+
+// $[USART3]
+#define PORTIO_USART3_CTS_PIN (8)
+#define PORTIO_USART3_CTS_PORT (gpioPortD)
+#define PORTIO_USART3_CTS_LOC (28)
+
+#define PORTIO_USART3_RTS_PIN (9)
+#define PORTIO_USART3_RTS_PORT (gpioPortD)
+#define PORTIO_USART3_RTS_LOC (28)
+
+#define PORTIO_USART3_RX_PIN (7)
+#define PORTIO_USART3_RX_PORT (gpioPortB)
+#define PORTIO_USART3_RX_LOC (10)
+
+#define PORTIO_USART3_TX_PIN (6)
+#define PORTIO_USART3_TX_PORT (gpioPortB)
+#define PORTIO_USART3_TX_LOC (10)
+
+// [USART3]$
+
+// $[VCOM]
+// [VCOM]$
+
+// $[VDAC0]
+// [VDAC0]$
+
+// $[VUART]
+// [VUART]$
+
+// $[WDOG]
+// [WDOG]$
+
+// $[WTIMER0]
+// [WTIMER0]$
+
+// $[WTIMER1]
+// [WTIMER1]$
+
+#endif /* HAL_CONFIG_H */
diff --git a/examples/platforms/efr32mg1/crypto/efr32-mbedtls-config.h b/examples/platforms/efr32mg1/crypto/efr32-mbedtls-config.h
new file mode 100644
index 0000000..14f1d1c
--- /dev/null
+++ b/examples/platforms/efr32mg1/crypto/efr32-mbedtls-config.h
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2020, 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/crypto_aes.c for devices with CRYPTO
+ *          sl_crypto/src/aes_aes.c for devices with AES
+ *
+ * See MBEDTLS_AES_C for more information.
+ */
+#define MBEDTLS_AES_ALT
+
+/**
+ * \def MBEDTLS_ECP_INTERNAL_ALT
+ * \def ECP_SHORTWEIERSTRASS
+ * \def MBEDTLS_ECP_ADD_MIXED_ALT
+ * \def MBEDTLS_ECP_DOUBLE_JAC_ALT
+ * \def MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
+ * \def MBEDTLS_ECP_NORMALIZE_JAC_ALT
+ *
+ * Enable hardware acceleration for the elliptic curve over GF(p) library.
+ *
+ * Module:  sl_crypto/src/crypto_ecp.c
+ * Caller:  library/ecp.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_INTERNAL_ALT
+#define ECP_SHORTWEIERSTRASS
+#define MBEDTLS_ECP_ADD_MIXED_ALT
+#define MBEDTLS_ECP_DOUBLE_JAC_ALT
+#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
+#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
+#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
+#endif
+
+/**
+ * \def MBEDTLS_SHA256_ALT
+ *
+ * Enable hardware acceleration for the SHA-224 and SHA-256 cryptographic
+ * hash algorithms.
+ *
+ * Module:  sl_crypto/src/crypto_sha.c
+ * 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/efr32mg1/diag.c b/examples/platforms/efr32mg1/diag.c
new file mode 100644
index 0000000..a7c3357
--- /dev/null
+++ b/examples/platforms/efr32mg1/diag.c
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2020, 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <openthread/config.h>
+#include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/radio.h>
+
+#include "platform-efr32.h"
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+
+/**
+ * Diagnostics mode variables.
+ *
+ */
+static bool sDiagMode = false;
+
+void otPlatDiagModeSet(bool aMode)
+{
+    sDiagMode = aMode;
+}
+
+bool otPlatDiagModeGet()
+{
+    return sDiagMode;
+}
+
+void otPlatDiagChannelSet(uint8_t aChannel)
+{
+    OT_UNUSED_VARIABLE(aChannel);
+}
+
+void otPlatDiagTxPowerSet(int8_t aTxPower)
+{
+    OT_UNUSED_VARIABLE(aTxPower);
+}
+
+void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aFrame);
+    OT_UNUSED_VARIABLE(aError);
+}
+
+void otPlatDiagAlarmCallback(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+}
+
+#endif // #if OPENTHREAD_CONFIG_DIAG_ENABLE
diff --git a/examples/platforms/efr32mg1/efr32mg1.ld b/examples/platforms/efr32mg1/efr32mg1.ld
new file mode 100644
index 0000000..92ba35e
--- /dev/null
+++ b/examples/platforms/efr32mg1/efr32mg1.ld
@@ -0,0 +1,246 @@
+/*
+ *  Copyright (c) 2020, 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 linker script for the
+ *   Silicon Labs efr32mg1 platform.
+ *
+ */
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 32K
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapBase
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __Vectors_End
+ *   __Vectors_Size
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.vectors))
+    __Vectors_End = .;
+    __Vectors_Size = __Vectors_End - __Vectors;
+    __end__ = .;
+
+    *(.text*)
+
+    KEEP(*(.init))
+    KEEP(*(.fini))
+
+    /* .ctors */
+    *crtbegin.o(.ctors)
+    *crtbegin?.o(.ctors)
+    *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+    *(SORT(.ctors.*))
+    *(.ctors)
+
+    /* .dtors */
+    *crtbegin.o(.dtors)
+    *crtbegin?.o(.dtors)
+    *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+    *(SORT(.dtors.*))
+    *(.dtors)
+
+    *(.rodata*)
+
+    KEEP(*(.eh_frame*))
+  } > FLASH
+
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > FLASH
+
+  __exidx_start = .;
+  .ARM.exidx :
+  {
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  } > FLASH
+  __exidx_end = .;
+
+  /* To copy multiple ROM to RAM sections,
+   * uncomment .copy.table section and,
+   * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+  /*
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+    LONG (__etext)
+    LONG (__data_start__)
+    LONG (__data_end__ - __data_start__)
+    LONG (__etext2)
+    LONG (__data2_start__)
+    LONG (__data2_end__ - __data2_start__)
+    __copy_table_end__ = .;
+  } > FLASH
+  */
+
+  /* To clear multiple BSS sections,
+   * uncomment .zero.table section and,
+   * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+  /*
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+    LONG (__bss_start__)
+    LONG (__bss_end__ - __bss_start__)
+    LONG (__bss2_start__)
+    LONG (__bss2_end__ - __bss2_start__)
+    __zero_table_end__ = .;
+  } > FLASH
+  */
+
+  __etext = .;
+
+  .data : AT (__etext)
+  {
+    __data_start__ = .;
+    *(vtable)
+    *(.data*)
+    . = ALIGN (4);
+    PROVIDE (__ram_func_section_start = .);
+    *(.ram)
+    PROVIDE (__ram_func_section_end = .);
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__init_array_end = .);
+
+    . = ALIGN(4);
+    /* finit data */
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP(*(SORT(.fini_array.*)))
+    KEEP(*(.fini_array))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+
+    KEEP(*(.jcr*))
+    . = ALIGN(4);
+    /* All data end */
+    __data_end__ = .;
+
+  } > RAM
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+    *(.bss*)
+    *(COMMON)
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > RAM
+
+  .heap (COPY):
+  {
+    __HeapBase = .;
+    __end__ = .;
+    end = __end__;
+    _end = __end__;
+    KEEP(*(.heap*))
+    __HeapLimit = .;
+  } > RAM
+
+  /* .stack_dummy section doesn't contains any symbols. It is only
+   * used for linker to calculate size of stack sections, and assign
+   * values to stack symbols later */
+  .stack_dummy (COPY):
+  {
+    KEEP(*(.stack*))
+  } > RAM
+
+  /* Set stack top to end of RAM, and stack limit move down by
+   * size of stack_dummy section */
+  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+  PROVIDE(__stack = __StackTop);
+
+  /*******************************************************************/
+  /* Define flash block for nvm3                                     */
+  .nvm (DSECT) : {
+    KEEP(*(.simee*))
+  } > FLASH
+
+  linker_nvm_end = ORIGIN(FLASH) + LENGTH(FLASH);
+  linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+  linker_nvm_size = SIZEOF(.nvm);
+  __nvm3Base = linker_nvm_begin;
+  /*******************************************************************/
+
+  /* Check if data + heap + stack exceeds RAM limit */
+  ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+
+  /* Check if FLASH usage exceeds FLASH size */
+  ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+}
diff --git a/examples/platforms/efr32mg1/entropy.c b/examples/platforms/efr32mg1/entropy.c
new file mode 100644
index 0000000..2b196bb
--- /dev/null
+++ b/examples/platforms/efr32mg1/entropy.c
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2020, 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 an entropy source based on ADC.
+ *
+ */
+
+#include <openthread/platform/entropy.h>
+
+#include "utils/code_utils.h"
+
+#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;
+}
+
+static uint32_t randomUint32Get(void)
+{
+    uint8_t  tmp;
+    uint32_t random = 0;
+
+    for (int i = 0; i < 4; i++)
+    {
+        tmp = 0;
+
+        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;
+}
+
+otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
+{
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION(aOutput, error = OT_ERROR_INVALID_ARGS);
+
+    for (uint16_t length = 0; length < aOutputLength; length++)
+    {
+        aOutput[length] = (uint8_t)randomUint32Get();
+    }
+
+exit:
+    return error;
+}
diff --git a/examples/platforms/efr32mg1/fem-control.c b/examples/platforms/efr32mg1/fem-control.c
new file mode 100644
index 0000000..f66415c
--- /dev/null
+++ b/examples/platforms/efr32mg1/fem-control.c
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (c) 2020, 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 "hal-config.h"
+
+#if (HAL_FEM_ENABLE)
+#include "util/plugin/plugin-common/fem-control/fem-control.c"
+#endif
diff --git a/examples/platforms/efr32mg1/flash.c b/examples/platforms/efr32mg1/flash.c
new file mode 100644
index 0000000..15d46ea
--- /dev/null
+++ b/examples/platforms/efr32mg1/flash.c
@@ -0,0 +1,364 @@
+/*
+ *  Copyright (c) 2020, 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 "openthread-core-efr32-config.h"
+#include <openthread/config.h>
+
+#if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE // Use OT NV system
+
+#include "em_msc.h"
+#include <string.h>
+#include <openthread/instance.h>
+
+#define FLASH_PAGE_NUM 2
+#define FLASH_DATA_END_ADDR (FLASH_BASE + FLASH_SIZE)
+#define FLASH_DATA_START_ADDR (FLASH_DATA_END_ADDR - (FLASH_PAGE_SIZE * FLASH_PAGE_NUM))
+#define FLASH_SWAP_PAGE_NUM (FLASH_PAGE_NUM / 2)
+#define FLASH_SWAP_SIZE (FLASH_PAGE_SIZE * FLASH_SWAP_PAGE_NUM)
+
+static inline uint32_t mapAddress(uint8_t aSwapIndex, uint32_t aOffset)
+{
+    uint32_t address;
+
+    address = FLASH_DATA_START_ADDR + aOffset;
+
+    if (aSwapIndex)
+    {
+        address += FLASH_SWAP_SIZE;
+    }
+
+    return address;
+}
+
+void otPlatFlashInit(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+}
+
+uint32_t otPlatFlashGetSwapSize(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return FLASH_SWAP_SIZE;
+}
+
+void otPlatFlashErase(otInstance *aInstance, uint8_t aSwapIndex)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    uint32_t address = mapAddress(aSwapIndex, 0);
+
+    for (uint32_t n = 0; n < FLASH_SWAP_PAGE_NUM; n++, address += FLASH_PAGE_SIZE)
+    {
+        MSC_ErasePage((uint32_t *)address);
+    }
+}
+
+void otPlatFlashWrite(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, const void *aData, uint32_t aSize)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    MSC_WriteWord((uint32_t *)mapAddress(aSwapIndex, aOffset), aData, aSize);
+}
+
+void otPlatFlashRead(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, void *aData, uint32_t aSize)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    memcpy(aData, (const uint8_t *)mapAddress(aSwapIndex, aOffset), aSize);
+}
+
+#else // Defaults to Silabs nvm3 system
+
+#include "nvm3.h"
+#include "nvm3_default.h"
+#include <string.h>
+#include <openthread/platform/settings.h>
+#include "common/code_utils.hpp"
+#include "common/logging.hpp"
+
+#define NVM3KEY_DOMAIN_OPENTHREAD 0x20000U
+#define NUM_INDEXED_SETTINGS \
+    OPENTHREAD_CONFIG_MLE_MAX_CHILDREN // Indexed key types are only supported for kKeyChildInfo (=='child table').
+#define ENUM_NVM3_KEY_LIST_SIZE 4      // List size used when enumerating nvm3 keys.
+
+static otError          addSetting(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+static nvm3_ObjectKey_t makeNvm3ObjKey(uint16_t otSettingsKey, int index);
+static otError          mapNvm3Error(Ecode_t nvm3Res);
+
+void otPlatSettingsInit(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    if (mapNvm3Error(nvm3_open(nvm3_defaultHandle, nvm3_defaultInit)) != OT_ERROR_NONE)
+    {
+        otLogDebgPlat("Error initializing nvm3 instance");
+    }
+}
+
+void otPlatSettingsDeinit(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    nvm3_close(nvm3_defaultHandle);
+}
+
+otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
+{
+    // Searches through all matching nvm3 keys to find the one with the required
+    // 'index', then reads the nvm3 data into the destination buffer.
+    // (Repeatedly enumerates a list of matching keys from the nvm3 until the
+    // required index is found).
+
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError  err;
+    uint16_t valueLength = 0;
+
+    nvm3_ObjectKey_t nvm3Key  = makeNvm3ObjKey(aKey, 0); // The base nvm3 key value.
+    bool             idxFound = false;
+    int              idx      = 0;
+    err                       = OT_ERROR_NOT_FOUND;
+    while ((idx <= NUM_INDEXED_SETTINGS) && (!idxFound))
+    {
+        // Get the next nvm3 key list.
+        nvm3_ObjectKey_t keys[ENUM_NVM3_KEY_LIST_SIZE]; // List holds the next set of nvm3 keys.
+        size_t           objCnt = nvm3_enumObjects(nvm3_defaultHandle, keys, ENUM_NVM3_KEY_LIST_SIZE, nvm3Key,
+                                         makeNvm3ObjKey(aKey, NUM_INDEXED_SETTINGS));
+        for (size_t i = 0; i < objCnt; ++i)
+        {
+            nvm3Key = keys[i];
+            if (idx == aIndex)
+            {
+                uint32_t objType;
+                size_t   objLen;
+                err = mapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, nvm3Key, &objType, &objLen));
+                if (err == OT_ERROR_NONE)
+                {
+                    valueLength = objLen;
+
+                    // Only perform read if an input buffer was passed in.
+                    if ((aValue != NULL) && (aValueLength != NULL))
+                    {
+                        // Read all nvm3 obj bytes into a tmp buffer, then copy the required
+                        // number of bytes to the read destination buffer.
+                        uint8_t *buf = malloc(valueLength);
+                        err          = mapNvm3Error(nvm3_readData(nvm3_defaultHandle, nvm3Key, buf, valueLength));
+                        if (err == OT_ERROR_NONE)
+                        {
+                            memcpy(aValue, buf, (valueLength < *aValueLength) ? valueLength : *aValueLength);
+                        }
+                        free(buf);
+                        SuccessOrExit(err);
+                    }
+                }
+                idxFound = true;
+                break;
+            }
+            ++idx;
+        }
+        if (objCnt < ENUM_NVM3_KEY_LIST_SIZE)
+        {
+            // Stop searching (there are no more matching nvm3 objects).
+            break;
+        }
+        ++nvm3Key; // Inc starting value for next nvm3 key list enumeration.
+    }
+
+exit:
+    if (aValueLength != NULL)
+    {
+        *aValueLength = valueLength; // always return actual nvm3 object length.
+    }
+
+    return err;
+}
+
+otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError err;
+
+    // Delete all nvm3 objects matching the input key (i.e. the 'setting indexes' of the key).
+    err = otPlatSettingsDelete(aInstance, aKey, -1);
+    if ((err == OT_ERROR_NONE) || (err == OT_ERROR_NOT_FOUND))
+    {
+        // Add new setting object (i.e. 'index0' of the key).
+        err = addSetting(aKey, aValue, aValueLength);
+        SuccessOrExit(err);
+    }
+
+exit:
+    return err;
+}
+
+otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    return addSetting(aKey, aValue, aValueLength);
+}
+
+otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
+{
+    // Searches through all matching nvm3 keys to find the one with the required
+    // 'index' (or index = -1 to delete all), then deletes the nvm3 object.
+    // (Repeatedly enumerates a list of matching keys from the nvm3 until the
+    // required index is found).
+
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError          err;
+    nvm3_ObjectKey_t nvm3Key  = makeNvm3ObjKey(aKey, 0); // The base nvm3 key value.
+    bool             idxFound = false;
+    int              idx      = 0;
+    err                       = OT_ERROR_NOT_FOUND;
+    while ((idx <= NUM_INDEXED_SETTINGS) && (!idxFound))
+    {
+        // Get the next nvm3 key list.
+        nvm3_ObjectKey_t keys[ENUM_NVM3_KEY_LIST_SIZE]; // List holds the next set of nvm3 keys.
+        size_t           objCnt = nvm3_enumObjects(nvm3_defaultHandle, keys, ENUM_NVM3_KEY_LIST_SIZE, nvm3Key,
+                                         makeNvm3ObjKey(aKey, NUM_INDEXED_SETTINGS));
+        for (size_t i = 0; i < objCnt; ++i)
+        {
+            nvm3Key = keys[i];
+            if ((idx == aIndex) || (aIndex == -1))
+            {
+                uint32_t objType;
+                size_t   objLen;
+                err = mapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, nvm3Key, &objType, &objLen));
+                if (err == OT_ERROR_NONE)
+                {
+                    // Delete the nvm3 object.
+                    err = mapNvm3Error(nvm3_deleteObject(nvm3_defaultHandle, nvm3Key));
+                    SuccessOrExit(err);
+                }
+                if (aIndex != -1)
+                {
+                    idxFound = true;
+                    break;
+                }
+            }
+            ++idx;
+        }
+        if (objCnt < ENUM_NVM3_KEY_LIST_SIZE)
+        {
+            // Stop searching (there are no more matching nvm3 objects).
+            break;
+        }
+        ++nvm3Key; // Inc starting value for next nvm3 key list enumeration.
+    }
+
+exit:
+    return err;
+}
+
+void otPlatSettingsWipe(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    // Delete nvm3 objects for all OT Settings keys (and any of their associated 'indexes').
+    // Note- any OT User nvm3 objects in the OT nvm3 area are NOT be erased.
+    for (uint16_t aKey = 0; aKey < 8; ++aKey)
+    {
+        otPlatSettingsDelete(NULL, aKey, -1);
+    }
+}
+
+// Local functions..
+
+static otError addSetting(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+{
+    // Helper function- writes input buffer data to a NEW nvm3 object.
+    // nvm3 object is created at the first available Key + index.
+
+    otError err;
+
+    if ((aValueLength == 0) || (aValue == NULL))
+    {
+        err = OT_ERROR_INVALID_ARGS;
+    }
+    else
+    {
+        for (int idx = 0; idx <= NUM_INDEXED_SETTINGS; ++idx)
+        {
+            nvm3_ObjectKey_t nvm3Key;
+            nvm3Key = makeNvm3ObjKey(aKey, idx);
+
+            uint32_t objType;
+            size_t   objLen;
+            err = mapNvm3Error(nvm3_getObjectInfo(nvm3_defaultHandle, nvm3Key, &objType, &objLen));
+            if (err == OT_ERROR_NOT_FOUND)
+            {
+                // Use this index for the new nvm3 object.
+                // Write the binary data to nvm3 (Creates nvm3 object if required).
+                err = mapNvm3Error(nvm3_writeData(nvm3_defaultHandle, nvm3Key, aValue, aValueLength));
+                break;
+            }
+            else if (err != OT_ERROR_NONE)
+            {
+                break;
+            }
+        }
+    }
+
+    return err;
+}
+
+static nvm3_ObjectKey_t makeNvm3ObjKey(uint16_t otSettingsKey, int index)
+{
+    return (NVM3KEY_DOMAIN_OPENTHREAD | (otSettingsKey << 8) | (index & 0xFF));
+}
+
+static otError mapNvm3Error(Ecode_t nvm3Res)
+{
+    otError err;
+
+    switch (nvm3Res)
+    {
+    case ECODE_NVM3_OK:
+        err = OT_ERROR_NONE;
+        break;
+
+    case ECODE_NVM3_ERR_KEY_NOT_FOUND:
+        err = OT_ERROR_NOT_FOUND;
+        break;
+
+    default:
+        err = OT_ERROR_FAILED;
+        break;
+    }
+
+    return err;
+}
+
+#endif // OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
diff --git a/examples/platforms/efr32mg1/logging.c b/examples/platforms/efr32mg1/logging.c
new file mode 100644
index 0000000..ad873dd
--- /dev/null
+++ b/examples/platforms/efr32mg1/logging.c
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2016, 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 logging.c
+ * Platform abstraction for the logging
+ *
+ */
+
+#include <openthread-core-config.h>
+#include <openthread/config.h>
+#include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/logging.h>
+
+#include <utils/logging_rtt.h>
+
+#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
+    (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
+void efr32LogInit(void)
+{
+    utilsLogRttInit();
+}
+
+void efr32LogDeinit(void)
+{
+    utilsLogRttDeinit();
+}
+
+OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
+{
+    va_list ap;
+
+    va_start(ap, aFormat);
+
+    utilsLogRttOutput(aLogLevel, aLogRegion, aFormat, ap);
+
+    va_end(ap);
+}
+#endif
diff --git a/examples/platforms/efr32mg1/misc.c b/examples/platforms/efr32mg1/misc.c
new file mode 100644
index 0000000..4b2076f
--- /dev/null
+++ b/examples/platforms/efr32mg1/misc.c
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2020, 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 <openthread/platform/misc.h>
+
+#include "em_rmu.h"
+#include "platform-efr32.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)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    NVIC_SystemReset();
+}
+
+otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otPlatResetReason reason;
+
+    if (sResetCause & RMU_RSTCAUSE_PORST)
+    {
+        reason = OT_PLAT_RESET_REASON_POWER_ON;
+    }
+    else if (sResetCause & RMU_RSTCAUSE_SYSREQRST)
+    {
+        reason = OT_PLAT_RESET_REASON_SOFTWARE;
+    }
+    else if (sResetCause & RMU_RSTCAUSE_WDOGRST)
+    {
+        reason = OT_PLAT_RESET_REASON_WATCHDOG;
+    }
+    else if (sResetCause & RMU_RSTCAUSE_EXTRST)
+    {
+        reason = OT_PLAT_RESET_REASON_EXTERNAL;
+    }
+    else if (sResetCause & RMU_RSTCAUSE_LOCKUPRST)
+    {
+        reason = OT_PLAT_RESET_REASON_FAULT;
+    }
+    else if ((sResetCause & RMU_RSTCAUSE_AVDDBOD) || (sResetCause & RMU_RSTCAUSE_DECBOD) ||
+             (sResetCause & RMU_RSTCAUSE_DVDDBOD) || (sResetCause & RMU_RSTCAUSE_EM4RST))
+    {
+        reason = OT_PLAT_RESET_REASON_ASSERT;
+    }
+    else
+    {
+        reason = OT_PLAT_RESET_REASON_UNKNOWN;
+    }
+
+    return reason;
+}
+
+void otPlatWakeHost(void)
+{
+    // TODO: implement an operation to wake the host from sleep state.
+}
diff --git a/examples/platforms/efr32mg1/openthread-core-efr32-config-check.h b/examples/platforms/efr32mg1/openthread-core-efr32-config-check.h
new file mode 100644
index 0000000..cf112c9
--- /dev/null
+++ b/examples/platforms/efr32mg1/openthread-core-efr32-config-check.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2020, 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 OPENTHREAD_CORE_EFR32_CONFIG_CHECK_H_
+#define OPENTHREAD_CORE_EFR32_CONFIG_CHECK_H_
+
+#include "board_config.h"
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+#error "Platform efr32mg1 doesn't support configuration option: OPENTHREAD_CONFIG_TIME_SYNC_ENABLE"
+#endif
+
+#ifndef RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
+#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+#error "Platform efr32mg1 not configured to support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
+#endif
+#endif
+
+#endif /* OPENTHREAD_CORE_EFR32_CONFIG_CHECK_H_ */
diff --git a/examples/platforms/efr32mg1/openthread-core-efr32-config.h b/examples/platforms/efr32mg1/openthread-core-efr32-config.h
new file mode 100644
index 0000000..d1cbde6
--- /dev/null
+++ b/examples/platforms/efr32mg1/openthread-core-efr32-config.h
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2020, 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.
+ */
+
+#include "board_config.h"
+#include "em_msc.h"
+
+#ifndef OPENTHREAD_CORE_EFR32_CONFIG_H_
+#define OPENTHREAD_CORE_EFR32_CONFIG_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_LOG_OUTPUT
+ *
+ * The efr32 platform provides an otPlatLog() function.
+ */
+#ifndef OPENTHREAD_CONFIG_LOG_OUTPUT /* allow command line override */
+#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
+#endif
+
+/*
+ * @def OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+ *
+ * Define to 1 if you want to enable physical layer to support OQPSK modulation in 915MHz band.
+ *
+ */
+#if RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
+#define OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT 1
+#else
+#define OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT 0
+#endif
+
+/*
+ * @def OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
+ *
+ * Define to 1 if you want to enable physical layer to support OQPSK modulation in 2.4GHz band.
+ *
+ */
+#if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT
+#define OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT 1
+#else
+#define OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_INFO
+ *
+ * The platform-specific string to insert into the OpenThread version string.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_INFO "EFR32"
+
+/*
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+ *
+ * Define to 1 if you want to enable software retransmission logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE
+ *
+ * Define to 1 if you want to enable software CSMA-CA backoff logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 0
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ *
+ * Define to 1 if you want to enable software transmission security logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 0
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE
+ *
+ * Define to 1 if you want to enable software energy scanning logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE 0
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
+ *
+ * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage.
+ *
+ * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ *
+ * Define to 1 to enable NCP UART support.
+ *
+ */
+#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+
+#endif // OPENTHREAD_CORE_EFR32_CONFIG_H_
diff --git a/examples/platforms/efr32mg1/platform-band.h b/examples/platforms/efr32mg1/platform-band.h
new file mode 100644
index 0000000..7c4d912
--- /dev/null
+++ b/examples/platforms/efr32mg1/platform-band.h
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (c) 2020, 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 defines the frequency band configuration structure for efr32.
+ *
+ */
+
+#ifndef PLATFORM_BAND_H_
+#define PLATFORM_BAND_H_
+
+#include <openthread/platform/radio.h>
+
+#include "rail.h"
+#include "rail_config.h"
+#include "rail_ieee802154.h"
+
+#define RAIL_TX_FIFO_SIZE (OT_RADIO_FRAME_MAX_SIZE + 1)
+
+#define RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY 255
+#define RADIO_SCHEDULER_CHANNEL_SCAN_PRIORITY 255
+#define RADIO_SCHEDULER_CHANNEL_SLIP_TIME 500000UL
+#define RADIO_SCHEDULER_TX_PRIORITY 100
+#define RADIO_SCHEDULER_TX_SLIP_TIME 500000UL
+
+#define RADIO_TIMING_CSMA_OVERHEAD_US 500
+#define RADIO_TIMING_DEFAULT_BYTETIME_US 32   // only used if RAIL_GetBitRate returns 0
+#define RADIO_TIMING_DEFAULT_SYMBOLTIME_US 16 // only used if RAIL_GetSymbolRate returns 0
+
+typedef struct efr32RadioCounters
+{
+    uint64_t mRailPlatTxTriggered;
+    uint64_t mRailPlatRadioReceiveDoneCbCount;
+    uint64_t mRailPlatRadioEnergyScanDoneCbCount;
+    uint64_t mRailPlatRadioTxDoneCbCount;
+    uint64_t mRailTxStarted;
+    uint64_t mRailTxStartFailed;
+    uint64_t mRailEventConfigScheduled;
+    uint64_t mRailEventConfigUnScheduled;
+    uint64_t mRailEventPacketSent;
+    uint64_t mRailEventChannelBusy;
+    uint64_t mRailEventEnergyScanCompleted;
+    uint64_t mRailEventCalNeeded;
+    uint64_t mRailEventPacketReceived;
+    uint64_t mRailEventNoAck;
+    uint64_t mRailEventTxAbort;
+    uint64_t mRailEventSchedulerStatusError;
+    uint64_t mRailEventsSchedulerStatusTransmitBusy;
+    uint32_t mRailEventsSchedulerStatusLastStatus;
+} efr32RadioCounters;
+
+typedef struct efr32CommonConfig
+{
+    RAIL_Config_t mRailConfig;
+#if RADIO_CONFIG_DMP_SUPPORT
+    RAILSched_Config_t railSchedState;
+#endif
+    uint8_t
+        mRailTxFifo[RAIL_TX_FIFO_SIZE]; // must be 2 power between 64 and 4096, and bigger than OT_RADIO_FRAME_MAX_SIZE
+} efr32CommonConfig;
+
+typedef struct efr32BandConfig
+{
+    const RAIL_ChannelConfig_t *mChannelConfig;
+    uint8_t                     mChannelMin;
+    uint8_t                     mChannelMax;
+} efr32BandConfig;
+
+#endif // PLATFORM_BAND_H_
diff --git a/examples/platforms/efr32mg1/platform-efr32.h b/examples/platforms/efr32mg1/platform-efr32.h
new file mode 100644
index 0000000..5ec48e2
--- /dev/null
+++ b/examples/platforms/efr32mg1/platform-efr32.h
@@ -0,0 +1,138 @@
+/*
+ *  Copyright (c) 2020, 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 <openthread/instance.h>
+
+#include "em_device.h"
+#include "em_system.h"
+
+#include "core_cm4.h"
+#include "rail.h"
+
+// Global OpenThread instance structure
+extern otInstance *sInstance;
+
+// Global reference to rail handle
+extern RAIL_Handle_t gRailHandle;
+
+/**
+ * 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 Logger driver.
+ *
+ */
+void efr32LogInit(void);
+
+/**
+ * Deinitialization of Logger driver.
+ *
+ */
+void efr32LogDeinit(void);
+
+/**
+ * Registers the sleep callback handler.  The callback is used to check that
+ * the application has no work pending and that it is safe to put the EFR32
+ * into a low energy sleep mode.
+ *
+ * The callback should return true if it is ok to enter sleep mode. Note
+ * that the callback itself is run with interrupts disabled and so should
+ * be kept as short as possible.  Anny interrupt including those from timers
+ * will wake the EFR32 out of sleep mode.
+ *
+ * @param[in]  aCallback  Callback function.
+ *
+ */
+void efr32SetSleepCallback(bool (*aCallback)(void));
+
+/**
+ * Put the EFR32 into a low power mode.  Before sleeping it will call a callback
+ * in the application registered with efr32SetSleepCallback to ensure that there
+ * is no outstanding work in the application to do.
+ */
+void efr32Sleep(void);
+
+#endif // PLATFORM_EFR32_H_
diff --git a/examples/platforms/efr32mg1/radio.c b/examples/platforms/efr32mg1/radio.c
new file mode 100644
index 0000000..abc67e1
--- /dev/null
+++ b/examples/platforms/efr32mg1/radio.c
@@ -0,0 +1,1160 @@
+/*
+ *  Copyright (c) 2020, 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 <assert.h>
+
+#include "openthread-system.h"
+#include <openthread/config.h>
+#include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/diag.h>
+#include <openthread/platform/radio.h>
+
+#include "common/logging.hpp"
+#include "utils/code_utils.h"
+
+#include "utils/soft_source_match_table.h"
+
+#include "board_config.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_system.h"
+#include "hal-config.h"
+#include "openthread-core-efr32-config.h"
+#include "pa_conversions_efr32.h"
+#include "platform-band.h"
+#include "rail.h"
+#include "rail_config.h"
+#include "rail_ieee802154.h"
+
+enum
+{
+    IEEE802154_MIN_LENGTH = 5,
+    IEEE802154_MAX_LENGTH = 127,
+    IEEE802154_ACK_LENGTH = 5,
+
+    // FCF + DSN + dest PANID + dest addr + src PANID + src addr (without security header)
+    IEEE802154_MAX_MHR_LENGTH = 2 + 1 + 2 + 8 + 2 + 8,
+
+    IEEE802154_FRAME_TYPE_MASK        = 0x7,
+    IEEE802154_FRAME_TYPE_ACK         = 0x2,
+    IEEE802154_FRAME_TYPE_MAC_COMMAND = 0x3,
+    IEEE802154_ACK_REQUEST            = 1 << 5,
+    IEEE802154_DSN_OFFSET             = 2,
+    IEEE802154_FCF_OFFSET             = 0,
+};
+
+enum
+{
+    EFR32_RECEIVE_SENSITIVITY    = -100, // dBm
+    EFR32_RSSI_AVERAGING_TIMEOUT = 300,  // us
+};
+
+enum
+{
+    EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY = 10, // High priority
+    EFR32_SCHEDULER_TX_PRIORITY          = 10, // High priority
+    EFR32_SCHEDULER_RX_PRIORITY          = 20, // Low priority
+};
+
+enum
+{
+#if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT && RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
+    EFR32_NUM_BAND_CONFIGS = 2,
+#else
+    EFR32_NUM_BAND_CONFIGS = 1,
+#endif
+};
+
+typedef enum
+{
+    ENERGY_SCAN_STATUS_IDLE,
+    ENERGY_SCAN_STATUS_IN_PROGRESS,
+    ENERGY_SCAN_STATUS_COMPLETED
+} energyScanStatus;
+
+typedef enum
+{
+    ENERGY_SCAN_MODE_SYNC,
+    ENERGY_SCAN_MODE_ASYNC
+} energyScanMode;
+
+RAIL_Handle_t gRailHandle;
+
+static volatile bool sTransmitBusy = false;
+static bool          sPromiscuous  = false;
+static otRadioState  sState        = OT_RADIO_STATE_DISABLED;
+
+enum
+{
+    ACKED_WITH_FP_MATCH_LENGTH = 1 + IEEE802154_MAX_MHR_LENGTH, // PHR and MHR
+    ACKED_WITH_FP_SLOTS = 16, // maximum number of Data Request packets in the RX FIFO. Length should be a power of 2.
+};
+
+typedef struct efr32AckedWithFP
+{
+    uint8_t mLength;
+    uint8_t mPacket[ACKED_WITH_FP_MATCH_LENGTH];
+} efr32AckedWithFP;
+static bool              sIsSrcMatchEnabled = false;
+static efr32AckedWithFP  sAckedWithFPFifo[ACKED_WITH_FP_SLOTS];
+static uint32_t          sAckedWithFPReadIndex;
+static volatile uint32_t sAckedWithFPWriteIndex;
+
+static uint8_t      sReceivePsdu[IEEE802154_MAX_LENGTH];
+static otRadioFrame sReceiveFrame;
+static otError      sReceiveError;
+
+static otRadioFrame     sTransmitFrame;
+static uint8_t          sTransmitPsdu[IEEE802154_MAX_LENGTH];
+static volatile otError sTransmitError;
+
+static efr32CommonConfig sCommonConfig;
+static efr32BandConfig   sBandConfigs[EFR32_NUM_BAND_CONFIGS];
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+static efr32RadioCounters sRailDebugCounters;
+#endif
+
+static volatile energyScanStatus sEnergyScanStatus;
+static volatile int8_t           sEnergyScanResultDbm;
+static energyScanMode            sEnergyScanMode;
+
+#define QUARTER_DBM_IN_DBM 4
+#define US_IN_MS 1000
+
+static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
+
+static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
+    .addresses = NULL,
+    .ackConfig =
+        {
+            .enable     = true,
+            .ackTimeout = 864,
+            .rxTransitions =
+                {
+                    .success = RAIL_RF_STATE_RX,
+                    .error   = RAIL_RF_STATE_RX,
+                },
+            .txTransitions =
+                {
+                    .success = RAIL_RF_STATE_RX,
+                    .error   = RAIL_RF_STATE_RX,
+                },
+        },
+    .timings =
+        {
+            .idleToRx            = 100,
+            .txToRx              = 192 - 10,
+            .idleToTx            = 100,
+            .rxToTx              = 192,
+            .rxSearchTimeout     = 0,
+            .txToRxSearchTimeout = 0,
+        },
+    .framesMask       = RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
+    .promiscuousMode  = false,
+    .isPanCoordinator = false,
+};
+
+#if RADIO_CONFIG_PA_USES_DCDC
+RAIL_DECLARE_TX_POWER_DCDC_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp);
+#else
+RAIL_DECLARE_TX_POWER_VBAT_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp);
+#endif
+
+static int8_t sTxPowerDbm = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER;
+
+static int8_t sCcaThresholdDbm = -75; // default -75dBm energy detect threshold
+
+static efr32BandConfig *sCurrentBandConfig = NULL;
+
+static RAIL_Handle_t efr32RailInit(efr32CommonConfig *aCommonConfig)
+{
+    RAIL_Status_t status;
+    RAIL_Handle_t handle;
+
+    handle = RAIL_Init(&aCommonConfig->mRailConfig, NULL);
+    assert(handle != NULL);
+
+    status = RAIL_ConfigCal(handle, RAIL_CAL_ALL);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    status = RAIL_ConfigEvents(handle, RAIL_EVENTS_ALL,
+                               RAIL_EVENT_RX_ACK_TIMEOUT |                      //
+                                   RAIL_EVENTS_TX_COMPLETION |                  //
+                                   RAIL_EVENT_RX_PACKET_RECEIVED |              //
+                                   RAIL_EVENT_RSSI_AVERAGE_DONE |               //
+                                   RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND | //
+                                   RAIL_EVENT_CAL_NEEDED |                      //
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+                                   RAIL_EVENT_CONFIG_SCHEDULED |   //
+                                   RAIL_EVENT_CONFIG_UNSCHEDULED | //
+#endif
+                                   RAIL_EVENT_SCHEDULER_STATUS //
+    );
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    uint16_t actualLenth = RAIL_SetTxFifo(handle, aCommonConfig->mRailTxFifo, 0, sizeof(aCommonConfig->mRailTxFifo));
+    assert(actualLenth == sizeof(aCommonConfig->mRailTxFifo));
+
+    return handle;
+}
+
+static void efr32RailConfigLoad(efr32BandConfig *aBandConfig)
+{
+    RAIL_Status_t status;
+#if HAL_PA_2P4_LOWPOWER == 1
+    RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_LP, HAL_PA_VOLTAGE, 10};
+#else
+    RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_HP, HAL_PA_VOLTAGE, 10};
+#endif
+    if (aBandConfig->mChannelConfig != NULL)
+    {
+        uint16_t firstChannel = RAIL_ConfigChannels(gRailHandle, aBandConfig->mChannelConfig, NULL);
+        assert(firstChannel == aBandConfig->mChannelMin);
+
+        txPowerConfig.mode = RAIL_TX_POWER_MODE_SUBGIG;
+    }
+    else
+    {
+        status = RAIL_IEEE802154_Config2p4GHzRadio(gRailHandle);
+        assert(status == RAIL_STATUS_NO_ERROR);
+    }
+    status = RAIL_ConfigTxPower(gRailHandle, &txPowerConfig);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+static void efr32RadioSetTxPower(int8_t aPowerDbm)
+{
+    RAIL_Status_t              status;
+    RAIL_TxPowerCurvesConfig_t txPowerCurvesConfig = {curves24Hp, curvesSg, curves24Lp, piecewiseSegments};
+
+    status = RAIL_InitTxPowerCurves(&txPowerCurvesConfig);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    status = RAIL_SetTxPowerDbm(gRailHandle, ((RAIL_TxPower_t)aPowerDbm) * 10);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+static efr32BandConfig *efr32RadioGetBandConfig(uint8_t aChannel)
+{
+    efr32BandConfig *config = NULL;
+
+    for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
+    {
+        if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax))
+        {
+            config = &sBandConfigs[i];
+            break;
+        }
+    }
+
+    return config;
+}
+
+static void efr32ConfigInit(void (*aEventCallback)(RAIL_Handle_t railHandle, RAIL_Events_t events))
+{
+    sCommonConfig.mRailConfig.eventsCallback = aEventCallback;
+    sCommonConfig.mRailConfig.protocol       = NULL; // only used by Bluetooth stack
+#if RADIO_CONFIG_DMP_SUPPORT
+    sCommonConfig.mRailConfig.scheduler = &(sCommonConfig.railSchedState);
+#else
+    sCommonConfig.mRailConfig.scheduler = NULL; // only needed for DMP
+#endif
+
+    uint8_t index = 0;
+
+#if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT
+    sBandConfigs[index].mChannelConfig = NULL;
+    sBandConfigs[index].mChannelMin    = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
+    sBandConfigs[index].mChannelMax    = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
+
+    index++;
+#endif
+
+#if RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
+    sBandConfigs[index].mChannelConfig = channelConfigs[0];
+    sBandConfigs[index].mChannelMin    = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
+    sBandConfigs[index].mChannelMax    = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
+#endif
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+    memset(&sRailDebugCounters, 0x00, sizeof(efr32RadioCounters));
+#endif
+
+    gRailHandle = efr32RailInit(&sCommonConfig);
+    assert(gRailHandle != NULL);
+    efr32RailConfigLoad(&(sBandConfigs[0]));
+}
+
+void efr32RadioInit(void)
+{
+    RAIL_Status_t status;
+
+    // check if RAIL_TX_FIFO_SIZE is power of two..
+    assert((RAIL_TX_FIFO_SIZE & (RAIL_TX_FIFO_SIZE - 1)) == 0);
+
+    // check the limits of the RAIL_TX_FIFO_SIZE.
+    assert((RAIL_TX_FIFO_SIZE >= 64) || (RAIL_TX_FIFO_SIZE <= 4096));
+
+    efr32ConfigInit(RAILCb_Generic);
+
+    CMU_ClockEnable(cmuClock_PRS, true);
+
+    status = RAIL_ConfigSleep(gRailHandle, RAIL_SLEEP_CONFIG_TIMERSYNC_ENABLED);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    sReceiveFrame.mLength  = 0;
+    sReceiveFrame.mPsdu    = sReceivePsdu;
+    sTransmitFrame.mLength = 0;
+    sTransmitFrame.mPsdu   = sTransmitPsdu;
+
+    sCurrentBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL);
+    assert(sCurrentBandConfig != NULL);
+
+    memset(sAckedWithFPFifo, 0, sizeof(sAckedWithFPFifo));
+    sAckedWithFPWriteIndex = 0;
+    sAckedWithFPReadIndex  = 0;
+
+    efr32RadioSetTxPower(sTxPowerDbm);
+
+    sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
+    sTransmitError    = OT_ERROR_NONE;
+    sTransmitBusy     = false;
+
+    otLogInfoPlat("Initialized", NULL);
+}
+
+void efr32RadioDeinit(void)
+{
+    RAIL_Status_t status;
+
+    RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true);
+    status = RAIL_ConfigEvents(gRailHandle, RAIL_EVENTS_ALL, 0);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    sCurrentBandConfig = NULL;
+}
+
+static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
+{
+    RAIL_Status_t    status;
+    otError          error  = OT_ERROR_NONE;
+    efr32BandConfig *config = NULL;
+
+    otEXPECT_ACTION(sEnergyScanStatus == ENERGY_SCAN_STATUS_IDLE, error = OT_ERROR_BUSY);
+
+    sEnergyScanStatus = ENERGY_SCAN_STATUS_IN_PROGRESS;
+    sEnergyScanMode   = aMode;
+
+    RAIL_Idle(gRailHandle, RAIL_IDLE, true);
+
+    config = efr32RadioGetBandConfig(aChannel);
+    otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
+
+    if (sCurrentBandConfig != config)
+    {
+        efr32RailConfigLoad(config);
+        sCurrentBandConfig = config;
+    }
+
+    RAIL_SchedulerInfo_t scanSchedulerInfo = {.priority        = RADIO_SCHEDULER_CHANNEL_SCAN_PRIORITY,
+                                              .slipTime        = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
+                                              .transactionTime = aAveragingTimeUs};
+
+    status = RAIL_StartAverageRssi(gRailHandle, aChannel, aAveragingTimeUs, &scanSchedulerInfo);
+    otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
+
+exit:
+    return error;
+}
+
+void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    uint64_t eui64;
+    uint8_t *eui64Ptr = NULL;
+
+    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)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    RAIL_Status_t status;
+
+    otLogInfoPlat("PANID=%X", aPanId);
+
+    utilsSoftSrcMatchSetPanId(aPanId);
+
+    status = RAIL_IEEE802154_SetPanId(gRailHandle, aPanId, 0);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    RAIL_Status_t status;
+
+    otLogInfoPlat("ExtAddr=%X%X%X%X%X%X%X%X", aAddress->m8[7], aAddress->m8[6], aAddress->m8[5], aAddress->m8[4],
+                  aAddress->m8[3], aAddress->m8[2], aAddress->m8[1], aAddress->m8[0]);
+
+    status = RAIL_IEEE802154_SetLongAddress(gRailHandle, (uint8_t *)aAddress->m8, 0);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    RAIL_Status_t status;
+
+    otLogInfoPlat("ShortAddr=%X", aAddress);
+
+    status = RAIL_IEEE802154_SetShortAddress(gRailHandle, aAddress, 0);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+bool otPlatRadioIsEnabled(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return (sState != OT_RADIO_STATE_DISABLED);
+}
+
+otError otPlatRadioEnable(otInstance *aInstance)
+{
+    otEXPECT(!otPlatRadioIsEnabled(aInstance));
+
+    otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
+    sState = OT_RADIO_STATE_SLEEP;
+
+exit:
+    return OT_ERROR_NONE;
+}
+
+otError otPlatRadioDisable(otInstance *aInstance)
+{
+    otEXPECT(otPlatRadioIsEnabled(aInstance));
+
+    otLogInfoPlat("State=OT_RADIO_STATE_DISABLED", NULL);
+    sState = OT_RADIO_STATE_DISABLED;
+
+exit:
+    return OT_ERROR_NONE;
+}
+
+otError otPlatRadioSleep(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION((sState != OT_RADIO_STATE_TRANSMIT) && (sState != OT_RADIO_STATE_DISABLED),
+                    error = OT_ERROR_INVALID_STATE);
+
+    otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
+
+    RAIL_Idle(gRailHandle, RAIL_IDLE, true);
+    sState = OT_RADIO_STATE_SLEEP;
+
+exit:
+    return error;
+}
+
+otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
+{
+    otError          error = OT_ERROR_NONE;
+    RAIL_Status_t    status;
+    efr32BandConfig *config;
+
+    OT_UNUSED_VARIABLE(aInstance);
+    otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE);
+
+    config = efr32RadioGetBandConfig(aChannel);
+    otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
+
+    if (sCurrentBandConfig != config)
+    {
+        RAIL_Idle(gRailHandle, RAIL_IDLE, true);
+        efr32RailConfigLoad(config);
+        sCurrentBandConfig = config;
+    }
+
+    RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
+        .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
+        // sliptime/transaction time is not used for bg rx
+    };
+
+    status = RAIL_StartRx(gRailHandle, aChannel, &bgRxSchedulerInfo);
+    otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
+
+    otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
+    sState                 = OT_RADIO_STATE_RECEIVE;
+    sReceiveFrame.mChannel = aChannel;
+
+exit:
+    return error;
+}
+
+otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
+{
+    otError           error      = OT_ERROR_NONE;
+    RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
+    RAIL_TxOptions_t  txOptions  = RAIL_TX_OPTIONS_DEFAULT;
+    efr32BandConfig * config;
+    RAIL_Status_t     status;
+    uint8_t           frameLength;
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+    sRailDebugCounters.mRailPlatTxTriggered++;
+#endif
+
+    assert(sTransmitBusy == false);
+
+    otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT),
+                    error = OT_ERROR_INVALID_STATE);
+
+    config = efr32RadioGetBandConfig(aFrame->mChannel);
+    otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
+
+    sState         = OT_RADIO_STATE_TRANSMIT;
+    sTransmitError = OT_ERROR_NONE;
+    sTransmitBusy  = true;
+
+    if (sCurrentBandConfig != config)
+    {
+        RAIL_Idle(gRailHandle, RAIL_IDLE, true);
+        efr32RailConfigLoad(config);
+        sCurrentBandConfig = config;
+    }
+
+    frameLength = (uint8_t)aFrame->mLength;
+    RAIL_WriteTxFifo(gRailHandle, &frameLength, sizeof frameLength, true);
+    RAIL_WriteTxFifo(gRailHandle, aFrame->mPsdu, frameLength - 2, false);
+
+    RAIL_SchedulerInfo_t txSchedulerInfo = {
+        .priority        = RADIO_SCHEDULER_TX_PRIORITY,
+        .slipTime        = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
+        .transactionTime = 0, // will be calculated later if DMP is used
+    };
+
+    if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST)
+    {
+        txOptions |= RAIL_TX_OPTION_WAIT_FOR_ACK;
+
+#if RADIO_CONFIG_DMP_SUPPORT
+        // time we wait for ACK
+        if (RAIL_GetSymbolRate(gRailHandle) > 0)
+        {
+            txSchedulerInfo.transactionTime += 12 * 1e6 / RAIL_GetSymbolRate(gRailHandle);
+        }
+        else
+        {
+            txSchedulerInfo.transactionTime += 12 * RADIO_TIMING_DEFAULT_SYMBOLTIME_US;
+        }
+#endif
+    }
+
+#if RADIO_CONFIG_DMP_SUPPORT
+    // time needed for the frame itself
+    // 4B preamble, 1B SFD, 1B PHR is not counted in frameLength
+    if (RAIL_GetBitRate(gRailHandle) > 0)
+    {
+        txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * 8 * 1e6 / RAIL_GetBitRate(gRailHandle);
+    }
+    else
+    { // assume 250kbps
+        txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * RADIO_TIMING_DEFAULT_BYTETIME_US;
+    }
+#endif
+
+    if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
+    {
+#if RADIO_CONFIG_DMP_SUPPORT
+        // time needed for CSMA/CA
+        txSchedulerInfo.transactionTime += RADIO_TIMING_CSMA_OVERHEAD_US;
+#endif
+        csmaConfig.csmaTries    = aFrame->mInfo.mTxInfo.mMaxCsmaBackoffs;
+        csmaConfig.ccaThreshold = sCcaThresholdDbm;
+
+        status = RAIL_StartCcaCsmaTx(gRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
+    }
+    else
+    {
+        status = RAIL_StartTx(gRailHandle, aFrame->mChannel, txOptions, &txSchedulerInfo);
+    }
+
+    if (status == RAIL_STATUS_NO_ERROR)
+    {
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailTxStarted++;
+#endif
+        otPlatRadioTxStarted(aInstance, aFrame);
+    }
+    else
+    {
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailTxStartFailed++;
+#endif
+        sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+        sTransmitBusy  = false;
+        otSysEventSignalPending();
+    }
+
+exit:
+    return error;
+}
+
+otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return &sTransmitFrame;
+}
+
+int8_t otPlatRadioGetRssi(otInstance *aInstance)
+{
+    int8_t rssi = OT_RADIO_RSSI_INVALID;
+    OT_UNUSED_VARIABLE(aInstance);
+
+    if ((RAIL_GetRadioState(gRailHandle) & RAIL_RF_STATE_RX))
+    {
+        int16_t railRssi = RAIL_RSSI_INVALID;
+        railRssi         = RAIL_GetRssi(gRailHandle, true);
+        if (railRssi != RAIL_RSSI_INVALID)
+        {
+            rssi = railRssi / QUARTER_DBM_IN_DBM;
+        }
+    }
+
+    return rssi;
+}
+
+otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
+}
+
+bool otPlatRadioGetPromiscuous(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return sPromiscuous;
+}
+
+void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    RAIL_Status_t status;
+
+    sPromiscuous = aEnable;
+
+    status = RAIL_IEEE802154_SetPromiscuousMode(gRailHandle, aEnable);
+    assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    // set Frame Pending bit for all outgoing ACKs if aEnable is false
+    sIsSrcMatchEnabled = aEnable;
+}
+
+static bool sAckedWithFPFifoIsFull(void)
+{
+    return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == otARRAY_LENGTH(sAckedWithFPFifo);
+}
+
+static bool sAckedWithFPFifoIsEmpty(void)
+{
+    return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == 0;
+}
+
+static efr32AckedWithFP *sAckedWithFPFifoGetWriteSlot(void)
+{
+    uint32_t idx = sAckedWithFPWriteIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
+    return &sAckedWithFPFifo[idx];
+}
+
+static const efr32AckedWithFP *sAckedWithFPFifoGetReadSlot(void)
+{
+    uint32_t idx = sAckedWithFPReadIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
+    return &sAckedWithFPFifo[idx];
+}
+
+static void insertIeee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
+{
+    assert(!sAckedWithFPFifoIsFull());
+    efr32AckedWithFP *const slot = sAckedWithFPFifoGetWriteSlot();
+
+    RAIL_RxPacketInfo_t packetInfo;
+
+    RAIL_GetRxIncomingPacketInfo(aRailHandle, &packetInfo);
+    assert(packetInfo.packetBytes >= 4); // PHR + FCF + DSN
+
+    if (packetInfo.packetBytes > sizeof(slot->mPacket))
+    {
+        packetInfo.packetBytes = sizeof(slot->mPacket);
+        if (packetInfo.firstPortionBytes >= sizeof(slot->mPacket))
+        {
+            packetInfo.firstPortionBytes = sizeof(slot->mPacket);
+            packetInfo.lastPortionData   = NULL;
+        }
+    }
+    slot->mLength = packetInfo.packetBytes;
+    RAIL_CopyRxPacket(slot->mPacket, &packetInfo);
+
+    ++sAckedWithFPWriteIndex;
+}
+
+static bool wasAckedWithFramePending(const uint8_t *aPsdu, uint8_t aPsduLength)
+{
+    bool     ackedWithFramePending = false;
+    uint16_t fcf                   = aPsdu[IEEE802154_FCF_OFFSET] | (aPsdu[IEEE802154_FCF_OFFSET + 1] << 8);
+
+    otEXPECT((fcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MAC_COMMAND);
+
+    while (!(ackedWithFramePending || sAckedWithFPFifoIsEmpty()))
+    {
+        const efr32AckedWithFP *const slot = sAckedWithFPFifoGetReadSlot();
+        if ((slot->mPacket[0] == aPsduLength) && (memcmp(slot->mPacket + 1, aPsdu, slot->mLength - 1) == 0))
+        {
+            ackedWithFramePending = true;
+        }
+        ++sAckedWithFPReadIndex;
+    }
+
+exit:
+    return ackedWithFramePending;
+}
+
+static void processNextRxPacket(otInstance *aInstance)
+{
+    RAIL_RxPacketHandle_t  packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
+    RAIL_RxPacketInfo_t    packetInfo;
+    RAIL_RxPacketDetails_t packetDetails;
+    RAIL_Status_t          status;
+    uint16_t               length;
+
+    packetHandle = RAIL_GetRxPacketInfo(gRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST, &packetInfo);
+
+    otEXPECT_ACTION(packetHandle != RAIL_RX_PACKET_HANDLE_INVALID &&
+                        packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS,
+                    packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
+
+    status = RAIL_GetRxPacketDetailsAlt(gRailHandle, packetHandle, &packetDetails);
+    otEXPECT(status == RAIL_STATUS_NO_ERROR);
+
+    length = packetInfo.packetBytes + 1;
+
+    // check the length in recv packet info structure; RAIL should take care of this.
+    assert(length == packetInfo.firstPortionData[0]);
+
+    // check the length validity of recv packet; RAIL should take care of this.
+    assert(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH);
+
+    otLogInfoPlat("Received data:%d", length);
+
+    // skip length byte
+    assert(packetInfo.firstPortionBytes > 0);
+    packetInfo.firstPortionData++;
+    packetInfo.firstPortionBytes--;
+    packetInfo.packetBytes--;
+
+    // read packet
+    RAIL_CopyRxPacket(sReceiveFrame.mPsdu, &packetInfo);
+
+    status = RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
+    if (status == RAIL_STATUS_NO_ERROR)
+    {
+        packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
+    }
+
+    sReceiveFrame.mLength = length;
+
+    if (packetDetails.isAck)
+    {
+        assert((length == IEEE802154_ACK_LENGTH) &&
+               (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK);
+
+        RAIL_YieldRadio(gRailHandle);
+        sTransmitBusy = false;
+
+        if (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
+        {
+            sTransmitError = OT_ERROR_NONE;
+        }
+        else
+        {
+            sTransmitError = OT_ERROR_NO_ACK;
+        }
+    }
+    else
+    {
+        // signal MAC layer for each received frame if promiscous is enabled
+        // otherwise only signal MAC layer for non-ACK frame
+        otEXPECT(sPromiscuous || (length != IEEE802154_ACK_LENGTH));
+
+        sReceiveError = OT_ERROR_NONE;
+
+        sReceiveFrame.mInfo.mRxInfo.mRssi = packetDetails.rssi;
+        sReceiveFrame.mInfo.mRxInfo.mLqi  = packetDetails.lqi;
+
+        // Get the timestamp when the SFD was received
+        assert(packetDetails.timeReceived.timePosition != RAIL_PACKET_TIME_INVALID);
+        packetDetails.timeReceived.totalPacketBytes = length + 1;
+
+        status = RAIL_GetRxTimeSyncWordEndAlt(gRailHandle, &packetDetails);
+        assert(status == RAIL_STATUS_NO_ERROR);
+        sReceiveFrame.mInfo.mRxInfo.mTimestamp = packetDetails.timeReceived.packetTime;
+
+        // Set this flag only when the packet is really acknowledged with frame pending set.
+        sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending =
+            wasAckedWithFramePending(sReceiveFrame.mPsdu, sReceiveFrame.mLength);
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+
+        if (otPlatDiagModeGet())
+        {
+            otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
+        }
+        else
+#endif
+        {
+            otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
+            otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+            sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
+#endif
+        }
+    }
+
+    otSysEventSignalPending();
+
+exit:
+
+    if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
+    {
+        RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
+    }
+}
+
+static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
+{
+    RAIL_Status_t status;
+
+    if (sIsSrcMatchEnabled)
+    {
+        RAIL_IEEE802154_Address_t sourceAddress;
+
+        status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
+        assert(status == RAIL_STATUS_NO_ERROR);
+
+        if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
+             utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
+            (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
+             utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
+        {
+            status = RAIL_IEEE802154_SetFramePending(aRailHandle);
+            assert(status == RAIL_STATUS_NO_ERROR);
+            insertIeee802154DataRequestCommand(aRailHandle);
+        }
+    }
+    else
+    {
+        status = RAIL_IEEE802154_SetFramePending(aRailHandle);
+        assert(status == RAIL_STATUS_NO_ERROR);
+        insertIeee802154DataRequestCommand(aRailHandle);
+    }
+}
+
+static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
+{
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+    if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
+    {
+        sRailDebugCounters.mRailEventConfigScheduled++;
+    }
+    if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
+    {
+        sRailDebugCounters.mRailEventConfigUnScheduled++;
+    }
+#endif
+    if (aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
+    {
+        ieee802154DataRequestCommand(aRailHandle);
+    }
+
+    if (aEvents & RAIL_EVENTS_TX_COMPLETION)
+    {
+        if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
+        {
+            if ((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
+            {
+                RAIL_YieldRadio(aRailHandle);
+                sTransmitError = OT_ERROR_NONE;
+                sTransmitBusy  = false;
+            }
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+            sRailDebugCounters.mRailEventPacketSent++;
+#endif
+        }
+        else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
+        {
+            RAIL_YieldRadio(aRailHandle);
+            sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+            sTransmitBusy  = false;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+            sRailDebugCounters.mRailEventChannelBusy++;
+#endif
+        }
+        else
+        {
+            RAIL_YieldRadio(aRailHandle);
+            sTransmitError = OT_ERROR_ABORT;
+            sTransmitBusy  = false;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+            sRailDebugCounters.mRailEventTxAbort++;
+#endif
+        }
+    }
+
+    if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
+    {
+        RAIL_YieldRadio(aRailHandle);
+        sTransmitError = OT_ERROR_NO_ACK;
+        sTransmitBusy  = false;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailEventNoAck++;
+#endif
+    }
+
+    if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
+    {
+        RAIL_HoldRxPacket(aRailHandle);
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailEventPacketReceived++;
+#endif
+    }
+
+    if (aEvents & RAIL_EVENT_CAL_NEEDED)
+    {
+        RAIL_Status_t status;
+
+        status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
+        assert(status == RAIL_STATUS_NO_ERROR);
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailEventCalNeeded++;
+#endif
+    }
+
+    if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
+    {
+        const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
+        RAIL_YieldRadio(aRailHandle);
+
+        sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
+
+        if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
+        {
+            sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
+        }
+        else
+        {
+            sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
+        }
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
+#endif
+    }
+    if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
+    {
+        RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
+
+        assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
+
+        if (status == RAIL_SCHEDULER_STATUS_CCA_CSMA_TX_FAIL || status == RAIL_SCHEDULER_STATUS_SINGLE_TX_FAIL ||
+            status == RAIL_SCHEDULER_STATUS_SCHEDULED_TX_FAIL ||
+            (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sTransmitBusy) ||
+            (status == RAIL_SCHEDULER_STATUS_EVENT_INTERRUPTED && sTransmitBusy))
+        {
+            sTransmitError = OT_ERROR_ABORT;
+            sTransmitBusy  = false;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+            sRailDebugCounters.mRailEventSchedulerStatusError++;
+#endif
+        }
+        else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL)
+        {
+            sEnergyScanStatus    = ENERGY_SCAN_STATUS_COMPLETED;
+            sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
+        }
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        else if (sTransmitBusy)
+        {
+            sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
+            sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
+        }
+#endif
+    }
+
+    otSysEventSignalPending();
+}
+
+otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
+}
+
+void efr32RadioProcess(otInstance *aInstance)
+{
+    if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
+    {
+        if (sTransmitError != OT_ERROR_NONE)
+        {
+            otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
+        }
+
+        sState = OT_RADIO_STATE_RECEIVE;
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+        if (otPlatDiagModeGet())
+        {
+            otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
+        }
+        else
+#endif
+            if (((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) || (sTransmitError != OT_ERROR_NONE))
+        {
+            otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
+        }
+        else
+        {
+            otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
+        }
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
+#endif
+
+        otSysEventSignalPending();
+    }
+    else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
+    {
+        sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
+        otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
+        otSysEventSignalPending();
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+        sRailDebugCounters.mRailEventEnergyScanCompleted++;
+#endif
+    }
+
+    processNextRxPacket(aInstance);
+}
+
+otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS);
+    *aPower = sTxPowerDbm;
+
+exit:
+    return error;
+}
+
+otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    RAIL_Status_t status;
+
+    status = RAIL_SetTxPowerDbm(gRailHandle, ((RAIL_TxPower_t)aPower) * 10);
+    assert(status == RAIL_STATUS_NO_ERROR);
+
+    sTxPowerDbm = aPower;
+
+    return OT_ERROR_NONE;
+}
+
+otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError error = OT_ERROR_NONE;
+    otEXPECT_ACTION(aThreshold != NULL, error = OT_ERROR_INVALID_ARGS);
+
+    *aThreshold = sCcaThresholdDbm;
+
+exit:
+    return error;
+}
+
+otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    sCcaThresholdDbm = aThreshold;
+
+    return OT_ERROR_NONE;
+}
+
+int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return EFR32_RECEIVE_SENSITIVITY;
+}
diff --git a/examples/platforms/efr32mg1/rail_config.h b/examples/platforms/efr32mg1/rail_config.h
new file mode 100644
index 0000000..5a62825
--- /dev/null
+++ b/examples/platforms/efr32mg1/rail_config.h
@@ -0,0 +1,14 @@
+#ifndef __RAIL_CONFIG_H__
+#define __RAIL_CONFIG_H__
+
+#include "board_config.h"
+#include "rail_types.h"
+#include <stdint.h>
+
+#define RADIO_CONFIG_XTAL_FREQUENCY 38400000UL
+
+#if RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
+extern const RAIL_ChannelConfig_t *channelConfigs[];
+#endif
+
+#endif // __RAIL_CONFIG_H__
diff --git a/examples/platforms/efr32mg1/startup-gcc.c b/examples/platforms/efr32mg1/startup-gcc.c
new file mode 100644
index 0000000..85c9e2a
--- /dev/null
+++ b/examples/platforms/efr32mg1/startup-gcc.c
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2020, 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/efr32mg1/system.c b/examples/platforms/efr32mg1/system.c
new file mode 100644
index 0000000..7b1aa3c
--- /dev/null
+++ b/examples/platforms/efr32mg1/system.c
@@ -0,0 +1,178 @@
+/*
+ *  Copyright (c) 2020, 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 <assert.h>
+#include <string.h>
+
+#include "openthread-system.h"
+#include <openthread/platform/uart.h>
+
+#include "common/logging.hpp"
+
+#include "bsp.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_emu.h"
+#include "em_system.h"
+#include "hal-config.h"
+#include "hal_common.h"
+#include "rail.h"
+#include "sl_mpu.h"
+#include "sl_sleeptimer.h"
+
+#include "openthread-core-efr32-config.h"
+#include "platform-efr32.h"
+
+#if (HAL_FEM_ENABLE)
+#include "fem-control.h"
+#endif
+
+#define USE_EFR32_LOG (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
+
+void halInitChipSpecific(void);
+
+otInstance *sInstance;
+static bool (*sCanSleepCallback)(void);
+
+void otSysInit(int argc, char *argv[])
+{
+    OT_UNUSED_VARIABLE(argc);
+    OT_UNUSED_VARIABLE(argv);
+    sl_status_t status;
+
+    __disable_irq();
+
+#undef FIXED_EXCEPTION
+#define FIXED_EXCEPTION(vectorNumber, functionName, deviceIrqn, deviceIrqHandler)
+#define EXCEPTION(vectorNumber, functionName, deviceIrqn, deviceIrqHandler, priorityLevel, subpriority) \
+    NVIC_SetPriority(deviceIrqn, NVIC_EncodePriority(PRIGROUP_POSITION, priorityLevel, subpriority));
+#include NVIC_CONFIG
+#undef EXCEPTION
+
+    NVIC_SetPriorityGrouping(PRIGROUP_POSITION);
+    CHIP_Init();
+    halInitChipSpecific();
+    BSP_Init(BSP_INIT_BCC);
+
+    CMU_ClockSelectSet(cmuClock_LFE, cmuSelect_LFRCO);
+    CMU_ClockEnable(cmuClock_CORELE, true);
+    CMU_ClockEnable(cmuClock_RTCC, true);
+    status = sl_sleeptimer_init();
+    assert(status == SL_STATUS_OK);
+
+#if (HAL_FEM_ENABLE)
+    initFem();
+    wakeupFem();
+#endif
+
+    __enable_irq();
+
+#if USE_EFR32_LOG
+    efr32LogInit();
+#endif
+    efr32RadioInit();
+    efr32AlarmInit();
+    efr32MiscInit();
+    efr32RandomInit();
+}
+
+bool otSysPseudoResetWasRequested(void)
+{
+    return false;
+}
+
+void otSysDeinit(void)
+{
+    efr32RadioDeinit();
+
+#if USE_EFR32_LOG
+    efr32LogDeinit();
+#endif
+}
+
+void efr32SetSleepCallback(bool (*aCallback)(void))
+{
+    sCanSleepCallback = aCallback;
+}
+
+void efr32Sleep(void)
+{
+    bool canDeepSleep      = false;
+    int  wakeupProcessTime = 1000;
+    CORE_DECLARE_IRQ_STATE;
+
+    if (RAIL_Sleep(wakeupProcessTime, &canDeepSleep) == RAIL_STATUS_NO_ERROR)
+    {
+        if (canDeepSleep)
+        {
+            CORE_ENTER_ATOMIC();
+            if (sCanSleepCallback != NULL && sCanSleepCallback())
+            {
+                EMU_EnterEM2(true);
+            }
+            CORE_EXIT_ATOMIC();
+            // TODO OT will handle an interrupt here and it mustn't call any RAIL APIs
+
+            while (RAIL_Wake(0) != RAIL_STATUS_NO_ERROR)
+            {
+            }
+        }
+        else
+        {
+            CORE_ENTER_ATOMIC();
+            if (sCanSleepCallback != NULL && sCanSleepCallback())
+            {
+                EMU_EnterEM1();
+            }
+            CORE_EXIT_ATOMIC();
+        }
+    }
+}
+
+void otSysProcessDrivers(otInstance *aInstance)
+{
+    sInstance = aInstance;
+
+    // should sleep and wait for interrupts here
+
+    efr32UartProcess();
+    efr32RadioProcess(aInstance);
+    efr32AlarmProcess(aInstance);
+}
+
+__WEAK void otSysEventSignalPending(void)
+{
+    // Intentionally empty
+}
diff --git a/examples/platforms/efr32mg1/uart.c b/examples/platforms/efr32mg1/uart.c
new file mode 100644
index 0000000..f93f75f
--- /dev/null
+++ b/examples/platforms/efr32mg1/uart.c
@@ -0,0 +1,194 @@
+/*
+ *  Copyright (c) 2020, 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 <stddef.h>
+
+#include "openthread-system.h"
+#include <openthread/platform/uart.h>
+
+#include "utils/code_utils.h"
+
+#include "em_core.h"
+#include "uartdrv.h"
+
+#include "hal-config.h"
+
+enum
+{
+    kReceiveFifoSize = 128,
+};
+
+#define USART_INIT                                                                               \
+    {                                                                                            \
+        USART0,                                               /* USART port */                   \
+            115200,                                           /* Baud rate */                    \
+            BSP_SERIAL_APP_TX_LOC,                            /* USART Tx pin location number */ \
+            BSP_SERIAL_APP_RX_LOC,                            /* USART Rx pin location number */ \
+            (USART_Stopbits_TypeDef)USART_FRAME_STOPBITS_ONE, /* Stop bits */                    \
+            (USART_Parity_TypeDef)USART_FRAME_PARITY_NONE,    /* Parity */                       \
+            (USART_OVS_TypeDef)USART_CTRL_OVS_X16,            /* Oversampling mode*/             \
+            false,                                            /* Majority vote disable */        \
+            HAL_SERIAL_APP_FLOW_CONTROL,                      /* Flow control */                 \
+            BSP_SERIAL_APP_CTS_PORT,                          /* CTS port number */              \
+            BSP_SERIAL_APP_CTS_PIN,                           /* CTS pin number */               \
+            BSP_SERIAL_APP_RTS_PORT,                          /* RTS port number */              \
+            BSP_SERIAL_APP_RTS_PIN,                           /* RTS pin number */               \
+            (UARTDRV_Buffer_FifoQueue_t *)&sUartRxQueue,      /* RX operation queue */           \
+            (UARTDRV_Buffer_FifoQueue_t *)&sUartTxQueue,      /* TX operation queue */           \
+            BSP_SERIAL_APP_CTS_LOC,                           /* CTS location */                 \
+            BSP_SERIAL_APP_RTS_LOC                            /* RTS location */                 \
+    }
+
+DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_RX_BUFS, sUartRxQueue);
+DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_TX_BUFS, sUartTxQueue);
+
+static UARTDRV_HandleData_t sUartHandleData;
+static UARTDRV_Handle_t     sUartHandle = &sUartHandleData;
+static uint8_t              sReceiveBuffer[2];
+static const uint8_t *      sTransmitBuffer = NULL;
+static volatile uint16_t    sTransmitLength = 0;
+
+typedef struct ReceiveFifo_t
+{
+    // The data buffer
+    uint8_t mBuffer[kReceiveFifoSize];
+    // The offset of the first item written to the list.
+    volatile uint16_t mHead;
+    // The offset of the next item to be written to the list.
+    volatile uint16_t mTail;
+} ReceiveFifo_t;
+
+static ReceiveFifo_t sReceiveFifo;
+
+static void processReceive(void);
+
+static void receiveDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount)
+{
+    // We can only write if incrementing mTail doesn't equal mHead
+    if (sReceiveFifo.mHead != (sReceiveFifo.mTail + 1) % kReceiveFifoSize)
+    {
+        sReceiveFifo.mBuffer[sReceiveFifo.mTail] = aData[0];
+        sReceiveFifo.mTail                       = (sReceiveFifo.mTail + 1) % kReceiveFifoSize;
+    }
+
+    UARTDRV_Receive(aHandle, aData, 1, receiveDone);
+    otSysEventSignalPending();
+}
+
+static void transmitDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount)
+{
+    sTransmitLength = 0;
+    otSysEventSignalPending();
+}
+
+static void processReceive(void)
+{
+    // Copy tail to prevent multiple reads
+    uint16_t tail = sReceiveFifo.mTail;
+
+    // If the data wraps around, process the first part
+    if (sReceiveFifo.mHead > tail)
+    {
+        otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, kReceiveFifoSize - sReceiveFifo.mHead);
+
+        // Reset the buffer mHead back to zero.
+        sReceiveFifo.mHead = 0;
+    }
+
+    // For any data remaining, process it
+    if (sReceiveFifo.mHead != tail)
+    {
+        otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, tail - sReceiveFifo.mHead);
+
+        // Set mHead to the local tail we have cached
+        sReceiveFifo.mHead = tail;
+    }
+}
+
+otError otPlatUartFlush(void)
+{
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+static void processTransmit(void)
+{
+    if (sTransmitBuffer != NULL && sTransmitLength == 0)
+    {
+        sTransmitBuffer = NULL;
+        otPlatUartSendDone();
+    }
+}
+
+otError otPlatUartEnable(void)
+{
+    UARTDRV_Init_t uartInit = USART_INIT;
+
+    sReceiveFifo.mHead = 0;
+    sReceiveFifo.mTail = 0;
+
+    UARTDRV_Init(sUartHandle, &uartInit);
+
+    for (uint8_t i = 0; i < sizeof(sReceiveBuffer); i++)
+    {
+        UARTDRV_Receive(sUartHandle, &sReceiveBuffer[i], sizeof(sReceiveBuffer[i]), receiveDone);
+    }
+
+    return OT_ERROR_NONE;
+}
+
+otError otPlatUartDisable(void)
+{
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
+{
+    otError error = OT_ERROR_NONE;
+
+    otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY);
+
+    sTransmitBuffer = aBuf;
+    sTransmitLength = aBufLength;
+
+    UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone);
+
+exit:
+    return error;
+}
+
+void efr32UartProcess(void)
+{
+    processReceive();
+    processTransmit();
+}
diff --git a/third_party/Makefile.am b/third_party/Makefile.am
index a008ae6..cb1a40f 100644
--- a/third_party/Makefile.am
+++ b/third_party/Makefile.am
@@ -45,6 +45,13 @@
 
 SUBDIRS =
 
+if OPENTHREAD_PLATFORM_EFR32MG1
+SUBDIRS                                += \
+    silabs                                \
+    jlink                                 \
+    $(NULL)
+endif
+
 if OPENTHREAD_PLATFORM_EFR32MG12
 SUBDIRS                                += \
     silabs                                \
diff --git a/third_party/silabs/Makefile.am b/third_party/silabs/Makefile.am
index 161585a..82087c3 100644
--- a/third_party/silabs/Makefile.am
+++ b/third_party/silabs/Makefile.am
@@ -28,6 +28,12 @@
 
 include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
 
+if OPENTHREAD_EXAMPLES_EFR32MG1
+lib_LIBRARIES                                                                 = \
+    libsilabs-efr32mg1-sdk.a                                                    \
+    $(NULL)
+endif
+
 if OPENTHREAD_EXAMPLES_EFR32MG12
 lib_LIBRARIES                                                                 = \
     libsilabs-efr32mg12-sdk.a                                                   \
@@ -114,6 +120,12 @@
     -Wno-missing-field-initializers                                             \
     $(NULL)
 
+SILABS_EFR32MG1_CPPFLAGS                                                      = \
+    -I$(SDK_SRC_DIR)/hardware/kit/EFR32MG1_$(BOARD)/config                      \
+    -I$(SDK_SRC_DIR)/platform/Device/SiliconLabs/EFR32MG1P/Include              \
+    -I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32/efr32xg1x               \
+    $(NULL)
+
 SILABS_EFR32MG12_CPPFLAGS                                                     = \
     -I$(SDK_SRC_DIR)/hardware/kit/EFR32MG12_$(BOARD)/config                     \
     -I$(SDK_SRC_DIR)/platform/Device/SiliconLabs/EFR32MG12P/Include             \
@@ -172,6 +184,11 @@
     gecko_sdk_suite/v2.7/util/third_party/mbedtls/sl_crypto/src/shax.c                    \
     $(NULL)
 
+SILABS_EFR32MG1_SOURCES                                                                           = \
+    gecko_sdk_suite/v2.7/platform/Device/SiliconLabs/EFR32MG1P/Source/system_efr32mg1p.c            \
+    gecko_sdk_suite/v2.7/platform/Device/SiliconLabs/EFR32MG1P/Source/GCC/startup_efr32mg1p.c       \
+    $(NULL)
+
 SILABS_EFR32MG12_SOURCES                                                                          = \
     gecko_sdk_suite/v2.7/platform/Device/SiliconLabs/EFR32MG12P/Source/system_efr32mg12p.c          \
     gecko_sdk_suite/v2.7/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/startup_efr32mg12p.c     \
@@ -198,6 +215,16 @@
     gecko_sdk_suite/v2.7/util/third_party/mbedtls/sl_crypto/src/se_trng.c                       \
     $(NULL)
 
+libsilabs_efr32mg1_sdk_a_CPPFLAGS                                                             = \
+    $(COMMONCPPFLAGS)                                                                           \
+    $(SILABS_EFR32MG1_CPPFLAGS)                                                                 \
+    $(NULL)
+
+libsilabs_efr32mg1_sdk_a_SOURCES                                                              = \
+    $(SILABS_COMMON_SOURCES)                                                                    \
+    $(SILABS_EFR32MG1_SOURCES)                                                                  \
+    $(NULL)
+
 libsilabs_efr32mg12_sdk_a_CPPFLAGS                                                            = \
     $(COMMONCPPFLAGS)                                                                           \
     $(SILABS_EFR32MG12_CPPFLAGS)                                                                \