Added support for DA15000. (#919)

This commit is contained in:
JakubBrachTieto
2017-01-04 20:48:42 -08:00
committed by Jonathan Hui
parent a360f2e46e
commit 9c12733366
92 changed files with 50978 additions and 2 deletions
+11 -2
View File
@@ -812,11 +812,11 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_APPLICATION_COAP],[${OPENTHREAD_ENABLE_APP
AC_ARG_WITH(examples,
[AS_HELP_STRING([--with-examples=TARGET],
[Specify the examples from one of: none, posix, cc2538 @<:@default=none@:>@.])],
[Specify the examples from one of: none, posix, cc2538, da15000 @<:@default=none@:>@.])],
[
case "${with_examples}" in
none|posix|cc2538)
none|posix|cc2538|da15000)
;;
*)
AC_MSG_ERROR([Invalid value ${with_examples} for --with-examples])
@@ -839,6 +839,10 @@ case ${with_examples} in
AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_CC2538],[${OPENTHREAD_EXAMPLES_CC2538}],[Define to 1 if you want to use cc2538 examples])
;;
da15000)
OPENTHREAD_EXAMPLES_DA15000=1
;;
esac
AC_MSG_RESULT(${OPENTHREAD_EXAMPLES})
@@ -872,6 +876,10 @@ if test "$PLATFORM_INFO" != "none"; then
AC_DEFINE_UNQUOTED([PLATFORM_INFO],["${PLATFORM_INFO}"],[OpenThread platform information])
fi
AC_SUBST(OPENTHREAD_EXAMPLES_DA15000)
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_DA15000], [test "${OPENTHREAD_EXAMPLES}" = "da15000"])
AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_DA15000],[${OPENTHREAD_EXAMPLES_DA15000}],[Define to 1 if you want to use da15000 examples])
#
# Tools
#
@@ -988,6 +996,7 @@ examples/apps/cli/Makefile
examples/apps/ncp/Makefile
examples/platforms/Makefile
examples/platforms/cc2538/Makefile
examples/platforms/da15000/Makefile
examples/platforms/posix/Makefile
examples/platforms/utils/Makefile
tools/Makefile
+269
View File
@@ -0,0 +1,269 @@
#
# 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.
.NOTPARALLEL:
AR = arm-none-eabi-ar
AS = 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
configure_OPTIONS = \
--enable-cli \
--enable-ncp \
--with-examples=da15000 \
$(NULL)
ifeq ($(CLI_LOGGING),1)
configure_OPTIONS += --enable-cli-logging
endif
ifeq ($(CERT_LOG),1)
configure_OPTIONS += --enable-cert-log
endif
ifeq ($(COMMISSIONER),1)
configure_OPTIONS += --enable-commissioner
endif
ifeq ($(JOINER),1)
configure_OPTIONS += --enable-joiner
endif
ifeq ($(DHCP6_SERVER),1)
configure_OPTIONS += --enable-dhcp6-server
endif
ifeq ($(DHCP6_CLIENT),1)
configure_OPTIONS += --enable-dhcp6-client
endif
COMMONCFLAGS = \
-fdata-sections \
-ffunction-sections \
-Os \
-g \
$(NULL)
CPPFLAGS = \
$(COMMONCFLAGS) \
$(target_CPPFLAGS) \
$(NULL)
CFLAGS = \
$(COMMONCFLAGS) \
$(target_CFLAGS) \
$(NULL)
CXXFLAGS = \
$(COMMONCFLAGS) \
$(target_CXXFLAGS) \
-fno-exceptions \
-fno-rtti \
$(NULL)
LDFLAGS = \
$(COMMONCFLAGS) \
$(target_LDFLAGS) \
-nostartfiles \
-specs=nano.specs \
-specs=nosys.specs \
-Wl,--gc-sections \
-Wl,-Map=map.map \
$(NULL)
ECHO := @echo
MAKE := make
MKDIR_P := mkdir -p
LN_S := ln -s
RM_F := rm -f
INSTALL := /usr/bin/install
INSTALLFLAGS := -p
TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
BuildPath = build
TopBuildDir = $(BuildPath)
AbsTopBuildDir = $(PWD)/$(TopBuildDir)
ResultPath = output
TopResultDir = $(ResultPath)
AbsTopResultDir = $(PWD)/$(TopResultDir)
TargetTuple = arm-none-eabi
ARCHS = cortex-m0
TopTargetLibDir = $(TopResultDir)/$(if $(1),$(1)-,)$(TargetTuple)/lib
#
# configure-arch <arch>
#
# Configure OpenThread for the specified architecture.
#
# arch - The architecture to configure.
#
define configure-arch
$(ECHO) " CONFIG $(1)-$(TargetTuple)..."
(cd $(BuildPath)/$(1)-$(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 \
--target=arm-none-eabi \
--prefix=/ \
$(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 $(1)-$(TargetTuple)"
$(MAKE) -C $(BuildPath)/$(1)-$(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 $(1)-$(TargetTuple)"
$(MAKE) -C $(BuildPath)/$(1)-$(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)/$(1)-$(TargetTuple)
DIRECTORIES += $(BuildPath)/$(1)-$(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)/$(1)-$(TargetTuple)/config.status
$(BuildPath)/$(1)-$(TargetTuple)/config.status: | $(BuildPath)/$(1)-$(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-m0
#
cortex-m0_target_ABI = cortex-m0
cortex-m0_target_CPPFLAGS = -mcpu=cortex-m0 -mfloat-abi=soft -mthumb
cortex-m0_target_CFLAGS = -mcpu=cortex-m0 -mfloat-abi=soft -mthumb
cortex-m0_target_CXXFLAGS = -mcpu=cortex-m0 -mfloat-abi=soft -mthumb
cortex-m0_target_LDFLAGS = -mcpu=cortex-m0 -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) ""
+11
View File
@@ -78,6 +78,17 @@ LDFLAGS_COMMON += \
$(NULL)
endif # OPENTHREAD_EXAMPLES_CC2538
if OPENTHREAD_EXAMPLES_DA15000
LDADD_COMMON += \
$(top_builddir)/examples/platforms/da15000/libopenthread-da15000.a \
$(NULL)
LDFLAGS_COMMON += \
-T $(top_srcdir)/examples/platforms/da15000/da15000.ld \
$(NULL)
endif
ot_cli_ftd_CPPFLAGS = \
$(CPPFLAGS_COMMON) \
$(NULL)
+10
View File
@@ -75,6 +75,16 @@ ot_ncp_LDFLAGS += \
$(NULL)
endif
if OPENTHREAD_EXAMPLES_DA15000
ot_ncp_LDADD += \
$(top_builddir)/examples/platforms/da15000/libopenthread-da15000.a \
$(NULL)
ot_ncp_LDFLAGS += \
-T $(top_srcdir)/examples/platforms/da15000/da15000.ld \
$(NULL)
endif
ot_ncp_SOURCES = \
main.c \
$(NULL)
+6
View File
@@ -32,6 +32,7 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
DIST_SUBDIRS = \
cc2538 \
da15000 \
posix \
utils \
$(NULL)
@@ -50,10 +51,15 @@ if OPENTHREAD_EXAMPLES_CC2538
SUBDIRS += cc2538
endif
if OPENTHREAD_EXAMPLES_DA15000
SUBDIRS = da15000
endif
# Always pretty (e.g. for 'make pretty') these subdirectories.
PRETTY_SUBDIRS = \
cc2538 \
da15000 \
posix \
utils \
$(NULL)
+111
View File
@@ -0,0 +1,111 @@
#
# 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.
#
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
lib_LIBRARIES = libopenthread-da15000.a
libopenthread_da15000_a_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/peripherals/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/adapters/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/memory/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/interfaces/ftdf/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/config \
-I$(top_srcdir)/third_party/dialog/DialogSDK \
-I$(top_srcdir)/third_party/dialog/DialogSDK/interfaces/ftdf/src \
-include$(top_srcdir)/examples/platforms/da15000/custom_config_qspi.h \
-Wno-unknown-pragmas \
-Wno-sign-compare \
-Wno-unused-function \
-Wno-unused-parameter \
-Wno-shadow \
-Wno-type-limits \
-Wno-unused-variable \
-Wno-missing-field-initializers \
-fno-strict-aliasing \
$(NULL)
libopenthread_da15000_settings.cpp: $(srcdir)/../utils/settings.cpp
cp $? $@
CLEANFILES = libopenthread_da15000_settings.cpp
libopenthread_da15000_a_SOURCES = \
alarm.c \
flash.c \
logging.c \
platform.c \
radio.c \
random.c \
vector.c \
cstartup.c \
uart.c \
cortex-m_cstartup.c \
startup-gcc.c \
libopenthread_da15000_settings.cpp \
clock.c \
misc.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/memory/src/qspi_automode.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_qspi.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_timer0.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_gpio.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_cpm.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_trng.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_rf.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_hard_fault.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_watchdog.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/sys_tcs.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_uart.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_otpc.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_fem_sky66112-11.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_dma.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/common.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/power.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/data.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/ad_ftdf_phy_api.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/ad_ftdf.c \
@top_builddir@/third_party/dialog/DialogSDK/interfaces/ftdf/src/main.c \
$(NULL)
noinst_HEADERS = \
platform-da15000.h \
$(NULL)
if OPENTHREAD_BUILD_COVERAGE
CLEANFILES += $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+111
View File
@@ -0,0 +1,111 @@
# Dialog OpenThread DA15000 Example
This directory contains example platform drivers for the [Dialog Semiconductor DA15000][da15000]
[da15000]: https://support.dialog-semiconductor.com/connectivity/product/openthread-sandbox
**NOTE:** Each Thread node requires a unique EUI-64.
Please make sure all Thread nodes in your network have a unique EUI-64 by setting NODE_ID in radio.c to a unique value.
## Build Examples (How to build and flash):
```bash
$ cd <path-to-openthread>
$ ./bootstrap
$ make -f examples/Makefile-da15000 clean
$ make -f examples/Makefile-da15000
```
Execute script to prepare image for flashing:
**NOTE:** Script is based on Dialog Tools binaries compiled for x86 Linux.
```bash
$ cd ./third_party/dialog/DialogTools
$ ./imgprep.sh
```
Flash Binaries:
**NOTE:** Flashing process requires JLinkGDBServer. Please visit https://www.segger.com/jlink-gdb-server.html for details.
1. Open another terminal window in order to start gdb server. Write the command (Linux):
```bash
$ JLinkGDBServer -ir -if swd -speed auto -device Cortex-M0 -logtofile on -localhostonly
```
2. Return to previous terminal window and execute a command in order to flash the board:
```bash
$ ./cli_programmer -b uartboot.bin gdbserver write_qspi 0x0 ../../../output/bin/arm-none-eabi-ot-cli-ftd.img
```
## Interact:
Board will indicate state of device according to LED blink speed.
| Frequency | Role |
| --- | --- |
| 5Hz | Leader |
| 2Hz | Router |
| 0.5Hz | End Device |
1. Open terminal to /dev/ttyACM0 (serial port settings: 9600 8-N-1).
2. Type help for list of commands
## Examples:
1. Create Topology and become Leader on channel 13.
```
> channel 13
Done
> panid 0xface
Done
> ifconfig up
Done
> thread start
Done
```
Wait and see that LED started to blink with 5Hz.
Check node state:
```
> state
Leader
```
2. Attach Router and ping Leader Mesh Local address.
Open terminal for second device /dev/ttyACM1 and issue commands:
```
> channel 13
Done
> panid 0xface
Done
> ifconfig up
Done
> thread start
```
Wait until LED start to blink. Should blink slower.
Check node state:
```
> state
Router
```
List addresses on terminal with Leader:
```
> ipaddr
fdde:ad00:beef:0:0:ff:fe00:4400
fdde:ad00:beef:0:92f5:9844:67ad:a0c9
fe80:0:0:0:2c11:aba1:ecc1:96da
```
Ping Leader from Router terminal:
```
> ping fdde:ad00:beef:0:92f5:9844:67ad:a0c9
16 bytes from fdde:ad00:beef:0:92f5:9844:67ad:a0c9: icmp_seq=2 hlim=64 time=359ms
```
+104
View File
@@ -0,0 +1,104 @@
/*
* 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 alarm.c
* Platform abstraction for the alarm
*/
#include <stdbool.h>
#include <stdint.h>
#include <platform/alarm.h>
#include "hw_timer0.h"
#include "hw_gpio.h"
#include "platform-da15000.h"
static bool s_is_running = false;
static uint32_t s_alarm = 0;
static uint32_t s_counter;
volatile bool s_alarm_fired = false;
static void timer0_interrupt_cb(void)
{
s_counter++;
}
void da15000AlarmProcess(otInstance *aInstance)
{
if ((s_is_running) && (s_alarm <= s_counter))
{
s_is_running = false;
otPlatAlarmFired(aInstance);
}
}
void da15000AlarmInit(void)
{
hw_timer0_init(NULL);
hw_timer0_set_clock_source(HW_TIMER0_CLK_SRC_FAST);
hw_timer0_set_pwm_mode(HW_TIMER0_MODE_PWM);
hw_timer0_set_fast_clock_div(HW_TIMER0_FAST_CLK_DIV_4);
hw_timer0_set_t0_reload(0x07D0, 0x07D0);
hw_timer0_register_int(timer0_interrupt_cb);
hw_timer0_set_on_clock_div(false);
}
uint32_t otPlatAlarmGetNow(void)
{
return s_counter;
}
void otPlatAlarmStartAt(otInstance *aInstance, uint32_t t0, uint32_t dt)
{
(void)aInstance;
s_alarm = t0 + dt;
s_is_running = true;
if (s_counter == 0)
{
hw_timer0_enable();
}
if (s_is_running == false)
{
s_is_running = true;
}
hw_timer0_unfreeze();
}
void otPlatAlarmStop(otInstance *aInstance)
{
(void)aInstance;
s_is_running = false;
hw_timer0_freeze();
}
+62
View File
@@ -0,0 +1,62 @@
/*
* 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 clock.c
* Clock init for Dialog da15000.
*
*/
#include "global_io.h"
#include "hw_cpm.h"
#include "hw_watchdog.h"
volatile uint8_t xtal16_settled = 0;
extern void XTAL16RDY_Handler(void);
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.
DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT
THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower
numeric values on an ARM Cortex-M). */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
void switch_to_rc16(void)
{
if (!hw_cpm_check_rc16_status()) // RC16 is disabled
{
hw_cpm_enable_rc16(); // Enable RC16
hw_cpm_short_delay(); // Wait until it is stable
}
// fast --> slow clock switch
hw_cpm_set_sysclk(SYS_CLK_IS_RC16); // Set RC16 as sys_clk
//cm_adjust_otp_access_timings(); // Adjust OTP timings
}
@@ -0,0 +1,116 @@
/*
* 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 cortex-m_cstartup.c
* ARM Cortex-M generic cstartup.
*
* Setup RAM as needed based on GCC linker script sections.
*/
#include <stdint.h>
//#include <tool.h>
#define __NAKED __attribute__((naked))
#define __USED __attribute__((used))
#define __NO_RETURN __attribute__((noreturn))
// forward declaration
extern void main(void);
extern void __cpu_startup(void);
extern void __gcc_program_start(void);
extern uint32_t __rwdata_start__; // End of .text region in FLASH
extern uint32_t _sdata; // Start of .data region in RAM
extern uint32_t _edata; // End of .data region in RAM
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
extern uint32_t __init_array_start;
extern uint32_t __init_array_end;
/********************************************************************/
void cstartup_rwdata()
{
// Get the addresses for the .data section (initialized data section)
uint32_t *data_rom = (uint32_t *) &__rwdata_start__;
uint32_t *data_ram = (uint32_t *) &_sdata;
uint32_t *data_ram_end = (uint32_t *) &_edata;
// Copy initialized data from ROM to RAM
while (data_ram < data_ram_end)
{
*data_ram++ = *data_rom++;
}
}
void cstartup_bss()
{
/* Clear the zero-initialized data section */
uint32_t *bss_start = (uint32_t *) &__bss_start__;
uint32_t *bss_end = (uint32_t *) &__bss_end__;
while (bss_start < bss_end)
{
*bss_start++ = 0;
}
}
void cstartup(void)
{
cstartup_rwdata();
cstartup_bss();
}
/********************************************************************/
/**
* ARM Cortex-M Start
*
* This function calls all of the needed startup routines and then
* branches to the main process.
*
* This contains the very first instructions that are run on boot.
*/
void __USED __NAKED __NO_RETURN __gcc_program_start(void)
{
// early platform initialization - configure clocks, etc.
__cpu_startup();
// C/C++ runtime initialization (BSS, Data, relocation, etc.)
cstartup();
// TBD we should pass parameters here.
main();
// No actions to perform after this so wait forever
while (1);
}
+54
View File
@@ -0,0 +1,54 @@
/*
* 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 cstartup.c
* cstartup for Dialog da15000.
* Called by __BOOT_STARTUP to initialize the processor on boot.
* The caller is aliased in tool.h to a compiler dependant value:
* IAR: __low_level_init
* GCC: __gcc_program_start
*
* For Cortex-M cores, called from cpu/arm/cortex-m/boot/cstartup.c.
*/
#include "global_io.h"
#include "bsp/include/black_orca.h"
#include "bsp/include/core_cm0.h"
void __cpu_startup(void)
{
// SetWord16(CLK_AMBA_REG, 0x00); // set clocks (hclk and pclk ) 16MHz
// SetWord16(SET_FREEZE_REG,FRZ_WDOG); // stop watchdog
// SetBits16(SYS_CTRL_REG,PAD_LATCH_EN,1); // enable pads
ENABLE_DEBUGGER; // enable debugger
// SetBits16(PMU_CTRL_REG, PERIPH_SLEEP,0); // exit peripheral power down
// SetBits16(PMU_CTRL_REG, RETAIN_RAM, dg_configMEM_RETENTION_MODE);
// SetBits16(AON_SPARE_REG, EN_BATSYS_RET, 1); // Power GPIOs during sleep
}
+116
View File
@@ -0,0 +1,116 @@
/*
* 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 custom_config_qspi.h
* Custom configuration file for FreeRTOS applications executing from QSPI.
*/
#ifndef CUSTOM_CONFIG_QSPI_H_
#define CUSTOM_CONFIG_QSPI_H_
#include "bsp_definitions.h"
#undef CONFIG_USE_BLE
#define CONFIG_USE_FTDF
#define __HEAP_SIZE 0x0600
#define __STACK_SIZE 0x0100
#define CONFIG_RETARGET
#define CONFIG_RETARGET_UART HW_UART1
#define dg_configPOWER_CONFIG (POWER_CONFIGURATION_2)
#define dg_configUSE_LP_CLK LP_CLK_32768
#define dg_configEXEC_MODE MODE_IS_CACHED
#define dg_configCODE_LOCATION NON_VOLATILE_IS_FLASH
#define dg_configEXT_CRYSTAL_FREQ EXT_CRYSTAL_IS_16M
#define dg_configIMAGE_SETUP DEVELOPMENT_MODE
#define dg_configEMULATE_OTP_COPY (0)
#define dg_configUSER_CAN_USE_TIMER1 (0)
#define dg_configMEM_RETENTION_MODE (0x1F)
#define dg_configMEM_RETENTION_MODE_PRESERVE_IMAGE (0x1F)
#define dg_configSHUFFLING_MODE (0x3)
#define dg_configUSE_WDOG (0)
#define dg_configUSE_DCDC (1)
#define dg_configPOWER_FLASH (1)
#define dg_configFLASH_POWER_DOWN (0)
#define dg_configFLASH_POWER_OFF (0)
#define dg_configBATTERY_TYPE (BATTERY_TYPE_LIMN2O4)
#define dg_configBATTERY_CHARGE_CURRENT 2 // 30mA
#define dg_configBATTERY_PRECHARGE_CURRENT 20 // 2.1mA
#define dg_configBATTERY_CHARGE_NTC 1 // disabled
#define dg_configUSE_USB 0
#define dg_configUSE_USB_CHARGER 0
#define dg_configALLOW_CHARGING_NOT_ENUM 1
#define dg_configUSE_ProDK (1)
#define dg_configUSE_SW_CURSOR (1)
#define dg_configCACHEABLE_QSPI_AREA_LEN NVMS_PARAM_PART_start
#define dg_configFEM_DLG_REF_BOARD (1)
#define dg_configUSE_HW_TRNG (1)
#define dg_configUSE_HW_TIMER0 (1)
/*************************************************************************************************\
* OS specific config
*/
#define OS_BAREMETAL
#define CPU_DA15000 (1)
/*************************************************************************************************\
* Peripheral specific config
*/
#define FTDF_PHY_API
#define dg_configUSE_HW_RF (1)
#define dg_configRF_ENABLE_RECALIBRATION (0)
#define FTDF_NO_CSL
#define FTDF_NO_TSCH
#define FTDF_LITE
#define dg_configFLASH_ADAPTER (0)
#define dg_configNVMS_ADAPTER (0)
#define dg_configNVMS_VES (0)
#define dg_configUSE_WDOG (0)
/* Include bsp default values */
#include "bsp_defaults.h"
#endif /* CUSTOM_CONFIG_QSPI_H_ */
+205
View File
@@ -0,0 +1,205 @@
/*
* 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.
*/
/******************************************************************************/
/* Peripheral memory map */
/******************************************************************************/
_BOOTLOADER_SIZE = 0 ;
_QSPI_SIZE = 2048K ; /* ld doesn't allow defines to be used for MEMORY */
_EXE_SIZE = 108K ; /* In RAM config, reserve space for the executable... */
_TEXT_START = 0x140 ;
MEMORY
{
vector (rx) : ORIGIN = 0x00000000, LENGTH = 0x0C0
magic (r) : ORIGIN = 0x000000C0, LENGTH = 0x080 /* patch table */
flash (rx) : ORIGIN = 0x00000140, LENGTH = 2048K
rom (rx) : ORIGIN = 0x07F00000, LENGTH = 256K
otp (rx) : ORIGIN = 0x07F80000, LENGTH = 256K
ram (rwx) : ORIGIN = 0x07FC0000+0x140, LENGTH = 128K-0x140
cacheram (rwx) : ORIGIN = 0x07FE0000, LENGTH = 16K
qspi (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
}
/**
* GCC linker script for ARM Cortex-M microcontrollers.
*/
/*
ENTRY(_start)
*/
ENTRY(__gcc_program_start)
/*
* Reserve memory for heap and stack. The linker will issue an error if there
* is not enough memory.
*
* NOTE: The reserved heap and stack will be added to the bss column of the
* binutils size command.
*/
_heap_size = 0x0; /* required amount of heap */
_stack_size = 0x0; /* required amount of stack */
/*
* The stack starts at the end of RAM and grows downwards. Full-descending
* stack; decrement first, then store.
*/
__stack_start__ = ORIGIN(ram) + LENGTH(ram);
__stack_end__ = __stack_start__ - _stack_size;
EXTERN(__vector_table)
SECTIONS
{
/* Reset and ISR vectors */
.isr_vector :
{
__isr_vector_start__ = .;
__cs3_interrupt_vector = __vector_table;
KEEP(*(.isr_vector))
ASSERT(. != __isr_vector_start__, "The .isr_vector section is empty");
} >vector
/* Special configuration section for some processors */
.magic :
{
KEEP(*(.magic))
} >magic
/* Text section (code and read-only data) */
.text :
{
. = _TEXT_START;
. = ALIGN(4);
_stext = .;
*(.text*) /* code */
_etext = .;
__rodata_start__ = .;
*(.rodata*) /* read only data */
/*
* Note: No ARM/Thumb interworking, so no .glue_7 or .glue_7t sections
*/
*(.ctors)
*(.dtors)
/* Static constructors and destructors */
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
} >flash
/*
* Stack unwinding and exception handling sections.
*
* ARM compilers emit object files with .ARM.extab and .ARM.exidx sections
* when using C++ exceptions. Also, at least GCC emits those sections when
* dividing large numbers (64-bit) in C. So we have to handle them.
*
* (ARM uses .ARM.extab and .ARM.exidx instead of the .eh_frame section
* used on x86.)
*/
.ARM.extab : /* exception unwinding information */
{
*(.ARM.extab*)
} >flash
.ARM.exidx : /* index entries for section unwinding */
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >flash
/*
* Initialized data section. This section is programmed into FLASH (LMA
* address) and copied to RAM (VMA address) in startup code.
*/
. = ALIGN(4);
__rwdata_start__ = .; /* LMA address is _sidata (in FLASH) */
.data : AT(__rwdata_start__)
{
. = ALIGN(4);
_sdata = .; /* data section VMA address */
*(text_retained)
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
_edata = .;
} >ram
/* Uninitialized data section (zeroed out by startup code) */
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__end__ = .;
} >ram
/*
* Reserve memory for heap and stack. The linker will issue an error if
* there is not enough memory.
*/
._heap :
{
. = ALIGN(4);
_sheap = .;
. = . + _heap_size;
. = ALIGN(4);
_eheap = .;
} >ram
._stack :
{
. = ALIGN(4);
. = . + _stack_size;
. = ALIGN(4);
} >ram
}
/* Nice to have */
__isr_vector_size__ = SIZEOF(.isr_vector);
__text_size__ = SIZEOF(.text);
__data_size__ = SIZEOF(.data);
__bss_size__ = SIZEOF(.bss);
PROVIDE (end = .);
+164
View File
@@ -0,0 +1,164 @@
/*
* 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.
*/
#include <openthread-types.h>
#include "hw_qspi.h"
#include "qspi_automode.h"
#include "platform/alarm.h"
#include "openthread-config.h"
#define FLASH_SECTOR_SIZE 0x1000
#define FLASH_PAGE_SIZE 0x0100
#define FLASH_BUFFER_SIZE 0x2000 // 8kB
#define FLASH_OFFSET 0x7B000 // Flash memory size is 512kB (0x7D000) and starts from 0x8000000. Offset point to 500kB position
#define W25Q_READ_STATUS_REGISTER1 0x05
/* Erase/Write in progress */
#define W25Q_STATUS1_BUSY_BIT 0
#define W25Q_STATUS1_BUSY_MASK (1 << W25Q_STATUS1_BUSY_BIT)
static uint32_t wait_status_timeout;
#define QSPI_SECTION __attribute__ ((section ("text_retained")))
QSPI_SECTION static inline uint8_t qspi_get_erase_status(void)
{
QSPIC->QSPIC_CHCKERASE_REG = 0;
return HW_QSPIC_REG_GETF(ERASECTRL, ERS_STATE);
}
// Erase QSPI memory section as non-blocking function. Remember to check utilsFlashStatusWait before write or read!!
ThreadError utilsFlashErasePage(uint32_t aAddress)
{
uint32_t flash_offset = (aAddress + FLASH_OFFSET) & ~(FLASH_SECTOR_SIZE - 1);
if (aAddress > FLASH_BUFFER_SIZE)
{
return kThreadError_InvalidArgs;
}
/* Setup erase block page */
HW_QSPIC_REG_SETF(ERASECTRL, ERS_ADDR, (flash_offset >>= 4));
/* Fire erase */
HW_QSPIC_REG_SETF(ERASECTRL, ERASE_EN, 1);
CACHE->CACHE_CTRL1_REG = CACHE_CACHE_CTRL1_REG_CACHE_FLUSH_Msk;
return kThreadError_None;
}
uint32_t utilsFlashGetSize(void)
{
return (uint32_t)FLASH_BUFFER_SIZE;
}
ThreadError utilsFlashStatusWait(uint32_t aTimeout)
{
wait_status_timeout = otPlatAlarmGetNow();
while (qspi_get_erase_status() && ((otPlatAlarmGetNow() - wait_status_timeout) < aTimeout));
if (qspi_get_erase_status())
{
return kThreadError_Busy;
}
else
{
return kThreadError_None;
}
}
ThreadError utilsFlashInit(void)
{
qspi_automode_init();
qspi_automode_flash_power_up();
utilsFlashErasePage(0);
utilsFlashErasePage(0x1000);
if (utilsFlashStatusWait(1000) == kThreadError_Busy)
{
return kThreadError_Failed;
}
else
{
return kThreadError_None;
}
}
uint32_t utilsFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
{
uint32_t flash_offset = (aAddress + FLASH_OFFSET);
return flash_offset;
}
uint32_t utilsFlashWrite2(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
{
uint32_t flash_offset = (aAddress + FLASH_OFFSET);
size_t offset = 0;
size_t written;
while (flash_offset < (aAddress + FLASH_OFFSET) + aSize)
{
qspi_automode_erase_flash_sector(flash_offset);
flash_offset += FLASH_SECTOR_SIZE;
}
flash_offset = (aAddress + FLASH_OFFSET);
while (offset < aSize)
{
written = qspi_automode_write_flash_page(flash_offset + offset, aData + offset,
aSize - offset);
offset += written;
}
return flash_offset;
}
uint32_t utilsFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
{
size_t written = 0;
size_t offset = 0;
uint32_t flash_offset = (aAddress + FLASH_OFFSET);
memcpy(aData, (void *)(MEMORY_QSPIF_BASE + flash_offset), aSize);
return aSize;
}
+42
View File
@@ -0,0 +1,42 @@
/*
* 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 <platform/logging.h>
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
(void)aLogLevel;
(void)aLogRegion;
(void)aFormat;
}
+43
View File
@@ -0,0 +1,43 @@
/*
* 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.
*/
#include <platform/misc.h>
#include <openthread-types.h>
#include "black_orca.h"
void otPlatReset(otInstance *aInstance)
{
(void)aInstance;
WDOG->WATCHDOG_CTRL_REG |= (1 << (WDOG_WATCHDOG_CTRL_REG_NMI_RST_Pos));
}
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
{
(void)aInstance;
return kPlatResetReason_PowerOn;
}
+74
View File
@@ -0,0 +1,74 @@
/*
* 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.
*/
#ifndef PLATFORM_DA15000_H_
#define PLATFORM_DA15000_H_
#include <openthread-types.h>
/**
* This function initializes the radio service used by OpenThread.
*
*/
void da15000RadioInit(void);
/**
* This function performs radio driver processing.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
void da15000RadioProcess(otInstance *aInstance);
/**
* This function initializes the alarm service used by OpenThread.
*
*/
void da15000AlarmInit(void);
/**
* This function performs alarm driver processing.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
void da15000AlarmProcess(otInstance *aInstance);
/**
* This function initializes the random number service used by OpenThread.
*
*/
void da15000RandomInit(void);
/**
* This function performs UART driver processing.
*
*/
void da15000UartProcess(void);
#endif /* PLATFORM_PLATFORM_DA15000_H_ */
+165
View File
@@ -0,0 +1,165 @@
/*
* 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
* This file includes the platform-specific initializers.
*/
#include <assert.h>
#include <stdint.h>
#include <openthread.h>
#include "platform/alarm.h"
#include <openthread-types.h>
#include "platform-da15000.h"
#include "black_orca.h"
#include "hw_cpm.h"
#include "hw_watchdog.h"
#include "ftdf.h"
#include "hw_gpio.h"
#include "platform/uart.h"
static bool blink = false;
static int mscounter_init;
static int mscounter;
#define LEADER_BLINK_TIME (200)
#define ROUTER_BLINK_TIME (500)
#define CHILD_BLINK_TIME (2000)
otInstance *sInstance;
void ClkInit(void)
{
NVIC_ClearPendingIRQ(XTAL16RDY_IRQn);
NVIC_EnableIRQ(XTAL16RDY_IRQn); // Activate XTAL16 Ready IRQ
hw_cpm_set_divn(false); // External crystal is 16MHz
hw_cpm_enable_rc32k();
hw_cpm_lp_set_rc32k();
hw_cpm_set_xtal16m_settling_time(dg_configXTAL16_SETTLE_TIME_RC32K);
hw_cpm_enable_xtal16m(); // Enable XTAL16M
hw_cpm_configure_xtal32k_pins(); // Configure XTAL32K pins
hw_cpm_configure_xtal32k(); // Configure XTAL32K
hw_cpm_enable_xtal32k(); // Enable XTAL32K
hw_watchdog_unfreeze(); // Start watchdog
while (!hw_cpm_is_xtal16m_started()); // Block until XTAL16M starts
hw_watchdog_freeze(); // Stop watchdog
hw_cpm_set_recharge_period((uint16_t)dg_configSET_RECHARGE_PERIOD);
hw_cpm_set_sysclk(SYS_CLK_IS_XTAL16M);
hw_cpm_set_hclk_div(0);
hw_cpm_set_pclk_div(0);
}
/*
* Example function. Blink LED according to node state
* Leader - 5Hz
* Router - 2Hz
* Child - 0.5Hz
*/
void ExampleProcess(otInstance *aInstance)
{
otDeviceRole devRole;
static int thrValue;
devRole = otGetDeviceRole(aInstance);
if (blink == false && otPlatAlarmGetNow() != 0)
{
mscounter_init = otPlatAlarmGetNow();
blink = true;
}
mscounter = otPlatAlarmGetNow() - mscounter_init;
switch (devRole)
{
case kDeviceRoleLeader:
thrValue = LEADER_BLINK_TIME;
break;
case kDeviceRoleRouter:
thrValue = ROUTER_BLINK_TIME;
break;
case kDeviceRoleChild:
thrValue = CHILD_BLINK_TIME;
break;
default:
thrValue = 0x00;
}
if ((thrValue != 0x00) && (mscounter >= thrValue))
{
hw_gpio_toggle(HW_GPIO_PORT_1, HW_GPIO_PIN_5);
mscounter_init = otPlatAlarmGetNow();
}
if (thrValue == 0)
{
hw_gpio_set_inactive(HW_GPIO_PORT_1, HW_GPIO_PIN_5);
}
}
void PlatformInit(int argc, char *argv[])
{
// Initialize System Clock
ClkInit();
// Initialize Random number generator
da15000RandomInit();
// Initialize Alarm
da15000AlarmInit();
// Initialize Radio
da15000RadioInit();
// Initialize UART
otPlatUartEnable();
// enable interrupts
portENABLE_INTERRUPTS();
(void)argc;
(void)argv;
}
void PlatformProcessDrivers(otInstance *aInstance)
{
sInstance = aInstance;
da15000AlarmProcess(aInstance);
da15000UartProcess();
da15000RadioProcess(aInstance);
ExampleProcess(aInstance);
}
+558
View File
@@ -0,0 +1,558 @@
/*
* 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 radio.cpp
* Platform abstraction for radio communication.
*/
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <common/code_utils.hpp>
#include <platform/alarm.h>
#include <platform/radio.h>
#include <openthread.h>
#include "platform-da15000.h"
#define DEBUG_LOG_ENABLE (0)
#include <ftdf.h>
#include <ad_ftdf.h>
#include "ad_ftdf_phy_api.h"
#include "hw_rf.h"
#include <global_io.h>
#include <regmap.h>
#include "black_orca.h"
#include "core_cm0.h"
#include "internal.h"
#include <hw_uart.h>
typedef struct __attribute__((packed)) RadioMessage
{
uint8_t mChannel;
uint8_t mPsdu[kMaxPHYPacketSize];
} RadioMessage;
static PhyState s_state = kStateDisabled;
static RadioMessage s_receive_message;
static RadioMessage s_transmit_message;
static RadioMessage s_ack_message;
static RadioPacket s_receive_frame;
static RadioPacket s_transmit_frame;
static RadioPacket s_ack_frame;
static bool s_data_pending = false;
static bool SendFrameDone = false;
static uint8_t s_extended_address[OT_EXT_ADDRESS_SIZE];
static uint16_t s_short_address;
static uint16_t s_panid;
//static int s_sockfd;
static bool s_promiscuous = false;
static uint8_t sleep_init_delay = 0;
static bool SED = false;
static uint32_t sleep_const_delay;
static otInstance *First_Instace;
uint32_t NODE_ID = 1;
#define DEFAULT_CHANNEL (11)
#define FTDF_OFFSET_CHANNEL (11)
void disable_interrupt()
{
NVIC_DisableIRQ(FTDF_GEN_IRQn);
}
void enable_interrupt()
{
NVIC_ClearPendingIRQ(FTDF_GEN_IRQn);
NVIC_EnableIRQ(FTDF_GEN_IRQn);
}
void phy_power_init()
{
// Set the radio_ldo voltage to 1.4 Volts
REG_SETF(CRG_TOP, LDO_CTRL1_REG, LDO_RADIO_SETVDD, 2);
// Switch on the RF LDO
REG_SETF(CRG_TOP, LDO_CTRL1_REG, LDO_RADIO_ENABLE, 1);
hw_rf_poweron();
}
void ad_ftdf_init_phy_api_V2(void)
{
NVIC_ClearPendingIRQ(FTDF_WAKEUP_IRQn);
NVIC_EnableIRQ(FTDF_WAKEUP_IRQn);
NVIC_ClearPendingIRQ(FTDF_GEN_IRQn);
NVIC_EnableIRQ(FTDF_GEN_IRQn);
volatile uint32_t *lmacReset = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_LMACRESET);
*lmacReset = MSK_R_FTDF_ON_OFF_REGMAP_LMACRESET;
volatile uint32_t *controlStatus = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_LMAC_CONTROL_STATUS);
while ((*controlStatus & MSK_F_FTDF_ON_OFF_REGMAP_LMACREADY4SLEEP) == 0) {}
volatile uint32_t *wakeupTimerEnableStatus = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_WAKEUPTIMERENABLESTATUS);
FTDF_SET_FIELD(ALWAYS_ON_REGMAP_WAKEUPTIMERENABLE, 0);
while (*wakeupTimerEnableStatus & MSK_F_FTDF_ON_OFF_REGMAP_WAKEUPTIMERENABLESTATUS) {}
FTDF_SET_FIELD(ALWAYS_ON_REGMAP_WAKEUPTIMERENABLE, 1);
while ((*wakeupTimerEnableStatus & MSK_F_FTDF_ON_OFF_REGMAP_WAKEUPTIMERENABLESTATUS) == 0) {}
}
void ad_ftdf_init_lmac()
{
FTDF_SET_FIELD(ON_OFF_REGMAP_CCAIDLEWAIT, 192);
volatile uint32_t *txFlagClear = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_TX_FLAG_CLEAR);
*txFlagClear = MSK_F_FTDF_ON_OFF_REGMAP_TX_FLAG_CLEAR;
volatile uint32_t *phyParams = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_PHY_PARAMETERS_2);
*phyParams = (FTDF_PHYTXSTARTUP << OFF_F_FTDF_ON_OFF_REGMAP_PHYTXSTARTUP) |
(FTDF_PHYTXLATENCY << OFF_F_FTDF_ON_OFF_REGMAP_PHYTXLATENCY) |
(FTDF_PHYTXFINISH << OFF_F_FTDF_ON_OFF_REGMAP_PHYTXFINISH) |
(FTDF_PHYTRXWAIT << OFF_F_FTDF_ON_OFF_REGMAP_PHYTRXWAIT);
phyParams = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_PHY_PARAMETERS_3);
*phyParams = (FTDF_PHYRXSTARTUP << OFF_F_FTDF_ON_OFF_REGMAP_PHYRXSTARTUP) |
(FTDF_PHYRXLATENCY << OFF_F_FTDF_ON_OFF_REGMAP_PHYRXLATENCY) |
(FTDF_PHYENABLE << OFF_F_FTDF_ON_OFF_REGMAP_PHYENABLE);
volatile uint32_t *ftdfCm = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_FTDF_CM);
*ftdfCm = FTDF_MSK_TX_CE | FTDF_MSK_RX_CE | FTDF_MSK_SYMBOL_TMR_CE;
volatile uint32_t *rxMask = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_RX_MASK);
*rxMask = MSK_R_FTDF_ON_OFF_REGMAP_RX_MASK;
volatile uint32_t *lmacMask = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_LMAC_MASK);
*lmacMask = MSK_F_FTDF_ON_OFF_REGMAP_RXTIMEREXPIRED_M;
volatile uint32_t *lmacCtrlMask = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_LMAC_CONTROL_MASK);
*lmacCtrlMask = MSK_F_FTDF_ON_OFF_REGMAP_SYMBOLTIMETHR_M |
MSK_F_FTDF_ON_OFF_REGMAP_SYMBOLTIME2THR_M |
MSK_F_FTDF_ON_OFF_REGMAP_SYNCTIMESTAMP_M;
volatile uint32_t *txFlagClearM;
txFlagClearM = FTDF_GET_FIELD_ADDR_INDEXED(ON_OFF_REGMAP_TX_FLAG_CLEAR_M, FTDF_TX_DATA_BUFFER);
*txFlagClearM |= MSK_F_FTDF_ON_OFF_REGMAP_TX_FLAG_CLEAR_M;
txFlagClearM = FTDF_GET_FIELD_ADDR_INDEXED(ON_OFF_REGMAP_TX_FLAG_CLEAR_M, FTDF_TX_WAKEUP_BUFFER);
*txFlagClearM |= MSK_F_FTDF_ON_OFF_REGMAP_TX_FLAG_CLEAR_M;
}
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid)
{
(void)aInstance;
s_panid = panid;
FTDF_setValue(FTDF_PIB_PAN_ID, &panid);
}
void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *address)
{
(void)aInstance;
for (unsigned i = 0; i < sizeof(s_extended_address); i++)
{
s_extended_address[i] = address[i];
}
FTDF_setValue(FTDF_PIB_EXTENDED_ADDRESS, s_extended_address);
}
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t address)
{
(void)aInstance;
s_short_address = address;
FTDF_setValue(FTDF_PIB_SHORT_ADDRESS, &address);
}
void da15000RadioInit(void)
{
/* Wake up power domains */
REG_CLR_BIT(CRG_TOP, PMU_CTRL_REG, FTDF_SLEEP);
while (REG_GETF(CRG_TOP, SYS_STAT_REG, FTDF_IS_UP) == 0x0);
REG_CLR_BIT(CRG_TOP, PMU_CTRL_REG, RADIO_SLEEP);
while (REG_GETF(CRG_TOP, SYS_STAT_REG, RAD_IS_UP) == 0x0);
REG_SETF(CRG_TOP, CLK_RADIO_REG, FTDF_MAC_ENABLE, 1);
REG_SETF(CRG_TOP, CLK_RADIO_REG, FTDF_MAC_DIV, 0);
phy_power_init();
hw_rf_system_init();
hw_rf_set_recommended_settings();
hw_rf_iff_calibration();
hw_rf_modulation_gain_calibration(0); //RF MODE 0
hw_rf_dc_offset_calibration();
// ad_ftdf_init_phy_api();
FTDF_pib.CCAMode = 2;
ad_ftdf_init_phy_api_V2();
ad_ftdf_init_lmac();
}
ThreadError otPlatRadioEnable(otInstance *aInstance)
{
First_Instace = aInstance;
(void)aInstance;
ThreadError error = kThreadError_None;
uint16_t DefaultChannel = DEFAULT_CHANNEL;
uint8_t value = 1;
FTDF_setValue(FTDF_PIB_RX_ON_WHEN_IDLE, &value); //Wake();
FTDF_setValue(FTDF_PIB_CURRENT_CHANNEL, &DefaultChannel); //SetChannel(channel);
uint32_t max_retries = 0;
FTDF_setValue(FTDF_PIB_MAX_FRAME_RETRIES, &max_retries);
FTDF_Bitmap32 options = FTDF_TRANSPARENT_ENABLE_FCS_GENERATION;
options |= FTDF_TRANSPARENT_WAIT_FOR_ACK;
options |= FTDF_TRANSPARENT_AUTO_ACK;
FTDF_enableTransparentMode(FTDF_TRUE, options);
otPlatRadioSetPromiscuous(aInstance, false);
s_receive_frame.mPsdu = s_receive_message.mPsdu;
s_transmit_frame.mPsdu = s_transmit_message.mPsdu;
s_ack_frame.mPsdu = s_ack_message.mPsdu;
s_state = kStateReceive;
return error;
}
ThreadError otPlatRadioDisable(otInstance *aInstance)
{
(void)aInstance;
s_state = kStateDisabled;
return kThreadError_None;
}
bool otPlatRadioIsEnabled(otInstance *aInstance)
{
(void)aInstance;
return (s_state != kStateDisabled);
}
ThreadError otPlatRadioSleep(otInstance *aInstance)
{
ThreadError error = kThreadError_Busy;
(void)aInstance;
if (s_state == kStateReceive && sleep_init_delay == 0)
{
sleep_init_delay = otPlatAlarmGetNow();
return kThreadError_None; //error;
}
else if ((otPlatAlarmGetNow() - sleep_init_delay) < 3000)
{
return kThreadError_None; //error;
}
if (s_state == kStateSleep || s_state == kStateReceive)
{
error = kThreadError_None;
SED = true;
sleep_const_delay = otPlatAlarmGetNow();
}
return error;
}
ThreadError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
{
ThreadError error = kThreadError_None;
(void)aInstance;
#if DEBUG_LOG_ENABLE
hw_uart_write_buffer(HW_UART1, "\nR", 2);
#endif
VerifyOrExit(s_state != kStateDisabled, error = kThreadError_Busy);
s_state = kStateReceive;
s_receive_frame.mChannel = aChannel;
uint32_t phyAckAttr;
phyAckAttr = 0x08 | ((aChannel - FTDF_OFFSET_CHANNEL) & 0xf) << 4;
FTDF_SET_FIELD(ON_OFF_REGMAP_PHYRXATTR, (((aChannel - FTDF_OFFSET_CHANNEL) & 0xf) << 4));
FTDF_SET_FIELD(ON_OFF_REGMAP_PHYACKATTR, phyAckAttr);
FTDF_SET_FIELD(ON_OFF_REGMAP_RXALWAYSON, 1);
FTDF_SET_FIELD(ON_OFF_REGMAP_RXENABLE, 1);
exit:
return error;
}
RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
{
(void)aInstance;
return &s_transmit_frame;
}
ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket)
{
ThreadError error = kThreadError_None;
(void)aInstance;
FTDF_Boolean csmaSuppress = 0;
VerifyOrExit(s_state == kStateReceive, error = kThreadError_Busy);
ad_ftdf_send_frame_simple(aPacket->mLength, aPacket->mPsdu, aPacket->mChannel, 0, csmaSuppress); //Prio 0 for all.
s_state = kStateTransmit;
s_data_pending = false;
#if DEBUG_LOG_ENABLE
hw_uart_write_buffer(HW_UART1, "\nT", 2);
#endif
exit:
return error;
}
int8_t otPlatRadioGetRssi(otInstance *aInstance)
{
(void)aInstance;
return 0;
}
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
{
(void)aInstance;
return kRadioCapsNone;
}
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
{
(void)aInstance;
uint8_t value;
value = aEnable;
FTDF_setValue(FTDF_PIB_PROMISCUOUS_MODE, &value);
s_promiscuous = aEnable;
}
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
{
(void)aInstance;
return s_promiscuous;
}
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
{
ThreadError error = kThreadError_None;
VerifyOrExit(s_state == kStateTransmit, error = kThreadError_InvalidState);
s_state = kStateReceive;
if (rxPending != NULL)
{
*rxPending = s_data_pending;
}
exit:
return error;
}
void FTDF_sendFrameTransparentConfirm(void *handle, FTDF_Bitmap32 status)
{
(void)handle;
(void)status;
volatile uint32_t *txStatus = FTDF_GET_REG_ADDR_INDEXED(RETENTION_RAM_TX_RETURN_STATUS_1, FTDF_TX_DATA_BUFFER);
SendFrameDone = true;
#if DEBUG_LOG_ENABLE
hw_uart_write_buffer(HW_UART1, "\nTD", 3);
#endif
}
void da15000RadioProcess(otInstance *aInstance)
{
bool rxPending;
uint8_t bufferForFTDFconfigValue = 0;
if (SendFrameDone)
{
FTDF_SET_FIELD(ON_OFF_REGMAP_RXENABLE, 1);
otPlatRadioHandleTransmitDone(&rxPending);
otPlatRadioTransmitDone(aInstance, &s_transmit_frame, false, kThreadError_None);
SendFrameDone = false;
}
if ((SED) && ((otPlatAlarmGetNow() - sleep_const_delay) > 100))
{
FTDF_setValue(FTDF_PIB_RX_ON_WHEN_IDLE, &bufferForFTDFconfigValue);
s_state = kStateSleep;
SED = false;
}
}
void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength,
FTDF_Octet *frame,
FTDF_Bitmap32 status,
FTDF_LinkQuality lqi)
{
(void)status;
RadioPacket otRadioPacket;
#if DEBUG_LOG_ENABLE
char buff[10];
sprintf(buff, "\nlq:%d", lqi);
hw_uart_write_buffer(HW_UART1, buff, 5);
#endif
otRadioPacket.mPower = kPhyInvalidRssi;
otRadioPacket.mLqi = lqi;
if (s_receive_frame.mChannel == 0)
{
s_receive_frame.mChannel = DEFAULT_CHANNEL;
}
otRadioPacket.mChannel = s_receive_frame.mChannel;
otRadioPacket.mLength = frameLength;
otRadioPacket.mPsdu = frame;
otPlatRadioReceiveDone(First_Instace, &otRadioPacket, kThreadError_None);
if (s_state != kStateDisabled)
{
s_state = kStateReceive;
}
}
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
{
(void)aInstance;
aIeeeEui64[0] = 0x80; //80-EA-CA is for Dialog Semiconductor
aIeeeEui64[1] = 0xEA;
aIeeeEui64[2] = 0xCA;
aIeeeEui64[3] = 0x00;
aIeeeEui64[4] = (NODE_ID >> 24) & 0xff;
aIeeeEui64[5] = (NODE_ID >> 16) & 0xff;
aIeeeEui64[6] = (NODE_ID >> 8) & 0xff;
aIeeeEui64[7] = NODE_ID & 0xff;
}
ThreadError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
{
ThreadError error = kThreadError_NotImplemented;
(void)aInstance;
(void)aScanChannel;
(void)aScanDuration;
return error;
}
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
{
(void)aInstance;
(void)aEnable;
}
ThreadError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress)
{
ThreadError error = kThreadError_NotImplemented;
(void)aInstance;
(void)aShortAddress;
return error;
}
ThreadError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress)
{
ThreadError error = kThreadError_NotImplemented;
(void)aInstance;
(void)aExtAddress;
return error;
}
ThreadError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress)
{
ThreadError error = kThreadError_NotImplemented;
(void)aInstance;
(void)aShortAddress;
return error;
}
ThreadError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress)
{
ThreadError error = kThreadError_NotImplemented;
(void)aExtAddress;
(void)aInstance;
return error;
}
void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
{
(void)aInstance;
}
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
{
(void)aInstance;
}
+107
View File
@@ -0,0 +1,107 @@
/*
* 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
* This file implements a pseudo-random number generator.
*
* @warning
* This implementation is not a true random number generator and does @em satisfy the Thread requirements.
*/
#include <platform/random.h>
#include "platform-da15000.h"
#include "black_orca.h"
#include "hw_trng.h"
#include <string.h>
#define HW_TRNG_RAM (0x40040000)
static uint32_t s_state = 1;
static uint32_t seed;
int zhal_get_entropy(uint8_t *outEntropy, size_t inSize)
{
uint32_t randword;
unsigned char *pbuf = outEntropy;
const size_t req_words = inSize >> 2;
const unsigned char *pbuf_end = outEntropy + inSize;
const unsigned char *preq_words_end = (unsigned char *)(((uint32_t *)outEntropy) + req_words);
ptrdiff_t remainder_bytes = pbuf_end - preq_words_end;
hw_trng_enable(NULL);
for (pbuf = outEntropy; pbuf < preq_words_end; pbuf += 4)
{
/* Wait for a random word to become available in the TRNG FIFO. */
while ((TRNG->TRNG_FIFOLVL_REG & TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOLVL_Msk) == 0);
randword = *((volatile uint32_t *)HW_TRNG_RAM);
memcpy(pbuf, &randword, 4);
}
if (remainder_bytes)
{
while ((TRNG->TRNG_FIFOLVL_REG & TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOLVL_Msk) == 0);
randword = *((volatile uint32_t *)HW_TRNG_RAM);
memcpy(pbuf, &randword, remainder_bytes);
}
hw_trng_disable();
return 0;
}
void da15000RandomInit(void)
{
zhal_get_entropy((uint8_t *)&seed, sizeof(seed));
s_state = seed;
}
uint32_t otPlatRandomGet(void)
{
uint32_t mlcg;
zhal_get_entropy((uint8_t *)&mlcg, sizeof(mlcg));
return mlcg;
}
ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength)
{
for (uint16_t length = 0; length < aInputLength; length++)
{
aOutput[length] = (uint8_t)otPlatRandomGet();
}
*aOutputLength = aInputLength;
return kThreadError_None;
}
+59
View File
@@ -0,0 +1,59 @@
/*
* 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.
*/
/**
* Stubs out exception handling and general C++ bloat
* for suitability for embedded environments.
*/
#include <stdint.h>
__extension__ typedef int __guard __attribute__((mode(__DI__)));
extern int __cxa_guard_acquire(__guard *g);
extern void __cxa_guard_release(__guard *g);
extern void __cxa_guard_abort(__guard *g);
extern void __cxa_pure_virtual(void);
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);
}
void *__dso_handle;
+122
View File
@@ -0,0 +1,122 @@
/*
* 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.
*/
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <hw_uart.h>
#include <common/code_utils.hpp>
#include <platform/uart.h>
#include "hw_gpio.h"
#include "platform-da15000.h"
static int s_in_fd;
static int s_out_fd;
void UartBuffClear(void);
ThreadError otPlatUartEnable(void)
{
ThreadError error = kThreadError_None;
uart_config uart_init =
{
.baud_rate = HW_UART_BAUDRATE_9600,
.data = HW_UART_DATABITS_8,
.stop = HW_UART_STOPBITS_1,
.parity = HW_UART_PARITY_NONE,
.use_dma = 0,
.use_fifo = 1,
.rx_dma_channel = HW_DMA_CHANNEL_0,
.tx_dma_channel = HW_DMA_CHANNEL_1,
};
hw_uart_init(CONFIG_RETARGET_UART, &uart_init);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_3,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_UART_TX);
hw_gpio_set_pin_function(HW_GPIO_PORT_2, HW_GPIO_PIN_3,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_UART_RX);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_5, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_GPIO);
UartBuffClear();
return error;
}
ThreadError otPlatUartDisable(void)
{
ThreadError error = kThreadError_None;
close(s_in_fd);
close(s_out_fd);
return error;
}
void da15000UartProcess(void)
{
uint8_t aBuf;
// Wait until received data are available
if (hw_uart_read_buf_empty(HW_UART1))
{
return;
}
// Read element from the receive FIFO
aBuf = UBA(HW_UART1)->UART2_RBR_THR_DLL_REG;
otPlatUartReceived(&aBuf, 1);
}
void UartBuffClear(void)
{
volatile uint8_t aBuf;
while (hw_uart_read_buf_empty(HW_UART1) == 0)
{
aBuf += UBA(HW_UART1)->UART2_RBR_THR_DLL_REG;
}
}
ThreadError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
ThreadError error = kThreadError_None;
hw_uart_write_buffer(HW_UART1, aBuf, aBufLength);
otPlatUartSendDone();
return error;
}
+288
View File
@@ -0,0 +1,288 @@
/*
* 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 cpu/dialog/da15000/boot/vector.c
* CpuIrq_da15x -- IRQ driver for ARM Cortex-M series cores.
*
*/
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma location=".isr_vector"
#define __WEAK __attribute__((weak))
#define __USED __attribute__((used))
#define __BOOT_VECTOR __attribute__ ((section(".isr_vector")))
#define __BOOT_STACK &__stack_start__
#define __BOOT_STARTUP __gcc_program_start
typedef void (*irq_handler_t)(void);
extern unsigned int __stack_start__[];
extern void __gcc_program_start(void);
/// Declaration of default interrupt service routine
static void halt_isr(void)
{
__asm("BKPT 255");
while (1);
}
static void default_isr(void)
{
while (1);
}
/* The kernel interrupts - in their CMSIS form.
These must be implemented locally, or compiler will
give conflicting definition for __vector_table.
*/
__WEAK void NMI_Handler() { }
__WEAK void HardFault_Handler()
{
halt_isr();
}
__WEAK void SVC_Handler()
{
halt_isr();
}
__WEAK void PendSV_Handler()
{
halt_isr();
}
__WEAK void SysTick_Handler()
{
halt_isr();
}
__WEAK void MemManage_Handler()
{
halt_isr();
}
__WEAK void DebugMon_Handler()
{
halt_isr();
}
__WEAK void BusFault_Handler()
{
halt_isr();
}
/* Default handlers for other DA15X peripheral interrupts. */
__WEAK void DEBUG_IRQHandler()
{
default_isr();
}
__WEAK void BLE_WAKEUP_LP_Handler()
{
default_isr(); /* 0 */
}
__WEAK void BLE_GEN_Handler()
{
default_isr(); /* 1 */
}
__WEAK void FTDF_WAKEUP_Handler()
{
default_isr(); /* 2 */
}
__WEAK void FTDF_GEN_Handler()
{
default_isr(); /* 3 */
}
__WEAK void RFCAL_Handler()
{
default_isr(); /* 4 */
}
__WEAK void COEX_Handler()
{
default_isr(); /* 5 */
}
__WEAK void CRYPTO_Handler()
{
default_isr(); /* 6 */
}
__WEAK void MRM_Handler()
{
default_isr(); /* 7 */
}
__WEAK void UART_Handler()
{
default_isr(); /* 8 */
}
__WEAK void UART2_Handler()
{
default_isr(); /* 9 */
}
__WEAK void I2C_Handler()
{
default_isr(); /* 10 */
}
__WEAK void I2C2_Handler()
{
default_isr(); /* 11 */
}
__WEAK void SPI_Handler()
{
default_isr(); /* 12 */
}
__WEAK void SPI2_Handler()
{
default_isr(); /* 13 */
}
__WEAK void ADC_Handler()
{
default_isr(); /* 14 */
}
__WEAK void KEYBRD_Handler()
{
default_isr(); /* 15 */
}
__WEAK void IRGEN_Handler()
{
default_isr(); /* 16 */
}
__WEAK void WKUP_GPIO_Handler()
{
default_isr(); /* 17 */
}
__WEAK void SWTIM0_Handler()
{
default_isr(); /* 18 */
}
__WEAK void SWTIM1_Handler()
{
default_isr(); /* 19 */
}
__WEAK void QUADEC_Handler()
{
default_isr(); /* 20 */
}
__WEAK void USB_Handler()
{
default_isr(); /* 21 */
}
__WEAK void PCM_Handler()
{
default_isr(); /* 22 */
}
__WEAK void SRC_IN_Handler()
{
default_isr(); /* 23 */
}
__WEAK void SRC_OUT_Handler()
{
default_isr(); /* 24 */
}
__WEAK void VBUS_Handler()
{
default_isr(); /* 25 */
}
__WEAK void DMA_Handler()
{
default_isr(); /* 26 */
}
__WEAK void RF_DIAG_Handler()
{
default_isr(); /* 27 */
}
__WEAK void TRNG_Handler()
{
default_isr(); /* 28 */
}
__WEAK void DCDC_Handler()
{
default_isr(); /* 29 */
}
__WEAK void XTAL16RDY_Handler()
{
default_isr(); /* 30 */
}
__WEAK void RESERVED31_Handler()
{
default_isr(); /* 31 */
}
__BOOT_VECTOR __USED
const irq_handler_t __vector_table[] =
{
// Cortex-M vector table
(irq_handler_t)__BOOT_STACK, //INT_Initial_Stack_Pointer = 0, // Initial Stack Pointer
(irq_handler_t)__BOOT_STARTUP, //INT_Initial_Program_Counter = 1, // Initial Program Counter
NMI_Handler, //INT_NMI = 2, // Non-maskable Interrupt (NMI)
HardFault_Handler, //INT_Hard_Fault = 3, // Hard Fault
MemManage_Handler, //INT_Mem_Manage_Fault = 4, // MemManage Fault
BusFault_Handler, //INT_Bus_Fault = 5, // Bus Fault
default_isr, //INT_Usage_Fault = 6, // Usage Fault
default_isr, //INT_Reserved7 = 7, // Reserved interrupt 7
default_isr, //INT_Reserved8 = 8, // Reserved interrupt 8
default_isr, //INT_Reserved9 = 9, // Reserved interrupt 9
default_isr, //INT_Reserved10 = 10, // Reserved interrupt 10
SVC_Handler, //INT_SVCall = 11, // Supervisor call (SVCall)
DebugMon_Handler, //INT_DebugMonitor = 12, // Debug Monitor
default_isr, //INT_Reserved13 = 13, // Reserved interrupt 13
PendSV_Handler, //INT_PendableSrvReq = 14, // Pendable request for system service (PendableSrvReq)
SysTick_Handler, //INT_SysTick = 15, // SysTick Interrupt
// Dialog DA15000 vector table
BLE_WAKEUP_LP_Handler, //BLE_WAKEUP_LP_IRQn = 0, // Wakeup from Sleep by BLE Interrupt request.
BLE_GEN_Handler, //BLE_GEN_IRQn = 1, // BLE Interrupt request. Sources:
FTDF_WAKEUP_Handler, //FTDF_WAKEUP_IRQn = 2, // Wakeup from Sleep by FTDF Interrupt request.
FTDF_GEN_Handler, //FTDF_GEN_IRQn = 3, // FTDF Interrupt request. Sources:
RFCAL_Handler, //RFCAL_IRQn = 4, // RF Calibration Interrupt request. Generated by the DPHY.
COEX_Handler, //COEX_IRQn = 5, // Coex Interrupt request.
CRYPTO_Handler, //CRYPTO_IRQn = 6, // Crypto Interrupt request. Sources:
MRM_Handler, //MRM_IRQn = 7, // Cache Miss Rate Monitor Interrupt request.
UART_Handler, //UART_IRQn = 8, // UART Interrupt request.
UART2_Handler, //UART2_IRQn = 9, // UART2 Interrupt request.
I2C_Handler, //I2C_IRQn = 10, // I2C Interrupt request.
I2C2_Handler, //I2C2_IRQn = 11, // I2C2 Interrupt request.
SPI_Handler, //SPI_IRQn = 12, // SPI Interrupt request.
SPI2_Handler, //SPI2_IRQn = 13, // SPI2 Interrupt request.
ADC_Handler, //ADC_IRQn = 14, // Analog-Digital Converter Interrupt request.
KEYBRD_Handler, //KEYBRD_IRQn = 15, // Keyboard scanner Interrupt request.
IRGEN_Handler, //IRGEN_IRQn = 16, // InfraRed Generator Interrupt request.
WKUP_GPIO_Handler, //WKUP_GPIO_IRQn = 17, // Wakeup with/without debouncing Interrupt request (when system
SWTIM0_Handler, //SWTIM0_IRQn = 18, // SW Timer Interrupt request (Timer0).
SWTIM1_Handler, //SWTIM1_IRQn = 19, // SW Timer Interrupt request (Timer1).
QUADEC_Handler, //QUADEC_IRQn = 20, // Quadrature Decoder Interrupt request.
USB_Handler, //USB_IRQn = 21, // USB device FS Interrupt request.
PCM_Handler, //PCM_IRQn = 22, // PCM Interrupt request.
SRC_IN_Handler, //SRC_IN_IRQn = 23, // Sample Rate Converter Input Interrupt request.
SRC_OUT_Handler, //SRC_OUT_IRQn = 24, // Sample Rate Converter Output Interrupt request.
VBUS_Handler, //VBUS_IRQn = 25, // VBUS presence Interrupt request.
DMA_Handler, //DMA_IRQn = 26, // DMA Interrupt request.
RF_DIAG_Handler, //RF_DIAG_IRQn = 27, // Baseband or Radio Diagnostics Interrupt request.
TRNG_Handler, //TRNG_IRQn = 28, // True Random Number Generation Interrupt request.
DCDC_Handler, //DCDC_IRQn = 29, // DCDC Interrupt request. Generated upon time out threshold reach.
XTAL16RDY_Handler, //XTAL16RDY_IRQn = 30, // Indicates that XTAL16 oscillator is trimmed and settled and can
DEBUG_IRQHandler, //RESERVED31_IRQn = 31, // RESERVED31 Interrupt request.
};
+175
View File
@@ -0,0 +1,175 @@
/**
* \addtogroup BSP
* \{
* \addtogroup ADAPTERS
* \{
* \addtogroup RF_ADAPTER
*
* \brief RF adapter
*
* \{
*/
/**
*****************************************************************************************
*
* @file
*
* @brief Radio module access API.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 AD_RF_H_
#define AD_RF_H_
#if dg_configRF_ADAPTER
#include <stdbool.h>
#include <stdint.h>
//#include "platform_devices.h"
#include "hw_rf.h"
/**
* @brief Performs RF adapter initialization
*/
void ad_rf_init(void);
/**
* \brief Retry a failed calibration
*
* This will power-cycle RF, reapply tcs and recommended settings, and
* retry calibration. If calibration fails again, it will reset the system
* (using the wdog)
*/
void ad_rf_retry_calibration();
/**
* \brief Start Calibration procedure and check if it succeeds
*
* This will start the calibration procedure, and check if the calibration initial
* part (the iff calibration) succeeds. If not, it will reset the RF block and retry.
* If the calibration still fails after the second attempt, it will trigger a
* watchdog reset
*
*/
static inline void ad_rf_start_and_check_calibration()
{
if (!hw_rf_start_calibration())
ad_rf_retry_calibration();
}
/**
* \brief Perform RF system initialization.
*
* This will preform a full RF system init, and check if the
* calibration initial part (the iff calibration) succeeds. If not, it will
* reset the RF block and retry.
* If the calibration still fails after the second attempt, it will trigger a
* watchdog reset
*
*/
static inline void ad_rf_system_init()
{
if (!hw_rf_system_init())
ad_rf_retry_calibration();
}
/**
* \brief Start Calibration procedure and return.
*
* This will block for some time (with interrupts disabled) in order to perform
* The first part of calibration (IFF, DC offset and the start of gain calib).
*
*/
static inline void ad_rf_start_calibration()
{
// OS_ENTER_CRITICAL_SECTION();
ad_rf_start_and_check_calibration();
// OS_LEAVE_CRITICAL_SECTION();
}
/**
* \brief Sets parameters according to their recommended values, taking RF state into account.
*
* Acts like \ref hw_rf_set_recommended_settings but makes sure that the RF power domain is on and
* unconfigured. Disables interrupts.
*
*/
static inline void ad_rf_request_recommended_settings(void)
{
// OS_ENTER_CRITICAL_SECTION();
hw_rf_request_recommended_settings();
// OS_LEAVE_CRITICAL_SECTION();
}
/**
* \brief Requests that the RF is turned on
*
* Requests that the RF is turned on, if not already on. Disables interrupts.
*
* \param [in] mode_ble True, if the rf is needed for ble
*
*/
static inline void ad_rf_request_on(bool mode_ble)
{
// OS_ENTER_CRITICAL_SECTION();
hw_rf_request_on(mode_ble);
// OS_LEAVE_CRITICAL_SECTION();
}
/**
* \brief Requests that the RF is turned off
*
* Requests that the RF is turned off, if not already off.
* The RF will be turned off only if there are no more
* requests (ie. all requesters have called ad_rf_request_off())
* Disables interrupts
*
* \param [in] mode_ble True, if the rf was needed for ble
*/
static inline void ad_rf_request_off(bool mode_ble)
{
// ad_gpadc_acquire();
// OS_ENTER_CRITICAL_SECTION();
hw_rf_request_off(mode_ble);
// OS_LEAVE_CRITICAL_SECTION();
// ad_gpadc_release();
}
#endif /* dg_configRF_ADAPTER */
#endif /* AD_RF_H_ */
/**
* \}
* \}
* \}
*/
+26
View File
@@ -0,0 +1,26 @@
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
---------------------------------------------------------------------------*/
+464
View File
@@ -0,0 +1,464 @@
/**
****************************************************************************************
*
* @file bsp_debug.h
*
* @brief Board Support Package. Debug Configuration.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 BSP_DEBUG_H_
#define BSP_DEBUG_H_
/* --------------------------------- DEBUG GPIO handling macros --------------------------------- */
#define DBG_CONFIGURE(flag, name, func) \
{ \
if (flag == 1) { \
name##_MODE_REG = 0x300 + func; \
} \
}
#define DBG_CONFIGURE_HIGH(flag, name) \
{ \
if (flag == 1) { \
name##_SET_REG = name##_PIN; \
name##_MODE_REG = 0x300; \
} \
}
#define DBG_CONFIGURE_LOW(flag, name) \
{ \
if (flag == 1) { \
name##_RESET_REG = name##_PIN; \
name##_MODE_REG = 0x300; \
} \
}
#define DBG_SET_HIGH(flag, name) \
{ \
if (flag == 1) { \
name##_SET_REG = name##_PIN; \
} \
}
#define DBG_SET_LOW(flag, name) \
{ \
if (flag == 1) { \
name##_RESET_REG = name##_PIN; \
} \
}
/* ---------------------------------------------------------------------------------------------- */
/* ---------------------------------- HardFault or NMI event ------------------------------------ */
#ifndef EXCEPTION_DEBUG
#define EXCEPTION_DEBUG (0)
#endif
/* ---------------------------------------------------------------------------------------------- */
/* --------------------------------- Clock and Power Manager ------------------------------------ */
#ifndef CPM_DEBUG
#define CPM_DEBUG (0)
#endif
#ifndef CPM_USE_FUNCTIONAL_DEBUG
#define CPM_USE_FUNCTIONAL_DEBUG (0) // Requires GPIO config.
#endif
#ifndef CPM_USE_TIMING_DEBUG
#define CPM_USE_TIMING_DEBUG (0) // Requires GPIO config.
#endif
#ifndef CPM_USE_RCX_DEBUG
#define CPM_USE_RCX_DEBUG (0) // Requires logging.
#endif
/* Controls which RAM blocks will be retained when the MEASURE_SLEEP_CURRENT test mode is used
* (optional). */
#ifndef dg_configTESTMODE_RETAIN_RAM
#define dg_configTESTMODE_RETAIN_RAM (0x1F)
#endif
/* Controls whether the Cache will be retained when the MEASURE_SLEEP_CURRENT test mode is used
* (optional). */
#ifndef dg_configTESTMODE_RETAIN_CACHE
#define dg_configTESTMODE_RETAIN_CACHE (0)
#endif
/* Controls whether the ECC RAM will be retained when the MEASURE_SLEEP_CURRENT test mode is used
* (optional). */
#ifndef dg_config_TESTMODE_RETAIN_ECCRAM
#define dg_config_TESTMODE_RETAIN_ECCRAM (0)
#endif
/* ---------------------------------------------------------------------------------------------- */
/* --------------------------------------- USB Charger ------------------------------------------ */
#ifndef DEBUG_USB_CHARGER
#define DEBUG_USB_CHARGER (0)
#endif
#ifndef DEBUG_USB_CHARGER_FSM
#define DEBUG_USB_CHARGER_FSM (0)
#endif
#ifndef USB_CHARGER_TIMING_DEBUG
#define USB_CHARGER_TIMING_DEBUG (0)
#endif
/* ---------------------------------------------------------------------------------------------- */
/* ------------------------------------------- BLE ---------------------------------------------- */
#ifndef BLE_USE_TIMING_DEBUG
#define BLE_USE_TIMING_DEBUG (0) // Requires GPIO config.
#endif
#ifndef BLE_ADAPTER_DEBUG
#define BLE_ADAPTER_DEBUG (0) // Requires GPIO config.
#endif
#ifndef BLE_RX_EN_DEBUG
#define BLE_RX_EN_DEBUG (0) // Requires GPIO config.
#endif
#define BLE_RX_EN_FUNC (57)
#ifndef BLE_WINDOW_STATISTICS
#define BLE_WINDOW_STATISTICS (0)
#endif
#ifndef BLE_SLEEP_PERIOD_DEBUG
#define BLE_SLEEP_PERIOD_DEBUG (0) // Requires logging and window statistics.
#endif
#ifndef BLE_WAKEUP_MONITOR_PERIOD
#define BLE_WAKEUP_MONITOR_PERIOD (1024)
#endif
#ifndef BLE_MAX_MISSES_ALLOWED
#define BLE_MAX_MISSES_ALLOWED (0)
#endif
#ifndef BLE_MAX_DELAYS_ALLOWED
#define BLE_MAX_DELAYS_ALLOWED (0)
#endif
/* ---------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------- */
/* ------------------------------------------ Common -------------------------------------------- */
#ifndef CMN_TIMING_DEBUG
#define CMN_TIMING_DEBUG (0) // Requires GPIO config.
#endif
/* ---------------------------------------------------------------------------------------------- */
/* ------------------------------------ GPIO configuration -------------------------------------- */
/* Enable/Disable GPIO pin assignment conflict detection
*/
#define DEBUG_GPIO_ALLOC_MONITOR_ENABLED (0)
/* Exception handling debug configuration
*
*/
#if (EXCEPTION_DEBUG == 0)
// Exception occurred (initial configuration: low)
#define EXCEPTIONDBG_MODE_REG *(volatile int *)0x20000000
#define EXCEPTIONDBG_SET_REG *(volatile int *)0x20000000
#define EXCEPTIONDBG_RESET_REG *(volatile int *)0x20000000
#define EXCEPTIONDBG_PIN (0)
#else
// Tick (P3[0])
#define EXCEPTIONDBG_MODE_REG GPIO->P30_MODE_REG
#define EXCEPTIONDBG_SET_REG GPIO->P3_SET_DATA_REG
#define EXCEPTIONDBG_RESET_REG GPIO->P3_RESET_DATA_REG
#define EXCEPTIONDBG_PIN (1 << 0)
#endif
/* Functional debug configuration
*
* Note that GPIO overlapping is allowed if the tracked events are discrete and the initial GPIO
* configuration is the same! No checking is performed for erroneous configuration though!
*
*/
#if (CPM_USE_FUNCTIONAL_DEBUG == 0)
// Tick (initial configuration: low)
#define CPMDBG_TICK_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_TICK_SET_REG *(volatile int *)0x20000000
#define CPMDBG_TICK_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_TICK_PIN (0)
// External Wake-up (initial configuration: low)
#define CPMDBG_EXT_WKUP_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_EXT_WKUP_SET_REG *(volatile int *)0x20000000
#define CPMDBG_EXT_WKUP_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_EXT_WKUP_PIN (0)
// Active / Sleep (initial configuration: high)
#define CPMDBG_POWERUP_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_POWERUP_SET_REG *(volatile int *)0x20000000
#define CPMDBG_POWERUP_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_POWERUP_PIN (0)
#else
// Tick (P2[3])
#define CPMDBG_TICK_MODE_REG GPIO->P23_MODE_REG
#define CPMDBG_TICK_SET_REG GPIO->P2_SET_DATA_REG
#define CPMDBG_TICK_RESET_REG GPIO->P2_RESET_DATA_REG
#define CPMDBG_TICK_PIN (1 << 3)
// External Wake-up (P3[0])
#define CPMDBG_EXT_WKUP_MODE_REG GPIO->P30_MODE_REG
#define CPMDBG_EXT_WKUP_SET_REG GPIO->P3_SET_DATA_REG
#define CPMDBG_EXT_WKUP_RESET_REG GPIO->P3_RESET_DATA_REG
#define CPMDBG_EXT_WKUP_PIN (1 << 0)
// Active / Sleep (P1[4])
#define CPMDBG_POWERUP_MODE_REG GPIO->P14_MODE_REG
#define CPMDBG_POWERUP_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_POWERUP_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_POWERUP_PIN (1 << 4)
#endif
/* Timing debug configuration
*
* Note that in this mode the pad latches are removed immediately after the execution resumes from
* the __WFI(). Because of this, it is not advised to use this feature in projects that use GPIOS.
* Nevertheless, in case it is used, make sure that the "peripheral initialization" is also done
* at that point, modifying sys_power_mgr.c accordingly.
*
* Note also that GPIO overlapping is allowed if the tracked events are discrete and the initial
* GPIO configuration is the same! No checking is performed for erroneous configuration though!
*
*/
#if (CPM_USE_TIMING_DEBUG == 0)
// CPM: sleep or idle entry (until __WFI() is called) (initial configuration: high)
#define CPMDBG_SLEEP_ENTER_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_ENTER_SET_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_ENTER_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_ENTER_PIN (0)
// CPM: sleep or idle exit (initial configuration: low)
#define CPMDBG_SLEEP_EXIT_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_EXIT_SET_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_EXIT_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_SLEEP_EXIT_PIN (0)
// Low clocks (initial configuration: low)
#define CPMDBG_LOWER_CLOCKS_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_LOWER_CLOCKS_SET_REG *(volatile int *)0x20000000
#define CPMDBG_LOWER_CLOCKS_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_LOWER_CLOCKS_PIN (0)
// XTAL16M settling (initial configuration: low)
#define CPMDBG_XTAL16M_SETTLED_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_XTAL16M_SETTLED_SET_REG *(volatile int *)0x20000000
#define CPMDBG_XTAL16M_SETTLED_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_XTAL16M_SETTLED_PIN (0)
#else
// CPM: sleep or idle entry (until __WFI() is called) (P1[7])
#define CPMDBG_SLEEP_ENTER_MODE_REG GPIO->P17_MODE_REG
#define CPMDBG_SLEEP_ENTER_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_SLEEP_ENTER_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_SLEEP_ENTER_PIN (1 << 7)
// CPM: sleep or idle exit (P1[6])
#define CPMDBG_SLEEP_EXIT_MODE_REG GPIO->P16_MODE_REG
#define CPMDBG_SLEEP_EXIT_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_SLEEP_EXIT_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_SLEEP_EXIT_PIN (1 << 6)
// Low clocks (P1[5])
#define CPMDBG_LOWER_CLOCKS_MODE_REG GPIO->P15_MODE_REG
#define CPMDBG_LOWER_CLOCKS_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_LOWER_CLOCKS_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_LOWER_CLOCKS_PIN (1 << 5)
// XTAL16M settling (P1[4])
#define CPMDBG_XTAL16M_SETTLED_MODE_REG GPIO->P14_MODE_REG
#define CPMDBG_XTAL16M_SETTLED_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_XTAL16M_SETTLED_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_XTAL16M_SETTLED_PIN (1 << 4)
#endif
#if (BLE_USE_TIMING_DEBUG == 0)
// BLE LP & GEN irqs (initial configuration: low)
#define CPMDBG_BLE_IRQ_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_IRQ_SET_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_IRQ_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_IRQ_PIN (0)
// BLE sleep prepare (final stage) (initial configuration: low)
#define CPMDBG_BLE_SLEEP_ENTRY_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_SLEEP_ENTRY_SET_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_SLEEP_ENTRY_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_BLE_SLEEP_ENTRY_PIN (0)
// BLE LP irq signal (diagnostics) (initial configuration: unknown)
#define CPMDBG_BLE_LP_IRQ_MODE_REG *(volatile int *)0x20000000
#else
// BLE LP & GEN ISRs (P1[4])
#define CPMDBG_BLE_IRQ_MODE_REG GPIO->P14_MODE_REG
#define CPMDBG_BLE_IRQ_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_BLE_IRQ_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_BLE_IRQ_PIN (1 << 4)
// BLE sleep prepare (final stage) (P1[4])
#define CPMDBG_BLE_SLEEP_ENTRY_MODE_REG GPIO->P14_MODE_REG
#define CPMDBG_BLE_SLEEP_ENTRY_SET_REG GPIO->P1_SET_DATA_REG
#define CPMDBG_BLE_SLEEP_ENTRY_RESET_REG GPIO->P1_RESET_DATA_REG
#define CPMDBG_BLE_SLEEP_ENTRY_PIN (1 << 4)
// BLE LP irq signal (diagnostics) (P2[3])
#define CPMDBG_BLE_LP_IRQ_MODE_REG GPIO->P23_MODE_REG
#endif
#if (BLE_ADAPTER_DEBUG == 0)
#define BLEBDG_ADAPTER_MODE_REG *(volatile int *)0x20000000
#define BLEBDG_ADAPTER_SET_REG *(volatile int *)0x20000000
#define BLEBDG_ADAPTER_RESET_REG *(volatile int *)0x20000000
#define BLEBDG_ADAPTER_PIN (0)
#else
#define BLEBDG_ADAPTER_MODE_REG GPIO->P30_MODE_REG
#define BLEBDG_ADAPTER_SET_REG GPIO->P3_SET_DATA_REG
#define BLEBDG_ADAPTER_RESET_REG GPIO->P3_RESET_DATA_REG
#define BLEBDG_ADAPTER_PIN (1 << 0)
#endif
#if (BLE_RX_EN_DEBUG == 0)
#define BLEBDG_RXEN_MODE_REG *(volatile int *)0x20000000
#define BLEBDG_RXEN_SET_REG *(volatile int *)0x20000000
#define BLEBDG_RXEN_RESET_REG *(volatile int *)0x20000000
#define BLEBDG_RXEN_PIN (0)
#else
#define BLEBDG_RXEN_MODE_REG GPIO->P12_MODE_REG
#define BLEBDG_RXEN_SET_REG GPIO->P1_SET_DATA_REG
#define BLEBDG_RXEN_RESET_REG GPIO->P1_RESET_DATA_REG
#define BLEBDG_RXEN_PIN (1 << 2)
#endif
#if (USB_CHARGER_TIMING_DEBUG == 0)
// CHRG: Inside critical section (initial configuration: low)
#define CHRGDBG_CRITICAL_SECTION_MODE_REG *(volatile int *)0x20000000
#define CHRGDBG_CRITICAL_SECTION_SET_REG *(volatile int *)0x20000000
#define CHRGDBG_CRITICAL_SECTION_RESET_REG *(volatile int *)0x20000000
#define CHRGDBG_CRITICAL_SECTION_PIN (0)
// CHRG: FSM task (initial configuration: low)
#define CHRGDBG_FSM_TASK_MODE_REG *(volatile int *)0x20000000
#define CHRGDBG_FSM_TASK_SET_REG *(volatile int *)0x20000000
#define CHRGDBG_FSM_TASK_RESET_REG *(volatile int *)0x20000000
#define CHRGDBG_FSM_TASK_PIN (0)
// CHRG: Control task (initial configuration: low)
#define CPMDBG_CONTROL_TASK_MODE_REG *(volatile int *)0x20000000
#define CPMDBG_CONTROL_TASK_SET_REG *(volatile int *)0x20000000
#define CPMDBG_CONTROL_TASK_RESET_REG *(volatile int *)0x20000000
#define CPMDBG_CONTROL_TASK_PIN (0)
#else
// CHRG: Inside critical section (P3[2])
#define CHRGDBG_CRITICAL_SECTION_MODE_REG GPIO->P32_MODE_REG
#define CHRGDBG_CRITICAL_SECTION_SET_REG GPIO->P3_SET_DATA_REG
#define CHRGDBG_CRITICAL_SECTION_RESET_REG GPIO->P3_RESET_DATA_REG
#define CHRGDBG_CRITICAL_SECTION_PIN (1 << 2)
// CHRG: FSM task (P3[3])
#define CHRGDBG_FSM_TASK_MODE_REG GPIO->P33_MODE_REG
#define CHRGDBG_FSM_TASK_SET_REG GPIO->P3_SET_DATA_REG
#define CHRGDBG_FSM_TASK_RESET_REG GPIO->P3_RESET_DATA_REG
#define CHRGDBG_FSM_TASK_PIN (1 << 3)
// CHRG: Control task (P3[4])
#define CPMDBG_CONTROL_TASK_MODE_REG GPIO->P34_MODE_REG
#define CPMDBG_CONTROL_TASK_SET_REG GPIO->P3_SET_DATA_REG
#define CPMDBG_CONTROL_TASK_RESET_REG GPIO->P3_RESET_DATA_REG
#define CPMDBG_CONTROL_TASK_PIN (1 << 4)
#endif
#if (CMN_TIMING_DEBUG == 0)
// Common: Inside critical section (initial configuration: low)
#define CMNDBG_CRITICAL_SECTION_MODE_REG *(volatile int *)0x20000000
#define CMNDBG_CRITICAL_SECTION_SET_REG *(volatile int *)0x20000000
#define CMNDBG_CRITICAL_SECTION_RESET_REG *(volatile int *)0x20000000
#define CMNDBG_CRITICAL_SECTION_PIN (0)
#else
// Common: Inside critical section (P4[6])
#define CMNDBG_CRITICAL_SECTION_MODE_REG GPIO->P40_MODE_REG
#define CMNDBG_CRITICAL_SECTION_SET_REG GPIO->P4_SET_DATA_REG
#define CMNDBG_CRITICAL_SECTION_RESET_REG GPIO->P4_RESET_DATA_REG
#define CMNDBG_CRITICAL_SECTION_PIN (1 << 0)
#endif
/* Enables the logging of stack (RW) heap memories usage.
*
* The feature shall only be enabled in development/debug mode
*/
#ifndef dg_configLOG_BLE_STACK_MEM_USAGE
#define dg_configLOG_BLE_STACK_MEM_USAGE (0)
#endif
#endif /* BSP_DEBUG_H_ */
/**
\}
\}
\}
*/
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
/**
****************************************************************************************
*
* @file bsp_definitions.h
*
* @brief Board Support Package. System Configuration file definitions.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 BSP_DEFINITIONS_H_
#define BSP_DEFINITIONS_H_
/* ------------------------------------ Generic definitions ------------------------------------- */
#define POWER_CONFIGURATION_1 0
#define POWER_CONFIGURATION_2 1
#define POWER_CONFIGURATION_3 2
#define LP_CLK_32000 0
#define LP_CLK_32768 1
#define LP_CLK_RCX 2
#define MODE_IS_MIRRORED 0
#define MODE_IS_CACHED 1
#define MODE_IS_RAM MODE_IS_CACHED
#define NON_VOLATILE_IS_OTP 0 // Code is in OTP
#define NON_VOLATILE_IS_FLASH 1 // Code is in QSPI Flash
#define NON_VOLATILE_IS_NONE 2 // Debug mode! Code is in RAM!
#define EXT_CRYSTAL_IS_16M 0
#define EXT_CRYSTAL_IS_32M 1
#define DEVELOPMENT_MODE 0 // Code is built for debugging
#define PRODUCTION_MODE 1 // Code is built for production
#define BATTERY_TYPE_2xNIMH 0
#define BATTERY_TYPE_3xNIMH 1
#define BATTERY_TYPE_LICOO2 2 // 2.5V discharge voltage, 4.20V charge voltage
#define BATTERY_TYPE_LIMN2O4 3 // 2.5V discharge voltage, 4.20V charge voltage
#define BATTERY_TYPE_NMC 4 // 2.5V discharge voltage, 4.20V charge voltage
#define BATTERY_TYPE_LIFEPO4 5 // 2.5V discharge voltage, 3.65V charge voltage
#define BATTERY_TYPE_LINICOAIO2 6 // 3.0V discharge voltage, 4.20V charge voltage
#define BATTERY_TYPE_CUSTOM 7
#define BATTERY_TYPE_NO_RECHARGE 8
#define BATTERY_TYPE_NO_BATTERY 9
#define BATTERY_TYPE_2xNIMH_ADC_VOLTAGE (2784)
#define BATTERY_TYPE_3xNIMH_ADC_VOLTAGE (4013)
#define BATTERY_TYPE_LICOO2_ADC_VOLTAGE (3439)
#define BATTERY_TYPE_LIMN2O4_ADC_VOLTAGE (3439)
#define BATTERY_TYPE_NMC_ADC_VOLTAGE (3439)
#define BATTERY_TYPE_LIFEPO4_ADC_VOLTAGE (2947)
#define BATTERY_TYPE_LINICOAIO2_ADC_VOLTAGE (3439)
/*
* The supported chip revisions.
*/
#define BLACK_ORCA_IC_REV_A 0
/*
* The supported chip steppings.
*/
#define BLACK_ORCA_IC_STEP_A 0
#define BLACK_ORCA_IC_STEP_B 1
#define BLACK_ORCA_IC_STEP_C 2
#define BLACK_ORCA_IC_STEP_D 3
/*
* The supported DK motherboards.
*/
#define BLACK_ORCA_MB_REV_A 0
#define BLACK_ORCA_MB_REV_B 1
/*
* The supported RF Front-End Modules
*/
#define FEM_NOFEM 0
#define FEM_SKY66112_11 1
#endif /* BSP_DEFINITIONS_H_ */
/**
\}
\}
\}
*/
+140
View File
@@ -0,0 +1,140 @@
/**
****************************************************************************************
*
* @file bsp_fem.h
*
* @brief Board Support Package. RF Front-End Module definitions.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 BSP_FEM_H_
#define BSP_FEM_H_
/* ------------------------------- RF FEM driver (SKY66112-11) configuration settings ----------- */
#ifdef dg_configFEM_DLG_REF_BOARD
#undef dg_configBLACK_ORCA_IC_STEP
#define dg_configBLACK_ORCA_IC_STEP BLACK_ORCA_IC_STEP_D
#define dg_configFEM FEM_SKY66112_11
#ifndef dg_configPOWER_EXT_1V8_PERIPHERALS
#if dg_configPOWER_EXT_1V8_PERIPHERALS == 0
#warning Setting dg_configPOWER_EXT_1V8_PERIPHERALS to 1 for FEM to work
#define dg_configPOWER_EXT_1V8_PERIPHERALS 1
#endif
#endif
#define dg_configFEM_SKY66112_11_FEM_BIAS_V18P
#define dg_configFEM_SKY66112_11_FEM_BIAS2_V18
#ifndef dg_configFEM_SKY66112_11_CSD_PORT
#define dg_configFEM_SKY66112_11_CSD_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_CSD_PIN
#define dg_configFEM_SKY66112_11_CSD_PIN HW_GPIO_PIN_2
#endif
#ifndef dg_configFEM_SKY66112_11_CPS_PORT
#define dg_configFEM_SKY66112_11_CPS_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_CPS_PIN
#define dg_configFEM_SKY66112_11_CPS_PIN HW_GPIO_PIN_7
#endif
#ifndef dg_configFEM_SKY66112_11_CRX_PORT
#define dg_configFEM_SKY66112_11_CRX_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_CRX_PIN
#define dg_configFEM_SKY66112_11_CRX_PIN HW_GPIO_PIN_4
#endif
#ifndef dg_configFEM_SKY66112_11_CTX_PORT
#define dg_configFEM_SKY66112_11_CTX_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_CTX_PIN
#define dg_configFEM_SKY66112_11_CTX_PIN HW_GPIO_PIN_6
#endif
#ifndef dg_configFEM_SKY66112_11_CHL_PORT
#define dg_configFEM_SKY66112_11_CHL_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_CHL_PIN
#define dg_configFEM_SKY66112_11_CHL_PIN HW_GPIO_PIN_5
#endif
#ifndef dg_configFEM_SKY66112_11_ANTSEL_PORT
#define dg_configFEM_SKY66112_11_ANTSEL_PORT HW_GPIO_PORT_4
#endif
#ifndef dg_configFEM_SKY66112_11_ANTSEL_PIN
#define dg_configFEM_SKY66112_11_ANTSEL_PIN HW_GPIO_PIN_3
#endif
#endif /* dg_configFEM_DLG_REF_BOARD */
#ifndef dg_configFEM
#define dg_configFEM FEM_NOFEM
#endif
#if dg_configFEM == FEM_SKY66112_11
#ifndef dg_configFEM_SKY66112_11_CSD_USE_DCF
#define dg_configFEM_SKY66112_11_CSD_USE_DCF 1
#endif
#ifndef dg_configFEM_SKY66112_11_TXSET_DCF
#define dg_configFEM_SKY66112_11_TXSET_DCF 47
#endif
#ifndef dg_configFEM_SKY66112_11_TXRESET_DCF
#define dg_configFEM_SKY66112_11_TXRESET_DCF 0
#endif
#ifndef dg_configFEM_SKY66112_11_RXSET_DCF
#define dg_configFEM_SKY66112_11_RXSET_DCF 1
#endif
#ifndef dg_configFEM_SKY66112_11_RXRESET_DCF
#define dg_configFEM_SKY66112_11_RXRESET_DCF 20
#endif
#endif /* dg_configFEM == FEM_SKY66112_11 */
#endif /* BSP_FEM_H_ */
/**
\}
\}
\}
*/
+100
View File
@@ -0,0 +1,100 @@
/**************************************************************************//**
* @file ARMCM0.h
* @brief CMSIS Core Peripheral Access Layer Header File for
* ARMCM0 Device Series
* @version V3.00
* @date 16. October 2015
******************************************************************************/
/* Copyright (c) 2011 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 ARMCM0_H
#define ARMCM0_H
#include "global_io.h"
/*
* ==========================================================================
* ---------- Interrupt Number Definition -----------------------------------
* ==========================================================================
*/
/*
* ==========================================================================
* ----------- Processor and Core Peripheral Section ------------------------
* ==========================================================================
*/
#include <core_cm0.h> /* Cortex-M0 processor and core peripherals */
#include "system_ARMCM0.h" /* System Header */
/******************************************************************************/
/* Device Specific Peripheral registers structures */
/******************************************************************************/
/*--------------------- General Purpose Input and Ouptut ---------------------*/
typedef union
{
__IO uint32_t WORD;
__IO uint8_t BYTE[4];
} GPIO_Data_TypeDef;
typedef struct
{
GPIO_Data_TypeDef DATA[256];
__O uint32_t DIR;
uint32_t RESERVED[3];
__O uint32_t IE;
} ARM_GPIO_TypeDef;
/******************************************************************************/
/* Peripheral memory map */
/******************************************************************************/
/* Peripheral and SRAM base address */
#define ARM_SRAM_BASE (( uint32_t)0x20000000UL)
#define ARM_PERIPH_BASE (( uint32_t)0x40000000UL)
/* Peripheral memory map */
#define ARM_GPIO_BASE ARM_PERIPH_BASE
#define ARM_GPIO0_BASE (ARM_GPIO_BASE)
#define ARM_GPIO1_BASE (ARM_GPIO_BASE + 0x0800UL)
#define ARM_GPIO2_BASE (ARM_GPIO_BASE + 0x1000UL)
/******************************************************************************/
/* Peripheral declaration */
/******************************************************************************/
#define ARM_GPIO0 ((ARM_GPIO_TypeDef *) ARM_GPIO0_BASE)
#define ARM_GPIO1 ((ARM_GPIO_TypeDef *) ARM_GPIO1_BASE)
#define ARM_GPIO2 ((ARM_GPIO_TypeDef *) ARM_GPIO2_BASE)
#endif /* ARMCM0_H */
+11935
View File
File diff suppressed because it is too large Load Diff
+287
View File
@@ -0,0 +1,287 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup PLATFORM
*
* \brief Black Orca Platform definitions
*
* \{
*/
/**
*****************************************************************************************
*
* @file black_orca.h
*
* @brief Central include header file for the Dialog Black Orca platform.
*
* @version 1.0
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 __BLACK_ORCA_H__
#define __BLACK_ORCA_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
/* assert gcc version is at least 4.9.3 */
# if GCC_VERSION < 40903
# error "Please use gcc version 4.9.3 or newer!"
# endif
#endif
#include "global_io.h"
#if dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A
# if dg_configBLACK_ORCA_IC_STEP == BLACK_ORCA_IC_STEP_D
# include "DA14680AD.h"
# elif dg_configBLACK_ORCA_IC_STEP == BLACK_ORCA_IC_STEP_C
# include "DA14680AC.h"
# elif dg_configBLACK_ORCA_IC_STEP == BLACK_ORCA_IC_STEP_A
# include "DA14680AA.h"
# else
# error "Unknown chip stepping for revision A -- check the value of dg_configBLACK_ORCA_IC_STEP"
# endif
#else
# error "Unknown chip revision -- check the value of dg_configBLACK_ORCA_IC_REV"
#endif
#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */
#include "system_DA14680.h" /* DA14680AA System */
/************************
* Black Orca Memory map
************************/
/**
* \brief Remapped device address range.
*/
#define MEMORY_REMAPPED_BASE 0x00000000
#define MEMORY_REMAPPED_END 0x04000000
/**
* \brief Remapped device memory size (64MiB).
*/
#define MEMORY_REMAPPED_SIZE (MEMORY_REMAPPED_END - MEMORY_REMAPPED_BASE)
/**
* \brief ROM address range.
*/
#define MEMORY_ROM_BASE 0x07F00000
#define MEMORY_ROM_END 0x07F40000
/**
* \brief ROM memory size (256KiB).
*/
#define MEMORY_ROM_SIZE (MEMORY_ROM_END - MEMORY_ROM_BASE)
/**
* \brief OTP Controller address range.
*/
#define MEMORY_OTPC_BASE 0x07F40000
#define MEMORY_OTPC_END 0x07F80000
/**
* \brief OTP memory address range.
*/
#define MEMORY_OTP_BASE 0x07F80000
#define MEMORY_OTP_END 0x07FC0000
/**
* \brief OTP memory size (256KiB).
*/
#define MEMORY_OTP_SIZE (MEMORY_OTP_END - MEMORY_OTP_BASE)
/**
* \brief SYSTEM RAM address range.
*/
#define MEMORY_SYSRAM_BASE 0x07FC0000
#define MEMORY_SYSRAM_END 0x07FE0000
/**
* \brief SYSTEM RAM size (128KiB).
*/
#define MEMORY_SYSRAM_SIZE (MEMORY_SYSRAM_END - MEMORY_SYSRAM_BASE)
/**
* \brief CACHE RAM address range.
*/
#define MEMORY_CACHERAM_BASE 0x07FE0000
#define MEMORY_CACHERAM_END 0x08000000
/**
* \brief CACHE RAM size (128KiB).
*/
#define MEMORY_CACHERAM_SIZE (MEMORY_CACHERAM_END - MEMORY_CACHERAM_BASE)
/**
* \brief QSPI Flash address range.
*/
#define MEMORY_QSPIF_BASE 0x08000000
#define MEMORY_QSPIF_END 0x0BF00000
/**
* \brief QSPI Flash memory size (63MiB).
*/
#define MEMORY_QSPIF_SIZE (MEMORY_QSPIF_END - MEMORY_QSPIF_BASE)
/**
* \brief QSPI Controller address range.
*/
#define MEMORY_QSPIC_BASE 0x0C000000
#define MEMORY_QSPIC_END 0x0C100000
#define WITHIN_RANGE(_a, _s, _e) (((uint32_t)(_a) >= (uint32_t)(_s)) && ((uint32_t)(_a) < (uint32_t)(_e)))
/**
* \brief Address is in the remapped memory region
*/
#define IS_REMAPPED_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_REMAPPED_BASE, MEMORY_REMAPPED_END)
/**
* \brief Address is in the ROM region
*/
#define IS_ROM_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_ROM_BASE, MEMORY_ROM_END)
/**
* \brief Address is in the OTP memory region
*/
#define IS_OTP_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_OTP_BASE, MEMORY_OTP_END)
/**
* \brief Address is in the OTP Controller memory region
*/
#define IS_OTPC_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_OTPC_BASE, MEMORY_OTPC_END)
/**
* \brief Address is in the SYSTEM RAM region
*/
#define IS_SYSRAM_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_SYSRAM_BASE, MEMORY_SYSRAM_END)
/**
* \brief Address is in the CACHE RAM region
*/
#define IS_CACHERAM_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_CACHERAM_BASE, MEMORY_CACHERAM_END)
/**
* \brief Address is in the QSPI Flash memory region
*/
#define IS_QSPIF_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_QSPIF_BASE, MEMORY_QSPIF_END)
/**
* \brief Address is in the QSPI Controller memory region
*/
#define IS_QSPIC_ADDRESS(_a) WITHIN_RANGE((_a), MEMORY_QSPIC_BASE, MEMORY_QSPIC_END)
#define _BLACK_ORCA_IC_VERSION(revision, stepping) \
((((uint32_t)(revision)) << 8) | ((uint32_t)(stepping)))
/**
* \brief Convenience macro to create the full chip version from revision and stepping.
* It takes letters as arguments.
*/
#define BLACK_ORCA_IC_VERSION(revision, stepping) \
_BLACK_ORCA_IC_VERSION(BLACK_ORCA_IC_REV_##revision, \
BLACK_ORCA_IC_STEP_##stepping)
/**
* \brief The chip version that we compile for.
*/
#define BLACK_ORCA_TARGET_IC \
_BLACK_ORCA_IC_VERSION(dg_configBLACK_ORCA_IC_REV, dg_configBLACK_ORCA_IC_STEP)
/**
* \brief Get the chip version of the system, at runtime.
*/
__STATIC_INLINE uint32_t black_orca_get_chip_version(void)
{
uint32_t rev = CHIP_VERSION->CHIP_REVISION_REG - 'A';
uint32_t step = CHIP_VERSION->CHIP_TEST1_REG;
return _BLACK_ORCA_IC_VERSION(rev, step);
}
// Forward declaration
__RETAINED_CODE void hw_cpm_assert_trigger_gpio(void);
#define ASSERT(a) { if (!(a)) while (1); }
#define ASSERT_WARNING(a) \
{ \
if (dg_configIMAGE_SETUP == DEVELOPMENT_MODE) { \
if (!(a)) { \
__asm volatile ( " cpsid i " ); \
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_WDOG_Msk; \
hw_cpm_assert_trigger_gpio(); \
do {} while(1); \
} \
} \
}
#define ASSERT_ERROR(a) \
{ \
if (dg_configIMAGE_SETUP == DEVELOPMENT_MODE) { \
if (!(a)) { \
__asm volatile ( " cpsid i " ); \
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_WDOG_Msk; \
hw_cpm_assert_trigger_gpio(); \
do {} while(1); \
} \
} \
else { \
if (!(a)) { \
__asm volatile ( " cpsid i " ); \
__asm volatile ( " bkpt 2 " ); \
} \
} \
}
#ifdef __cplusplus
}
#endif
#endif /* __BLACK_ORCA_H__ */
/**
* \}
* \}
* \}
*/
+691
View File
@@ -0,0 +1,691 @@
/** \addtogroup ARM
* \brief ARM core documentation
* \{
*/
/**************************************************************************//**
* @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
* @version V3.20
* @date 25. February 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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.
---------------------------------------------------------------------------*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __CORE_CM0_H_GENERIC
#define __CORE_CM0_H_GENERIC
/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
CMSIS violates the following MISRA-C:2004 rules:
\li Required Rule 8.5, object/function definition in header file.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
Function-like macros are used to allow more efficient code.
*/
/*******************************************************************************
* CMSIS definitions
******************************************************************************/
/** \ingroup Cortex_M0
@{
*/
/* CMSIS CM0 definitions */
#define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
#define __CM0_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
#define __CORTEX_M (0x00) /*!< Cortex-M Core */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#define __STATIC_INLINE static __inline
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
#define __STATIC_INLINE static inline
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#define __STATIC_INLINE static inline
#endif
/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
*/
#define __FPU_USED 0
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#include <stdint.h> /* standard types definitions */
#include <core_cmInstr.h> /* Core Instruction Access */
#include <core_cmFunc.h> /* Core Function Access */
#endif /* __CORE_CM0_H_GENERIC */
#ifndef __CMSIS_GENERIC
#ifndef __CORE_CM0_H_DEPENDANT
#define __CORE_CM0_H_DEPENDANT
/* check device defines and use defaults */
#if defined __CHECK_DEVICE_DEFINES
#ifndef __CM0_REV
#define __CM0_REV 0x0000
#warning "__CM0_REV not defined in device header file; using default!"
#endif
#ifndef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS 2
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CMSIS_glob_defs CMSIS Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/*@} end of group Cortex_M0 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core NVIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/** \defgroup CMSIS_core_register Defines and Type Definitions
\brief Type definitions and defines for Cortex-M processor based devices.
*/
/** \ingroup CMSIS_core_register
\defgroup CMSIS_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/** \brief Union type to access the Application Program Status Register (APSR).
*/
typedef union
{
struct
{
#if (__CORTEX_M != 0x04)
uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
#else
uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
#endif
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} APSR_Type;
/** \brief Union type to access the Interrupt Program Status Register (IPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} IPSR_Type;
/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
*/
typedef union
{
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
#if (__CORTEX_M != 0x04)
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
#else
uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
#endif
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
uint32_t N:1; /*!< bit: 31 Negative condition code flag */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} xPSR_Type;
/** \brief Union type to access the Control Registers (CONTROL).
*/
typedef union
{
struct
{
uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
} b; /*!< Structure used for bit access */
uint32_t w; /*!< Type used for word access */
} CONTROL_Type;
/*@} end of group CMSIS_CORE */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
\brief Type definitions for the NVIC Registers
@{
*/
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31];
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[31];
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31];
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[31];
uint32_t RESERVED4[64];
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
} NVIC_Type;
/*@} end of group CMSIS_NVIC */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_SCB System Control Block (SCB)
\brief Type definitions for the System Control Block Registers
@{
*/
/** \brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
uint32_t RESERVED0;
__IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Application Interrupt and Reset Control Register Definitions */
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
/* SCB System Control Register Definitions */
#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
/* SCB Configuration Control Register Definitions */
#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
/* SCB System Handler Control and State Register Definitions */
#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
/*@} end of group CMSIS_SCB */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
\brief Type definitions for the System Timer Registers.
@{
*/
/** \brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
/*@} end of group CMSIS_SysTick */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR)
are only accessible over DAP and not via processor. Therefore
they are not covered by the Cortex-M0 header file.
@{
*/
/*@} end of group CMSIS_CoreDebug */
/** \ingroup CMSIS_core_register
\defgroup CMSIS_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of Cortex-M0 Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core NVIC Functions
- Core SysTick Functions
- Core Register Access Functions
******************************************************************************/
/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## NVIC functions #################################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
\brief Functions that manage interrupts and exceptions via the NVIC.
@{
*/
#include "black_orca.h" /* Declares IRQn_Type */
/* Interrupt Priorities are WORD accessible only under ARMv6M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
/** \brief Enable External Interrupt
The function enables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Disable External Interrupt
The function disables a device-specific interrupt in the NVIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
{
NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Get Pending Interrupt
The function reads the pending register in the NVIC and returns the pending bit
for the specified interrupt.
\param [in] IRQn Interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
*/
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
}
/** \brief Set Pending Interrupt
The function sets the pending bit of an external interrupt.
\param [in] IRQn Interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
}
/** \brief Clear Pending Interrupt
The function clears the pending bit of an external interrupt.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
}
/** \brief Set Interrupt Priority
The function sets the priority of an interrupt.
\note The priority cannot be set for every core interrupt.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
*/
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
else {
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
}
/** \brief Get Interrupt Priority
The function reads the priority of an interrupt. The interrupt
number can be positive to specify an external (device specific)
interrupt, or negative to specify an internal (core) interrupt.
\param [in] IRQn Interrupt number.
\return Interrupt Priority. Value is aligned automatically to the implemented
priority bits of the microcontroller.
*/
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{
if(IRQn < 0) {
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
else {
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
}
/** \brief System Reset
The function initiates a system reset request to reset the MCU.
*/
__STATIC_INLINE void NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
while(1); /* wait until reset */
}
/*@} end of CMSIS_Core_NVICFunctions */
/* ################################## SysTick function ############################################ */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
#if (__Vendor_SysTickConfig == 0)
/** \brief System Tick Configuration
The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
#endif
/*@} end of CMSIS_Core_SysTickFunctions */
#endif /* __CORE_CM0_H_DEPENDANT */
#endif /* __CMSIS_GENERIC */
#ifdef __cplusplus
}
#endif
/**
\} end of ARM group
*/
+645
View File
@@ -0,0 +1,645 @@
/** \addtogroup ARM
* \{
*/
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V3.20
* @date 25. February 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i" : : : "memory");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i" : : : "memory");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f" : : : "memory");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f" : : : "memory");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
__ASM volatile ("");
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
__ASM volatile ("");
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */
/**
\} end of ARM group
*/
+697
View File
@@ -0,0 +1,697 @@
/** \addtogroup ARM
* \{
*/
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V3.20
* @date 05. March 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 __CORE_CMINSTR_H
#define __CORE_CMINSTR_H
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/* Define macros for porting to both thumb1 and thumb2.
* For thumb1, use low register (r0-r7), specified by constrant "l"
* Otherwise, use general registers, specified by constrant "r" */
#if defined (__thumb__) && !defined (__thumb2__)
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
#define __CMSIS_GCC_USE_REG(r) "l" (r)
#else
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
#define __CMSIS_GCC_USE_REG(r) "r" (r)
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
return __builtin_bswap32(value);
#else
uint32_t result;
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
return (short)__builtin_bswap16(value);
#else
uint32_t result;
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
return (op1 >> op2) | (op1 << (32 - op2));
}
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __ASM volatile ("bkpt "#value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return ((uint8_t) result); /* Add explicit type cast here */
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return ((uint16_t) result); /* Add explicit type cast here */
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
{
__ASM volatile ("clrex" ::: "memory");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
{
uint32_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return ((uint8_t) result); /* Add explicit type cast here */
}
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */
/**
\} end of ARM group
*/
+362
View File
@@ -0,0 +1,362 @@
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
/*
*----------------------------------------------------------------------------------------------------------------------------------------
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
*
* Description : IO, data type definitions and memory map selector.
*
* Remark(s) : None.
*
*----------------------------------------------------------------------------------------------------------------------------------------
*
* Synchronicity keywords:
*
* Id : $Id: global_io.h.rca 1.1 Wed Oct 24 09:42:42 2012 wroovers Experimental wroovers $
* Source : $Source: /services/syncdata/hazelaar/8500/server_vault/applab/14580/sw/keil/keil_full_emb_SWHL6V16LL6V32_24okt_crosstest_OK_fpga14b/src/inc/global_io.h.rca $
*
*----------------------------------------------------------------------------------------------------------------------------------------
*
* Synchronicity history:
*
* Log : $Log: global_io.h.rca $
* Log :
* Log : Revision: 1.1 Mon Oct 1 11:08:33 2012 wroovers
* Log : First Working set
* Log :
* Log : Revision: 1.2 Mon Mar 19 11:52:13 2012 snijders
* Log : Updated the '*int*' typedef's. Put the 'bool' (C++ only) typedef in comment, see comment.
* Log : Added typedef HWORD and updated the already existing WORD and DWORD (according to the ARM data type definitions).
* Log : Removed the IAR depending '__far' and 'inline' defines (obsolete).
* Log : Removed the CR16C_SW_V4 depending '__far' define (obsolete).
* Log : Removed the 'NULL' define (most probably also obsolete).
* Log :
* Log : Revision: 1.1 Tue Mar 6 11:00:42 2012 snijders
* Log : Initial check in for Project bbtester. Copied from "../sitel_io.h" and renamed to "global_io.h".
* Log : Updated the header, no further changes yet.
*
*----------------------------------------------------------------------------------------------------------------------------------------
*
* History:
*
* sc14580a
* --------
* 19-mar-2012/HS: Updated the '*int*' typedef's. Put the 'bool' (C++ only) typedef in comment, see comment.
* Added typedef HWORD and updated the already existing WORD and DWORD (according to the ARM data type definitions).
* Removed the IAR depending '__far' and 'inline' defines (obsolete).
* Removed the CR16C_SW_V4 depending '__far' define (obsolete).
* Removed the 'NULL' define (most probably also obsolete).
* 06-mar-2012/HS: Initial check in for Project bbtester. Copied from "../sitel_io.h" and renamed to "global_io.h".
* Updated the header, no further changes yet.
*
*----------------------------------------------------------------------------------------------------------------------------------------
*/
#include <stddef.h>
typedef unsigned char uint8; // 8 bits
typedef char int8; // 8 bits
typedef unsigned short uint16; // 16 bits
typedef short int16; // 16 bits
typedef unsigned long uint32; // 32 bits
typedef long int32; // 32 bits
typedef unsigned long long uint64; // 64 bits
typedef long long int64; // 64 bits
/* See also "Data Types" on pag. 21 of the (Doulos) Cortex-M0 / SoC 1.0 training documentation. */
typedef unsigned char BYTE; // 8 bits = Byte
typedef unsigned short HWORD; // 16 bits = Halfword
typedef unsigned long WORD; // 32 bits = Word
typedef long long DWORD; // 64 bits = Doubleword
// Retention memory attributes
#define __RETAINED __attribute__((section("retention_mem_zi")))
#define __RETAINED_RW __attribute__((section("retention_mem_rw")))
#define __RETAINED_UNINIT __attribute__((section("retention_mem_uninit")))
#if ((dg_configCODE_LOCATION == NON_VOLATILE_IS_FLASH) && (dg_configEXEC_MODE == MODE_IS_CACHED))
#define __RETAINED_CODE __attribute__((section("text_retained"))) __attribute__((noinline))
#else
#define __RETAINED_CODE
#endif
// Interrupt macros
#define GLOBAL_INT_DISABLE() \
do { \
uint32 __l_irq_rest = __get_PRIMASK(); \
__set_PRIMASK(1); \
DBG_CONFIGURE_HIGH(CMN_TIMING_DEBUG, CMNDBG_CRITICAL_SECTION);
#define GLOBAL_INT_RESTORE() \
if (__l_irq_rest == 0) { \
DBG_CONFIGURE_LOW(CMN_TIMING_DEBUG, CMNDBG_CRITICAL_SECTION); \
__set_PRIMASK(0); \
} \
else { \
__set_PRIMASK(1); \
} \
} while(0)
#ifndef offsetof
#if defined(__GNUC__)
#define offsetof(type, member) __builtin_offsetof(type, member)
#else
#define offsetof(type,member) ((size_t)(&((type *)0)->member))
#endif
#endif
#define containingoffset(address, type, field) ((type*)((uint8*)(address)-(size_t)(&((type*)0)->field)))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
#define BIT8 0x0100
#define BIT9 0x0200
#define BIT10 0x0400
#define BIT11 0x0800
#define BIT12 0x1000
#define BIT13 0x2000
#define BIT14 0x4000
#define BIT15 0x8000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
#if defined(__GNUC__)
#define SWAP16(a) __builtin_bswap16(a)
#define SWAP32(a) __builtin_bswap32(a)
#else
#define SWAP16(a) ((a<<8) | (a>>8))
#define SWAP32(a) ((a>>24 & 0xff) | (a>>8 & 0xff00) | (a<<8 & 0xff0000) | (a<<24 & 0xff000000))
#endif
#if defined(__GNUC__)
#define DEPRECATED __attribute__ ((deprecated))
#define DEPRECATED_MSG(msg) __attribute__ ((deprecated(msg)))
#else
#warning Deprecated macro must be implemented for this compiler
#define DEPRECATED
#define DEPRECATED_MSG(msg)
#endif
/**
* \brief Access register field mask.
*
* Returns a register field mask (aimed to be used with local variables).
* e.g.
* \code
* uint16_t tmp;
*
* tmp = CRG_TOP->SYS_STAT_REG;
*
* if (tmp & REG_MSK(CRG_TOP, SYS_STAT_REG, XTAL16_TRIM_READY)) {
* ...
* \endcode
*/
#define REG_MSK(base, reg, field) \
(base ## _ ## reg ## _ ## field ## _Msk)
/**
* \brief Access register field position.
*
* Returns a register field position (aimed to be used with local variables).
*/
#define REG_POS(base, reg, field) \
(base ## _ ## reg ## _ ## field ## _Pos)
/**
* \brief Access register field value.
*
* Returns a register field value (aimed to be used with local variables).
* e.g.
* \code
* uint16_t tmp;
* int counter;
* tmp = CRG_TOP->TRIM_CTRL_REG;
* counter = REG_GET_FIELD(CRG_TOP, TRIM_CTRL_REG, XTAL_COUNT_N, tmp);
* ...
* \endcode
*/
#define REG_GET_FIELD(base, reg, field, var) \
((var & (base ## _ ## reg ## _ ## field ## _Msk)) >> \
(base ## _ ## reg ## _ ## field ## _Pos))
/**
* \brief Set register field value.
*
* Sets a register field value (aimed to be used with local variables).
* e.g.
* \code
* uint16_t tmp;
*
* tmp = CRG_TOP->TRIM_CTRL_REG;
* REG_SET_FIELD(CRG_TOP, TRIM_CTRL_REG, XTAL_COUNT_N, tmp, 10);
* REG_SET_FIELD(CRG_TOP, TRIM_CTRL_REG, XTAL_TRIM_SELECT, tmp, 2);
* CRG_TOP->TRIM_CTRL_REG = tmp;
* ...
* \endcode
*/
#define REG_SET_FIELD(base, reg, field, var, val) \
var = ((var & ~((base ## _ ## reg ## _ ## field ## _Msk))) | \
((val << (base ## _ ## reg ## _ ## field ## _Pos)) & \
(base ## _ ## reg ## _ ## field ## _Msk)))
/**
* \brief Clear register field value.
*
* Clears a register field value (aimed to be used with local variables).
* e.g.
* \code
* uint16_t tmp;
*
* tmp = CRG_TOP->TRIM_CTRL_REG;
* REG_CLR_FIELD(CRG_TOP, TRIM_CTRL_REG, XTAL_COUNT_N, tmp);
* REG_CLR_FIELD(CRG_TOP, TRIM_CTRL_REG, XTAL_TRIM_SELECT, tmp);
* CRG_TOP->TRIM_CTRL_REG = tmp;
* ...
* \endcode
*/
#define REG_CLR_FIELD(base, reg, field, var) \
var &= ~(base ## _ ## reg ## _ ## field ## _Msk)
/**
* \brief Return the value of a register field.
*
* e.g.
* \code
* uint16_t val;
*
* val = REG_GETF(CRG_TOP, TRIM_CTRL_REG, XTAL_COUNT_N);
* ...
* \endcode
*/
#define REG_GETF(base, reg, field) \
(((base->reg) & (base##_##reg##_##field##_Msk)) >> (base##_##reg##_##field##_Pos))
/**
* \brief Set the value of a register field.
*
* e.g.
* \code
*
* REG_SETF(CRG_TOP, TRIM_CTRL_REG, XTAL_COUNT_N, new_value);
* ...
* \endcode
*/
#define REG_SETF(base, reg, field, new_val) \
base->reg = ((base->reg & ~(base##_##reg##_##field##_Msk)) | \
((base##_##reg##_##field##_Msk) & ((new_val) << (base##_##reg##_##field##_Pos))))
/**
* \brief Set a bit of a register.
*
* e.g.
* \code
*
* REG_SET_BIT(CRG_TOP, CLK_TMR_REG, TMR1_ENABLE);
* ...
* \endcode
*/
#define REG_SET_BIT(base, reg, field) \
do { \
base->reg |= (1 << (base##_##reg##_##field##_Pos)); \
} while (0)
/**
* \brief Clear a bit of a register.
*
* e.g.
* \code
*
* REG_CLR_BIT(CRG_TOP, CLK_TMR_REG, TMR1_ENABLE);
* ...
* \endcode
*/
#define REG_CLR_BIT(base, reg, field) \
do { \
base->reg &= ~(base##_##reg##_##field##_Msk); \
} while (0)
/**
* \brief Sets register bits, indicated by the mask, to a value.
*
* e.g.
* \code
* REG_SET_MASKED(RFCU_POWER, RF_CNTRL_TIMER_5_REG, 0xFF00, 0x1818);
* \endcode
*/
#define REG_SET_MASKED(base, reg, mask, value) \
do { \
base->reg = (base->reg & ~(mask)) | ((value) & (mask)); \
} while (0)
#define ENABLE_DEBUGGER \
do { \
REG_SET_BIT(CRG_TOP, SYS_CTRL_REG, DEBUGGER_ENABLE); \
} while(0)
#define DISABLE_DEBUGGER \
do { \
REG_CLR_BIT(CRG_TOP, SYS_CTRL_REG, DEBUGGER_ENABLE); \
} while(0)
#define SWRESET \
do { \
REG_SET_BIT(GPREG, DEBUG_REG, SW_RESET); \
} while (0)
#endif
+143
View File
@@ -0,0 +1,143 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup INTERRUPTS
*
* \brief Interrupt priority configuration
*
* \{
*/
/**
*****************************************************************************************
*
* @file interrupts.h
*
* @brief Interrupt priority configuration
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 INTERRUPTS_H_
#define INTERRUPTS_H_
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Setup interrupt priorities
*
* When CPU is reset all interrupts have some priority setup.
* Reset -3
* NMI -2
* HardFault -1
* All other interrupts have configurable priority that is set to 0.
* If some interrupts should have priority other then default, this function should be called.
* Argument \p prios can specify only those interrupts that need to have value other than default.
* For memory efficiency table with priorities for each interrupt consist of interrupt priority
* tag PRIORITY_x followed by interrupts that should have this priority, interrupts names are from
* enum IRQn_Type.
*
* \note If interrupt priorities do not need to be changed dynamically at runtime, best way to
* specify static configuration is to create table named __dialog_interrupt_priorities that will
* be used automatically at startup.
*
* Most convenient way to prepare such table is to use macros like in example below:
*
* \code{.c}
* INTERRUPT_PRIORITY_CONFIG_START(__dialog_interrupt_priorities)
* PRIORITY_0, // Start interrupts with priority 0 (highest)
* SVCall_IRQn,
* PendSV_IRQn,
* SysTick_IRQn,
* PRIORITY_1, // Start interrupts with priority 1
* BLE_WAKEUP_LP_IRQn,
* BLE_GEN_IRQn,
* FTDF_WAKEUP_IRQn,
* FTDF_GEN_IRQn,
* PRIORITY_2,
* SRC_IN_IRQn,
* SRC_OUT_IRQn,
* PRIORITY_3,
* UART_IRQn,
* UART2_IRQn,
* INTERRUPT_PRIORITY_CONFIG_END
* \endcode
*
* Table __dialog_interrupt_priorities can now be used to call this function.
* Table can specify all interrupts or only those that need to be changed.
*
* \param [in] prios table with interrupts and priorities to setup
*
*/
void set_interrupt_priorities(const int8_t prios[]);
/**
* \brief Check whether running in interrupt context.
*
* \return true if the CPU is serving an interrupt.
*/
static inline bool in_interrupt(void)
{
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
}
/**
* \brief Default interrupt priorities table.
*
*/
extern const int8_t __dialog_interrupt_priorities[];
/*
* Following macros allow easy way to build table with interrupt priorities.
* See example in set_interrupt_priorities function description.
*/
#define INTERRUPT_PRIORITY_CONFIG_START(name) const int8_t name[] = {
#define PRIORITY_0 (RESERVED31_IRQn + 1)
#define PRIORITY_1 (RESERVED31_IRQn + 2)
#define PRIORITY_2 (RESERVED31_IRQn + 3)
#define PRIORITY_3 (RESERVED31_IRQn + 4)
#define PRIORITY_TABLE_END (RESERVED31_IRQn + 5)
#define INTERRUPT_PRIORITY_CONFIG_END PRIORITY_TABLE_END };
#ifdef __cplusplus
extern }
#endif
#endif /* INTERRUPTS_H_ */
/**
* \}
* \}
* \}
*/
+136
View File
@@ -0,0 +1,136 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup SUOTA
*
* \brief SUOTA structure definitions
*
* \{
*/
/**
*****************************************************************************************
*
* @file suota.h
*
* @brief SUOTA structure definitions
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 SUOTA_H_
#define SUOTA_H_
#include <stdint.h>
#define SUOTA_VERSION_1_0 10
#define SUOTA_VERSION_1_1 11
#ifndef SUOTA_VERSION
#define SUOTA_VERSION SUOTA_VERSION_1_1
#endif
/**
* \struct suota_1_1_product_header_t;
*
* \brief SUOTA 1.1 product header as defined by Dialog SUOTA specification.
*
*/
typedef struct {
uint8_t signature[2];
uint16_t flags;
uint32_t current_image_location;
uint32_t update_image_location;
uint8_t reserved[8];
} suota_1_1_product_header_t;
#define SUOTA_1_1_PRODUCT_HEADER_SIGNATURE_B1 0x70
#define SUOTA_1_1_PRODUCT_HEADER_SIGNATURE_B2 0x62
#define SUOTA_1_0_PRODUCT_HEADER_SIGNATURE_B1 0x70
#define SUOTA_1_0_PRODUCT_HEADER_SIGNATURE_B2 0x52
/**
* \struct suota_1_0_image_header_t
*
* \brief SUOTA 1.0 image header as defined by Dialog SUOTA specification.
*
*/
typedef struct {
uint8_t signature[2];
uint8_t valid_flag;
uint8_t image_id;
uint32_t code_size;
uint32_t crc;
uint8_t version[16];
uint32_t timestamp;
uint8_t encryption;
uint8_t reserved[31];
} suota_1_0_image_header_t;
/**
* \struct suota_1_1_image_header_t
*
* \brief SUOTA 1.1 image header as defined by Dialog SUOTA specification.
*
*/
typedef struct {
uint8_t signature[2];
uint16_t flags;
uint32_t code_size;
uint32_t crc;
uint8_t version[16];
uint32_t timestamp;
uint32_t exec_location;
} suota_1_1_image_header_t;
#define SUOTA_1_1_IMAGE_HEADER_SIGNATURE_B1 0x70
#define SUOTA_1_1_IMAGE_HEADER_SIGNATURE_B2 0x61
#define SUOTA_1_0_IMAGE_HEADER_SIGNATURE_B1 0x70
#define SUOTA_1_0_IMAGE_HEADER_SIGNATURE_B2 0x51
#define SUOTA_1_1_IMAGE_FLAG_FORCE_CRC 0x01
#define SUOTA_1_1_IMAGE_FLAG_VALID 0x02
#define SUOTA_1_1_IMAGE_FLAG_RETRY1 0x04
#define SUOTA_1_1_IMAGE_FLAG_RETRY2 0x08
#if (SUOTA_VERSION == SUOTA_VERSION_1_0)
typedef suota_1_0_image_header_t suota_image_header_t;
#else
typedef suota_1_1_image_header_t suota_image_header_t;
#endif
#endif /* SUOTA_H_ */
/**
* \}
* \}
* \}
*/
+64
View File
@@ -0,0 +1,64 @@
/**************************************************************************//**
* @file system_ARMCM0.h
* @brief CMSIS Device System Header File for
* ARMCM0 Device Series
* @version V2.00
* @date 18. August 2015
******************************************************************************/
/* Copyright (c) 2011 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 SYSTEM_ARMCM0_H
#define SYSTEM_ARMCM0_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/** @brief Setup the microcontroller system.
Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/** \brief Update SystemCoreClock variable.
Updates the SystemCoreClock with current core Clock
retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_ARMCM0_H */
+91
View File
@@ -0,0 +1,91 @@
/**************************************************************************//**
* @file system_DA14680.h
* @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File for
* Device DA14680
* @version V3.10
* @date 23. November 2012
*
* @note
*
******************************************************************************/
/* Copyright (c) 2012 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 SYSTEM_DA14680_H
#define SYSTEM_DA14680_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemCoreClock variable.
*/
extern void SystemInit (void);
/**
* Update SystemCoreClock variable
*
* @return none
*
* @brief Updates the SystemCoreClock with current core Clock
* retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
/**
* \brief Convert a CPU address to a physical address
*
* To calculate the physical address, the current remapping (SYS_CTRL_REG.REMAP_ADR0)
* is used.
*
* \param [in] addr address seen by CPU
*
* \return physical address (for DMA, AES/HASH etc.) -- can be same or different as addr
*
*/
extern uint32_t black_orca_phy_addr(uint32_t addr);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_DA14680_H */
+162
View File
@@ -0,0 +1,162 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup MEMORY
*
* \brief QSPI flash access when running in auto mode
*
* \{
*/
/**
****************************************************************************************
*
* @file qspi_automode.h
*
* @brief Access QSPI flash when running in auto mode
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 QSPI_AUTOMODE_H_
#define QSPI_AUTOMODE_H_
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <black_orca.h>
#include <hw_qspi.h>
/**
* QSPI controller allows to execute code directly from QSPI flash.
* When code is executing from flash there is no possibility to reprogram it.
* To be able to modify flash memory while it is used for code execution it must me assured that
* for time needed for erase/write no code is running from flash.
* To achieve this code in this file allows to copy programming functions to RAM and execute it
* from there.
* Great flexibility is achieved by putting all code needed for flash modification in one section
* that will be copied to RAM.
* Code in this section will not access any other functions or constant variables (that could reside
* in flash).
*/
/**
* \brief Get size of RAM buffer needed for code to modify QSPI flash.
*
* Called must allocate buffer at least of this size and pass it qspi_set_code_buffer() to allow
* flash modification.
*
* \return size of buffer needed
*
*/
DEPRECATED
uint32_t qspi_automode_get_code_buffer_size(void);
/**
* \brief Set buffer that will be used for code that modifies flash.
*
* This function should be called with buffer allocated for flash manipulation code.
* Size of this buffer should be at least the value returned from qspi_get_code_buffer_size().
* If function is called with NULL all further calls to qspi_write_flash_page() or
* qspi_erase_flash_sector() will crash.
* To preserve memory it is quite wise to allocate buffer before erase/write, update flash and
* then call this function with NULL and free memory.
*
* \param [in] ram buffer for code that will be used for erase and write.
*
*/
DEPRECATED_MSG("Function does not need to be called")
void qspi_automode_set_code_buffer(void *ram);
/**
* \brief Write flash memory
*
* This function allows to write up to page size of data to flash.
* If size is greater than page size, flash can wrap data and overwrite content of page.
* It's possible to write less then page size.
* Memory should be erased before.
*
* \note: Do not pass buf pointing to QSPI mapped memory.
*
* \param [in] addr offset in flash to write data to
* \param [in] buf pointer to data to write
* \param [in] size number of bytes to write
*
* return number of bytes written
*
*/
size_t qspi_automode_write_flash_page(uint32_t addr, const uint8_t *buf, size_t size);
/**
* \brief Erase flash sector
*
* \param [in] addr starting offset of sector
*/
void qspi_automode_erase_flash_sector(uint32_t addr);
/**
* \brief Read flash memory
*
* \param [in] addr starting offset
* \param [out] buf buffer to read data to
* \param [in] len number of bytes to read
*
* \returns number of bytes read
*/
size_t qspi_automode_read(uint32_t addr, uint8_t *buf, size_t len);
/**
* \brief Get address of flash
*
* \param [in] addr starting offset
*
* \returns address in CPU address space where data is located
*/
static inline const void *qspi_automode_addr(uint32_t addr)
{
return (const void *) (MEMORY_QSPIF_BASE + addr);
}
/**
* \brief Power up flash
*/
void qspi_automode_flash_power_up(void);
/**
* \brief Init QSPI controller
*/
bool qspi_automode_init(void);
#endif /* QSPI_AUTOMODE_H_ */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,680 @@
/**
****************************************************************************************
*
* @file qspi_automode.c
*
* @brief Access QSPI flash when running in auto mode
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdio.h>
#include <stdint.h>
#include <string.h>
#include <black_orca.h>
#include <hw_qspi.h>
/*
* QSPI controller allows to execute code directly from QSPI flash.
* When code is executing from flash there is no possibility to reprogram it.
* To be able to modify flash memory while it is used for code execution it must me assured that
* for time needed for erase/write no code is running from flash.
* To achieve this code in this file allows to copy programming functions to RAM and execute it
* from there.
* Great flexibility is achieved by putting all code needed for flash modification in one section
* that will be copied to RAM.
* Code in this section will not access any other functions or constant variables (that could reside
* in flash).
*/
/* Erase/Write in progress */
#define W25Q_STATUS1_BUSY_BIT 0
#define W25Q_STATUS1_BUSY_MASK (1 << W25Q_STATUS1_BUSY_BIT)
#define W25Q_STATUS1_WEL_BIT 1
#define W25Q_STATUS1_WEL_MASK (1 << W25Q_STATUS1_WEL_BIT)
#define W25Q_WRITE_STATUS_REGISTER 0x01
#define W25Q_PAGE_PROGRAM 0x02
#define W25Q_WRITE_DISABLE 0x04
#define W25Q_READ_STATUS_REGISTER1 0x05
#define W25Q_WRITE_ENABLE 0x06
#define W25Q_SECTOR_ERASE 0x20
#define W25Q_QUAD_PAGE_PROGRAM 0x32
#define W25Q_READ_STATUS_REGISTER2 0x35
#define W25Q_BLOCK_ERASE 0x52
#define W25Q_ERASE_PROGRAM_SUSPEND 0x75
#define W25Q_ERASE_PROGRAM_RESUME 0x7A
#define W25Q_BLOCK_ERASE_64K 0xD8
#define W25Q_CHIP_ERASE 0xC7
#define W25Q_RELEASE_POWER_DOWN 0xAB
#define W25Q_FAST_READ_QUAD 0xEB
#define FLASH_MAX_WRITE_SIZE dg_configFLASH_MAX_WRITE_SIZE
/*
* Use QUAD mode for page write.
* If flash does not support QUAD mode or it is not connected for QUAD mode set it to 0.
*/
#ifndef QUAD_MODE
#define QUAD_MODE 1
#endif
#ifndef ERASE_IN_AUTOMODE
#define ERASE_IN_AUTOMODE 1
#endif
/*
* Macros to put functions that need to be copied to ram in one section.
*/
#define QSPI_SECTION __attribute__ ((section ("text_retained")))
#define QSPI_SECTION_NOINLINE __attribute__ ((section ("text_retained"), noinline))
QSPI_SECTION static uint8_t flash_read_status_register_1(void);
/*
* Set bus mode to single or QUAD mode.
* Flash does not support DUAL page program so it is not supported here.
*/
QSPI_SECTION static inline void qspi_set_bus_mode(HW_QSPI_BUS_MODE mode)
{
if (mode == HW_QSPI_BUS_MODE_SINGLE)
{
QSPIC->QSPIC_CTRLBUS_REG = REG_MSK(QSPIC, QSPIC_CTRLBUS_REG, QSPIC_SET_SINGLE);
}
else
{
#if QUAD_MODE
QSPIC->QSPIC_CTRLBUS_REG = REG_MSK(QSPIC, QSPIC_CTRLBUS_REG, QSPIC_SET_QUAD);
#endif
}
}
/*
* Enable CS
*/
QSPI_SECTION static inline void qspi_cs_enable(void)
{
QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
}
/*
* Disable CS
*/
QSPI_SECTION static inline void qspi_cs_disable(void)
{
QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
}
/*
* Write 8 bits to QSPI bus.
*/
QSPI_SECTION static inline void qspi_write8(uint8_t data)
{
*((volatile uint8_t *) & (QSPIC->QSPIC_WRITEDATA_REG)) = data;
}
/*
* Write 32 bits to QSPI bus.
* It creates more efficient transmission then 8 bits write.
*/
QSPI_SECTION static inline void qspi_write32(uint32_t data)
{
QSPIC->QSPIC_WRITEDATA_REG = data;
}
/*
* Read byte from QSPI bus.
*/
QSPI_SECTION static inline uint8_t qspi_read8(void)
{
return *((volatile uint8_t *) & (QSPIC->QSPIC_READDATA_REG));
}
/*
* Escape continues read mode that could be programmed in auto mode.
* Without this when controller is switched to manual mode it could treat incoming
* commands as addresses.
*/
QSPI_SECTION static inline void flash_reset_continuous_mode(void)
{
qspi_cs_enable();
qspi_write8(0xFF);
qspi_cs_disable();
}
QSPI_SECTION uint8_t flash_release_power_down(void)
{
uint8_t id;
qspi_cs_enable();
qspi_write32(0x000000AB);
id = qspi_read8();
qspi_cs_disable();
while (flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
return id;
}
/*
* Get auto mode state of controller.
*/
QSPI_SECTION static inline bool qspi_get_automode(void)
{
return REG_GETF(QSPIC, QSPIC_CTRLMODE_REG, QSPIC_AUTO_MD);
}
/*
* Set auto or manual mode
*/
QSPI_SECTION static inline void qspi_set_automode(bool automode)
{
REG_SETF(QSPIC, QSPIC_CTRLMODE_REG, QSPIC_AUTO_MD, automode);
}
/*
* Write bytes on QSPI bus.
*/
QSPI_SECTION static void qspi_write(const uint8_t *wbuf, size_t wlen)
{
size_t i;
qspi_cs_enable();
for (i = 0; i < wlen; ++i)
{
qspi_write8(wbuf[i]);
}
qspi_cs_disable();
}
/*
* Do write then read transaction on QSPI bus.
*/
QSPI_SECTION static void qspi_transact(const uint8_t *wbuf, size_t wlen, uint8_t *rbuf,
size_t rlen)
{
size_t i;
qspi_cs_enable();
for (i = 0; i < wlen; ++i)
{
qspi_write8(wbuf[i]);
}
for (i = 0; i < rlen; ++i)
{
rbuf[i] = qspi_read8();
}
qspi_cs_disable();
}
/*
* Enable write to flash.
* Must be called before every write and erase.
*/
QSPI_SECTION static void flash_write_enable(void)
{
uint8_t status;
uint8_t cmd[] = { W25Q_WRITE_ENABLE };
do
{
qspi_write(cmd, 1);
do
{
status = flash_read_status_register_1();
}
while (status & W25Q_STATUS1_BUSY_MASK);
}
while (!(status & W25Q_STATUS1_WEL_MASK));
}
QSPI_SECTION static size_t flash_write_page(uint32_t addr, const uint8_t *buf, uint16_t size)
{
size_t i = 0;
size_t odd = ((uint32_t) buf) & 3;
flash_write_enable();
qspi_cs_enable();
qspi_write32((QUAD_MODE ? W25Q_QUAD_PAGE_PROGRAM : W25Q_PAGE_PROGRAM) |
((addr >> 8) & 0xFF00) | ((addr << 8) & 0xFF0000) | (addr << 24));
/* Reduce max write size, that can reduce interrupt latency time */
if (size > FLASH_MAX_WRITE_SIZE)
{
size = FLASH_MAX_WRITE_SIZE;
}
/* Make sure write will not cross page boundary */
if ((addr & 0xFF) + size > 256)
{
size = 256 - ((addr + 256) & 0xFF);
}
#if QUAD_MODE
qspi_set_bus_mode(HW_QSPI_BUS_MODE_QUAD);
#endif
if (odd)
{
odd = 4 - odd;
for (i = 0; i < odd && i < size; ++i)
{
qspi_write8(buf[i]);
}
}
for (; i + 3 < size; i += 4)
{
qspi_write32(*((uint32_t *) &buf[i]));
}
for (; i < size; i++)
{
qspi_write8(*((uint8_t *) &buf[i]));
}
#if QUAD_MODE
qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
#endif
qspi_cs_disable();
return i;
}
/*
* Read flash status register.
* It is important not to go to auto mode before flash finishes write or erase.
*/
QSPI_SECTION static uint8_t flash_read_status_register_1(void)
{
uint8_t status;
uint8_t cmd[] = { W25Q_READ_STATUS_REGISTER1 };
qspi_transact(cmd, 1, &status, 1);
return status;
}
#if !ERASE_IN_AUTOMODE
/*
* Erase flash sector 4KB command.
*/
QSPI_SECTION static void flash_erase_sector(uint32_t addr)
{
uint8_t cmd[4] = { W25Q_SECTOR_ERASE, addr >> 16, addr >> 8, addr };
flash_write_enable();
qspi_write(cmd, 4);
}
#endif
QSPI_SECTION static inline uint8_t qspi_get_erase_status(void)
{
QSPIC->QSPIC_CHCKERASE_REG = 0;
return HW_QSPIC_REG_GETF(ERASECTRL, ERS_STATE);
}
QSPI_SECTION static inline HW_QSPI_ADDR_SIZE qspi_get_address_size(void)
{
return (HW_QSPI_ADDR_SIZE)HW_QSPIC_REG_GETF(CTRLMODE, USE_32BA);
}
QSPI_SECTION_NOINLINE static bool qspi_writable(void)
{
bool am = qspi_get_automode();
bool writable;
/*
* From now on QSPI may not be available, turn of interrupts.
*/
GLOBAL_INT_DISABLE();
/*
* Turn off auto mode to allow write.
*/
qspi_set_automode(false);
/*
* Set default mode for commands.
*/
qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
/*
* Exit continues mode, after this flash will interpret commands again.
*/
flash_reset_continuous_mode();
/*
* Check if flash is ready.
*/
writable = !(flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
/*
* Restore auto mode.
*/
qspi_set_automode(am);
/*
* Let other code to be executed including QSPI one.
*/
GLOBAL_INT_RESTORE();
return writable;
}
/*
* Erase sector using QSPI controller.
*/
QSPI_SECTION static void qspi_erase_sector(uint32_t addr)
{
/* Wait for previous erase to end */
while (qspi_get_erase_status() != 0)
{
}
if (qspi_get_address_size() == HW_QSPI_ADDR_SIZE_32)
{
addr >>= 12;
}
else
{
addr >>= 4;
}
/* Setup erase block page */
HW_QSPIC_REG_SETF(ERASECTRL, ERS_ADDR, addr);
/* Fire erase */
HW_QSPIC_REG_SETF(ERASECTRL, ERASE_EN, 1);
}
/*
* Write page to flash.
* This function blocks interrupts switches to manual mode, writes page (or less) of data.
* Then it waits for flash to become ready before switching back to auto mode.
* Make sure that buf does not point to QSPI mapped memory.
*/
QSPI_SECTION_NOINLINE static size_t write_page(uint32_t addr, const uint8_t *buf, uint16_t size)
{
bool am = qspi_get_automode();
size_t written;
/*
* From now on QSPI may not be available, turn of interrupts.
*/
GLOBAL_INT_DISABLE();
/*
* Turn off auto mode to allow write.
*/
qspi_set_automode(false);
/*
* Set default mode for commands.
*/
qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
/*
* Exit continues mode, after this flash will interpret commands again.
*/
flash_reset_continuous_mode();
while (flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
/*
* Write page of data.
*/
written = flash_write_page(addr, buf, size);
/*
* Wait for flash to become ready again.
*/
while (flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
/*
* Restore auto mode.
*/
qspi_set_automode(am);
/*
* Let other code to be executed including QSPI one.
*/
GLOBAL_INT_RESTORE();
return written;
}
/*
* Erase flash sector.
* This function blocks interrupts switches to manual mode, erases sector.
* Then it waits for flash to become ready before switching back to auto mode.
*/
QSPI_SECTION_NOINLINE static void erase_sector(uint32_t addr)
{
#if ERASE_IN_AUTOMODE
/*
* Erase sector in automode
*/
qspi_erase_sector(addr);
/*
* Wait for erase to finish
*/
while (qspi_get_erase_status())
{
}
#else
bool am = qspi_get_automode();
/*
* From now on QSPI may not be available, turn of interrupts.
*/
GLOBAL_INT_DISABLE();
/*
* Turn off auto mode to allow write.
*/
qspi_set_automode(false);
/*
* Set default mode for commands.
*/
qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
flash_release_power_down();
/*
* Exit continues mode, after this flash will interpret commands again.
*/
flash_reset_continuous_mode();
while (flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
/*
* Execute erase command.
*/
flash_erase_sector(addr);
/*
* Wait for flash to become ready again.
*/
while (flash_read_status_register_1() & W25Q_STATUS1_BUSY_MASK);
/*
* Restore auto mode.
*/
qspi_set_automode(am);
/*
* Let other code to be executed including QSPI one.
*/
GLOBAL_INT_RESTORE();
#endif
}
uint32_t qspi_automode_get_code_buffer_size(void)
{
/* Return 1 in case some code will pass this value to memory allocation function */
return 1;
}
void qspi_automode_set_code_buffer(void *ram)
{
(void) ram; /* Unused */
}
bool qspi_automode_writable(void)
{
return qspi_writable();
}
size_t qspi_automode_write_flash_page(uint32_t addr, const uint8_t *buf, size_t size)
{
while (!qspi_automode_writable())
{
}
return write_page(addr, buf, size);
}
void qspi_automode_erase_flash_sector(uint32_t addr)
{
while (!qspi_automode_writable())
{
}
erase_sector(addr);
}
size_t qspi_automode_read(uint32_t addr, uint8_t *buf, size_t len)
{
memcpy(buf, (void *)(MEMORY_QSPIF_BASE + addr), len);
return len;
}
void qspi_automode_flash_power_up(void)
{
if (dg_configCODE_LOCATION != NON_VOLATILE_IS_FLASH)
{
bool am = qspi_get_automode();
/*
* Turn off auto mode to allow write.
*/
qspi_set_automode(false);
/*
* Set default mode for commands.
*/
qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
flash_release_power_down();
/*
* Restore auto mode.
*/
qspi_set_automode(am);
}
}
static const qspi_config qspi_cfg =
{
HW_QSPI_ADDR_SIZE_24, HW_QSPI_POL_HIGH, HW_QSPI_SAMPLING_EDGE_NEGATIVE
};
bool qspi_automode_init(void)
{
hw_qspi_enable_clock();
/*
* Setup erase instruction that will be sent by QSPI controller to erase sector in automode.
*/
hw_qspi_set_erase_instruction(W25Q_SECTOR_ERASE, HW_QSPI_BUS_MODE_SINGLE,
HW_QSPI_BUS_MODE_SINGLE, 8, 5);
/*
* Setup instruction pair that will temporarily suspend erase operation to allow read.
*/
hw_qspi_set_suspend_resume_instructions(W25Q_ERASE_PROGRAM_SUSPEND, HW_QSPI_BUS_MODE_SINGLE,
W25Q_ERASE_PROGRAM_RESUME, HW_QSPI_BUS_MODE_SINGLE, 7);
/*
* QSPI controller must send write enable before erase, this sets it up.
*/
hw_qspi_set_write_enable_instruction(W25Q_WRITE_ENABLE, HW_QSPI_BUS_MODE_SINGLE);
/*
* Setup instruction that will be used to periodically check erase operation status.
* Check LSB which is 1 when erase is in progress.
*/
hw_qspi_set_read_status_instruction(W25Q_READ_STATUS_REGISTER1, HW_QSPI_BUS_MODE_SINGLE,
HW_QSPI_BUS_MODE_SINGLE, W25Q_STATUS1_BUSY_BIT, 1, 20, 0);
/*
* This sequence is necessary if flash is working in continuous read mode, when instruction
* is not sent on every read access just address. Sending 0xFFFF will exit this mode.
* This sequence is sent only when QSPI is working in automode and decides to send one of
* instructions above.
* If flash is working in DUAL bus mode sequence should be 0xFFFF and size should be
* HW_QSPI_BREAK_SEQ_SIZE_2B.
*/
hw_qspi_set_break_sequence(0xFFFF, HW_QSPI_BUS_MODE_SINGLE, HW_QSPI_BREAK_SEQ_SIZE_1B, 0);
/*
* If application starts from FLASH then bootloader must have set read instruction.
*/
if (dg_configCODE_LOCATION != NON_VOLATILE_IS_FLASH)
{
hw_qspi_init(&qspi_cfg);
hw_qspi_set_div(HW_QSPI_DIV_1);
flash_reset_continuous_mode();
hw_qspi_set_read_instruction(W25Q_FAST_READ_QUAD, 1, 2, HW_QSPI_BUS_MODE_SINGLE,
HW_QSPI_BUS_MODE_QUAD, HW_QSPI_BUS_MODE_QUAD,
HW_QSPI_BUS_MODE_QUAD);
hw_qspi_set_extra_byte(0xA0, HW_QSPI_BUS_MODE_QUAD, 1);
hw_qspi_set_automode(true);
}
HW_QSPIC_REG_SETF(BURSTCMDB, CS_HIGH_MIN, 1);
return true;
}
File diff suppressed because it is too large Load Diff
+330
View File
@@ -0,0 +1,330 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup DMA
* \{
*/
/**
****************************************************************************************
*
* @file hw_dma.h
*
* @brief Definition of API for the DMA Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_DMA_H_
#define HW_DMA_H_
#if dg_configUSE_HW_DMA
#include <stdint.h>
#include <black_orca.h>
/*
* ENUMERATION DEFINITIONS
*****************************************************************************************
*/
/**
* \brief DMA channel number
*
*/
typedef enum {
HW_DMA_CHANNEL_0 = 0, /**< Channel number 0 */
HW_DMA_CHANNEL_1 = 1, /**< Channel number 1 */
HW_DMA_CHANNEL_2 = 2, /**< Channel number 2 */
HW_DMA_CHANNEL_3 = 3, /**< Channel number 3 */
HW_DMA_CHANNEL_4 = 4, /**< Channel number 4 */
HW_DMA_CHANNEL_5 = 5, /**< Channel number 5 */
HW_DMA_CHANNEL_6 = 6, /**< Channel number 6 */
HW_DMA_CHANNEL_7 = 7, /**< Channel number 7 */
HW_DMA_CHANNEL_INVALID = 8 /**< Invalid Channel number */
} HW_DMA_CHANNEL;
/**
* \brief DMA channel enable/disable
*
*/
typedef enum {
HW_DMA_STATE_DISABLED = 0x0, /**< DMA disabled */
HW_DMA_STATE_ENABLED = 0x1 /**< DMA enabled */
} HW_DMA_STATE;
/**
* \brief DMA channel bus width transfer
*
*/
typedef enum {
HW_DMA_BW_BYTE = 0x0, /**< Byte */
HW_DMA_BW_HALFWORD = 0x2, /**< Halfword */
HW_DMA_BW_WORD = 0x4 /**< Word */
} HW_DMA_BW;
/**
* \brief DMA channel interrupt enable/disable
*
*/
typedef enum {
HW_DMA_IRQ_STATE_DISABLED = 0x0, /**< Disable interrupt on this channel */
HW_DMA_IRQ_STATE_ENABLED = 0x8 /**< Enable interrupt on this channel */
} HW_DMA_IRQ_STATE;
/**
* \brief DMA request input multiplexer controlled
*
*/
typedef enum {
HW_DMA_DREQ_START = 0x0, /**< DMA channel starts immediately */
HW_DMA_DREQ_TRIGGERED = 0x10 /**< DMA channel must be triggered by peripheral DMA request */
} HW_DMA_DREQ;
/**
* \brief Increment destination address mode
*
*/
typedef enum {
HW_DMA_BINC_FALSE = 0x0, /**< Do not increment */
HW_DMA_BINC_TRUE = 0x20 /**< Increment according value of BW */
} HW_DMA_BINC;
/**
* \brief Increment of source address mode
*
*/
typedef enum {
HW_DMA_AINC_FALSE = 0x0, /**< Do not increment */
HW_DMA_AINC_TRUE = 0x40 /**< Increment according value of BW */
} HW_DMA_AINC;
/**
* \brief Channel mode
*
* In normal mode the DMA transfer stops the transfer after
* length DMAx_LEN_REG.
* In circular mode the DMA channel repeats the transfer
* after length DMAx_LEN_REG with the initial register values
* DMAx_A_START_REG, DMAx_B_START_REG, DMAx_LEN_REG, DMAx_INT_REG.
*
* \note only works if DREQ_MODE = 1
*
*/
typedef enum {
HW_DMA_MODE_NORMAL = 0x0, /**< Normal mode */
HW_DMA_MODE_CIRCULAR = 0x80 /**< Circular mode */
} HW_DMA_MODE;
/**
* \brief Channel priority
*
* Set priority level of DMA channel to determine which DMA
* channel will be activated in case more than one DMA channel
* requests DMA.
*
*/
typedef enum {
HW_DMA_PRIO_0 = 0x000, /**< Lowest priority */
HW_DMA_PRIO_1 = 0x100, /**< .. */
HW_DMA_PRIO_2 = 0x200, /**< .. */
HW_DMA_PRIO_3 = 0x300, /**< .. */
HW_DMA_PRIO_4 = 0x400, /**< .. */
HW_DMA_PRIO_5 = 0x500, /**< .. */
HW_DMA_PRIO_6 = 0x600, /**< .. */
HW_DMA_PRIO_7 = 0x700 /**< Highest priority */
} HW_DMA_PRIO;
/**
* \brief DMA idle mode
*
* In blocking mode the DMA performs a fast back-to-back
* copy, disabling bus access for any bus master with lower priority.
* In interrupting mode the DMA inserts a wait cycle after each
* store allowing the CR16 to steal cycles or cache to perform a
* burst read.
*
* \note if DREQ_MODE = 1, DMA_IDLE does not have any effect
*
*/
typedef enum {
HW_DMA_IDLE_BLOCKING_MODE = 0x000, /**< Blocking mode */
HW_DMA_IDLE_INTERRUPTING_MODE = 0x800 /**< Interrupting mode */
} HW_DMA_IDLE;
/**
* \brief DMA init mode
*
*/
typedef enum {
HW_DMA_INIT_AX_BX_AY_BY = 0x0000, /**< DMA performs copy A1 to B1, A2 to B2 */
HW_DMA_INIT_AX_BX_BY = 0x1000 /**< DMA performs copy A1 to B1, B2 */
} HW_DMA_INIT;
/**
* \brief Channel request trigger
*
*/
typedef enum {
HW_DMA_TRIG_SPI_RXTX = 0x0,
HW_DMA_TRIG_SPI2_RXTX = 0x1,
HW_DMA_TRIG_UART_RXTX = 0x2,
HW_DMA_TRIG_UART2_RXTX = 0x3,
HW_DMA_TRIG_I2C_RXTX = 0x4,
HW_DMA_TRIG_I2C2_RXTX = 0x5,
HW_DMA_TRIG_USB_RXTX = 0x6,
HW_DMA_TRIG_I2S_LEFTRIGHT = 0x8,
HW_DMA_TRIG_PDM_LEFTRIGHT = 0x9,
HW_DMA_TRIG_FTDF_RXTX = 0xA,
HW_DMA_TRIG_ECC_RXTX = 0xB,
HW_DMA_TRIG_ADC = 0xC,
HW_DMA_TRIG_NONE = 0xF
} HW_DMA_TRIG;
/**
* \brief DMA channel transfer callback
*
* This function is called by the DMA driver when the
* interrupt is fired.
*
* \param [in] user_data transfered data
* \param [in] len length of transfered data
*
*/
typedef void (*hw_dma_transfer_cb)(void *user_data, uint16_t len);
/**
* \brief DMA parameters structure
*
*/
typedef struct {
HW_DMA_CHANNEL channel_number; /**< DMA Channel Number to be used */
HW_DMA_BW bus_width; /**< Transfer Bus width: 8, 16 or 32 bits */
HW_DMA_IRQ_STATE irq_enable; /**< Enable or disable IRQ generation */
uint16 irq_nr_of_trans; /**< Number of transfers before IRQ generation
set to 0 to fire IRQ after transfer ends */
HW_DMA_DREQ dreq_mode; /**< Start DMA immediately or triggered by peripheral */
HW_DMA_AINC a_inc; /**< Increment of source address */
HW_DMA_BINC b_inc; /**< Increment of destination address */
HW_DMA_MODE circular; /**< Select normal or circular operation */
HW_DMA_PRIO dma_prio; /**< Channel priority from 0 to 7 */
HW_DMA_IDLE dma_idle; /**< Idle mode: blocking or interrupting */
HW_DMA_INIT dma_init; /**< Copy mode: block copy or mem init */
HW_DMA_TRIG dma_req_mux; /**< DMA trigger */
uint32 src_address; /**< Source address */
uint32 dest_address; /**< Destination address */
uint16 length; /**< Number of DMA transfers */
hw_dma_transfer_cb callback; /**< Function to call after irq_nr_of_trans transfers */
void *user_data; /**< Data to pass to Callback */
} DMA_setup;
/*
* API FUNCTIONS DEFINITIONS
*****************************************************************************************
*/
/**
* \brief Initialize DMA Channel
*
* \param [in] channel_setup pointer to struct of type DMA_Setup
*
*/
void hw_dma_channel_initialization(DMA_setup *channel_setup);
/**
* \brief Enable or disable a DMA channel
*
* \param [in] channel_number DMA Channel Number to start/stop
* \param [in] dma_on enable/disable DMA channel
*
*/
void hw_dma_channel_enable(HW_DMA_CHANNEL channel_number, HW_DMA_STATE dma_on);
/**
* \brief Stop DMA channel if operation is in progress
*
* If no transfer is in progress nothing happens.
* If there is outstanding DMA transfer it will be stopped and
* callback will be called with count of data already transfered
*
* \param [in] channel_number DMA channel number to stop
*
*/
void hw_dma_channel_stop(HW_DMA_CHANNEL channel_number);
/**
* \brief Read number of transmitted bytes so far
*
* Use this function to see how many bytes were transfered
* via DMA channel so far. This number can changed very soon.
*
* \param [in] channel_number DMA channel number
*
* \return number of bytes already transfered (when transfer is in progress),
* 0 - if transfer is already finished,
* undefined if called or not started channel
*
*/
uint16_t hw_dma_transfered_bytes(HW_DMA_CHANNEL channel_number);
/**
* \brief Freeze DMA
*
*/
static inline void hw_dma_freeze(void)
{
GPREG->SET_FREEZE_REG = REG_MSK(GPREG, SET_FREEZE_REG, FRZ_DMA);
}
/**
* \brief Unfreeze DMA
*
*/
static inline void hw_dma_unfreeze(void)
{
GPREG->RESET_FREEZE_REG = REG_MSK(GPREG, RESET_FREEZE_REG, FRZ_DMA);
}
/**
* \brief Check if any DMA channel is active.
*
* \return true, if a channel is active else false.
*/
bool hw_dma_channel_active(void);
#endif /* dg_configUSE_HW_DMA */
#endif /* HW_DMA_H_ */
/**
* \}
* \}
* \}
*/
+193
View File
@@ -0,0 +1,193 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup FEM
* \{
*/
/**
*****************************************************************************************
*
* @file
*
* @brief FEM Driver for SKYWORKS SKY66112-11 Low Level Driver API.
*
* GPIOs used for controlling the FEM are configured using the following macros, that should be placed
* in custom_config.h:
*
* CSD : dg_configFEM_SKY66112_11_CSD_PORT/PIN
* CPS : dg_configFEM_SKY66112_11_CPS_PORT/PIN
* CRX : dg_configFEM_SKY66112_11_CRX_PORT/PIN
* CTX : dg_configFEM_SKY66112_11_CTX_PORT/PIN
* CHL : dg_configFEM_SKY66112_11_CHL_PORT/PIN
* ANTSEL: dg_configFEM_SKY66112_11_ANTSEL_PORT/PIN
*
* FEM BIAS Voltage control is enabled by the following macros:
*
* V18 : dg_configFEM_SKY66112_11_FEM_BIAS_V18
* V18P : dg_configFEM_SKY66112_11_FEM_BIAS_V18P
*
* If none of them is set, FEM BIAS will not be controlled by this driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_FEM_H_
#define HW_FEM_H_
#if dg_configFEM == FEM_SKY66112_11
#include <stdbool.h>
#if defined(dg_configFEM_SKY66112_11_FEM_BIAS_V18) && defined(dg_configFEM_SKY66112_11_FEM_BIAS_V18P)
#error Only one of dg_configFEM_SKY66112_11_FEM_BIAS_V18 and dg_configFEM_SKY66112_11_FEM_BIAS_V18P can be set at a time
#endif
/* Configuration/state structure (actually just a byte) */
typedef struct __attribute__ ((__packed__)) {
uint8_t tx_power: 1;
uint8_t tx_bypass: 1;
uint8_t rx_bypass: 1;
uint8_t antsel: 1;
uint8_t started: 1;
} hw_fem_config;
/**
* \brief Configures FEM TX Power
*
* \param [in] high Set true to enable high TX power
*
*/
void hw_fem_set_txpower(bool high);
/**
* \brief Configures FEM Antenna to use
*
* \param [in] one false: antenna 0, true: antenna 1
*
*/
void hw_fem_set_antenna(bool one);
/**
* \brief Configures FEM TX bypass mode
*
* \param [in] enable false: Use PA, true: bypass
*
*/
void hw_fem_set_tx_bypass(bool enable);
/**
* \brief Configures FEM RX bypass mode
*
* \param [in] enable false: Use LNA, true: bypass
*
*/
void hw_fem_set_rx_bypass(bool enable);
/**
* \brief Gets the TX Power setting
*
* \return true, if TX Power is high, false if low
*
*/
bool hw_fem_get_txpower(void);
/**
* \brief Gets the selected antenna
*
* \return false: antenna 1, true: antenna 2
*
*/
bool hw_fem_get_antenna(void);
/**
* \brief Gets the TX bypass mode
*
* \return false: No TX bypass, true: TX bypass
*
*/
bool hw_fem_get_tx_bypass(void);
/**
* \brief Gets the RX bypass mode
*
* \return false: No RX bypass, true: RX bypass
*
*/
bool hw_fem_get_rx_bypass(void);
/**
* \brief Sets the FEM Bias
*
* \param [in] voltage The voltage to set the FEM Bias to (mV)
*
* \return 0: success, -1: Out of range value entered, -2: FEM BIAS not supported on this board
*
*/
int hw_fem_set_bias(uint16_t voltage);
/**
* \brief Sets the 2nd FEM Bias
*
* \param [in] voltage The voltage to set the 2nd FEM Bias to (mV)
*
* \return 0: success, -1: Out of range value entered, -2: 2nd FEM BIAS not supported on this board
*
*/
int hw_fem_set_bias2(uint16_t voltage);
/**
* \brief Starts and configures FEM.
*
* Configures and sets GPIOs according to configuration set by hw_fem_set_config(). Also configures
* DCF Timers.
*
*
* \note To be called by the RF driver when RF is powered on
*
*/
void hw_fem_start(void);
/**
* \brief Stops FEM.
*
* Stops DCF timers and sets all FEM control signals to 0 to achieve the lowest possible power
*
* \note To be called by the RF driver when RF is powered off
*
*/
void hw_fem_stop(void);
#endif /* dg_configFEM == FEM_SKY66112_11 */
#endif /* HW_FEM_H_ */
/**
* \}
* \}
* \}
*/
+716
View File
@@ -0,0 +1,716 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup GPADC
* \{
*/
/**
*****************************************************************************************
*
* @file hw_gpadc.h
*
* @brief Definition of API for the GPADC Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_GPADC_H
#define HW_GPADC_H
#if dg_configUSE_HW_GPADC
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/**
* \brief ADC input mode
*
*/
typedef enum {
HW_GPADC_INPUT_MODE_DIFFERENTIAL = 0, /**< differential mode (default) */
HW_GPADC_INPUT_MODE_SINGLE_ENDED = 1 /**< single ended mode */
} HW_GPADC_INPUT_MODE;
/**
* \brief ADC clock source
*
*/
typedef enum {
HW_GPADC_CLOCK_INTERNAL = 0, /**< internal high-speed clock (default) */
HW_GPADC_CLOCK_DIGITAL = 1 /**< digital clock (16/96MHz) */
} HW_GPADC_CLOCK;
/**
* \brief ADC input
*
* \p GPADC_INPUT_SE_* values should be used only in single ended mode
* \p GPADC_INPUT_DIFF_* values should be used only in differential mode
*
*/
typedef enum {
HW_GPADC_INPUT_SE_P12 = 0, /**< GPIO 1.2 */
HW_GPADC_INPUT_SE_P14 = 1, /**< GPIO 1.4 */
HW_GPADC_INPUT_SE_P13 = 2, /**< GPIO 1.3 */
HW_GPADC_INPUT_SE_P07 = 3, /**< GPIO 0.7 */
HW_GPADC_INPUT_SE_AVS = 4, /**< analog ground level */
HW_GPADC_INPUT_SE_VDD = 5,
HW_GPADC_INPUT_SE_VDCDC = 6,
HW_GPADC_INPUT_SE_V33 = 7,
HW_GPADC_INPUT_SE_VBAT = 9, /**< battery */
HW_GPADC_INPUT_SE_TEMPSENS = 14, /**< temperature sensor */
HW_GPADC_INPUT_SE_P06 = 16, /**< GPIO 0.6 */
HW_GPADC_INPUT_SE_P10 = 17, /**< GPIO 1.0 */
HW_GPADC_INPUT_SE_P15 = 18, /**< GPIO 1.5 */
HW_GPADC_INPUT_SE_P24 = 19, /**< GPIO 2.4 */
HW_GPADC_INPUT_DIFF_P12_P14 = 0, /**< GPIO 1.2 vs 1.4 */
HW_GPADC_INPUT_DIFF_P13_P07 = 1, /**< GPIO 1.3 vs 0.7 */
} HW_GPADC_INPUT;
/**
* \brief ADC interrupt handler
*
*/
typedef void (*hw_gpadc_interrupt_cb)(void);
/**
* \brief ADC configuration
*
*/
typedef struct {
HW_GPADC_CLOCK clock; /**< clock source */
HW_GPADC_INPUT_MODE input_mode; /**< input mode */
HW_GPADC_INPUT input; /**< ADC input */
uint8_t sample_time; /**< sample time */
bool continous; /**< continous mode state */
uint8_t interval; /**< interval between conversions in continous mode */
bool input_attenuator; /**< input attenuator state */
bool chopping; /**< chopping state */
uint8_t oversampling; /**< oversampling value */
} gpadc_config;
/**
* \brief Initialize ADC
*
* \p cfg can be NULL - no configuration is performed in such case.
*
* \param [in] cfg configuration
*
*/
void hw_gpadc_init(const gpadc_config *cfg);
/**
* \brief Configure ADC
*
* Shortcut to call appropriate configuration function. If \p cfg is NULL, this function does
* nothing.
*
* \param [in] cfg configuration
*
*/
void hw_gpadc_configure(const gpadc_config *cfg);
/**
* \brief Reset ADC to its default values without disabling the LDO.
*
*/
void hw_gpadc_reset(void);
/**
* \brief Register interrupt handler
*
* Interrupt is enabled after calling this function. Application is responsible for clearing
* interrupt using hw_gpadc_clear_interrupt(). If no callback is specified interrupt is cleared by
* driver.
*
* \param [in] cb callback fired on interrupt
*
* \sa hw_gpadc_clear_interrupt
*
*/
void hw_gpadc_register_interrupt(hw_gpadc_interrupt_cb cb);
/**
* \brief Unregister interrupt handler
*
* Interrupt is disabled after calling this function.
*
*/
void hw_gpadc_unregister_interrupt(void);
/**
* \brief Clear interrupt
*
* Application should call this in interrupt handler to clear interrupt.
*
* \sa hw_gpadc_register_interrupt
*
*/
static inline void hw_gpadc_clear_interrupt(void)
{
GPADC->GP_ADC_CLEAR_INT_REG = 1;
}
/**
* \brief Enable ADC
*
* Sampling is started after calling this function, to start conversion application should call
* hw_gpadc_start().
*
* \sa hw_gpadc_start
*
*/
static inline void hw_gpadc_enable(void)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_EN, 1);
}
/**
* \brief Disable ADC
*
* Application should wait for conversion to be completed before disabling ADC. In case of
* continuous mode, application should disable continuous mode and then wait for conversion to be
* completed in order to have ADC in defined state.
*
* \sa hw_gpadc_in_progress
* \sa hw_gpadc_set_continuous
*
*/
static inline void hw_gpadc_disable(void)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_EN, 0);
}
/**
* \brief Set the delay required to enable the ADC_LDO.
*
* param [in] LDO enable delay
*
*/
static inline void hw_gpadc_set_ldo_delay(uint32_t delay)
{
REG_SETF(GPADC, GP_ADC_CTRL3_REG, GP_ADC_EN_DEL, delay);
}
/** \brief Perform ADC calibration
*
* Calibration is performed. The input mode must be HW_GPADC_INPUT_SE_VDD (1.2V).
* LDO constant and dynamic currents may be on. The input mode must be Single Ended. The calibration
* is performed only once.
*
* \sa hw_gpadc_set_input_mode
*
*/
void hw_gpadc_calibrate(void);
/**
* \brief Start conversion
*
* Application should not call this function while conversion is still in progress.
*
* \sa hw_gpadc_in_progress
*
*/
static inline void hw_gpadc_start(void)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_START, 1);
}
/**
* \brief Check if conversion is in progress
*
* \return conversion state
*
*/
static inline bool hw_gpadc_in_progress(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_START);
}
/**
* \brief Set continuous mode
*
* With continuous mode enabled ADC will automatically restart conversion once completed. It's still
* required to start 1st conversion using hw_gpadc_start(). Interval between subsequent conversions
* can be adjusted using hw_gpadc_set_interval().
*
* \param [in] enabled continuous mode state
*
* \sa hw_gpadc_start
* \sa hw_gpadc_set_interval
*
*/
static inline void hw_gpadc_set_continuous(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CONT, !!enabled);
}
/**
* \brief Get continuous mode state
*
* \return continuous mode state
*
*/
static inline bool hw_gpadc_get_continuous(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CONT);
}
/**
* \brief Set input channel
*
* Application is responsible for using proper input symbols depending on whether single ended or
* differential mode is used.
*
* \param [in] input input channel
*
* \sa hw_gpadc_set_input_mode
* \sa GPADC_INPUT_MODE
*
*/
static inline void hw_gpadc_set_input(HW_GPADC_INPUT input)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SEL, input);
}
/**
* \brief Get current input channel
*
* \return input channel
*
*/
static inline HW_GPADC_INPUT hw_gpadc_get_input(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SEL);
}
/**
* \brief Set input mode
*
* \param [in] mode input mode
*
*/
static inline void hw_gpadc_set_input_mode(HW_GPADC_INPUT_MODE mode)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SE, mode);
}
/**
* \brief Get current input mode
*
* return input mode
*
*/
static inline HW_GPADC_INPUT_MODE hw_gpadc_get_input_mode(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SE);
}
/**
* \brief Set clock source
*
* \param [in] clock clock source
*
*/
static inline void hw_gpadc_set_clock(HW_GPADC_CLOCK clock)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CLK_SEL, clock);
}
/**
* \brief Get current clock source
*
* \return clock source
*
*/
static inline HW_GPADC_CLOCK hw_gpadc_get_clock(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CLK_SEL);
}
/**
* \brief Set oversampling
*
* With oversampling enabled multiple successive conversions will be executed and results are added
* together to increase effective number of bits in result.
*
* Number of samples taken is 2<sup>\p n_samples</sup>. Valid values for \p n_samples are 0-7 thus
* at most 128 samples can be taken. In this case 17bits of result are generated with the least
* significant bit being discarded.
*
* \param [in] n_samples number of samples to be taken
*
* \sa hw_gpadc_get_raw_value
*
*/
static inline void hw_gpadc_set_oversampling(uint8_t n_samples)
{
REG_SETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_CONV_NRS, n_samples);
}
/**
* \brief Get current oversampling
*
* \return number of samples to be taken
*
* \sa hw_gpadc_set_oversampling
*
*/
static inline uint8_t hw_gpadc_get_oversampling(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_CONV_NRS);
}
/**
* \brief Set sample time
*
* Sample time is \p mult x 32 clock cycles or 1 clock cycle when \p mult is 0. Valid values are
* 0-15.
*
* \param [in] mult multiplier
*
*/
static inline void hw_gpadc_set_sample_time(uint8_t mult)
{
REG_SETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_SMPL_TIME, mult);
}
/**
* \brief Get current sample time
*
* \return multiplier
*
* \sa hw_gpadc_set_sample_time
*
*/
static inline uint8_t hw_gpadc_get_sample_time(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_SMPL_TIME);
}
/**
* \brief Set state of input attenuator
*
* Enabling internal attenuator scales input voltage by factor of 3 thus increasing effective input
* scale from 0-1.2V to 0-3.6V in single ended mode or from -1.2-1.2V to -3.6-3.6V in differential
* mode.
*
* \param [in] enabled attenuator state
*
*/
static inline void hw_gpadc_set_input_attenuator_state(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_ATTN3X, !!enabled);
}
/**
* \brief Get current state of input attenuator
*
* \return attenuator state
*
*/
static inline bool hw_gpadc_get_input_attenuator_state(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_ATTN3X);
}
/**
* \brief Set input mute state
*
* Once enabled, samples are taken at mid-scale to determine internal offset and/or notice of the
* ADC with regards to VDD_REF.
*
* \param [in] enabled mute state
*
* \sa hw_gpadc_calibrate
*
*/
static inline void hw_gpadc_set_mute(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_MUTE, !!enabled);
}
/**
* \brief Get current input mute state
*
* \return mute state
*
* \sa hw_gpadc_set_mute
*
*/
static inline bool hw_gpadc_get_mute(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_MUTE);
}
/**
* \brief Set input and output sign change
*
* Once enabled, sign of ADC input and output is changed.
*
* \param [in] enabled sign change state
*
*/
static inline void hw_gpadc_set_sign_change(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SIGN, !!enabled);
}
/**
* \brief Set input and output sign change
*
* \return sign change state
*
*/
static inline bool hw_gpadc_get_sign_change(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_SIGN);
}
/**
* \brief Set chopping state
*
* Once enabled, two samples with opposite polarity are taken to cancel offset.
*
* \param [in] enabled chopping state
*
*/
static inline void hw_gpadc_set_chopping(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CHOP, !!enabled);
}
/**
* \brief Get current chopping state
*
* \return chopping state
*
*/
static inline bool hw_gpadc_get_chopping(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_CHOP);
}
/**
* \brief Set state of constant 20uA load current on ADC LDO output
*
* Constant 20uA load current on LDO output can be enabled so that the current will not drop to 0.
*
* \param [in] enabled load current state
*
*/
static inline void hw_gpadc_set_ldo_constant_current(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_I20U, !!enabled);
}
/**
* \brief Get current state of constant 20uA load current on ADC LDO output
*
* \return load current current state
*
* \sa hw_gpadc_set_ldo_constant_current
*
*/
static inline bool hw_gpadc_get_ldo_constant_current(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_I20U);
}
/**
* \brief Set state of dynamic 10uA load current on ADC LDO output
*
* 10uA load current on LDO output can be enabled during sample phase so that the load current
* during sampling and conversion phase becomes approximately the same.
*
* \param [in] enabled load current state
*
*/
static inline void hw_gpadc_set_ldo_dynamic_current(bool enabled)
{
REG_SETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_IDYN, !!enabled);
}
/**
* \brief Get current state of dynamic 10uA load current on ADC LDO output
*
* \return load current current state
*
* \sa hw_gpadc_set_ldo_dynamic_current
*
*/
static inline bool hw_gpadc_get_ldo_dynamic_current(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL2_REG, GP_ADC_IDYN);
}
/**
* \brief Set interval between conversions in continuous mode
*
* Interval time is \p mult x 1.024ms. Valid values are 0-255.
*
* \param [in] mult multiplier
*
* \sa hw_gpadc_set_continuous
*
*/
static inline void hw_gpadc_set_interval(uint8_t mult)
{
REG_SETF(GPADC, GP_ADC_CTRL3_REG, GP_ADC_INTERVAL, mult);
}
/**
* \brief Get current interval between conversions in continuous mode
*
* \return multiplier
*
* \sa hw_gpadc_set_interval
*
*/
static inline uint8_t hw_gpadc_get_interval(void)
{
return REG_GETF(GPADC, GP_ADC_CTRL3_REG, GP_ADC_INTERVAL);
}
/**
* \brief Set offset adjustment for positive ADC array
*
* \param [in] offset offset value
*
* \sa hw_gpadc_calibrate
* \sa hw_gpadc_set_negative_offset
*
*/
static inline void hw_gpadc_set_offset_positive(uint16_t offset)
{
GPADC->GP_ADC_OFFP_REG = offset & REG_MSK(GPADC, GP_ADC_OFFP_REG, GP_ADC_OFFP);
}
/**
* \brief Get current offset adjustment for positive ADC array
*
* \return offset value
*
*/
static inline uint16_t hw_gpadc_get_offset_positive(void)
{
return GPADC->GP_ADC_OFFP_REG & REG_MSK(GPADC, GP_ADC_OFFP_REG, GP_ADC_OFFP);
}
/**
* \brief Set offset adjustment for negative ADC array
*
* \param [in] offset offset value
*
* \sa hw_gpadc_calibrate
* \sa hw_gpadc_set_positive_offset
*
*/
static inline void hw_gpadc_set_offset_negative(uint16_t offset)
{
GPADC->GP_ADC_OFFN_REG = offset & REG_MSK(GPADC, GP_ADC_OFFN_REG, GP_ADC_OFFN);
}
/**
* \brief Get current offset adjustment for negative ADC array
*
* \return offset value
*
*/
static inline uint16_t hw_gpadc_get_offset_negative(void)
{
return GPADC->GP_ADC_OFFN_REG & REG_MSK(GPADC, GP_ADC_OFFN_REG, GP_ADC_OFFN);
}
/**
* \brief Get raw conversion result value
*
* Upper 10 bits are always valid, lower 6 bits are only valid in case oversampling is enabled.
*
* \return conversion result value
*
* \sa hw_gpadc_start
* \sa hw_gpadc_set_oversampling
* \sa hw_gpadc_get_value
*
*/
static inline uint16_t hw_gpadc_get_raw_value(void)
{
return GPADC->GP_ADC_RESULT_REG;
}
/**
* \brief Get conversion result value
*
* Invalid bits are discarded from result, i.e. oversampling is taken into account when calculating
* value.
*
* \return conversion result value
*
* \sa hw_gpadc_set_oversampling
* \sa hw_gpadc_get_raw_value
*
*/
static inline uint16_t hw_gpadc_get_value(void)
{
return hw_gpadc_get_raw_value() >> (6 - MIN(6, hw_gpadc_get_oversampling()));
}
/**
* \brief Start a measurement and wait for the result.
*
* \sa hw_gpadc_start
* \sa hw_gpadc_in_progress
* \sa hw_gpadc_clear_interrupt
*
*/
void hw_gpadc_adc_measure(void);
/**
* \brief Take measurements using the ADC and evaluate the results.
*
* \sa hw_gpadc_adc_measure
* \sa hw_gpadc_get_raw_value
*
*/
void hw_gpadc_test_measurements(void);
#endif /* dg_configUSE_HW_GPADC */
#endif /* HW_GPADC_H_ */
/**
* \}
* \}
* \}
*/
+493
View File
@@ -0,0 +1,493 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup GPIO
* \{
*/
/**
*****************************************************************************************
*
* @file hw_gpio.h
*
* @brief Definition of API for the GPIO Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_GPIO_H_
#define HW_GPIO_H_
#if dg_configUSE_HW_GPIO
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/* GPIO layout definitions */
/** Number of GPIO ports available */
#define HW_GPIO_NUM_PORTS (5)
/** Number of GPIO pins available (cumulative) */
#define HW_GPIO_NUM_PINS (HW_GPIO_PORT_0_NUM_PINS + HW_GPIO_PORT_1_NUM_PINS + \
HW_GPIO_PORT_2_NUM_PINS + HW_GPIO_PORT_3_NUM_PINS + \
HW_GPIO_PORT_4_NUM_PINS)
/** Number of GPIO pins available in port 0 */
#define HW_GPIO_PORT_0_NUM_PINS (8)
/** Number of GPIO pins available in port 1 */
#define HW_GPIO_PORT_1_NUM_PINS (8)
/** Number of GPIO pins available in port 2 */
#define HW_GPIO_PORT_2_NUM_PINS (5)
/** Number of GPIO pins available in port 3 */
#define HW_GPIO_PORT_3_NUM_PINS (8)
/** Number of GPIO pins available in port 4 */
#define HW_GPIO_PORT_4_NUM_PINS (8)
/** Number of pins in each GPIO port */
extern const uint8_t hw_gpio_port_num_pins[HW_GPIO_NUM_PORTS];
/**
* \brief GPIO input/output mode
*
*/
typedef enum {
HW_GPIO_MODE_INPUT = 0, /**< GPIO as an input */
HW_GPIO_MODE_INPUT_PULLUP = 0x100, /**< GPIO as an input with pull-up */
HW_GPIO_MODE_INPUT_PULLDOWN = 0x200, /**< GPIO as an input with pull-down */
HW_GPIO_MODE_OUTPUT = 0x300, /**< GPIO as an (implicitly push-pull) output */
HW_GPIO_MODE_OUTPUT_PUSH_PULL = 0x300, /**< GPIO as an (explicitly push-pull) output */
HW_GPIO_MODE_OUTPUT_OPEN_DRAIN = 0x700, /**< GPIO as an open-drain output */
} HW_GPIO_MODE;
/**
* \brief GPIO power source
*
*/
typedef enum {
HW_GPIO_POWER_V33 = 0, /**< V33 (3.3 V) power rail */
HW_GPIO_POWER_VDD1V8P = 1, /**< VDD1V8P (1.8 V) power rail */
} HW_GPIO_POWER;
/**
* \brief GPIO port number
*
*/
typedef enum {
HW_GPIO_PORT_0 = 0, /**< GPIO Port 0 */
HW_GPIO_PORT_1 = 1, /**< GPIO Port 1 */
HW_GPIO_PORT_2 = 2, /**< GPIO Port 2 */
HW_GPIO_PORT_3 = 3, /**< GPIO Port 3 */
HW_GPIO_PORT_4 = 4 /**< GPIO Port 4 */
} HW_GPIO_PORT;
/**
* \brief GPIO pin number
*
*/
typedef enum {
HW_GPIO_PIN_0 = 0, /**< GPIO Pin 0 */
HW_GPIO_PIN_1 = 1, /**< GPIO Pin 1 */
HW_GPIO_PIN_2 = 2, /**< GPIO Pin 2 */
HW_GPIO_PIN_3 = 3, /**< GPIO Pin 3 */
HW_GPIO_PIN_4 = 4, /**< GPIO Pin 4 */
HW_GPIO_PIN_5 = 5, /**< GPIO Pin 5 */
HW_GPIO_PIN_6 = 6, /**< GPIO Pin 6 */
HW_GPIO_PIN_7 = 7, /**< GPIO Pin 7 */
} HW_GPIO_PIN;
/**
* \brief GPIO function
*
*/
typedef enum {
HW_GPIO_FUNC_GPIO = 0, /**< GPIO */
HW_GPIO_FUNC_UART_RX = 1, /**< GPIO as UART RX */
HW_GPIO_FUNC_UART_TX = 2, /**< GPIO as UART TX */
HW_GPIO_FUNC_UART_IRDA_RX = 3, /**< GPIO as UART IRDA RX */
HW_GPIO_FUNC_UART_IRDA_TX = 4, /**< GPIO as UART IRDA TX */
HW_GPIO_FUNC_UART2_RX = 5, /**< GPIO as UART2 RX */
HW_GPIO_FUNC_UART2_TX = 6, /**< GPIO as UART2 TX */
HW_GPIO_FUNC_UART2_IRDA_RX = 7, /**< GPIO as UART2 IRDA RX */
HW_GPIO_FUNC_UART2_IRDA_TX = 8, /**< GPIO as UART2 IRDA TX */
HW_GPIO_FUNC_UART2_CTSN = 9, /**< GPIO as UART2 CTSN */
HW_GPIO_FUNC_UART2_RTSN = 10, /**< GPIO as UART2 RTSN */
HW_GPIO_FUNC_SPI_DI = 11, /**< GPIO as SPI DI */
HW_GPIO_FUNC_SPI_DO = 12, /**< GPIO as SPI DO */
HW_GPIO_FUNC_SPI_CLK = 13, /**< GPIO as SPI CLK */
HW_GPIO_FUNC_SPI_EN = 14, /**< GPIO as SPI EN */
HW_GPIO_FUNC_SPI2_DI = 15, /**< GPIO as SPI2 DI */
HW_GPIO_FUNC_SPI2_DO = 16, /**< GPIO as SPI2 DO */
HW_GPIO_FUNC_SPI2_CLK = 17, /**< GPIO as SPI2 CLK */
HW_GPIO_FUNC_SPI2_EN = 18, /**< GPIO as SPI2 EN */
HW_GPIO_FUNC_I2C_SCL = 19, /**< GPIO as I2C SCL */
HW_GPIO_FUNC_I2C_SDA = 20, /**< GPIO as I2C SDA */
HW_GPIO_FUNC_I2C2_SCL = 21, /**< GPIO as I2C2 SCL */
HW_GPIO_FUNC_I2C2_SDA = 22, /**< GPIO as I2C2 SDA */
HW_GPIO_FUNC_PWM0 = 23, /**< GPIO as PWM0 */
HW_GPIO_FUNC_PWM1 = 24, /**< GPIO as PWM1 */
HW_GPIO_FUNC_PWM2 = 25, /**< GPIO as PWM2 */
HW_GPIO_FUNC_PWM3 = 26, /**< GPIO as PWM3 */
HW_GPIO_FUNC_PWM4 = 27, /**< GPIO as PWM4 */
HW_GPIO_FUNC_BLE_DIAG = 28, /**< GPIO as BLE DIAG */
HW_GPIO_FUNC_FTDF_DIAG = 29, /**< GPIO as FTDF DIAG */
HW_GPIO_FUNC_PCM_DI = 30, /**< GPIO as PCM DI */
HW_GPIO_FUNC_PCM_DO = 31, /**< GPIO as PCM DO */
HW_GPIO_FUNC_PCM_FSC = 32, /**< GPIO as PCM FSC */
HW_GPIO_FUNC_PCM_CLK = 33, /**< GPIO as PCM CLK */
HW_GPIO_FUNC_PDM_DI = 34, /**< GPIO as PDM DI */
HW_GPIO_FUNC_PDM_DO = 35, /**< GPIO as PDM DO */
HW_GPIO_FUNC_PDM_CLK = 36, /**< GPIO as PDM CLK */
HW_GPIO_FUNC_USB_SOF = 37, /**< GPIO as USB SOF */
HW_GPIO_FUNC_ADC = 38, /**< GPIO as ADC */
HW_GPIO_FUNC_USB = 38, /**< GPIO as USB */
HW_GPIO_FUNC_QSPI = 38, /**< GPIO as QSPI */
HW_GPIO_FUNC_XTAL32 = 38, /**< GPIO as XTAL32 */
HW_GPIO_FUNC_QUADEC_XA = 39, /**< GPIO as QUADEC XA */
HW_GPIO_FUNC_QUADEC_XB = 40, /**< GPIO as QUADEC XB */
HW_GPIO_FUNC_QUADEC_YA = 41, /**< GPIO as QUADEC YA */
HW_GPIO_FUNC_QUADEC_YB = 42, /**< GPIO as QUADEC YB */
HW_GPIO_FUNC_QUADEC_ZA = 43, /**< GPIO as QUADEC ZA */
HW_GPIO_FUNC_QUADEC_ZB = 44, /**< GPIO as QUADEC ZB */
HW_GPIO_FUNC_IR_OUT = 45, /**< GPIO as IR OUT */
HW_GPIO_FUNC_BREATH = 46, /**< GPIO as BREATH */
HW_GPIO_FUNC_KB_ROW = 47, /**< GPIO as KB ROW */
HW_GPIO_FUNC_COEX_EXT_ACT0 = 48, /**< GPIO as COEX EXT ACT0 */
HW_GPIO_FUNC_COEX_EXT_ACT1 = 49, /**< GPIO as COEX EXT ACT1 */
HW_GPIO_FUNC_COEX_SMART_ACT = 50, /**< GPIO as COEX SMART ACT */
HW_GPIO_FUNC_COEX_SMART_PRI = 51, /**< GPIO as COEX SMART PRI */
HW_GPIO_FUNC_CLOCK = 52, /**< GPIO as CLOCK */
HW_GPIO_FUNC_ONESHOT = 53, /**< GPIO as ONESHOT */
HW_GPIO_FUNC_PWM5 = 54, /**< GPIO as PWM5 */
HW_GPIO_FUNC_PORT0_DCF = 55, /**< GPIO as PORT0 DCF */
HW_GPIO_FUNC_PORT1_DCF = 56, /**< GPIO as PORT1 DCF */
HW_GPIO_FUNC_PORT2_DCF = 57, /**< GPIO as PORT2 DCF */
HW_GPIO_FUNC_PORT3_DCF = 58, /**< GPIO as PORT3 DCF */
HW_GPIO_FUNC_PORT4_DCF = 59, /**< GPIO as PORT4 DCF */
HW_GPIO_FUNC_RF_ANT_TRIM0 = 60, /**< GPIO as RF ANT TRIM0 */
HW_GPIO_FUNC_RF_ANT_TRIM1 = 61, /**< GPIO as RF ANT TRIM1 */
HW_GPIO_FUNC_RF_ANT_TRIM2 = 62 /**< GPIO as RF ANT TRIM2 */
} HW_GPIO_FUNC;
/**
* \brief GPIO pin configuration
*
* It's recommended to use \p HW_GPIO_PINCONFIG and \p HW_GPIO_PINCONFIG_RESERVE to set pin entries.
* Each configuration must be terminated using \p HW_GPIO_PINCONFIG_END macro.
*
*/
typedef struct {
uint8_t pin; /**< pin name, high-nibble is port number and low-nibble is pin */
HW_GPIO_MODE mode; /**< pin mode */
HW_GPIO_FUNC func; /**< pin function */
bool high; /**< initial pin state, true for high and false for low */
bool reserve; /*<< true if pin should be also reserved */
} __attribute__((packed)) gpio_config;
/**
* \brief GPIO pin configuration for \p gpio_config
*
* \p xport and \p xpin are specified as symbols from \p HW_GPIO_PORT and \p HW_GPIO_PIN enums
* respectively or more conveniently as plain numeric values.
* \p xmode and \p xfunc have the same values as defined in \p HW_GPIO_MODE and \p HW_GPIO_FUNC enums
* respectively, except they have prefix stripped.
*
* \param [in] xport port number
* \param [in] xpin pin number
* \param [in] xmode pin mode
* \param [in] xfunc pin function
* \param [in] xhigh true for high state, false otherwise
*
*/
#define HW_GPIO_PINCONFIG(xport, xpin, xmode, xfunc, xhigh) \
{ \
.pin = (xport << 4) | (xpin & 0x0F), \
.mode = HW_GPIO_MODE_ ## xmode, \
.func = HW_GPIO_FUNC_ ## xfunc, \
.high = xhigh, \
.reserve = false, \
}
/**
* \brief GPIO pin configuration and reservation for \p gpio_config
*
* This macro is virtually identical to \p HW_GPIO_PINCONFIG, except it also reserves pin.
*
* \param [in] xport port number
* \param [in] xpin pin number
* \param [in] xmode pin mode
* \param [in] xfunc pin function
* \param [in] xhigh true for high state, false otherwise
*
* \sa HW_GPIO_PINCONFIG
*
*/
#define HW_GPIO_PINCONFIG_RESERVE(xport, xpin, xmode, xfunc, xhigh) \
{ \
.pin = (xport << 4) | (xpin & 0x0F), \
.mode = HW_GPIO_MODE_ ## xmode, \
.func = HW_GPIO_FUNC_ ## xfunc, \
.high = xhigh, \
.reserve = true, \
}
/**
* \brief Macro to properly terminate array of \p gpio_config definition
*
*/
#define HW_GPIO_PINCONFIG_END \
{ \
.pin = 0xFF, \
}
/**
* \brief GPIO configuration
*
* This is a shortcut to configure multiple GPIOs in one call.
* \p cfg is an array of GPIO pins configuration, it should be terminated by dummy element with
* \p pin member set to 0xFF (macro \p HW_GPIO_PINCONFIG can be used for this purpose).
*
* \param [in] cfg GPIO pins configuration
*
* \sa hw_gpio_configure_pin
* \sa hw_gpio_set_pin_function
*
*/
void hw_gpio_configure(const gpio_config cfg[]);
/**
* \brief Reserve GPIO pin
*
* Reserve pin for exclusive usage.
* This macro can be used in application peripheral_setup function to detect
* usage of same GPIO pin by different applications.
*
* \param [in] port GPIO port number
* \param [in] pin GPIO pin number
*
* \return true if pin was successfully reserved and setup, false if pin was already reserved
*
*/
bool hw_gpio_reserve_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin);
/**
* \brief Reserve GPIO pin and set pin function
*
* Reserve pin and set up it function. If pin was already reserved do nothing.
*
* \param [in] port GPIO port number
* \param [in] pin GPIO pin number
* \param [in] mode GPIO access mode
* \param [in] function GPIO function
* \param [in] high in case of PID_GPIO and OUTPUT value to set on pin
*
* \return true if pin was successfully reserved and setup, false if pin was already reserved
*
*/
bool hw_gpio_reserve_and_configure_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function, bool high);
/**
* \brief Unreserve GPIO pin
*
* Free reserved pin. If pin was not reserved do nothing.
* Configuration of pin does not change just reservation.
*
* \note If pin was reserved using RESERVE_GPIO it will also be unreserved.
* If RESERVE_GPIO was not enabled by compile time flags call to this function
* may cause unexpected result.
*
* \param [in] port GPIO port number
* \param [in] pin GPIO pin number
*
* \sa hw_gpio_reserve_and_configure_pin
* \sa hw_gpio_reserve_pin
* \sa RESERVE_GPIO
*
*/
void hw_gpio_unreserve_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin);
#if (DEBUG_GPIO_ALLOC_MONITOR_ENABLED == 1)
/**
* \brief Reserve GPIO pin
*
* Reserve pin for exclusive usage. If pin is already allocated trigger breakpoint.
* This macro should be used in application peripheral_setup function to detect
* usage of same GPIO pin by different applications.
*
* If runtime GPIO reservation is needed, use hw_gpio_reserve_pin,
* hw_gpio_reserve_and_configure_pin and hw_gpio_unreserve_pin instead.
*
* \param [in] name parameter ignored, used for debug only
* \param [in] port GPIO port number
* \param [in] pin GPIO pin number
* \param [in] func parameter ignored (for compatibility)
*
* \sa hw_gpio_reserve_pin
* \sa hw_gpio_reserve_and_configure_pin
* \sa hw_gpio_unreserve_pin instead
*
*/
#define RESERVE_GPIO(name, port, pin, func) \
do { \
if (!hw_gpio_reserve_pin((port), (pin))) { \
/* If debugger stops at this line, there is configuration problem */ \
/* pin is used without being reserved first */ \
__BKPT(0); /* this pin has not been previously reserved! */ \
} \
} while (0)
#else
#define RESERVE_GPIO( name, port, pin, func ) \
do { \
\
} while (0)
#endif // (DEBUG_GPIO_ALLOC_MONITOR_ENABLED == 1)
/**
* \brief Set the pin type and mode
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
* \param [in] mode GPIO pin mode
* \param [in] function GPIO pin usage
*
*/
void hw_gpio_set_pin_function(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function);
/**
* \brief Get the pin type and mode
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
* \param [out] mode GPIO pin mode
* \param [out] function GPIO pin usage
*
*/
void hw_gpio_get_pin_function(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE* mode,
HW_GPIO_FUNC* function);
/**
* \brief Combined function to set the state and the type and mode of the GPIO pin
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
* \param [in] mode GPIO pin mode
* \param [in] function GPIO pin usage
* \param [in] high set to TRUE to set the pin into high else low
*
*/
void hw_gpio_configure_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function, const bool high);
/**
* \brief Configure power source for pin output
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
* \param [in] power GPIO power source
*
*/
void hw_gpio_configure_pin_power(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_POWER power);
/**
* \brief Set a GPIO in high state
*
* The GPIO should have been previously configured as an output!
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
*
*/
void hw_gpio_set_active(HW_GPIO_PORT port, HW_GPIO_PIN pin);
/**
* \brief Set a GPIO in low state
*
* The GPIO should have been previously configured as an output!
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
*
*/
void hw_gpio_set_inactive(HW_GPIO_PORT port, HW_GPIO_PIN pin);
/**
* \brief Get the GPIO status
*
* The GPIO should have been previously configured as input!
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
*
* \return true if the pin is high, false if low
*
*/
bool hw_gpio_get_pin_status(HW_GPIO_PORT port, HW_GPIO_PIN pin);
/**
* \brief Toggle GPIO pin state
*
* \param [in] port GPIO port
* \param [in] pin GPIO pin
*
*/
void hw_gpio_toggle(HW_GPIO_PORT port, HW_GPIO_PIN pin);
/**
* \brief Find pins with specific function
*
* Function searches for pins configured for specific function.
* If buf is not NULL and buf_size is greater than 0 pins are stored in buf
* high-nibble is port number and low-nibble is pin.
* If number of pins found is greater then buf_size only buf_size entries are filled, though
* the returned number of found pins is correct.
*
* \param [in] func function to lookup
* \param [out] buf buffer for port-pin pairs that are configured for specific function
* \param [in] buf_size size of buf
*
* \return number of pins with specific function put in buf
* 0 - no pin is configured for this function
*
*/
int hw_gpio_get_pins_with_function(HW_GPIO_FUNC func, uint8_t *buf, int buf_size);
#endif /* dg_configUSE_HW_GPIO */
#endif /* HW_GPIO_H_ */
/**
* \}
* \}
* \}
*/
+70
View File
@@ -0,0 +1,70 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Exception_Handlers
* \{
*/
/**
*****************************************************************************************
*
* @file hw_hard_fault.h
*
* @brief Hard-Fault Handler include file.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_HARD_FAULT_H_
#define HW_HARD_FAULT_H_
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
#define HARDFAULT_MAGIC_NUMBER 0xBADC0FFE
/**
* \brief Holds the stack contents when a hard-fault occurs.
*
* \details The stack contents are copied at this variable when a hard-fault occurs. The first
* position is marked with a special "flag" (0xBADC0FFE) to indicate that the data that
* follow are valid.
*/
extern uint32_t hardfault_event_data[9];
#endif /* HW_HARD_FAULT_H_ */
/**
* \}
* \}
* \}
*/
+150
View File
@@ -0,0 +1,150 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup LED
* \{
*/
/**
*****************************************************************************************
*
* @file hw_led.h
*
* @brief Definition of API for the LED Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_LED_H_
#define HW_LED_H_
#include <black_orca.h>
/**
* \brief Source for LED1
*/
typedef enum {
HW_LED_SRC1_PWM2 = 0, /**< LED1 controlled by PWM2 */
HW_LED_SRC1_BREATH = 1 /**< LED1 controlled by Breath Timer */
} HW_LED_SRC1;
/**
* \brief Source for LED2
*/
typedef enum {
HW_LED_SRC2_PWM3 = 0, /**< LED2 controlled by PWM3 */
HW_LED_SRC2_BREATH = 1 /**< LED2 controlled by Breath Timer */
} HW_LED_SRC2;
/**
* \brief Source for LED3
*/
typedef enum {
HW_LED_SRC3_PWM4 = 0, /**< LED3 controlled by PWM4 */
HW_LED_SRC3_BREATH = 1 /**< LED3 controlled by Breath Timer */
} HW_LED_SRC3;
/**
* \brief Set the source that controls LED1
*
* \param [in] src the source that controls LED1
*
* \sa HW_LED_SRC1
*/
__STATIC_INLINE void hw_led_set_led1_src(HW_LED_SRC1 src)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED1_SRC_SEL, src);
}
/**
* \brief Set the source that controls LED2
*
* \param [in] src the source that controls LED2
*
* \sa HW_LED_SRC2
*/
__STATIC_INLINE void hw_led_set_led2_src(HW_LED_SRC2 src)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED2_SRC_SEL, src);
}
/**
* \brief Set the source that controls LED3
*
* \param [in] src the source that controls LED3
*
* \sa HW_LED_SRC3
*/
__STATIC_INLINE void hw_led_set_led3_src(HW_LED_SRC3 src)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED3_SRC_SEL, src);
}
/**
* \brief Enable or disable LED1
*
* \param [in] state true to enable LED1, or false to disable it
*
*/
__STATIC_INLINE void hw_led_enable_led1(bool state)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED1_EN, state);
}
/**
* \brief Enable or disable LED2
*
* \param [in] state true to enable LED2, or false to disable it
*
*/
__STATIC_INLINE void hw_led_enable_led2(bool state)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED2_EN, state);
}
/**
* \brief Enable or disable LED3
*
* \param [in] state true to enable LED3, or false to disable it
*
*/
__STATIC_INLINE void hw_led_enable_led3(bool state)
{
REG_SETF(GPREG, LED_CONTROL_REG, LED3_EN, state);
}
#endif /* HW_LED_H_ */
/**
* \}
* \}
* \}
*/
+568
View File
@@ -0,0 +1,568 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup OTPC
* \{
*/
/**
****************************************************************************************
*
* @file hw_otpc.h
*
* @brief Definition of API for the OTP Controller driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_OTPC_H_
#define HW_OTPC_H_
#if dg_configUSE_HW_OTPC
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/**
* \brief Get the mask of a field of an OTPC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_OTPC_REG_FIELD_MASK(reg, field) \
(OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Msk)
/**
* \brief Get the bit position of a field of an OTPC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_OTPC_REG_FIELD_POS(reg, field) \
(OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Pos)
/**
* \brief Prepare (i.e. shift and mask) a value to be used for an OTPC register field.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
* \param [in] val is the value to prepare
*
*/
#define HW_OTPC_FIELD_VAL(reg, field, val) \
(((val) << HW_OTPC_REG_FIELD_POS(reg, field)) & HW_OTPC_REG_FIELD_MASK(reg, field))
/**
* \brief Get the value of a field of an OTPC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
*
* \return the value of the register field
*
*/
#define HW_OTPC_REG_GETF(reg, field) \
((OTPC->OTPC_##reg##_REG & (OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Msk)) >> (OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Pos))
/**
* \brief Set the value of a field of an OTPC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
* \param [in] new_val is the value to write
*
*/
#define HW_OTPC_REG_SETF(reg, field, new_val) \
OTPC->OTPC_##reg##_REG = ((OTPC->OTPC_##reg##_REG & ~(OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Msk)) | \
((OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Msk) & ((new_val) << (OTPC_OTPC_##reg##_REG_##OTPC_##reg##_##field##_Pos))))
/**
* \brief OTP Controller mode
*/
typedef enum {
HW_OTPC_MODE_STBY = 0,
HW_OTPC_MODE_MREAD = 1,
HW_OTPC_MODE_MPROG = 2,
HW_OTPC_MODE_AREAD = 3,
HW_OTPC_MODE_APROG = 4,
HW_OTPC_MODE_TBLANK = 5,
HW_OTPC_MODE_TDEC = 6,
HW_OTPC_MODE_TWR = 7
} HW_OTPC_MODE;
#define MAX_RR_AVAIL (8)
#define OTP_CLK_IS_16M (0)
#define OTP_CLK_IS_32M (1)
#define OTP_CLK_IS_48M (2)
/**
* \brief Word inside cell to program/read
*
* Cell contents in memory starts with low word (i.e. to program/read both words in cell at once,
* HW_OTPC_WORD_LOW should be used for addressing).
*
*/
typedef enum {
HW_OTPC_WORD_LOW = 0,
HW_OTPC_WORD_HIGH = 1
} HW_OTPC_WORD;
/**
* \brief System clock frequency in MHz
*
*/
typedef enum {
HW_OTPC_SYS_CLK_FREQ_1 = 0,
HW_OTPC_SYS_CLK_FREQ_2 = 1,
HW_OTPC_SYS_CLK_FREQ_3 = 2,
HW_OTPC_SYS_CLK_FREQ_4 = 3,
HW_OTPC_SYS_CLK_FREQ_6 = 4,
HW_OTPC_SYS_CLK_FREQ_8 = 5,
HW_OTPC_SYS_CLK_FREQ_12 = 6,
HW_OTPC_SYS_CLK_FREQ_16 = 7,
HW_OTPC_SYS_CLK_FREQ_24 = 8,
HW_OTPC_SYS_CLK_FREQ_32 = 9,
HW_OTPC_SYS_CLK_FREQ_48 = 10
} HW_OTPC_SYS_CLK_FREQ;
/*
* Reset values of OTPC registers
*/
#define OTPC_MODE_REG_RESET (0x00000000)
#define OTPC_PCTRL_REG_RESET (0x00000000)
#define OTPC_STAT_REG_RESET (0x00000051)
#define OTPC_AHBADR_REG_RESET (0x07FC0000)
#define OTPC_CELADR_REG_RESET (0x00000000)
#define OTPC_NWORDS_REG_RESET (0x00000000)
#define OTPC_FFPRT_REG_RESET (0x00000000)
#define OTPC_FFRD_REG_RESET (0x00000000)
#define OTPC_PWORDL_REG_RESET (0x00000000)
#define OTPC_PWORDH_REG_RESET (0x00000000)
#define OTPC_TIM1_REG_RESET (0x1A104F20)
#define OTPC_TIM2_REG_RESET (0x00010000)
/**
* \brief Convert system clock frequency expressed in MHz to equivalent HW_OTPC_SYS_CLK_FREQ value
*
* \sa HW_OTPC_SYS_CLK_FREQ
*/
__RETAINED_CODE HW_OTPC_SYS_CLK_FREQ hw_otpc_convert_sys_clk_mhz(uint32_t clk_freq);
/**
* \brief Initialize the OTP Controller.
*
* \warning The AHB clock must be up to 48MHz! It is a responsibility of the caller to check this!
*
*/
static inline void hw_otpc_init(void)
{
#if (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A)
/*
* Reset OTP controller
*/
OTPC->OTPC_MODE_REG = HW_OTPC_MODE_STBY; // Set OTPC to standby
REG_SET_BIT(CRG_TOP, SYS_CTRL_REG, OTPC_RESET_REQ); // Reset the OTP Controller
REG_CLR_BIT(CRG_TOP, SYS_CTRL_REG, OTPC_RESET_REQ);// Get the OTP Controller out of Reset
/*
* Initialize the POR registers
*/
OTPC->OTPC_NWORDS_REG = OTPC_NWORDS_REG_RESET;
OTPC->OTPC_TIM1_REG = OTPC_TIM1_REG_RESET;
OTPC->OTPC_TIM2_REG = OTPC_TIM2_REG_RESET;
#endif
/*
* Enable OTPC clock
*/
CRG_TOP->CLK_AMBA_REG |= 1 << REG_POS(CRG_TOP, CLK_AMBA_REG, OTP_ENABLE);
}
/**
* \brief Close the OTP Controller.
*
*/
static inline void hw_otpc_close(void)
{
/*
* Disable OTPC clock
*/
CRG_TOP->CLK_AMBA_REG &= ~REG_MSK(CRG_TOP, CLK_AMBA_REG, OTP_ENABLE);
}
/**
* \brief Check if the OTP Cotnroller is active.
*
* \return 1 if it is active, else 0.
*
*/
static inline uint32_t hw_otpc_is_active(void) __attribute__((always_inline));
static inline uint32_t hw_otpc_is_active(void)
{
/*
* Disable OTPC clock
*/
return !!(CRG_TOP->CLK_AMBA_REG & REG_MSK(CRG_TOP, CLK_AMBA_REG, OTP_ENABLE));
}
/**
* \brief Put the OTP Controller in STBY mode and turn-off clock.
*
*/
void hw_otpc_disable(void);
/**
* \brief Set the access speed of the OTP Controller based on the system clock.
*
* \details Switch from PLL to XTAL : call function after clock switch with high_clk_speed == false
* Switch from XTAL to PLL : call function before clock switch with high_clk_speed == true
*
* \param [in] clk_speed The frequency of the system clock: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 and 48.
*
* \warning The OTP clock must have been enabled (OTP_ENABLE == 1).
* (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
__RETAINED_CODE void hw_otpc_set_speed(HW_OTPC_SYS_CLK_FREQ clk_speed);
/**
* \brief Set or reset the power saving mode of the OTP Controller.
*
* \param [in] inactivity_period The number of HCLK cycles to remain powered while no access is made.
* If set to 0, this feature is disabled.
*
* \warning The hw_otpc_init() and hw_otpc_set_speed() must have been called.
* (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*/
void hw_otpc_power_save(uint32_t inactivity_period);
/**
* \brief Get the number of the Repair Records.
*
* \return The number of used Repair Records.
*
* \warning The hw_otpc_init() and hw_otpc_set_speed() must have been called. The OTPC mode will be reset.
* (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*/
uint32_t hw_otpc_num_of_rr(void);
/**
* \brief Program manually an OTP entry.
*
* \param [in] cell_offset Cell offset to be programmed.
*
* \param [in] pword_l The low 32-bits of the 64-bit word to be written.
*
* \param [in] pword_h The high 32-bits of the 64-bit word to be written.
*
* \param [in] use_rr Use a Repair Record if writing fails when true.
*
* \return true for success, false for failure
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_manual_word_prog(uint32_t cell_offset, uint32_t pword_l, uint32_t pword_h, bool use_rr);
/**
* \brief Program manually an OTP block.
*
* \param [in] p_data The start address of the data to copy from.
*
* \param [in] cell_offset Cell offset to start programming from.
*
* \param [in] cell_word Word inside cell to start programming from.
*
* \param [in] num_of_words The actual number of the words to be written.
*
* \param [in] use_rr true to use Repair Records if writing fails
*
* \return true for success, false for failure
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_manual_prog(const uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_word,
uint32_t num_of_words, bool use_rr);
/**
* \brief Put the OTP in manual read mode.
*
* \details In manual read mode the OTP is memory mapped to the address MEMORY_OTP_BASE. So, any
* access to this memory space results into reading from the OTP. The caller must make sure
* that the function hw_otpc_manual_read_off() is called when reading from the OTP is
* finished.
*
* \param [in] spare_rows true to access the spare rows area, false to access normal memory cell
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
void hw_otpc_manual_read_on(bool spare_rows);
/**
* \brief Take the OTP out of manual read mode and put it in STBY.
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
void hw_otpc_manual_read_off(void);
/**
* \brief Program manually a Repair Record in the OTP's spare area.
*
* \param [in] cell_offset The address programmed with errors.
* \param [in] pword_l The low 32-bits of the 64-bit word to be written.
* \param [in] pword_h The high 32-bits of the 64-bit word to be written.
* \return true for success, false for failure
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_write_rr(uint32_t cell_offset, uint32_t pword_l, uint32_t pword_h);
/**
* \brief Program OTP via DMA.
*
* \param [in] p_data The start address of the data in RAM.
*
* \param [in] cell_offset Cell offset to be programmed.
*
* \param [in] cell_word Word inside cell to be programmed.
*
* \param [in] num_of_words The actual number of the words to be written. The driver will write this
* value minus 1 to the specific register.
*
* \param [in] spare_rows true to access the spare rows area, false to access normal memory cell
*
* \return true for success, false for failure (the programming should be retried or fixed!)
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_dma_prog(const uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_word,
uint32_t num_of_words, bool spare_rows);
/**
* \brief Read OTP via DMA.
*
* \param [in] p_data The address in RAM to write the data to.
*
* \param [in] cell_offset Cell offset to be programmed.
*
* \param [in] cell_word Word inside cell to be programmed.
*
* \param [in] num_of_words The actual number of the words to be read. The driver will write this
* value minus 1 to the specific register.
*
* \param [in] spare_rows true to access the spare rows area, false to access normal memory cell
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
void hw_otpc_dma_read(uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_word,
uint32_t num_of_words, bool spare_rows);
/**
* \brief Program OTP via FIFO (Auto mode).
*
* \param [in] p_data The start address of the data in RAM.
*
* \param [in] cell_offset Cell offset to be programmed.
*
* \param [in] cell_word Word inside cell to be programmed.
*
* \param [in] num_of_words The actual number of the words to be written. The driver will write this
* value minus 1 to the specific register.
*
* \param [in] spare_rows true to access the spare rows area, false to access normal memory cell
*
* \return true for success, false for failure
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_fifo_prog(const uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_word,
uint32_t num_of_words, bool spare_rows);
/**
* \brief Read OTP via FIFO.
*
* \param [in] p_data The address in RAM to write the data to.
*
* \param [in] cell_offset Cell offset to be programmed.
*
* \param [in] cell_word Word inside cell to be programmed.
*
* \param [in] num_of_words The actual number of the words to be read. The driver will write this
* value minus 1 to the specific register.
*
* \param [in] spare_rows true to access the spare rows area, false to access normal memory cell
*
* \return true for success, false for failure
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
bool hw_otpc_fifo_read(uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_word,
uint32_t num_of_words, bool spare_rows);
/**
* \brief Prepare OTPC to execute an OTP copy after wakeup.
*
* \param [in] num_of_bytes The actual number of the bytes to be copied. The driver will write the
* proper value to the specific register.
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
void hw_otpc_prepare(uint32_t num_of_bytes);
/**
* \brief Cancel any previous preparations of the OTPC for executing an OTP copy after wakeup.
*
* \warning The hw_otpc_init() and the hw_otpc_set_speed() must have been called and the mode must
* be STBY. (Note: the hw_otpc_set_speed() must be called only once when the PLL is used or
* during each clock switch when both PLL and XTAL16 are used, since the register bits it
* modifies are retained.)
*
*/
void hw_otpc_cancel_prepare(void);
/**
* \brief Get cell memory address
*
* Returns mapped memory address for given cell, can be used for e.g. manual reading.
*
* \param [in] cell_offset cell offset
*
* \return cell memory address
*
* \sa hw_otpc_manual_read_on
*
*/
static inline void *hw_otpc_cell_to_mem(uint32_t cell_offset)
{
return (void *) (MEMORY_OTP_BASE + (cell_offset << 3)); // cell size is 8 bytes
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TEST FUNCTIONALITY
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* \brief Execution of the BLANK test.
*
* \return The test result.
* <ul>
* <li> 0, if the test succeeded
* <li> 1, if the test 1 failed
* </ul>
*
*/
int hw_otpc_blank(void);
/**
* \brief Execution of the TDEC test.
*
* \return The test result.
* <ul>
* <li> 0, if the test succeeded
* <li> 1, if the test 1 failed
* </ul>
*
*/
int hw_otpc_tdec(void);
/**
* \brief Execution of the TWR test.
*
* \return The test result.
* <ul>
* <li> 0, if the test succeeded
* <li> 1, if the test 1 failed
* </ul>
*
*/
int hw_otpc_twr(void);
#endif /* dg_configUSE_HW_OTPC */
#endif /* HW_OTPC_H_ */
/**
\}
\}
\}
*/
+998
View File
@@ -0,0 +1,998 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup QSPI
* \{
*/
/**
*****************************************************************************************
*
* @file hw_qspi.h
*
* @brief Definition of API for the QSPI Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_QSPI_H_
#define HW_QSPI_H_
#if dg_configUSE_HW_QSPI
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/**
* \brief Get the mask of a field of an QSPIC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_QSPIC_REG_FIELD_MASK(reg, field) \
(QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Msk)
/**
* \brief Get the bit position of a field of an QSPIC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_QSPIC_REG_FIELD_POS(reg, field) \
(QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Pos)
/**
* \brief Get the value of a field of an QSPIC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
*
* \return the value of the register field
*
*/
#define HW_QSPIC_REG_GETF(reg, field) \
((QSPIC->QSPIC_##reg##_REG & (QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Msk)) >> (QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Pos))
/**
* \brief Set the value of a field of an QSPIC register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
* \param [in] new_val is the value to write
*
*/
#define HW_QSPIC_REG_SETF(reg, field, new_val) \
QSPIC->QSPIC_##reg##_REG = ((QSPIC->QSPIC_##reg##_REG & ~(QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Msk)) | \
((QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Msk) & ((new_val) << (QSPIC_QSPIC_##reg##_REG_##QSPIC_##field##_Pos))))
/*
* ENUMERATION DEFINITIONS
*****************************************************************************************
*/
/**
* \brief Bus mode
*
*/
typedef enum {
HW_QSPI_BUS_MODE_SINGLE, /**< Bus mode in single mode */
HW_QSPI_BUS_MODE_DUAL, /**< Bus mode in dual mode */
HW_QSPI_BUS_MODE_QUAD /**< Bus mode in quad mode */
} HW_QSPI_BUS_MODE;
/**
* \brief Flash memory address size
*
*/
typedef enum {
HW_QSPI_ADDR_SIZE_24, /**< QSPI flash memory uses 24 bits address */
HW_QSPI_ADDR_SIZE_32 /**< QSPI flash memory uses 32 bits address */
} HW_QSPI_ADDR_SIZE;
/**
* \brief Idle clock state
*
*/
typedef enum {
HW_QSPI_POL_LOW = 0, /**< SPI clock will be low at idle */
HW_QSPI_POL_HIGH = 1 /**< SPI clock will be high at idle */
} HW_QSPI_POL;
/**
* \brief Type of QSPI_CLK edge for sampling received data
*
*/
typedef enum {
HW_QSPI_SAMPLING_EDGE_POSITIVE = 0, /**< Sample the received data with the positive edge of the QSPI_SCK */
HW_QSPI_SAMPLING_EDGE_NEGATIVE = 1 /**< Sample the received data with the negative edge of the QSPI_SCK */
} HW_QSPI_SAMPLING_EDGE;
/**
* \brief Selected data size of a wrapping burst
*
*/
typedef enum {
HW_QSPI_WRAP_SIZE_8BITS = 0, /**< Byte access (8-bits) */
HW_QSPI_WRAP_SIZE_16BITS = 1, /**< Half word access (8-bits) */
HW_QSPI_WRAP_SIZE_32BITS = 2, /**< Word access (8-bits) */
} HW_QSPI_WRAP_SIZE;
/**
* \brief Selected data length of a wrapping burst
*
*/
typedef enum {
HW_QSPI_WRAP_LEN_4BEAT = 0, /**< 4 beat wrapping burst */
HW_QSPI_WRAP_LEN_8BEAT = 1, /**< 8 beat wrapping burst */
HW_QSPI_WRAP_LEN_16BEAT = 2, /**< 16 beat wrapping burst */
} HW_QSPI_WRAP_LEN;
/**
* \brief Size of Burst Break Sequence
*
*/
typedef enum {
HW_QSPI_BREAK_SEQ_SIZE_1B = 0, /**< One byte */
HW_QSPI_BREAK_SEQ_SIZE_2B = 1 /**< Two bytes */
} HW_QSPI_BREAK_SEQ_SIZE;
/**
* \brief QSPI pads slew rate control
*
*/
typedef enum {
HW_QSPI_SLEW_RATE_0, /**< xx V/ns (weak) */
HW_QSPI_SLEW_RATE_1, /**< xx V/ns */
HW_QSPI_SLEW_RATE_2, /**< xx V/ns */
HW_QSPI_SLEW_RATE_3 /**< xx V/ns (strong) */
} HW_QSPI_SLEW_RATE;
/**
* \brief QSPI pads drive current
*
*/
typedef enum {
HW_QSPI_DRIVE_CURRENT_4, /**< 4 mA */
HW_QSPI_DRIVE_CURRENT_8, /**< 8 mA */
HW_QSPI_DRIVE_CURRENT_12, /**< 12 mA */
HW_QSPI_DRIVE_CURRENT_16, /**< 16 mA */
} HW_QSPI_DRIVE_CURRENT;
/**
* \brief QSPI clock divider setting
*
*/
typedef enum {
HW_QSPI_DIV_1 = 0, /**< divide by 1 */
HW_QSPI_DIV_2 = 1, /**< divide by 2 */
HW_QSPI_DIV_4 = 2, /**< divide by 4 */
HW_QSPI_DIV_8 = 3 /**< divide by 8 */
} HW_QSPI_DIV;
/**
* \brief QSPI configuration
*
*/
typedef struct {
HW_QSPI_ADDR_SIZE address_size;
HW_QSPI_POL idle_clock;
HW_QSPI_SAMPLING_EDGE sampling_edge;
} qspi_config;
/**
* \brief Enable CS on QSPI bus
*
* Use this in manual mode.
*
*/
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
static inline void hw_qspi_cs_enable(void)
{
QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
}
/**
* \brief Disable CS on QSPI bus
*
* Use this in manual mode.
*
*/
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
static inline void hw_qspi_cs_disable(void)
{
QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
}
/**
* \brief Select QSPI bus mode
*
* Use this in manual mode.
*
* \note Selecting QUAD mode will automatically configure pins IO2 and IO3 to input.
*
* \param [in] mode selects single/dual/quad mode for QSPI bus
*
*/
void hw_qspi_set_bus_mode(HW_QSPI_BUS_MODE mode);
/**
* \brief Check is SPI Bus is busy
*
* \return 0 - SPI Bus is idle,
* 1 - SPI Bus is active. ReadData, WriteData or DummyData activity is in progress
*
*/
static inline uint8_t hw_qspi_is_busy(void)
{
return (uint8_t) QSPIC->QSPIC_STATUS_REG;
}
/**
* \brief Generate 32 bits read transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* \return data read during read transfer
*
*/
static inline uint32_t hw_qspi_read32(void)
{
return QSPIC->QSPIC_READDATA_REG;
}
/**
* \brief Generate 16 bits read transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* \return data read during read transfer
*
*/
static inline uint16_t hw_qspi_read16(void)
{
return *((volatile uint16_t *) &(QSPIC->QSPIC_READDATA_REG));
}
/**
* \brief Generate 8 bits read transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* \return data read during read transfer
*
*/
static inline uint8_t hw_qspi_read8(void)
{
return *((volatile uint8_t *) &(QSPIC->QSPIC_READDATA_REG));
}
/**
* \brief Generate 32 bits write transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* param [in] data data to transfer
*
*/
static inline void hw_qspi_write32(uint32_t data)
{
QSPIC->QSPIC_WRITEDATA_REG = data;
}
/**
* \brief Generate 16 bits write transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* param [in] data data to transfer
*
*/
static inline void hw_qspi_write16(uint16_t data)
{
*((volatile uint16_t *) &(QSPIC->QSPIC_WRITEDATA_REG)) = data;
}
/**
* \brief Generate 8 bits write transfer on QSPI bus
*
* The data is transferred using the selected mode of the SPI bus (SPI, Dual
* SPI, Quad SPI).
*
* param [in] data data to transfer
*
*/
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
static inline void hw_qspi_write8(uint8_t data)
{
*((volatile uint8_t *) &(QSPIC->QSPIC_WRITEDATA_REG)) = data;
}
/**
* \brief Generate a clock pulses to the SPI bus for 32 bits transfer
*
* During this activity in the SPI bus, the QSPI_IOx data pads are in hi-z state.
* Number of pulses depends on selected mode of the SPI bus (SPI, Dual SPI, Quad SPI).
*
*/
static inline void hw_qspi_dummy32(void)
{
QSPIC->QSPIC_DUMMYDATA_REG = 0;
}
/**
* \brief Generate a clock pulses to the SPI bus for 16 bits transfer
*
* During this activity in the SPI bus, the QSPI_IOx data pads are in hi-z state.
* Number of pulses depends on selected mode of the SPI bus (SPI, Dual SPI, Quad SPI).
*
*/
static inline void hw_qspi_dummy16(void)
{
*((volatile uint16_t *) &(QSPIC->QSPIC_DUMMYDATA_REG)) = 0;
}
/**
* \brief Generate a clock pulses to the SPI bus for 8 bits transfer
*
* During this activity in the SPI bus, the QSPI_IOx data pads are in hi-z state.
* Number of pulses depends on selected mode of the SPI bus (SPI, Dual SPI, Quad SPI).
*
*/
static inline void hw_qspi_dummy8(void)
{
*((volatile uint8_t *) &(QSPIC->QSPIC_DUMMYDATA_REG)) = 0;
}
/**
* \brief Specifies address with that flash memory uses
*
* The controller uses 32 of 24 bits for address during Auto mode transfer.
*
* \param [in] size selects 32 or 24 address size
*
*/
static inline void hw_qspi_set_address_size(HW_QSPI_ADDR_SIZE size)
{
HW_QSPIC_REG_SETF(CTRLMODE, USE_32BA, (size == HW_QSPI_ADDR_SIZE_32 ? 1 : 0));
}
/**
* \brief Get address size that flash memory uses
*
* The controller uses 32 of 24 bits for address during Auto mode transfer.
*
* \return currently selected address size
*
* \sa hw_qspi_set_address_size
*
*/
static inline HW_QSPI_ADDR_SIZE hw_qspi_get_address_size(void)
{
return (HW_QSPI_ADDR_SIZE) HW_QSPIC_REG_GETF(CTRLMODE, USE_32BA);
}
/**
* \brief Controls translation of burst accesses form AMBA bus to the QSPI bus
*
* \param [in] force 0 - controller translates a burst access on the AMBA bus
* to a burst access on the QSPI bus. That results to a minimum
* command/address phases, but the QSPI_CS is low for as
* long as the access occures,
* 1 - controller will split a burst access on the AMBA bus
* into single accesses on the qspi bus. This results to a separate
* read command to the FLASH memory foreach data
* required. A 4-beat word incremental AMBA access will be
* split into 4 different sequences of reading (command/address/
* extra clock/read data). QSPI_CS will be only high while a qspi
* access occures. This results to lower power dissipation with
* respect to QSPIC_FORCENSEQ_EN=0 at cost of performance
*
*/
static inline void hw_qspi_force_nseq(uint8_t force)
{
HW_QSPIC_REG_SETF(CTRLMODE, FORCENSEQ_EN, force);
}
/**
* \brief Enable or disable auto mode on QSPI
*
* \note Selecting auto mode when any command previously configured has chosen
* QUAD mode for any phase will automatically configure pins IO2 and IO3 to input.
*
* \param [in] automode true auto mode selected,
* false manual mode selected
*
* \sa hw_qspi_set_read_instruction
* \sa hw_qspi_set_read_status_instruction
* \sa hw_qspi_set_suspend_resume_instructions
* \sa hw_qspi_set_write_enable_instruction
* \sa hw_qspi_set_extra_byte
* \sa hw_qspi_set_erase_instruction
* \sa hw_qspi_set_break_sequence
*
*/
void hw_qspi_set_automode(bool automode);
/**
* \brief Read automode state
*
* \return true auto mode is selected,
* false manual mode is selected
*
*/
static inline bool hw_qspi_get_automode(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, AUTO_MD);
}
/**
* \brief Get read pipe clock delay
*
* \return read pipe clock delay relative to the falling edge of QSPI_SCK
*
*/
static inline uint8_t hw_qspi_get_read_pipe_clock_delay(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, PCLK_MD);
}
/**
* \brief Set read pipe clock delay
*
* \param [in] delay read pipe clock delay relative to the falling edge of QSPI_SCK
* value should be in range 0..7
*
*/
static inline void hw_qspi_set_read_pipe_clock_delay(uint8_t delay)
{
HW_QSPIC_REG_SETF(CTRLMODE, PCLK_MD, delay);
}
/**
* \brief Check if read pipe is enabled
*
* \return 1 if read pipe is enabled, 0 otherwise
*
*/
static inline uint8_t hw_qspi_is_read_pipe_clock_enabled(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, RPIPE_EN);
}
/**
* \brief Enable read pipe
*
* \param [in] enable 1 enable read pipe,
* 0 disable read pipe
*
*/
static inline void hw_qspi_enable_readpipe(uint8_t enable)
{
HW_QSPIC_REG_SETF(CTRLMODE, RPIPE_EN, enable);
}
/**
* \brief Get read sampling edge
*
* \return type of QSPI_CLK edge for sampling received data
*
*/
static inline HW_QSPI_SAMPLING_EDGE hw_qspi_get_read_sampling_edge(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, RXD_NEG);
}
/**
* \brief Set read sampling edge
*
* \param [in] edge sets whether read samples or taken on rising or falling edge
* of QSPI_SCK
*
*/
static inline void hw_qspi_set_read_sampling_edge(HW_QSPI_SAMPLING_EDGE edge)
{
HW_QSPIC_REG_SETF(CTRLMODE, RXD_NEG, edge);
}
/**
* \brief Check if hready signal is used
*
* \return 0 - when wait states are not added via hready signal during access to
* QSPIC_WRITEDATA, QSPIC_READDATA and QSPIC_DUMMYDATA registers,
* 1 - when wait states are added via hready signal during access to
* QSPIC_WRITEDATA, QSPIC_READDATA and QSPIC_DUMMYDATA registers.
* In this case read read QSPI_STATUS register to check the end of
* activity at the SPI bus
*
*/
static inline uint8_t hw_qspi_is_hready_enabled(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, HRDY_MD);
}
/**
* \brief Enable/disable adding wait states during register access
*
* \param [in] enable 0 - wait states will be added in hready signal during access to
* QSPIC_WRITEDATA, QSPIC_READDATA and QSPIC_DUMMYDATA registers
*
*/
static inline void hw_qspi_enable_hready(uint8_t enable)
{
HW_QSPIC_REG_SETF(CTRLMODE, HRDY_MD, enable);
}
/**
* \brief Get clock mode
*
* \return 0 - SPI mode 0 is used for QSPI_CLK, the QSPI_SCK is low when QSPI_CS is high (idle),
* 1 - SPI mode 3 is used for QSPI_CLK, the QSPI_SCK is high when QSPI_CS is high (idle)
*
*/
static inline uint8_t hw_qspi_get_clock_mode(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, CLK_MD);
}
/**
* \brief Set clock mode
*
* \param [in] mode HW_SPI_POL_LOW - SPI mode 0 is used for QSPI_CLK,
* The QSPI_SCK is low when QSPI_CS is high (idle),
* HW_SPI_POL_HIGH - SPI mode 3 is used for QSPI_CLK,
* The QSPI_SCK is high when QSPI_CS is high (idle)
*
*/
static inline void hw_qspi_set_clock_mode(HW_QSPI_POL mode)
{
HW_QSPIC_REG_SETF(CTRLMODE, CLK_MD, mode);
}
/**
* \brief Set IO2 direction
*
* \param [in] output QSPI_IO2 output enable. Use this only in SPI or Dual SPI
* mode to control /WP signal. When the Auto Mode is selected
* and the QUAD SPI is used, set this to false.
* false: The QSPI_IO2 pad is input
* true: The QSPI_IO2 pad is output
*
*/
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
static inline void hw_qspi_set_io2_output(bool output)
{
HW_QSPIC_REG_SETF(CTRLMODE, IO2_OEN, output);
}
/**
* \brief Set IO3 direction
*
* \param [in] output Use this only in SPI or Dual SPI mode to control /HOLD signal.
* When the Auto Mode is selected and the QUAD SPI is used,
* set this to false.
* false: The QSPI_IO3 pad is input,
* true: The QSPI_IO3 pad is output
*
*/
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
static inline void hw_qspi_set_io3_output(bool output)
{
HW_QSPIC_REG_SETF(CTRLMODE, IO3_OEN, output);
}
/**
* \brief Set state for IO2 when it's configured as output
*
* \param [in] val QSPI_IO2 value to set (0 or 1)
*
* \sa hw_qspi_set_io2_direction
*
*/
static inline void hw_qspi_set_io2(uint8_t val)
{
HW_QSPIC_REG_SETF(CTRLMODE, IO2_DAT, val);
}
/**
* \brief Set state for IO3 when it's configured as output
*
* \param [in] val QSPI_IO3 value to set (0 or 1)
*
* \sa hw_qspi_set_io3_direction
*
*/
static inline void hw_qspi_set_io3(uint8_t val)
{
HW_QSPIC_REG_SETF(CTRLMODE, IO3_DAT, val);
}
/**
* \brief Read state of IO2 when not in QUAD mode
*
* \return value of IO2 pin (0 or 1)
*
*/
static inline uint8_t hw_qspi_get_io2(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, IO2_DAT);
}
/**
* \brief Read state of IO3 when not in QUAD mode
*
* \return value of IO3 pin (0 or 1)
*
*/
static inline uint8_t hw_qspi_get_io3(void)
{
return HW_QSPIC_REG_GETF(CTRLMODE, IO3_DAT);
}
/**
* \brief Set read instructions for QSPI flash
*
* This function sets up instruction to be sent to flash memory when data is requested
* on AHB bus.
*
* \param [in] inst instruction for Incremental Burst or Single read access.
* This value is the selected instruction at the cases of incremental
* burst or single read access. Also this value is used when a wrapping
* burst is not supported.
* \param [in] send_once 0 - transmit instruction at any burst access,
* 1 - transmit instruction only in the first access after the
* selection of Auto Mode.
* \param [in] dummy_count number of dummy bytes to send 0..4
* \param [in] inst_phase describes the mode of the SPI bus during the instruction phase
* \param [in] addr_phase describes the mode of the SPI bus during the address phase
* \param [in] dummy_phase describes the mode of the SPI bus during the dummy phase
* \param [in] data_phase describes the mode of the SPI bus during the data phase
*
* \sa hw_qspi_set_extra_byte
* \sa hw_qspi_set_wrapping_burst_instruction
*
*/
void hw_qspi_set_read_instruction(uint8_t inst, uint8_t send_once, uint8_t dummy_count,
HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE addr_phase,
HW_QSPI_BUS_MODE dummy_phase,
HW_QSPI_BUS_MODE data_phase);
/**
* \brief Set wrapping burst read instructions for QSPI flash
*
* Calling this function will set up wrapping burst instruction to use.
* Use this feature only when the serial FLASH memory supports a special
* instruction for wrapping burst access.
*
* \param [in] inst instruction for Wrapping Burst
* \param [in] len describes the selected length of a wrapping burst
* \param [in] size describes the selected data size of a wrapping burst
*
*/
void hw_qspi_set_wrapping_burst_instruction(uint8_t inst, HW_QSPI_WRAP_LEN len,
HW_QSPI_WRAP_SIZE size);
/**
* \brief Set extra byte to use in read instruction
*
* \param [in] extra_byte the value of an extra byte which will be transferred after
* address. This byte is used for telling memory if it should stay
* in continuous read mode or wait for normal instruction after CS
* goes inactive
* \param [in] bus_mode describes the mode of the SPI bus during the extra byte phase.
* \param [in] half_disable_out 1 - disable (hi-z) output during the transmission
* of bits [3:0] of extra byte
*
* \sa hw_qspi_set_read_instruction
*
*/
void hw_qspi_set_extra_byte(uint8_t extra_byte, HW_QSPI_BUS_MODE bus_mode,
uint8_t half_disable_out);
/**
* \brief Set dummy byte count
*
* Number of dummy bytes to send when read instruction is executed.
*
* \param [in] count number of dummy bytes to send 0..4
*
*/
void hw_qspi_set_dummy_bytes_count(uint8_t count);
/**
* \brief Set number of clock when CS stays high
*
* \param [in] clock_count between the transmission of two different instructions to the
* flash memory, the qspi bus stays in idle state (QSPI_CS high)
* for at least this number of spi clock cycles. See the QSPIC_ERS_CS_HI
* register for an exception
*
*/
static inline void hw_qspi_set_min_cs_high(uint8_t clock_count)
{
HW_QSPIC_REG_SETF(BURSTCMDB, CS_HIGH_MIN, clock_count);
}
/**
* \brief Set up erase instructions
*
* Instruction will be send after call to hw_qspi_erase_block.
*
* \param [in] inst code value of the erase instruction
* \param [in] inst_phase mode of the QSPI Bus during the instruction phase of the erase instruction
* \param [in] addr_phase the mode of the QSPI Bus during the address phase of the erase instruction
* \param [in] hclk_cycles the controller must stay without flash memory reading
* requests for this number of AMBA AHB hclk cycles, before
* performs the command of erase or resume 15 - 0
* \param [in] cs_hi_cycles after the execution of instructions: write enable, erase, erase
* suspend and erase resume, the QSPI_CS remains high for at
* least this number of qspi bus clock cycles
*
* \sa hw_qspi_erase_block
*
*/
void hw_qspi_set_erase_instruction(uint8_t inst, HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE addr_phase, uint8_t hclk_cycles, uint8_t cs_hi_cycles);
/**
* \brief Set up write enable instruction
*
* Instruction setup by this function will be executed before erase.
*
* \param [in] write_enable code value of the write enable instruction
* \param [in] inst_phase mode of the QSPI Bus during the instruction phase
*
* \sa hw_qspi_erase_block
* \sa hw_qspi_set_erase_instruction
*
*/
void hw_qspi_set_write_enable_instruction(uint8_t write_enable, HW_QSPI_BUS_MODE inst_phase);
/**
* \brief Set up erase suspend/resume instructions
*
* \param [in] erase_suspend_inst code value of the erase suspend instruction.
* \param [in] suspend_inst_phase mode of the QSPI Bus during the instruction phase
* of the suspend instruction
* \param [in] erase_resume_inst code value of the erase resume instruction.
* \param [in] resume_inst_phase mode of the QSPI Bus during the instruction phase
* of the resume instruction
* \param [in] minimum_delay defines the minimum time distance between the instruction
* erase suspend and the previous instruction erase resume.
* This delay will be also applied after the Erase command.
* 0 - don't wait. The controller starts the erase suspend procedure
* immediately,
* 1..63 - controller waits at least this number of 288kHz clock cycles
* before the suspension of erasing. Time starts counting after
* the end of the previous erase resume
*
*/
void hw_qspi_set_suspend_resume_instructions(uint8_t erase_suspend_inst,
HW_QSPI_BUS_MODE suspend_inst_phase,
uint8_t erase_resume_inst,
HW_QSPI_BUS_MODE resume_inst_phase,
uint8_t minimum_delay);
/**
* \brief Set status command
*
* This command will be send by QSPI controller when it needs to check status of flash memory.
* This command is also send indirectly when hw_qspi_get_erase_status is called.
*
* \param [in] inst instruction for read status
* \param [in] inst_phase mode of the QSPI Bus during the instruction phase of the read
* status instruction
* \param [in] receive_phase mode of the QSPI Bus during the receive status phase of
* the read status instruction
* \param [in] busy_pos it describes which bit from the bits of status represents
* the Busy bit (7 - 0)
* \param [in] busy_val defines the value of the Busy bit which means that the flash is busy
* 0 - flash is busy when the Busy bit is equal to 0,
* 1 - flash is busy when the Busy bit is equal to 1
* \param [in] read_delay defines the minimum time distance between the instruction
* read status register and previous instructions like erase or
* resume. The same delay will be also applied after the Erase command.
* 0 - don't wait. The controller starts to read the Flash memory
* status register immediately.
* 1..63 - controller waits at least the number of QSPI_CLK
* cycles and afterwards it starts to read the Flash memory status
* register. Time starts counting after the end of the previous
* erase/resume.
* \param [in] sts_delay defines the register to count the delay to wait for the FLASH Status
* Register read after an erase or erase/ resume command.
* 0 - delay is controlled by the \p read_dealy (QSPIC_RESSTS_DLY)
* which counts on the qspi clock,
* 1 - delay is controlled by the \p minimum_delay value passed to
* hw_qspi_set_suspend_resume_instructions (QSPIC_RESSUS_DLY) which
* counts on the 288 kHz clock
*
* \sa hw_qspi_set_suspend_resume_instructions
* \sa hw_qspi_get_erase_status
*
*/
void hw_qspi_set_read_status_instruction(uint8_t inst, HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE receive_phase,
uint8_t busy_pos,
uint8_t busy_val,
uint8_t read_delay,
uint8_t sts_delay);
/**
* \brief Erase block/sector of flash memory
*
* For this function to work, erase instructions must be set up
* with hw_qspi_set_erase_instruction.
* User should call hw_qspi_get_erase_status to check if block erased.
*
* \note If user doesn't call hw_qspi_get_erase_status that returns status 0
* QSPI controller will not be able to switch to manual mode.
*
* \param [in] addr memory address of block/sector thats is requested to be erased
* for 24 bits addressing, bits [23:12] determine the block/sector
* address bits. Bits [11:0] are ignored by the controller.
* For 32 bits addressing, bits [31:12] determine the block/sectors
* address bits. Bits [11:0] are ignored by the controller
*
* \sa hw_qspi_set_erase_instruction
* \sa hw_qspi_get_erase_status
* \sa hw_qspi_set_automode
*
*/
void hw_qspi_erase_block(uint32_t addr);
/**
* \brief Get erase status
*
* \return progress of sector/block erasing
* 0 = no erase,
* 1 = pending erase request,
* 2 = erase procedure is running,
* 3 = suspended erase procedure,
* 4 = finishing the erase procedure
*
*/
static inline uint8_t hw_qspi_get_erase_status(void)
{
QSPIC->QSPIC_CHCKERASE_REG = 0;
return HW_QSPIC_REG_GETF(ERASECTRL, ERS_STATE);
}
/**
* \brief Set burst break sequence
*
* \param [in] sequence value will be transmitted as the burst break sequence
* \param [in] mode mode of the QSPI Bus during the transmission of the burst break sequence
* \param [in] size size of Burst Break Sequence
* \param [in] dis_out disable output during the transmission of the second half (sequence[3:0]).
* Setting this bit is only useful if size = 1.
* 0 - controller drives the QSPI bus during the transmission
* of the sequence[3:0],
* 1 - controller leaves the QSPI bus in Hi-Z during the transmission
* of the sequence[3:0]
*
*/
void hw_qspi_set_break_sequence(uint16_t sequence, HW_QSPI_BUS_MODE mode,
HW_QSPI_BREAK_SEQ_SIZE size, uint8_t dis_out);
/**
* \brief Disable burst break sequence
*
*/
static inline void hw_qspi_disable_burst_break_sequence(void)
{
HW_QSPIC_REG_SETF(BURSTBRK, BRK_EN, 0);
}
/**
* \brief Set configuration of QSPI pads
*
* \param [in] rate QSPI pads slew rate control
* \param [in] current QSPI pads drive current
*
*/
void hw_qspi_set_pads(HW_QSPI_SLEW_RATE rate, HW_QSPI_DRIVE_CURRENT current);
/**
* \brief QSPI controller initialization
*
* This function will enable QSPI controller in manual mode.
*
* \note This function doesn't change QSPI_DIV
*
*/
void hw_qspi_init(const qspi_config *cfg);
/**
* \brief Enable QSPI controller clock
*
*/
static inline void hw_qspi_enable_clock(void)
{
CRG_TOP->CLK_AMBA_REG |= 1 << REG_POS(CRG_TOP, CLK_AMBA_REG, QSPI_ENABLE);
}
/**
* \brief Disable QSPI controller clock
*
*/
static inline void hw_qspi_disable_clock(void)
{
CRG_TOP->CLK_AMBA_REG &= ~REG_MSK(CRG_TOP, CLK_AMBA_REG, QSPI_ENABLE);
}
/**
* \brief Set the QSPI clock divider
*
* \param [in] div QSPI clock divider
*
* \sa HW_QSPI_DIV
*/
void hw_qspi_set_div(HW_QSPI_DIV div);
/**
* \brief Get the QSPI clock divider
*
* \return the QSPI clock divider setting
*
* \sa HW_QSPI_DIV
*/
static inline HW_QSPI_DIV hw_qspi_get_div(void)
{
return REG_GETF(CRG_TOP, CLK_AMBA_REG, QSPI_DIV);
}
#endif /* dg_configUSE_HW_QSPI */
#endif /* HW_QSPI_H_ */
/**
* \}
* \}
* \}
*/
+304
View File
@@ -0,0 +1,304 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup RF
* \{
*/
/**
*****************************************************************************************
*
* @file hw_rf.h
*
* @brief Radio module (RF) Low Level Driver API.
*
* @note The following recalibration-related weak functions can be overridden, if needed,
* to provide additional functionality
*
* @note
* ~~~{.c}
* bool hw_rf_preoff_cb(void)
* ~~~
*
* @note Called before actually shutting down the RF PD. If this returns true, the PD
* will NOT be shutdown, but will stay on. This function can be used to decide
* whether an RF recalibration is needed and to start the respective operation.
* The default implementation (if an explicit implementation is omitted) returns
* false (i.e. the RF PD shuts off immediately).
*
* @note
* ~~~{.c}
* void hw_rf_postconf_cb(void)
* ~~~
*
* @note Called after the RF recommended settings are applied, or after the
* recalibration procedure is completed. Can be used to start/reset a
* recalibration timer, in case periodic recalibration is enabled using
* dg_configRF_RECALIBRATION_TIMER_TIMEOUT
*
* @note
* ~~~{.c}
* void hw_rf_precalib_cb(void)
* void hw_rf_postcalib_cb(void):
* ~~~
*
* @note Called when the re-calibration (not the initial calibration) procedure
* starts/ends. Can be used to instruct the system not to go to sleep during
* this time.
*
* @note
* ~~~{.c}
* void hw_rf_apply_tcs_cb(void)
* ~~~
*
* @note Called before applying the rf recommended settings. The implementation should
* apply the TCS values
*
* @note
* ~~~{.c}
* uint32_t hw_rf_get_start_iff_time(void)
* ~~~
*
* @note Called to get the time when IFF calibration starts
*
* @note
* ~~~{.c}
* bool hw_rf_check_iff_timeout(uint32_t start_time)
* ~~~
*
* @note Called to check if IFF calibration has timed-out (i.e. took too long). It takes argument the
* IFF calib start_time, as return by hw_rf_get_start_iff_time(). It should normally check against
* config macro dg_configRF_IFF_CALIBRATION_TIMEOUT.
*
* @warning All the above functions are called in a critical section. They should not block.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_RF_H_
#define HW_RF_H_
#if dg_configUSE_HW_RF
#include <stdbool.h>
#include "black_orca.h"
#include "hw_cpm.h"
#if dg_configFEM == FEM_SKY66112_11
#include "hw_fem_sky66112-11.h"
#endif
/**
* \brief Initializes RF system, and performs the initial calibration
*
* \note The RF PD must be on before this is called
*
* \return True, if iff calib is successful, false otherwise
*/
bool hw_rf_system_init(void);
/**
* \brief Sets parameters according to their recommended values.
*/
void hw_rf_set_recommended_settings(void);
/**
* \brief (Re)calibrates Intermediate Frequency Filter (IFF).
*/
bool hw_rf_iff_calibration(void);
/**
* \brief (Re)calibrates RF DC offset.
*/
void hw_rf_dc_offset_calibration(void);
/**
* \brief (Re)calibrates modulation gain.
*/
void hw_rf_modulation_gain_calibration(bool);
/**
* \brief Convenience function to (re)calibrate all RF related modules.
*
* \return True if calibration (specifically, the iff calibration part)
* succeeds, false if not
*/
bool hw_rf_calibration(void);
/**
* \brief Start Calibration procedure and return.
*
* This will block for some time in order to perform
* the first part of calibration (IFF, DC offset and the start of gain calib).
* Interrupts must be disabled by the caller.
*
* \return True if calibration was successful, false if not (i.e. iff calib hang)
*
*/
bool hw_rf_start_calibration();
/**
* \brief Turns on RF module.
*/
static inline void hw_rf_poweron(void) __attribute__((always_inline));
static inline void hw_rf_poweron(void)
{
#if ( (dg_configUSE_BOD == 1) && (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) \
&& (dg_configBLACK_ORCA_IC_STEP <= BLACK_ORCA_IC_STEP_D))
hw_cpm_deactivate_bod_protection();
#endif
/* If PD_RAD is up, make sure to power it down to issue a reset */
if (REG_GETF(CRG_TOP, SYS_STAT_REG, RAD_IS_UP)) {
#if ( (dg_configUSE_BOD == 1) && (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) \
&& (dg_configBLACK_ORCA_IC_STEP <= BLACK_ORCA_IC_STEP_D))
hw_cpm_delay_usec(30);
#endif
REG_SET_BIT(CRG_TOP, PMU_CTRL_REG, RADIO_SLEEP);
while (REG_GETF(CRG_TOP, SYS_STAT_REG, RAD_IS_DOWN) == 0x0);
}
REG_CLR_BIT(CRG_TOP, PMU_CTRL_REG, RADIO_SLEEP);
while (!REG_GETF(CRG_TOP, SYS_STAT_REG, RAD_IS_UP));
#if ( (dg_configUSE_BOD == 1) && (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) \
&& (dg_configBLACK_ORCA_IC_STEP <= BLACK_ORCA_IC_STEP_D))
hw_cpm_delay_usec(30);
hw_cpm_activate_bod_protection();
#endif
// Enable the PLLdig/RFCU clock
REG_SET_BIT(CRG_TOP, CLK_RADIO_REG, RFCU_ENABLE);
REG_SETF(CRG_TOP, CLK_RADIO_REG, RFCU_DIV, 1);
#if dg_configFEM == FEM_SKY66112_11
hw_fem_start();
#endif
}
/**
* \brief Turns off RF module.
*/
static inline void hw_rf_poweroff()
{
#if dg_configFEM == FEM_SKY66112_11
hw_fem_stop();
#endif
#if ( (dg_configUSE_BOD == 1) && (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) \
&& (dg_configBLACK_ORCA_IC_STEP <= BLACK_ORCA_IC_STEP_D))
hw_cpm_deactivate_bod_protection();
hw_cpm_delay_usec(30);
#endif
REG_SET_BIT(CRG_TOP, PMU_CTRL_REG, RADIO_SLEEP);
while (!REG_GETF(CRG_TOP, SYS_STAT_REG, RAD_IS_DOWN));
#if ( (dg_configUSE_BOD == 1) && (dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A) \
&& (dg_configBLACK_ORCA_IC_STEP <= BLACK_ORCA_IC_STEP_D))
hw_cpm_delay_usec(30);
hw_cpm_activate_bod_protection();
#endif
}
/**
* \brief Sets parameters according to their recommended values, taking RF state into account.
*
* Acts like \ref hw_rf_set_recommended_settings but makes sure that the RF power domain is on and
* unconfigured.
* Interrupts must be disabled by the caller.
*
*/
void hw_rf_request_recommended_settings(void);
/**
* \brief Requests that the RF is turned on
*
* Requests that the RF is turned on, if not already on.
* Interrupts must be disabled by the caller.
*
* \param [in] mode_ble True, if the rf is needed for ble
*/
__RETAINED_CODE void hw_rf_request_on(bool mode_ble);
/**
* \brief Requests that the RF is turned off
*
* Requests that the RF is turned off, if not already off.
* The RF will be turned off only if there are no more
* requests (ie. all requesters have called hw_rf_request_off())
* Interrupts must be disabled by the caller.
*
* \param [in] mode_ble True, if the rf was needed for ble
*/
void hw_rf_request_off(bool mode_ble);
/*
* \brief Start transmitting a continuous wave (unmodulated transmission)
*
* \param [in] mode is the mode to use. 1: BLE, 2 or 3: FTDF (0: Normal, use hw_rf_stop_*)
*
* \param [in] ch is the Channel to transmit on, calculated as:
* (mode is BLE) ch = (F 2402) / 2, where F ranges from 2402 MHz to 2480 MHz.
* Range: 0x00 0x27.
* (mode is FTDF) ch = (F 2405) / 5, where F ranges from 2405 MHz to 2480 MHz.
* Range: 0x00 0xf.
*/
void hw_rf_start_continuous_wave(uint8_t mode, uint8_t ch);
/*
* \brief Stop transmitting a continuous wave (unmodulated transmission)
*
*/
void hw_rf_stop_continuous_wave(void);
/*
* \brief Set TX Power
*
* This actually sets the index of the RF_TX_PWER_LUT_X_REG to use.
*
* \param [in] lut The index of the LUT to use. 0 disables this functionality.
* 1: 0dbm, 2: -1dbm, 3: -2dbm, 4: -3dbm, 5: -4dbm
*/
static inline void hw_rf_set_tx_power(uint8_t lut)
{
RFCU->RF_TX_PWR_REG = lut;
}
#endif /* dg_configUSE_HW_RF */
#endif /* HW_RF_H_ */
/**
* \}
* \}
* \}
*/
+381
View File
@@ -0,0 +1,381 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Timer0
* \{
*/
/**
*****************************************************************************************
*
* @file hw_timer0.h
*
* @brief Definition of API for the Timer0 Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_TIMER0_H_
#define HW_TIMER0_H_
#if dg_configUSE_HW_TIMER0
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/**
* \brief Get the mask of a field of an TIMER0 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_TIMER0_REG_FIELD_MASK(reg, field) \
(GP_TIMERS_TIMER0_##reg##_REG_##field##_Msk)
/**
* \brief Get the bit position of a field of an TIMER0 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_TIMER0_REG_FIELD_POS(reg, field) \
(GP_TIMERS_TIMER0_##reg##_REG_##field##_Pos)
/**
* \brief Get the value of a field of an TIMER0 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
*
* \return the value of the register field
*
*/
#define HW_TIMER0_REG_GETF(reg, field) \
((GP_TIMERS->TIMER0_##reg##_REG & (GP_TIMERS_TIMER0_##reg##_REG_##field##_Msk)) >> (GP_TIMERS_TIMER0_##reg##_REG_##field##_Pos))
/**
* \brief Set the value of a field of an TIMER0 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
* \param [in] new_val is the value to write
*
*/
#define HW_TIMER0_REG_SETF(reg, field, new_val) \
GP_TIMERS->TIMER0_##reg##_REG = ((GP_TIMERS->TIMER0_##reg##_REG & ~(GP_TIMERS_TIMER0_##reg##_REG_##field##_Msk)) | \
((GP_TIMERS_TIMER0_##reg##_REG_##field##_Msk) & ((new_val) << (GP_TIMERS_TIMER0_##reg##_REG_##field##_Pos))))
/**
* \brief Clock source for timer
*
*/
typedef enum {
HW_TIMER0_CLK_SRC_SLOW = 0, /**< 32kHz (slow) clock */
HW_TIMER0_CLK_SRC_FAST = 1 /**< 2/4/8/16MHz (fast) clock */
} HW_TIMER0_CLK_SRC;
/**
* \brief Fast clock division factor
*
*/
typedef enum {
HW_TIMER0_FAST_CLK_DIV_1 = 0, /**< divide by 1 */
HW_TIMER0_FAST_CLK_DIV_2, /**< divide by 2 */
HW_TIMER0_FAST_CLK_DIV_4, /**< divide by 4 */
HW_TIMER0_FAST_CLK_DIV_8, /**< divide by 8 */
} HW_TIMER0_FAST_CLK_DIV;
/**
* \brief PWM mode
*
*/
typedef enum {
HW_TIMER0_MODE_PWM = 0, /**< PWM signal is '1' during high state */
HW_TIMER0_MODE_CLOCK = 1 /**< PWM signal is clock divided by 2 during high state */
} HW_TIMER0_MODE;
/**
* \brief Timer interrupt callback
*
*/
typedef void (*hw_timer0_interrupt_cb)(void);
/*
* \brief Timer configuration
*
*/
typedef struct {
HW_TIMER0_CLK_SRC clk_src; /**< clock source */
HW_TIMER0_FAST_CLK_DIV fast_clk_div; /**< clock division factor (only applicable when fast clock is selected as source) */
bool on_clock_div; /**< enable ON-counter clock divider (clock for ON-counter is divided by 10) */
uint16_t on_reload; /**< reload value for ON-counter */
uint16_t t0_reload_m; /**< reload value for T0-counter M-register */
uint16_t t0_reload_n; /**< reload value for T0-counter N-register */
} timer0_config;
/**
* \brief Initialize the timer
*
* Turn on clock for timer and configure timer. After initialization both timer and its interrupt
* are disabled. \p cfg can be NULL - no configuration is performed in such case.
*
* \param [in] cfg configuration
*
*/
void hw_timer0_init(const timer0_config *cfg);
/**
* \brief Timer configuration
*
* Shortcut to call appropriate configuration function. If \p cfg is NULL, this function does
* nothing.
*
* \param [in] cfg configuration
*
*/
void hw_timer0_configure(const timer0_config *cfg);
/**
* \brief Register an interrupt handler
*
* \param [in] handler Function pointer to call when timer interrupt occurs
*
*/
void hw_timer0_register_int(hw_timer0_interrupt_cb handler);
/**
* \brief Unregister an interrupt handler
*
*/
void hw_timer0_unregister_int(void);
/**
* \brief Enable the timer
*
*/
static inline void hw_timer0_enable(void)
{
HW_TIMER0_REG_SETF(CTRL, TIM0_CTRL, 1);
}
/**
* \brief Disable the timer
*
*/
static inline void hw_timer0_disable(void)
{
HW_TIMER0_REG_SETF(CTRL, TIM0_CTRL, 0);
}
/**
* \brief Set clock source for timer
*
* \param [in] clk_src clock source
*
* \sa TIMER0_CLK_SRC
*
*/
static inline void hw_timer0_set_clock_source(HW_TIMER0_CLK_SRC clk_src)
{
HW_TIMER0_REG_SETF(CTRL, TIM0_CLK_SEL, clk_src);
}
/**
* \brief Get current clock source for timer
*
* \return clock source
*
*/
static inline HW_TIMER0_CLK_SRC hw_timer0_get_clock_source(void)
{
return HW_TIMER0_REG_GETF(CTRL, TIM0_CLK_SEL);
}
/**
* \brief Set fast clock division factor
*
* \param [in] div division factor
*
* \sa TIMER0_FAST_CLK_DIV
*
*/
static inline void hw_timer0_set_fast_clock_div(HW_TIMER0_FAST_CLK_DIV div)
{
REG_SETF(CRG_TOP, CLK_TMR_REG, TMR0_DIV, div);
}
/**
* \brief Get current fast clock division factor
*
* \return division factor
*
*/
static inline HW_TIMER0_FAST_CLK_DIV hw_timer0_get_fast_clock_div(void)
{
return REG_GETF(CRG_TOP, CLK_TMR_REG, TMR0_DIV);
}
/**
* \brief Set state of clock divider for ON-counter
*
* Once enabled, ON-counter clock will be divided by 10.
*
* \param [in] enabled clock divider status
*
*/
static inline void hw_timer0_set_on_clock_div(bool enabled)
{
HW_TIMER0_REG_SETF(CTRL, TIM0_CLK_DIV, !enabled);
}
/**
* \brief Get current state of clock divider for ON-counter
*
* \return clock divider status
*
*/
static inline bool hw_timer0_get_on_clock_div(void)
{
return !HW_TIMER0_REG_GETF(CTRL, TIM0_CLK_DIV);
}
/**
* \brief Set PWM mode for timer
*
* \param [in] mode PWM mode
*
* \sa TIMER0_MODE
*
*/
static inline void hw_timer0_set_pwm_mode(HW_TIMER0_MODE mode)
{
HW_TIMER0_REG_SETF(CTRL, PWM_MODE, mode);
}
/**
* \brief Get current PWM mode for timer
*
* \return PWM mode
*
*/
static inline HW_TIMER0_MODE hw_timer0_get_pwm_mode(void)
{
return HW_TIMER0_REG_GETF(CTRL, PWM_MODE);
}
/**
* \brief Set reload value for T0-counter
*
* T0 counter value is decremented on each clock cycle. At the beginning it's loaded from M-register
* and then, once reached zero, loaded from N-register (and then M and N again).
*
* PWM0 is high when counting down M-register and low when counting down N-register.
* For PWM1 is the opposite.
*
* \param [in] m_value M-register reload value
* \param [in] n_value N-register reload value
*
*/
static inline void hw_timer0_set_t0_reload(uint16_t m_value, uint16_t n_value)
{
GP_TIMERS->TIMER0_RELOAD_M_REG = m_value;
GP_TIMERS->TIMER0_RELOAD_N_REG = n_value;
}
/**
* \brief Set reload value for ON-counter
*
* ON counter value is decremented on each clock cycle. Once ON reaches zero it will remain zero
* until T0 counter completes decrementing N-register value. When this happens, interrupt is
* generated.
*
* \param [in] value reload value
*
* \sa hw_timer0_set_on_clock_div
*
*/
static inline void hw_timer0_set_on_reload(uint16_t value)
{
GP_TIMERS->TIMER0_ON_REG = value;
}
/**
* \brief Get T0-counter value
*
* \return counter value
*
*/
static inline uint16_t hw_timer0_get_t0(void)
{
return (GP_TIMERS->TIMER0_RELOAD_M_REG);
}
/**
* \brief Get ON-counter value
*
* \return counter value
*
*/
static inline uint16_t hw_timer0_get_on(void)
{
return (GP_TIMERS->TIMER0_ON_REG);
}
/**
* \brief Freeze timer
*
*/
static inline void hw_timer0_freeze(void)
{
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SWTIM0_Msk;
}
/**
* \brief Unfreeze timer
*
*/
static inline void hw_timer0_unfreeze(void)
{
GPREG->RESET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SWTIM0_Msk;
}
#endif /* dg_configUSE_HW_TIMER0 */
#endif /* HW_TIMER0_H_ */
/**
* \}
* \}
* \}
*/
+955
View File
@@ -0,0 +1,955 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Timer1
* \{
*/
/**
*****************************************************************************************
*
* @file hw_timer1.h
*
* @brief Definition of API for the Timer1 Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_TIMER1_H_
#define HW_TIMER1_H_
#if dg_configUSE_HW_TIMER1
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
/**
* \brief Get the mask of a field of an TIMER1 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_TIMER1_REG_FIELD_MASK(reg, field) \
(TIMER1_CAPTIM_##reg##_REG_##field##_Msk)
/**
* \brief Get the bit position of a field of an TIMER1 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_TIMER1_REG_FIELD_POS(reg, field) \
(TIMER1_CAPTIM_##reg##_REG_##field##_Pos)
/**
* \brief Get the value of a field of an TIMER1 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
*
* \return the value of the register field
*
*/
#define HW_TIMER1_REG_GETF(reg, field) \
((TIMER1->CAPTIM_##reg##_REG & (TIMER1_CAPTIM_##reg##_REG_##field##_Msk)) >> (TIMER1_CAPTIM_##reg##_REG_##field##_Pos))
/**
* \brief Set the value of a field of an TIMER1 register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
* \param [in] new_val is the value to write
*
*/
#define HW_TIMER1_REG_SETF(reg, field, new_val) \
TIMER1->CAPTIM_##reg##_REG = ((TIMER1->CAPTIM_##reg##_REG & ~(TIMER1_CAPTIM_##reg##_REG_##field##_Msk)) | \
((TIMER1_CAPTIM_##reg##_REG_##field##_Msk) & ((new_val) << (TIMER1_CAPTIM_##reg##_REG_##field##_Pos))))
#define EXT_CLK 16 // 16 MHz
#define INT_CLK 32 // 32 kHz
/**
* \brief Mode of operation
*
* PWM is enabled in both modes.
*
*/
typedef enum {
HW_TIMER1_MODE_TIMER = 0, /**< timer/capture mode */
HW_TIMER1_MODE_ONESHOT = 1 /**< one-shot mode */
} HW_TIMER1_MODE;
/**
* \brief Clock source for timer
*
*/
typedef enum {
HW_TIMER1_CLK_SRC_INT = 0, /**< Internal clock 32 kHz (slow) */
HW_TIMER1_CLK_SRC_EXT = 1 /**< External clock 2/4/8/16 MHz (fast) */
} HW_TIMER1_CLK_SRC;
/**
* \brief Counting direction
*
*/
typedef enum {
HW_TIMER1_DIR_UP = 0, /**< Timer counts up (counter is incremented) */
HW_TIMER1_DIR_DOWN = 1 /**< Timer counts down (counter is decremented) */
} HW_TIMER1_DIR;
/**
* \brief Type of triggering events
*
*/
typedef enum {
HW_TIMER1_TRIGGER_RISING = 0, /**< Event activated rising edge */
HW_TIMER1_TRIGGER_FALLING = 1 /**< Event activated falling edge */
} HW_TIMER1_TRIGGER;
/**
* \brief One shot mode phases
*
*/
typedef enum {
HW_TIMER1_ONESHOT_WAIT = 0, /**< Wait for the event */
HW_TIMER1_ONESHOT_DELAY = 1, /**< Delay before started */
HW_TIMER1_ONESHOT_STARTED = 2, /**< Start shot */
HW_TIMER1_ONESHOT_ACTIVE = 3 /**< Shot is active */
} HW_TIMER1_ONESHOT;
/**
* \brief GPIOs for timer1
*
* Mainly use for mark which GPIO will triggers timer counting.
*
*/
typedef enum {
HW_TIMER1_GPIO_NONE = 0, /**< None of GPIO */
/* port 0 */
HW_TIMER1_GPIO_P00 = 1, /**< Port 0, pin 0 */
HW_TIMER1_GPIO_P01 = 2, /**< Port 0, pin 1 */
HW_TIMER1_GPIO_P02 = 3, /**< Port 0, pin 2 */
HW_TIMER1_GPIO_P03 = 4, /**< Port 0, pin 3 */
HW_TIMER1_GPIO_P04 = 5, /**< Port 0, pin 4 */
HW_TIMER1_GPIO_P05 = 6, /**< Port 0, pin 5 */
HW_TIMER1_GPIO_P06 = 7, /**< Port 0, pin 6 */
HW_TIMER1_GPIO_P07 = 8, /**< Port 0, pin 7 */
/* port 1 */
HW_TIMER1_GPIO_P10 = 9, /**< Port 1, pin 0 */
HW_TIMER1_GPIO_P11 = 10, /**< Port 1, pin 1 */
HW_TIMER1_GPIO_P12 = 11, /**< Port 1, pin 2 */
HW_TIMER1_GPIO_P13 = 12, /**< Port 1, pin 3 */
HW_TIMER1_GPIO_P14 = 13, /**< Port 1, pin 4 */
HW_TIMER1_GPIO_P15 = 14, /**< Port 1, pin 5 */
HW_TIMER1_GPIO_P16 = 15, /**< Port 1, pin 6 */
HW_TIMER1_GPIO_P17 = 16, /**< Port 1, pin 7 */
/* port 2 */
HW_TIMER1_GPIO_P20 = 17, /**< Port 2, pin 0 */
HW_TIMER1_GPIO_P21 = 18, /**< Port 2, pin 1 */
HW_TIMER1_GPIO_P22 = 19, /**< Port 2, pin 2 */
HW_TIMER1_GPIO_P23 = 20, /**< Port 2, pin 3 */
HW_TIMER1_GPIO_P24 = 21, /**< Port 2, pin 4 */
/* port 3 */
HW_TIMER1_GPIO_P30 = 22, /**< Port 3, pin 0 */
HW_TIMER1_GPIO_P31 = 23, /**< Port 3, pin 1 */
HW_TIMER1_GPIO_P32 = 24, /**< Port 3, pin 2 */
HW_TIMER1_GPIO_P33 = 25, /**< Port 3, pin 3 */
HW_TIMER1_GPIO_P34 = 26, /**< Port 3, pin 4 */
HW_TIMER1_GPIO_P35 = 27, /**< Port 3, pin 5 */
HW_TIMER1_GPIO_P36 = 28, /**< Port 3, pin 6 */
HW_TIMER1_GPIO_P37 = 29, /**< Port 3, pin 7 */
/* port 4 */
HW_TIMER1_GPIO_P40 = 30, /**< Port 4, pin 0 */
HW_TIMER1_GPIO_P41 = 31, /**< Port 4, pin 1 */
HW_TIMER1_GPIO_P42 = 32, /**< Port 4, pin 2 */
HW_TIMER1_GPIO_P43 = 33, /**< Port 4, pin 3 */
HW_TIMER1_GPIO_P44 = 34, /**< Port 4, pin 4 */
HW_TIMER1_GPIO_P45 = 35, /**< Port 4, pin 5 */
HW_TIMER1_GPIO_P46 = 36, /**< Port 4, pin 6 */
HW_TIMER1_GPIO_P47 = 37, /**< Port 4, pin 7 */
} HW_TIMER1_GPIO;
/**
* \brief Timer interrupt callback
*
*/
typedef void (*hw_timer1_handler_cb)(void);
/*
* \brief Timer configuration for timer/capture mode
*
* \sa timer1_config
* \sa hw_timer1_configure_timer
*
*/
typedef struct {
HW_TIMER1_DIR direction; /**< counting direction */
uint32_t reload_val; /**< reload value */
bool free_run; /**< free-running mode state */
HW_TIMER1_GPIO gpio1; /**< 1st GPIO for capture mode */
HW_TIMER1_TRIGGER trigger1; /**< 1st GPIO capture trigger */
HW_TIMER1_GPIO gpio2; /**< 2nd GPIO for capture mode */
HW_TIMER1_TRIGGER trigger2; /**< 2nd GPIO capture trigger */
} timer1_config_timer_capture;
/*
* \brief Timer configuration for oneshot mode
*
* \sa timer1_config
* \sa hw_timer1_configure_oneshot
*
*/
typedef struct {
uint16_t delay; /**< delay (ticks) between GPIO event and output pulse */
uint32_t shot_width; /**< width (ticks) of generated pulse */
HW_TIMER1_GPIO gpio; /**< GPIO to wait for event */
HW_TIMER1_TRIGGER trigger; /**< GPIO trigger */
} timer1_config_oneshot;
/*
* \brief Timer PWM configuration
*
* \sa timer1_config
* \sa hw_timer1_configure_pwm
* \sa hw_timer1_set_pwm_freq
* \sa hw_timer1_set_pwm_duty_cycle
*/
typedef struct {
uint16_t frequency; /**< frequency */
uint16_t duty_cycle; /**< duty cycle */
} timer1_config_pwm;
/*
* \brief Timer configuration
*
* Only one of \p timer and \p oneshot configuration can be set since they are stored in the same
* union (and will overwrite each other). Proper configuration structure is selected depending on
* timer mode set.
*
* \sa timer1_config_timer_capture
* \sa timer1_config_oneshot
* \sa timer1_config_pwm
* \sa hw_timer1_configure
*
*/
typedef struct {
HW_TIMER1_CLK_SRC clk_src; /**< clock source */
uint16_t prescaler; /**< clock prescaler */
timer1_config_timer_capture timer; /**< configuration for timer/capture mode */
timer1_config_oneshot oneshot; /**< configuration for oneshot mode */
timer1_config_pwm pwm; /**< PWM configuration */
} timer1_config;
#if dg_configUSER_CAN_USE_TIMER1 == 1
/**
* \brief Timer initialization
*
* Turn on clock for timer and configure timer. After initialization both timer and its interrupt
* are disabled. \p cfg can be NULL - no configuration is performed in such case.
*
* \param [in] mode timer mode
* \param [in] cfg configuration
*
*/
void hw_timer1_init(HW_TIMER1_MODE mode, const timer1_config *cfg);
/**
* \brief Timer configuration
*
* Shortcut to call appropriate configuration function. If \p cfg is NULL, this function does
* nothing except switching timer to selected mode.
*
* \param [in] mode timer mode
* \param [in] cfg configuration
*
*/
void hw_timer1_configure(HW_TIMER1_MODE mode, const timer1_config *cfg);
/**
* \brief Timer configuration for timer/capture mode
*
* Shortcut to call appropriate configuration function. This does not switch timer to timer/capture
* mode, it should be done separately using hw_timer1_set_mode().
*
* \param [in] cfg configuration
*
*/
void hw_timer1_configure_timer(const timer1_config_timer_capture *cfg);
/**
* \brief Timer configuration for oneshot mode
*
* Shortcut to call appropriate configuration function. This does not switch timer to oneshot
* mode, it should be done separately using hw_timer1_set_mode().
*
* \param [in] cfg configuration
*
*/
void hw_timer1_configure_oneshot(const timer1_config_oneshot *cfg);
/**
* \brief Set clock source of the timer
*
* \param [in] clk clock source of the timer, external or internal
*
*/
static inline void hw_timer1_set_clk(HW_TIMER1_CLK_SRC clk)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_SYS_CLK_EN, clk);
}
/**
* \brief Set timer clock prescaler
*
* Actual timer frequency is \p timer_freq = \p freq_clock / (\p value + 1)
*
* \param [in] value prescaler
*
*/
static inline void hw_timer1_set_prescaler(uint16_t value)
{
TIMER1->CAPTIM_PRESCALER_REG = value;
}
/**
* \brief Set timer reload value
*
* \note This changes the same register value as hw_timer1_set_oneshot_delay() since both parameters
* share the same register (value is interpreted differently depending on timer mode).
*
* \param [in] value reload value
*
* \sa hw_timer1_set_oneshot_delay
*
*/
static inline void hw_timer1_set_reload(uint32_t value)
{
TIMER1->CAPTIM_RELOAD_REG = (uint16_t) value;
}
/**
* \brief Set pulse delay in oneshot mode
*
* \note This changes the same register value as hw_timer1_set_reload() since both parameters share
* the same register (value is interpreted differently depending on timer mode).
*
* \param [in] delay delay (ticks)
*
* \sa hw_timer1_set_reload
*
*/
static inline void hw_timer1_set_oneshot_delay(uint32_t delay)
{
TIMER1->CAPTIM_RELOAD_REG = (uint16_t) delay;
}
/**
* \brief Set shot width
*
* This applies only to one-shot mode.
*
* \param [in] duration shot phase duration
*
*/
static inline void hw_timer1_set_shot_width(uint32_t duration)
{
TIMER1->CAPTIM_SHOTWIDTH_REG = (uint16_t) duration;
}
/**
* \brief Turn on free run mode of the timer
*
*/
static inline void hw_timer1_set_freerun(bool enabled)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_FREE_RUN_MODE_EN, enabled);
}
/**
* \brief Set a type of the edge which triggers event1
*
* \param [in] edge type of edge, rising or falling
*
*/
static inline void hw_timer1_set_event1_trigger(HW_TIMER1_TRIGGER edge)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_IN1_EVENT_FALL_EN, edge);
}
/**
* \brief Set a type of the edge which triggers event2
*
* \param [in] edge type of edge, rising or falling
*
*/
static inline void hw_timer1_set_event2_trigger(HW_TIMER1_TRIGGER edge)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_IN2_EVENT_FALL_EN, edge);
}
/**
* \brief Set a GPIO input which triggers event1
*
* \param [in] gpio GPIO input
*
*/
static inline void hw_timer1_set_event1_gpio(HW_TIMER1_GPIO gpio)
{
TIMER1->CAPTIM_GPIO1_CONF_REG = gpio;
}
/**
* \brief Set a GPIO input which triggers event2
*
* \param [in] gpio GPIO input
*
*/
static inline void hw_timer1_set_event2_gpio(HW_TIMER1_GPIO gpio)
{
TIMER1->CAPTIM_GPIO2_CONF_REG = gpio;
}
/**
* \brief Get clock source of the timer
*
* \return clock source
*
*/
static inline HW_TIMER1_CLK_SRC hw_timer1_get_clk(void)
{
return HW_TIMER1_REG_GETF(CTRL, CAPTIM_SYS_CLK_EN);
}
/**
* \brief Get timer clock prescaler
*
* Actual timer frequency is \p timer_freq = \p freq_clock / (\p retval + 1)
*
* \return prescaler value
*
* \sa hw_timer1_get_prescaler_val
*
*/
static inline uint16_t hw_timer1_get_prescaler(void)
{
return TIMER1->CAPTIM_PRESCALER_REG;
}
/**
* \brief Get timer reload value
*
* \return reload value
*
* \sa hw_timer1_set_reload
*
*/
static inline uint32_t hw_timer1_get_reload(void)
{
return TIMER1->CAPTIM_RELOAD_REG;
}
/**
* \brief Get pulse delay in oneshot mode
*
* \return delay (ticks)
*
* \sa hw_timer1_get_oneshot_delay
*
*/
static inline uint32_t hw_timer1_get_oneshot_delay(void)
{
return TIMER1->CAPTIM_RELOAD_REG;
}
/**
* \brief Get shot width
*
* This applies only to one-shot mode.
*
* \return shot width value
*
*/
static inline uint32_t hw_timer1_get_shot_width(void)
{
return TIMER1->CAPTIM_SHOTWIDTH_REG;
}
/**
* \brief Get free-running mode state
*
* \return free-running mode state
*
*/
static inline bool hw_timer1_get_freerun(void)
{
return HW_TIMER1_REG_GETF(CTRL, CAPTIM_FREE_RUN_MODE_EN);
}
/**
* \brief Get a type of the edge which triggers event1
*
* \return edge type
*
*/
static inline HW_TIMER1_TRIGGER hw_timer1_get_event1_trigger(void)
{
return HW_TIMER1_REG_GETF(CTRL, CAPTIM_IN1_EVENT_FALL_EN);
}
/**
* \brief Get a type of the edge which triggers event2
*
* \return edge type
*
*/
static inline HW_TIMER1_TRIGGER hw_timer1_get_event2_trigger(void)
{
return HW_TIMER1_REG_GETF(CTRL, CAPTIM_IN2_EVENT_FALL_EN);
}
/**
* \brief Get a GPIO input which triggers event1
*
* \return GPIO input
*
*/
static inline HW_TIMER1_GPIO hw_timer1_get_event1_gpio(void)
{
return TIMER1->CAPTIM_GPIO1_CONF_REG;
}
/**
* \brief Get a GPIO input which triggers event2
*
* \return GPIO input
*
*/
static inline HW_TIMER1_GPIO hw_timer1_get_event2_gpio(void)
{
return TIMER1->CAPTIM_GPIO2_CONF_REG;
}
/**
* \brief Get the capture time for event on GPIO1
*
* \return time for event on GPIO1
*
*/
static inline uint32_t hw_timer1_get_capture1(void)
{
return TIMER1->CAPTIM_CAPTURE_GPIO1_REG;
}
/**
* \brief Get the capture time for event on GPIO2
*
* \return time for event on GPIO2
*
*/
static inline uint32_t hw_timer1_get_capture2(void)
{
return TIMER1->CAPTIM_CAPTURE_GPIO2_REG;
}
/**
* \brief Set the direction of timer counting
*
* \param [in] dir counting direction of the timer, up or down
*
*/
static inline void hw_timer1_set_direction(HW_TIMER1_DIR dir)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_COUNT_DOWN_EN, dir);
}
/**
* \brief Turn on one shot mode
*
*/
static inline void hw_timer1_set_mode(HW_TIMER1_MODE mode)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_ONESHOT_MODE_EN, mode);
}
/**
* \brief Turn on capture mode
*
*/
static inline HW_TIMER1_MODE hw_timer1_get_mode(void)
{
return HW_TIMER1_REG_GETF(CTRL, CAPTIM_ONESHOT_MODE_EN);
}
/**
* \brief Get the tick count of the timer
*
* \return current value of the timer ticks
*
* \sa hw_timer1_get_prescaler_val
*
*/
static inline uint32_t hw_timer1_get_count(void)
{
return TIMER1->CAPTIM_TIMER_VAL_REG;
}
/**
* \brief Get the current phase of the one shot mode
*
* \return current phase of the one shot mode
*
*/
static inline HW_TIMER1_ONESHOT hw_timer1_get_oneshot_phase(void)
{
return HW_TIMER1_REG_GETF(STATUS, CAPTIM_ONESHOT_PHASE);
}
/**
* \brief Get the current state of IN1
*
* \return current logic level of IN1
*
*/
static inline bool hw_timer1_get_gpio1_state(void)
{
return HW_TIMER1_REG_GETF(STATUS, CAPTIM_IN1_STATE);
}
/**
* \brief Get the current state of IN2
*
* \return current logic level of IN2
*
*/
static inline bool hw_timer1_get_gpio2_state(void)
{
return HW_TIMER1_REG_GETF(STATUS, CAPTIM_IN2_STATE);
}
/**
* \brief Get the current prescaler counter value
*
* This is value of internal counter used for prescaling. It can be used to have finer granularity
* when reading timer value.
*
* For reading current setting of prescaler, see hw_timer1_get_prescaler().
*
* \return current prescaler counter value
*
* \sa hw_timer1_get_count
* \sa hw_timer1_get_prescaler
*
*/
static inline uint16_t hw_timer1_get_prescaler_val(void)
{
return TIMER1->CAPTIM_PRESCALER_VAL_REG;
}
/**
* \brief Register an interrupt handler.
*
* \param [in] handler function pointer to handler to call when an interrupt occurs
*
*/
void hw_timer1_register_int(hw_timer1_handler_cb handler);
/**
* \brief Unregister an interrupt handler
*
*/
void hw_timer1_unregister_int(void);
/**
* \brief Freeze timer
*
*/
static inline void hw_timer1_freeze(void)
{
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SWTIM1_Msk;
}
/**
* \brief Unfreeze timer
*
*/
static inline void hw_timer1_unfreeze(void)
{
GPREG->RESET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_SWTIM1_Msk;
}
#else // (dg_configUSER_CAN_USE_TIMER1 == 0)
#define LP_CNT_REG_RANGE ( 16 )
#define LP_CNT_MAX_VALUE ( (1 << LP_CNT_REG_RANGE) - 1 )
#define LP_CNT_PRESCALED_MASK ( LP_CNT_MAX_VALUE )
#define LP_CNT_NATIVE_MASK ( (1 << (LP_CNT_REG_RANGE + dg_configTim1PrescalerBitRange)) - 1 )
/**
* \brief Configure timer as tick timer
*
* \details Setup Timer1 for use as a tick timer:
* <ul>
* <li> use LP clock and prescaler (if configured)
* <li> free running mode
* <li> IRQ masked
* <li> up counter
* <li> timer mode
* <li> disabled
* </ul>
*
*/
void hw_timer1_lp_clk_init(void);
/**
* \brief Enable interrupt
*
* \return void
*
*/
static inline void hw_timer1_int_enable(void)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_IRQ_EN, 1);
NVIC_ClearPendingIRQ(SWTIM1_IRQn);
NVIC_EnableIRQ(SWTIM1_IRQn);
}
/**
* \brief Disable interrupt
*
* \return void
*
*/
static inline void hw_timer1_int_disable(void)
{
NVIC_DisableIRQ(SWTIM1_IRQn);
HW_TIMER1_REG_SETF(CTRL, CAPTIM_IRQ_EN, 0);
}
/**
* \brief Get counter's value
*
* \return The current value of the counter (prescaled).
*
*/
static inline uint32_t hw_timer1_get_value(void) __attribute__((always_inline));
static inline uint32_t hw_timer1_get_value(void)
{
return TIMER1->CAPTIM_TIMER_VAL_REG;
}
/**
* \brief Macro to get the current value of the timer, both prescaled and in LP clock cycles.
*
* \details Special care is needed when a prescaler is used. In this case, the
* counting sequence is the following (assuminga prescaler of 3):
* prescaler: 0 1 2 3 0 1 2 3 0
* counter: 0 1 2
*
* If not implemented properly then the following may happen:
* - let's assume that we are at the end of the {0, 3} period
* - the counter's value is read and the result is 0
* - at that moment, the counter increases it's prescaler value (and the counter's value
* respectively), so the time becomes {1, 0}
* - the reading of the prescaler's value will give 0 but {0, 0} is earlier than {0, 3} (when
* the operation started) and this may result in errors in time computations.
*
*/
#define HW_TIMER1_GET_INSTANT(prescaled, fine) \
do { \
if (dg_configTim1Prescaler != 0) { \
uint32_t prescaler_v; \
\
do { \
prescaler_v = TIMER1->CAPTIM_PRESCALER_VAL_REG; \
prescaled = TIMER1->CAPTIM_TIMER_VAL_REG; \
} while (prescaler_v != TIMER1->CAPTIM_PRESCALER_VAL_REG); \
\
fine = ( (uint32_t)prescaled * (1 + dg_configTim1Prescaler) + prescaler_v); \
} \
else { \
prescaled = TIMER1->CAPTIM_TIMER_VAL_REG; \
fine = prescaled; \
} \
} while (0)
/**
* \brief Macro to set the trigger value. The previous trigger value is returned to the caller.
*
*/
#define HW_TIMER1_SET_TRIGGER(value, last_value) \
do { \
last_value = TIMER1->CAPTIM_RELOAD_REG; \
TIMER1->CAPTIM_RELOAD_REG = value; \
} while (0)
/**
* \brief Get trigger value
*
* \return The current value of the trigger (prescaled).
*
*/
static inline uint32_t hw_timer1_get_trigger(void)
{
return TIMER1->CAPTIM_RELOAD_REG;
}
/**
* \brief Set an "invalid" trigger value, which refers far away in the future
*
*/
static inline void hw_timer1_invalidate_trigger(void) __attribute__((always_inline));
static inline void hw_timer1_invalidate_trigger(void)
{
uint32_t lp_current_time; // prescaled
uint32_t trigger;
uint32_t dummy __attribute__((unused));
lp_current_time = hw_timer1_get_value(); // Get current time
trigger = (lp_current_time - 1) & LP_CNT_PRESCALED_MASK; // Get an "invalid" trigger
HW_TIMER1_SET_TRIGGER(trigger, dummy); // Move trigger too far in the future so
// that no interrupt from the timer arrives.
}
#endif // dg_configUSER_CAN_USE_TIMER1
/**
* \brief Enable the timer
*
*/
static inline void hw_timer1_enable(void)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_EN, 1);
REG_SET_BIT(CRG_TOP, CLK_TMR_REG, TMR1_ENABLE);
}
/**
* \brief Disable the timer
*
*/
static inline void hw_timer1_disable(void)
{
HW_TIMER1_REG_SETF(CTRL, CAPTIM_EN, 0);
REG_CLR_BIT(CRG_TOP, CLK_TMR_REG, TMR1_ENABLE);
}
/**
* \brief Timer PWM configuration
*
* Shortcut to call appropriate configuration function.
*
* \param [in] cfg configuration
*
*/
void hw_timer1_configure_pwm(const timer1_config_pwm *cfg);
/**
* \brief Set PWM frequency prescaler
*
* Actual PWM frequency is \p pwm_freq = \p timer_freq / (\p value + 1)
*
* \param [in] value PWM frequency defined as above
*
* \sa hw_timer1_set_prescaler
*
*/
static inline void hw_timer1_set_pwm_freq(uint16_t value)
{
TIMER1->CAPTIM_PWM_FREQ_REG = value;
}
/**
* \brief Set PWM duty cycle
*
* Actualy PWM duty cycle is \p pwm_dc = \p value / (\p pwm_freq + 1)
*
* \param [in] value PWM duty cycle defined as above
*
* \sa hw_timer1_set_pwm_freq
*
*/
static inline void hw_timer1_set_pwm_duty_cycle(uint16_t value)
{
TIMER1->CAPTIM_PWM_DC_REG = value;
}
/**
* \brief Get PWM frequency prescaler
*
* Actual PWM frequency is \p pwm_freq = \p timer_freq / (\p retval + 1)
*
* \return PWM frequency as defined above
*
*/
static inline uint16_t hw_timer1_get_pwm_freq(void)
{
return TIMER1->CAPTIM_PWM_FREQ_REG;
}
/**
* \brief Get PWM duty cycle
*
* Actualy PWM duty cycle is \p pwm_dc = \p retval / (\p pwm_freq + 1)
*
* \return PWM duty cycle as defined above
*
*/
static inline uint16_t hw_timer1_get_pwm_duty_cycle(void)
{
return TIMER1->CAPTIM_PWM_DC_REG;
}
#endif /* dg_configUSE_HW_TIMER1 */
#endif /* HW_TIMER1_H_ */
/**
* \}
* \}
* \}
*/
+98
View File
@@ -0,0 +1,98 @@
/**
*****************************************************************************************
*
* @file hw_trng.h
*
* @brief Definition of API for the True Random Number Generator Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
*****************************************************************************************
*/
#if dg_configUSE_HW_TRNG
#include <black_orca.h>
/**
* \brief TRNG callback.
*
* This function is called by the TRNG driver when the interrupt is fired.
*
* \note If the TRNG is not needed anymore the hw_trng_disable function should be called in the
* callback function to save power.
*
*/
typedef void (*hw_trng_cb)(void);
/**
* \brief TRNG enable.
*
* This function enables the TRNG. If callback is not NULL it will be called when a TRNG interrupt
* occurs. The interrupt is triggered when the TRNG FIFO is full.
*
* \param [in] callback The callback function that is called when a TRNG interrupt occurs.
*
* \note If the amount of random numbers needed is less than the contents of the FIFO it is faster
* and more power efficient to use a wait loop in combination with the hw_trng_get_fifo_level
* function. If the FIFO has the required level use the hw_trng_get_numbers function to get the
* random numbers.
*
*/
void hw_trng_enable(hw_trng_cb callback);
/**
* \brief TRNG get numbers.
*
* This function reads the random number from the TRNG FIFO.
*
* \param [in] buffer The buffer to write the numbers to.
* \param [in] size The size of the buffer (max 32).
*
* \note Do not forget to disable the TRNG after reading the amount of numbers needed to save
* power.
*
*/
void hw_trng_get_numbers(uint32_t* buffer, uint8_t size);
/**
* \brief TRNG get FIFO level.
*
* This function returns the current level of the TRNG FIFO.
*
* \return The current level of the TRNG FIFO.
*
*/
uint8_t hw_trng_get_fifo_level(void);
/**
* \brief TRNG disable.
*
* This function disables the TRNG and its interrupt.
*
*/
void hw_trng_disable(void);
#endif /* dg_configUSE_HW_TRNG */
File diff suppressed because it is too large Load Diff
+186
View File
@@ -0,0 +1,186 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Watchdog_Timer
* \{
*/
/**
*****************************************************************************************
*
* @file hw_watchdog.h
*
* @brief Definition of API for the Watchdog timer Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_WATCHDOG_H_
#define HW_WATCHDOG_H_
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
#define NMI_MAGIC_NUMBER 0xDEADBEEF
/**
* \brief Holds the stack contents when an NMI occurs.
*
* \details The stack contents are copied at this variable when an NMI occurs. The first position is
* marked with a special "flag" (0xDEADBEEF) to indicate that the data that follow are valid.
*/
extern uint32_t nmi_event_data[9];
/**
* \brief Types of generated states if reload value is 0
*
* Generate NMI (non-maskable interrupt) or RST (reset of the system)
*
*/
typedef enum {
HW_WDG_RESET_NMI = 0, /**< Generate NMI if the watchdog reaches 0 and WDOG reset if the counter become less or equal to -16 */
HW_WDG_RESET_RST = 1 /**< Generate WDOG reset it the counter becomes less or equal than 0 */
} HW_WDG_RESET;
/**
* \brief Watchdog timer interrupt callback
*
* \param [in] hardfault_args pointer to call stack
*
*/
typedef void (*hw_watchdog_interrupt_cb)(unsigned long *exception_args);
/**
* \brief Freeze the watchdog
*
* \return true if operation is allowed, else false
*
*/
__RETAINED_CODE bool hw_watchdog_freeze(void);
/**
* \brief Unfreeze the watchdog
*
*/
__RETAINED_CODE void hw_watchdog_unfreeze(void);
/**
* \brief Set positive reload value of the watchdog timer
*
* \param [in] value reload value from 0 (0x00) to 255 (0xFF)
*
*/
static inline void hw_watchdog_set_pos_val(uint8_t value) __attribute__((always_inline));
static inline void hw_watchdog_set_pos_val(uint8_t value)
{
WDOG->WATCHDOG_REG = (uint16_t)value;
}
/**
* \brief Set negative reload value of the watchdog timer
*
* \param [in] value reload value from -16 (0x1FF) to 0 (0x00)
*
*/
static inline void hw_watchdog_set_neg_val(uint8_t value)
{
WDOG->WATCHDOG_REG = WDOG_WATCHDOG_REG_WDOG_VAL_NEG_Msk | (uint16_t)value;
}
/**
* \brief Get reload value of the watchdog timer
*
*/
static inline uint16_t hw_watchdog_get_val(void)
{
return REG_GETF(WDOG, WATCHDOG_REG, WDOG_VAL);
}
/**
* \brief Generate a reset signal of the system if reload value reaches 0
*
*/
static inline void hw_watchdog_gen_RST(void) __attribute__((always_inline));
static inline void hw_watchdog_gen_RST(void)
{
REG_SET_BIT(WDOG, WATCHDOG_CTRL_REG, NMI_RST);
}
/**
* \brief Register an interrupt handler
*
* \param [in] handler function pointer to handler to call when an interrupt occurs
*
*/
void hw_watchdog_register_int(hw_watchdog_interrupt_cb handler);
/**
* \brief Unregister an interrupt handler
*
*/
__RETAINED_CODE void hw_watchdog_unregister_int(void);
/**
* \brief Handle NMI interrupt.
*
* \param [in] hardfault_args pointer to call stack
*
*/
__RETAINED_CODE void hw_watchdog_handle_int(unsigned long *hardfault_args);
/**
* \brief Check whether the timer has expired
*
* \return true, if the timer has expired, false otherwise
*
*/
bool hw_watchdog_is_timer_expired(void);
/**
* \brief Check what is generated when watchdog reaches 0 value
*
* If it is NMI (interrupt) or RST (system/wdog reset).
*
* \return HW_WDG_RESET_NMI if NMI interrupt is generated, otherwise HW_WDG_RESET_RST
*
*/
HW_WDG_RESET hw_watchdog_is_irq_or_rst_gen(void);
#endif /* HW_WATCHDOG_H_ */
/**
* \}
* \}
* \}
*/
+462
View File
@@ -0,0 +1,462 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Wakeup_Timer
* \{
*/
/**
*****************************************************************************************
*
* @file hw_wkup.h
*
* @brief Definition of API for the Wakeup timer Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 HW_WKUP_H_
#define HW_WKUP_H_
#if dg_configUSE_HW_USB_WKUP
#include <stdbool.h>
#include <stdint.h>
#include <black_orca.h>
#include "hw_gpio.h"
/**
* \brief Get the mask of a field of an WKUP register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_WKUP_REG_FIELD_MASK(reg, field) \
(WAKEUP_WKUP_##reg##_REG_##field##_Msk)
/**
* \brief Get the bit position of a field of an WKUP register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to access
*
*/
#define HW_WKUP_REG_FIELD_POS(reg, field) \
(WAKEUP_WKUP_##reg##_REG_##field##_Pos)
/**
* \brief Get the value of a field of an WKUP register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
*
* \return the value of the register field
*
*/
#define HW_WKUP_REG_GETF(reg, field) \
((WAKEUP->WKUP_##reg##_REG & (WAKEUP_WKUP_##reg##_REG_##field##_Msk)) >> (WAKEUP_WKUP_##reg##_REG_##field##_Pos))
/**
* \brief Set the value of a field of an WKUP register.
*
* \param [in] reg is the register to access
* \param [in] field is the register field to write
* \param [in] new_val is the value to write
*
*/
#define HW_WKUP_REG_SETF(reg, field, new_val) \
WAKEUP->WKUP_##reg##_REG = ((WAKEUP->WKUP_##reg##_REG & ~(WAKEUP_WKUP_##reg##_REG_##field##_Msk)) | \
((WAKEUP_WKUP_##reg##_REG_##field##_Msk) & ((new_val) << (WAKEUP_WKUP_##reg##_REG_##field##_Pos))))
/**
* \brief Pin state which increments event counter
*
*/
typedef enum {
HW_WKUP_PIN_STATE_HIGH = 0,
HW_WKUP_PIN_STATE_LOW = 1
} HW_WKUP_PIN_STATE;
/**
* \brief Wakeup timer configuration
*
*/
typedef struct {
uint8_t threshold; /**< counter threshold */
uint8_t debounce; /**< debounce time in ms */
uint8_t pin_state[HW_GPIO_NUM_PORTS]; /**< pin states in each port, see hw_wkup_configure_port */
uint8_t pin_trigger[HW_GPIO_NUM_PORTS]; /**< pin triggers in each port, see hw_wkup_configure_port */
} wkup_config;
typedef void (*hw_wkup_interrupt_cb)(void);
/**
* \brief Initialize peripheral
*
* Resets Wakeup Timer to initial state, i.e. interrupt is disabled and all pin triggers are
* disabled.
*
* \p cfg can be NULL - no configuration is performed in such case.
*
* \param [in] cfg configuration
*
*/
void hw_wkup_init(const wkup_config *cfg);
/**
* \brief Configure peripheral
*
* Shortcut to call appropriate configuration function. If \p cfg is NULL, this function does
* nothing.
*
* \param [in] cfg configuration
*
*/
void hw_wkup_configure(const wkup_config *cfg);
/**
* \brief Register interrupt handler
*
* Callback function is called when interrupt is generated, i.e. event counter reaches configured
* value. Interrupt is automatically enabled after calling this function. Application should reset
* interrupt in callback function using hw_wkup_reset_interrupt(). If no callback is specified,
* interrupt will be automatically cleared by driver.
*
* \param [in] cb callback function
* \param [in] prio the priority of the interrupt
*
* \sa hw_wkup_unregister_interrupt
* \sa hw_wkup_clear_interrupt
* \sa hw_wkup_set_counter_threshold
* \sa hw_wkup_get_counter
*
*/
void hw_wkup_register_interrupt(hw_wkup_interrupt_cb cb, uint32_t prio);
/**
* \brief Unregister interrupt handler
*
* Interrupt is automatically disabled after calling this function.
*
*/
void hw_wkup_unregister_interrupt(void);
/**
* \brief Reset interrupt
*
* This function MUST be called by any user-specified interrupt callback, to clear the interrupt.
*
*/
static inline void hw_wkup_reset_interrupt(void)
{
WAKEUP->WKUP_RESET_IRQ_REG = 1;
}
/**
* \brief Interrupt handler
*
*/
void hw_wkup_handler(void);
/**
* \brief Set debounce time
*
* Setting debounce time to 0 will disable hardware debouncing. Maximum debounce time is 63ms.
*
* \param [in] time_ms debounce time in miliseconds
*
*/
static inline void hw_wkup_set_debounce_time(uint8_t time_ms)
{
HW_WKUP_REG_SETF(CTRL, WKUP_DEB_VALUE, time_ms);
}
/**
* \brief Get current debounce time
*
* \return debounce time in miliseconds
*
*/
static inline uint8_t hw_wkup_get_debounce_time(void)
{
return HW_WKUP_REG_GETF(CTRL, WKUP_DEB_VALUE);
}
/**
* \brief Set threshold for event counter
*
* Interrupt is generated after event counter reaches configured value.
*
* \param [in] level number of events
*
* \sa hw_wkup_register_interrupt
* \sa hw_wkup_get_counter
*
*/
static inline void hw_wkup_set_counter_threshold(uint8_t level)
{
HW_WKUP_REG_SETF(COMPARE, COMPARE, level);
}
/**
* \brief Get threshold for event counter
*
* \return number of events
*
*/
static inline uint8_t hw_wkup_get_counter_threshold(void)
{
return HW_WKUP_REG_GETF(COMPARE, COMPARE);
}
/**
* \brief Get current value of event counter
*
* Number of events counted so far. Can be reset using hw_wkup_reset_counter().
*
* \return number of events
*
* \note The counter is automatically reset by the hardware when the interrupt is generated.
*
* \sa hw_wkup_reset_counter
*
*/
static inline uint8_t hw_wkup_get_counter(void)
{
return HW_WKUP_REG_GETF(COUNTER, EVENT_VALUE);
}
/**
* \brief Reset event counter
*
* There is no need to reset counter manually in interrupt callback - it's reset automatically by
* hardware.
*
*/
static inline void hw_wkup_reset_counter(void)
{
WAKEUP->WKUP_RESET_CNTR_REG = 1;
}
/**
* \brief Set GPIO pin event counting state
*
* Once enabled, state changes on pin will increment event counter. State which triggers event can
* be set using hw_wkup_set_pin_trigger().
*
* \param [in] port port number
* \param [in] pin pin number
* \param [in] enabled pin event counting state
*
* \sa hw_wkup_set_pin_trigger
* \sa hw_wkup_configure_pin
* \sa hw_wkup_configure_port
*
*/
static inline void hw_wkup_set_pin_state(HW_GPIO_PORT port, HW_GPIO_PIN pin, bool enabled)
{
uint16_t sel_rx_reg = *((volatile uint16_t *)WAKEUP_BASE + 5 + port);
sel_rx_reg &= ~(1 << pin);
sel_rx_reg |= (!!enabled) << pin;
*((volatile uint16_t *)WAKEUP_BASE + 5 + port) = sel_rx_reg;
}
/** \brief Get GPIO pin event counting state
*
* \param [in] port port number
* \param [in] pin pin number
*
* \return pin event counting state
*
* \sa hw_wkup_set_pin_state
*
*/
static inline bool hw_wkup_get_pin_state(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
uint16_t sel_rx_reg = *((volatile uint16_t *)WAKEUP_BASE + 5 + port);
return (sel_rx_reg & (1 << pin)) >> pin;
}
/**
* \brief Set GPIO pin state which triggers event
*
* Pin event counting should be enabled for this setting to have any effect.
*
* \param [in] port port number
* \param [in] pin pin number
* \param [in] state pin state
*
* \sa hw_wkup_set_pin_counter_state
* \sa hw_wkup_configure_pin
* \sa hw_wkup_configure_port
*
*/
static inline void hw_wkup_set_pin_trigger(HW_GPIO_PORT port, HW_GPIO_PIN pin,
HW_WKUP_PIN_STATE state)
{
uint16_t pol_rx_reg = *((volatile uint16_t *)WAKEUP_BASE + 10 + port);
pol_rx_reg &= ~(1 << pin);
pol_rx_reg |= (!!state) << pin;
*((volatile uint16_t *)WAKEUP_BASE + 10 + port) = pol_rx_reg;
}
/** \brief Get GPIO pin state which triggers event
*
* \param [in] port port number
* \param [in] pin pin number
*
* \return pin state
*
* \sa hw_wkup_set_pin_trigger
*
*/
static inline HW_WKUP_PIN_STATE hw_wkup_get_pin_trigger(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
uint16_t pol_rx_reg = *((volatile uint16_t *)WAKEUP_BASE + 10 + port);
return (pol_rx_reg & (1 << pin)) >> pin;
}
/**
* \brief Set GPIO pin event counting and triggered state
*
* Effectively, this is shortcut for calling hw_wkup_set_pin_state() and hw_wkup_set_pin_trigger().
*
* \param [in] port port number
* \param [in] pin pin number
* \param [in] enabled pin event counting state
* \param [in] state pin state
*
* \sa hw_wkup_set_pin_counter_state
* \sa hw_wkup_set_pin_trigger
* \sa hw_wkup_configure_port
*
*/
static inline void hw_wkup_configure_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin, bool enabled,
HW_WKUP_PIN_STATE state)
{
// first set up the proper polarity...
hw_wkup_set_pin_trigger(port, pin, state);
// ...then enable counting on the specific GPIO
hw_wkup_set_pin_state(port, pin, enabled);
}
/**
* \brief Configure event counting and triggering state for whole GPIO port
*
* In \p enabled and \p state bitmasks each bit describes state of corresponding pin in port.
* For \p enabled 0 means disabled and 1 means enabled.
* For \p state 0 means event is triggered on low state and 1 means trigger is on high state.
*
* \param [in] port port number
* \param [in] enabled pin event counting bitmask
* \param [in] state pin state bitmask
*
* \sa hw_wkup_set_pin_counter_state
* \sa hw_wkup_set_pin_trigger
* \sa hw_wkup_configure_pin
*
*/
static inline void hw_wkup_configure_port(HW_GPIO_PORT port, uint8_t enabled, uint8_t state)
{
*((volatile uint16_t *)WAKEUP_BASE + 10 + port) = ~state; // register has inverted logic than state bitmask
*((volatile uint16_t *)WAKEUP_BASE + 5 + port) = enabled;
}
/**
* \brief Get event counting state of all pins in GPIO port
*
* Meaning of bits in returned bitmask is the same as in hw_wkup_configure_port().
*
* \return port pin event counter state bitmask
*
* \sa hw_wkup_configure_port
*
*/
static inline uint8_t hw_wkup_get_port_state(HW_GPIO_PORT port)
{
return *((volatile uint16_t *)WAKEUP_BASE + 5 + port);
}
/**
* \brief Get event triggering state for all pins in GPIO port
*
* Meaning of bits in returned bitmask is the same as in hw_wkup_configure_port().
*
* \return port pin event triggering state bitmask
*
* \sa hw_wkup_configure_port
*
*/
static inline uint8_t hw_wkup_get_port_trigger(HW_GPIO_PORT port)
{
return ~(*((volatile uint16_t *)WAKEUP_BASE + 10 + port)); // register has inverted logic that returned bitmask
}
/**
* \brief Emulate key hit
*
* Event counter will be increased with debounce time taken into account (if enabled).
*
*/
static inline void hw_wkup_emulate_key_hit(void)
{
HW_WKUP_REG_SETF(CTRL, WKUP_SFT_KEYHIT, 1);
HW_WKUP_REG_SETF(CTRL, WKUP_SFT_KEYHIT, 0);
}
/**
* \brief Freeze wakeup timer
*
*/
static inline void hw_wkup_freeze(void)
{
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_WKUPTIM_Msk;
}
/**
* \brief Unfreeze wakeup timer
*
*/
static inline void hw_wkup_unfreeze(void)
{
GPREG->RESET_FREEZE_REG = GPREG_RESET_FREEZE_REG_FRZ_WKUPTIM_Msk;
}
#endif /* dg_configUSE_HW_USB_WKUP */
#endif /* HW_WKUP_H_ */
/**
* \}
* \}
* \}
*/
+110
View File
@@ -0,0 +1,110 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup TCS_HANDLER
*
* \brief TCS Handler
*
* \{
*/
/**
****************************************************************************************
*
* @file sys_tcs.h
*
* @brief TCS Handler header file.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 SYS_TCS_H_
#define SYS_TCS_H_
#include <stdint.h>
#include "black_orca.h"
typedef enum sys_tcs_area_type {
#ifdef CONFIG_USE_BLE
tcs_ble,
#endif
#ifdef CONFIG_USE_FTDF
tcs_ftdf,
#endif
tcs_radio,
tcs_charger,
tcs_audio,
tcs_system, /* Last area. Add any missing areas above this! */
} sys_tcs_area_t;
extern bool is_calibrated_chip;
/**
* \brief Initialize the variables used from the TCS handling module.
*
*/
void sys_tcs_init(void);
/**
* \brief Store TCS <address, value> pair in the Global TCS array if it points to a register
* that is not in the AON power dowmain or is not retained, else it applies the vaule to
* the register.
*
* \param [in] address the address of the register
* \param [in] value the value for this register
*
* \return true if the chip is calibrated (the BANDGAP setting has been applied), else false.
*
* \warning When this function is called, the RC16 must have been set as the system clock!
*
*/
bool sys_tcs_store_pair(uint32_t address, uint32_t value);
/**
* \brief Sort the registers of the registers in the Memory Map of the chip to a different "classes"
* in the TCS array.
*
*/
void sys_tcs_sort_array(void);
/**
* \brief Apply the <address, value> pairs located in a "class" of the TCS array. This is done only
* for calibrated chips!
*
*/
void sys_tcs_apply(sys_tcs_area_t area);
#endif /* SYS_TCS_H_ */
/**
\}
\}
\}
*/
@@ -0,0 +1,743 @@
/**
\addtogroup BSP
\{
\addtogroup DEVICES
\{
\addtogroup CPM
\{
*/
/**
****************************************************************************************
*
* @file hw_cpm.c
*
* @brief Clock and Power Manager Driver
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_CPM
#include <stdint.h>
#include "hw_cpm.h"
#include "hw_watchdog.h"
/*
* These variables should be defined and initialized by the framework/sdk used
*/
extern sys_clk_t cm_sysclk;
extern ahb_div_t cm_ahbclk;
\
/*
* Local variables
*/
/*
* Forward declarations
*/
/*
* Function definitions
*/
uint32_t hw_cpm_sysclk_is_rc16(void)
{
uint32_t ret = 0;
if (REG_GETF(CRG_TOP, CLK_CTRL_REG, SYS_CLK_SEL) == SYS_CLK_IS_RC16)
{
ret = 1;
}
return ret;
}
uint32_t hw_cpm_sysclk_is_xtal16m(void)
{
uint32_t ret = 0;
if (REG_GETF(CRG_TOP, CLK_CTRL_REG, SYS_CLK_SEL) == SYS_CLK_IS_XTAL16M)
{
ret = 1;
}
return ret;
}
void hw_cpm_set_divn(bool freq)
{
uint32_t regval;
int val;
if (freq)
{
val = 1;
}
else
{
val = 0;
}
regval = CRG_TOP->CLK_CTRL_REG;
REG_SET_FIELD(CRG_TOP, CLK_CTRL_REG, DIVN_XTAL32M_MODE, regval, val);
REG_SET_FIELD(CRG_TOP, CLK_CTRL_REG, XTAL32M_MODE, regval, val);
CRG_TOP->CLK_CTRL_REG = regval;
CRG_TOP->DIVN_SYNC_REG = val;
}
bool hw_cpm_is_rc16_allowed(void)
{
bool ret = false;
uint32_t tmp;
do
{
tmp = CRG_TOP->SYS_STAT_REG;
#ifdef CONFIG_USE_FTDF
// Check FTDF
if (tmp & REG_MSK(CRG_TOP, SYS_STAT_REG, FTDF_IS_UP))
{
break;
}
#endif
#ifdef CONFIG_USE_BLE
// Check BLE
if (tmp & REG_MSK(CRG_TOP, SYS_STAT_REG, BLE_IS_UP))
{
break;
}
#endif
// Check APHY/DPHY & COEX
if (tmp & REG_MSK(CRG_TOP, SYS_STAT_REG, RAD_IS_UP))
{
break;
}
if (tmp & REG_MSK(CRG_TOP, SYS_STAT_REG, PER_IS_UP))
{
// Check SRC
if (REG_GETF(APU, SRC1_CTRL_REG, SRC_EN) == 1)
{
break;
}
// Check PDM
if (REG_GETF(CRG_PER, PDM_DIV_REG, CLK_PDM_EN) == 1)
{
break;
}
// Check USB
if (REG_GETF(USB, USB_MCTRL_REG, USBEN) == 1)
{
break;
}
tmp = CRG_PER->CLK_PER_REG;
// Check UART1/2
if (tmp & REG_MSK(CRG_PER, CLK_PER_REG, UART_ENABLE))
{
break;
}
/* -------------------------------------------------------------------------------*/
// Check ADC clock
if (REG_GETF(GPADC, GP_ADC_CTRL_REG, GP_ADC_EN) &&
(!(tmp & REG_MSK(CRG_PER, CLK_PER_REG, ADC_CLK_SEL))))
{
break;
}
// Check I2C clock
if ((tmp & REG_MSK(CRG_PER, CLK_PER_REG, I2C_ENABLE)) &&
(!(tmp & REG_MSK(CRG_PER, CLK_PER_REG, I2C_CLK_SEL))))
{
break;
}
// Check SPI clock
if ((tmp & REG_MSK(CRG_PER, CLK_PER_REG, SPI_ENABLE)) &&
(!(tmp & REG_MSK(CRG_PER, CLK_PER_REG, SPI_CLK_SEL))))
{
break;
}
// Check PCM clock
tmp = CRG_PER->PCM_DIV_REG;
if ((tmp & REG_MSK(CRG_PER, PCM_DIV_REG, CLK_PCM_EN)) &&
(!(tmp & REG_MSK(CRG_PER, PCM_DIV_REG, PCM_SRC_SEL))))
{
break;
}
/* KBSCN and QUAD are not seriously affected by the clock switch and, thus,
* they cannot block it!
*/
}
tmp = CRG_TOP->CLK_TMR_REG;
// Check Timer0 clock
if ((tmp & REG_MSK(CRG_TOP, CLK_TMR_REG, TMR0_ENABLE)) &&
(!(tmp & REG_MSK(CRG_TOP, CLK_TMR_REG, TMR0_CLK_SEL))))
{
break;
}
// Check Timer2 clock
if ((tmp & REG_MSK(CRG_TOP, CLK_TMR_REG, TMR2_ENABLE)) &&
(!(tmp & REG_MSK(CRG_TOP, CLK_TMR_REG, TMR2_CLK_SEL))))
{
break;
}
/* Breathe, SOC and WDOG are not seriously affected by the clock switch and, thus,
* they cannot block it!
*/
ret = true;
}
while (0);
return ret;
}
void hw_cpm_set_sysclk(uint32_t mode)
{
/* Make sure a valid sys clock is requested */
ASSERT_WARNING(mode <= SYS_CLK_IS_PLL);
REG_SETF(CRG_TOP, CLK_CTRL_REG, SYS_CLK_SEL, mode);
// Wait until the switch is done!
switch (mode)
{
case SYS_CLK_IS_XTAL16M:
while (REG_GETF(CRG_TOP, CLK_CTRL_REG, RUNNING_AT_XTAL16M) == 0) {}
break;
case SYS_CLK_IS_RC16:
while (REG_GETF(CRG_TOP, CLK_CTRL_REG, RUNNING_AT_RC16M) == 0) {}
break;
case SYS_CLK_IS_LP:
while (REG_GETF(CRG_TOP, CLK_CTRL_REG, RUNNING_AT_32K) == 0) {}
break;
case SYS_CLK_IS_PLL:
while (REG_GETF(CRG_TOP, CLK_CTRL_REG, RUNNING_AT_PLL96M) == 0) {}
break;
default:
ASSERT_WARNING(0);
break;
}
}
void hw_cpm_short_delay(void)
{
volatile int i;
for (i = 0; i < 20; i++);
}
void hw_cpm_pll_sys_on(void)
{
/* Before enabling the PLL LDO, the 1.4V voltage needs to be present; in real-life this
* is achieved by first turning on the 1.4V ACORE LDO, then the DCDC converter to take over
* the generation of 1.4V and finally turning off the ACORE LDO.
*/
/* LDO PLL enable. */
REG_SET_BIT(GPREG, PLL_SYS_CTRL1_REG, LDO_PLL_ENABLE);
/* Configure system PLL. */
REG_SETF(GPREG, PLL_SYS_CTRL1_REG, PLL_R_DIV, 1); /* Default/reset value. */
/* Program N-divider and DEL_SEL. */
REG_SET_BIT(GPREG, PLL_SYS_CTRL2_REG, PLL_SEL_MIN_CUR_INT); // Last review date: Feb 15, 2016 - 12:25:47
/* Now turn on PLL. */
REG_SET_BIT(GPREG, PLL_SYS_CTRL1_REG, PLL_EN);
while ((GPREG->PLL_SYS_STATUS_REG & REG_MSK(GPREG, PLL_SYS_STATUS_REG, LDO_PLL_OK)) == 0) {}
/* And wait until lock. */
while ((GPREG->PLL_SYS_STATUS_REG & REG_MSK(GPREG, PLL_SYS_STATUS_REG, PLL_LOCK_FINE)) == 0) {}
}
void hw_cpm_pll_sys_off(void)
{
// The PLL is not the system clk.
while ((CRG_TOP->CLK_CTRL_REG & REG_MSK(CRG_TOP, CLK_CTRL_REG, RUNNING_AT_PLL96M)) != 0);
GPREG->PLL_SYS_CTRL1_REG = 0x0000; // Switch off the PLL.
}
void hw_cpm_start_calibration(cal_clk_t clk_type, uint32_t cycles)
{
ASSERT_WARNING(REG_GETF(ANAMISC, CLK_REF_SEL_REG, REF_CAL_START) == 0); // Must be disabled
ANAMISC->CLK_REF_CNT_REG = cycles; // # of cal clock cycles
REG_SETF(ANAMISC, CLK_REF_SEL_REG, REF_CLK_SEL, clk_type);
REG_SET_BIT(ANAMISC, CLK_REF_SEL_REG, REF_CAL_START);
}
uint32_t hw_cpm_get_calibration_data(void)
{
uint32_t high;
uint32_t low;
uint32_t value;
while (REG_GETF(ANAMISC, CLK_REF_SEL_REG, REF_CAL_START) == 1); // Wait until it's finished
high = ANAMISC->CLK_REF_VAL_H_REG;
low = ANAMISC->CLK_REF_VAL_L_REG;
value = (high << 16) + low;
return value;
}
void hw_cpm_dcdc_config(void)
{
uint32_t reg;
/*
* Preferred settings section
* Last review date: Feb 15, 2016 - 12:25:47
*/
REG_CLR_BIT(DCDC, DCDC_CTRL_0_REG, DCDC_FW_ENABLE);
reg = DCDC->DCDC_IRQ_MASK_REG;
REG_SET_FIELD(DCDC, DCDC_IRQ_MASK_REG, DCDC_V18P_TIMEOUT_IRQ_MASK, reg, 1);
REG_SET_FIELD(DCDC, DCDC_IRQ_MASK_REG, DCDC_VDD_TIMEOUT_IRQ_MASK, reg, 1);
REG_SET_FIELD(DCDC, DCDC_IRQ_MASK_REG, DCDC_V18_TIMEOUT_IRQ_MASK, reg, 1);
REG_SET_FIELD(DCDC, DCDC_IRQ_MASK_REG, DCDC_V14_TIMEOUT_IRQ_MASK, reg, 1);
DCDC->DCDC_IRQ_MASK_REG = reg;
REG_SET_BIT(DCDC, DCDC_TRIM_REG, DCDC_P_COMP_MAN_TRIM);
DCDC->DCDC_V14_0_REG &= ~(REG_MSK(DCDC, DCDC_V14_0_REG, DCDC_V14_CUR_LIM_MIN) |
REG_MSK(DCDC, DCDC_V14_0_REG, DCDC_V14_FAST_RAMPING));
DCDC->DCDC_V18_0_REG &= ~(REG_MSK(DCDC, DCDC_V18_0_REG, DCDC_V18_CUR_LIM_MIN) |
REG_MSK(DCDC, DCDC_V18_0_REG, DCDC_V18_FAST_RAMPING));
DCDC->DCDC_V18P_0_REG &= ~(REG_MSK(DCDC, DCDC_V18P_0_REG, DCDC_V18P_CUR_LIM_MIN) |
REG_MSK(DCDC, DCDC_V18P_0_REG, DCDC_V18P_FAST_RAMPING));
DCDC->DCDC_VDD_0_REG &= ~(REG_MSK(DCDC, DCDC_VDD_0_REG, DCDC_VDD_CUR_LIM_MIN) |
REG_MSK(DCDC, DCDC_VDD_0_REG, DCDC_VDD_FAST_RAMPING));
REG_SETF(DCDC, DCDC_VDD_1_REG, DCDC_VDD_CUR_LIM_MAX_LV, 0xD);
// End of preferred settings
DCDC->DCDC_VDD_1_REG |= ((1 << REG_POS(DCDC, DCDC_VDD_1_REG, DCDC_VDD_ENABLE_HV)) |
(1 << REG_POS(DCDC, DCDC_VDD_1_REG, DCDC_VDD_ENABLE_LV)));
REG_SETF(DCDC, DCDC_V14_0_REG, DCDC_V14_VOLTAGE, 0x7);
if (dg_configPOWER_FLASH == 1)
{
REG_SETF(DCDC, DCDC_V18_0_REG, DCDC_V18_VOLTAGE, 0x16);
}
if (dg_configPOWER_EXT_1V8_PERIPHERALS == 1)
{
REG_SETF(DCDC, DCDC_V18P_0_REG, DCDC_V18P_VOLTAGE, 0x16);
}
if (dg_configPOWER_FLASH == 1)
{
DCDC->DCDC_V18_1_REG |= (1 << REG_POS(DCDC, DCDC_V18_1_REG, DCDC_V18_ENABLE_HV));
DCDC->DCDC_V18_1_REG &= ~REG_MSK(DCDC, DCDC_V18_1_REG, DCDC_V18_ENABLE_LV);
}
else
{
DCDC->DCDC_V18_1_REG &= ~(REG_MSK(DCDC, DCDC_V18_1_REG, DCDC_V18_ENABLE_HV) |
REG_MSK(DCDC, DCDC_V18_1_REG, DCDC_V18_ENABLE_LV));
}
if (dg_configPOWER_EXT_1V8_PERIPHERALS == 1)
{
DCDC->DCDC_V18P_1_REG |= (1 << REG_POS(DCDC, DCDC_V18P_1_REG, DCDC_V18P_ENABLE_HV));
DCDC->DCDC_V18P_1_REG &= ~REG_MSK(DCDC, DCDC_V18P_1_REG, DCDC_V18P_ENABLE_LV);
}
else
{
DCDC->DCDC_V18P_1_REG &= ~(REG_MSK(DCDC, DCDC_V18P_1_REG, DCDC_V18P_ENABLE_HV) |
REG_MSK(DCDC, DCDC_V18P_1_REG, DCDC_V18P_ENABLE_LV));
}
}
void hw_cpm_dcdc_on(void)
{
DCDC->DCDC_V14_1_REG |= ((1 << REG_POS(DCDC, DCDC_V14_1_REG, DCDC_V14_ENABLE_HV)) |
(1 << REG_POS(DCDC, DCDC_V14_1_REG, DCDC_V14_ENABLE_LV)));
REG_SETF(DCDC, DCDC_VDD_0_REG, DCDC_VDD_VOLTAGE, 0x10); // 1.2 V
REG_SETF(DCDC, DCDC_CTRL_0_REG, DCDC_MODE, 1);
// Trim the LDOs down to lowest possible voltage so DCDC can take over
CRG_TOP->LDO_CTRL1_REG &= ~REG_MSK(CRG_TOP, LDO_CTRL1_REG, LDO_RADIO_SETVDD);
REG_SETF(CRG_TOP, LDO_CTRL1_REG, LDO_CORE_SETVDD, 0x2);
// Turn off LDOs
CRG_TOP->LDO_CTRL1_REG &= ~REG_MSK(CRG_TOP, LDO_CTRL1_REG, LDO_RADIO_ENABLE);
CRG_TOP->LDO_CTRL2_REG &= ~(REG_MSK(CRG_TOP, LDO_CTRL2_REG, LDO_1V2_ON) |
REG_MSK(CRG_TOP, LDO_CTRL2_REG, LDO_1V8_FLASH_ON) |
REG_MSK(CRG_TOP, LDO_CTRL2_REG, LDO_1V8_PA_ON));
// Trim the LDOs back to normal levels
hw_cpm_reset_radio_vdd();
CRG_TOP->LDO_CTRL1_REG &= ~REG_MSK(CRG_TOP, LDO_CTRL1_REG, LDO_CORE_SETVDD);
}
void hw_cpm_set_preferred_values(void)
{
uint32_t reg;
reg = CRG_TOP->CLK_16M_REG;
REG_SET_FIELD(CRG_TOP, CLK_16M_REG, XTAL16_HPASS_FLT_EN, reg, 1); // Last review date: Feb 15, 2016 - 12:25:47
REG_SET_FIELD(CRG_TOP, CLK_16M_REG, XTAL16_AMP_TRIM, reg, 5);
REG_SET_FIELD(CRG_TOP, CLK_16M_REG, XTAL16_CUR_SET, reg, 5);
CRG_TOP->CLK_16M_REG = reg;
REG_SETF(CRG_TOP, BANDGAP_REG, LDO_SLEEP_TRIM, 0x8);
if (BLACK_ORCA_TARGET_IC >= BLACK_ORCA_IC_VERSION(A, C))
{
REG_SETF(CRG_TOP, BANDGAP_REG, BYPASS_COLD_BOOT_DISABLE, 1); // Last review date: Feb 15, 2016 - 12:25:47
}
}
void hw_cpm_configure_xtal32k_pins(void)
{
GPIO->P20_MODE_REG = 0x26;
GPIO->P21_MODE_REG = 0x26;
}
void hw_cpm_trigger_sw_cursor(void)
{
volatile int i;
if (dg_configUSE_SW_CURSOR == 1)
{
if (dg_configBLACK_ORCA_MB_REV == BLACK_ORCA_MB_REV_B)
{
SW_CURSOR_SET = 1 << SW_CURSOR_PIN;
}
else
{
SW_CURSOR_RESET = 1 << SW_CURSOR_PIN;
}
SW_CURSOR_GPIO = 0x300;
for (i = 0; i < 100; i++)
{
}
if (dg_configBLACK_ORCA_MB_REV == BLACK_ORCA_MB_REV_B)
{
SW_CURSOR_RESET = 1 << SW_CURSOR_PIN;
}
hw_cpm_setup_sw_cursor();
}
}
void hw_cpm_reset_system(void)
{
__asm volatile(" cpsid i ");
hw_watchdog_unregister_int();
hw_watchdog_set_pos_val(1);
hw_watchdog_unfreeze();
while (1);
}
void hw_cpm_reboot_system(void)
{
__asm volatile(" cpsid i ");
hw_watchdog_gen_RST();
hw_watchdog_set_pos_val(1);
hw_watchdog_unfreeze();
while (1);
}
void hw_cpm_assert_trigger_gpio(void)
{
if (EXCEPTION_DEBUG == 1)
{
if (dg_configUSE_LP_CLK != LP_CLK_RCX)
{
hw_cpm_configure_xtal32k_pins();
}
hw_cpm_power_up_per_pd();
hw_cpm_deactivate_pad_latches();
DBG_SET_HIGH(EXCEPTION_DEBUG, EXCEPTIONDBG);
}
}
#define HW_CPM_ACTIVATE_BOD_PROTECTION \
do { \
uint16_t val = 0; \
\
REG_SET_FIELD(CRG_TOP, BOD_CTRL_REG, BOD_VDD_LVL, val, 1); /* VDD Level (700mV) */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL_REG, BOD_V33_TRIM, val, 2); /* V33 trim */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL_REG, BOD_1V8_PA_TRIM, val, 2); /* 1V8P trim */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL_REG, BOD_1V8_FLASH_TRIM, val, 2); /* 1V8 trim */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL_REG, BOD_VDD_TRIM, val, 2); /* VDD trim */ \
CRG_TOP->BOD_CTRL_REG = val; \
\
val = 0; \
/* 1V8 Flash enable */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL2_REG, BOD_VBAT_EN, val, 1); \
/* 1V8 Flash enable */ \
if ((dg_configPOWER_FLASH == 1) && (dg_configFLASH_POWER_OFF == 0)) { \
REG_SET_FIELD(CRG_TOP, BOD_CTRL2_REG, BOD_1V8_FLASH_EN, val, 1); \
} \
/* 1V8P enable */ \
if (dg_configPOWER_EXT_1V8_PERIPHERALS == 1) { \
REG_SET_FIELD(CRG_TOP, BOD_CTRL2_REG, BOD_1V8_PA_EN, val, 1); \
} \
REG_SET_FIELD(CRG_TOP, BOD_CTRL2_REG, BOD_VDD_EN, val, 1); /* VDD enable */ \
REG_SET_FIELD(CRG_TOP, BOD_CTRL2_REG, BOD_RESET_EN, val, 1); /* Reset enable */ \
CRG_TOP->BOD_CTRL2_REG = val; \
} while (0);
void hw_cpm_activate_bod_protection(void)
{
HW_CPM_ACTIVATE_BOD_PROTECTION
}
void hw_cpm_activate_bod_protection_at_init(void)
{
HW_CPM_ACTIVATE_BOD_PROTECTION
}
void hw_cpm_delay_usec(uint32_t usec)
{
sys_clk_t sclk;
ahb_div_t hclk;
uint8_t freq;
sclk = cm_sysclk;
hclk = cm_ahbclk;
freq = 16 >> hclk;
/* Requested delay time must be > 0 usec */
ASSERT_WARNING(usec != 0);
/*
* ldr r3, [pc, #148] 2 cycles
* push {r4, lr} 2 cycles
* ldrb r1, [r3, #17] 2 cycles
* ldrb r2, [r3, #8] 2 cycles
* movs r3, #16 1 cycle
* asrs r3, r2 1 cycle
* uxtb r3, r2 1 cycle
* ----------
* cmp r0, #0 4 cycles overhead in total
* bne.n 0x8003106 <hw_cpm_delay_usec+30>
* cpsid i
* bkpt 0x0002
*
* Total: 11 cycles
*/
__asm volatile(" cmp %[sclk], #1 \n" // 1 cycle : 1 (sysclk_RC16, sysclk_XTAL16M)
" ble start \n" // 1 or 3 cycles: 2/4
" cmp %[sclk], #3 \n" // 1 cycle : 3 (sysclk_PLL48)
" bgt s96M \n" // 1 or 3 cycles: 4/6
" blt s32M \n" // 1 or 3 cycles: 5/7
"s48M: add r4, %[freq], %[freq] \n" // 1 cycle : 6
" add %[freq], r4, %[freq] \n" // 1 cycle : 7
" b start \n" // 3 cycles : 10
"s96M: add r4, %[freq], %[freq] \n" // 1 cycle : 7
" add %[freq], r4, %[freq] \n" // 1 cycle : 8
" lsl %[freq], %[freq], #1 \n" // 1 cycle : 9
" b start \n" // 3 cycles : 12
"s32M: lsl %[freq], %[freq], #1 \n" // 1 cycle : 8
/* -----------------------------------------------------*/
/* Overhead up to this point:
* sysclk_RC16 : 15 cycles (error: 15/16 - 15 usec)
* sysclk_XTAL16M : 15 cycles (error: 15/16 - 15 usec)
* sysclk_XTAL32M : 19 cycles (error: 19/32 - 19/2 usec)
* sysclk_PLL48 : 21 cycles (error: 21/48 - 21/3 usec)
* sysclk_PLL96 : 23 cycles (error: 23/96 - 23/6 usec)
*/
"start: cmp %[freq], #16 \n" // 1 cycle : 1
" bgt high \n" // 1 or 3 cycles: 2/4
" blt low \n" // 1 or 3 cycles: 3/5
" mov %[sclk], #4 \n" // 1 cycle : 4
" b calc \n" // 3 cycles : 7
"high: cmp %[freq], #24 \n" // 1 cycle : 5
" bne c32M \n" // 1 or 3 cycles: 6/8
" mov %[sclk], #6 \n" // 1 cycle : 7
" b calc \n" // 3 cycles : 10
"c32M: cmp %[freq], #32 \n" // 1 cycle : 9
" bne c48M \n" // 1 or 3 cycles: 10/12
" mov %[sclk], #8 \n" // 1 cycle : 11
" b calc \n" // 3 cycles : 12
"c48M: cmp %[freq], #48 \n" // 1 cycle : 13
" bne c96M \n" // 1 or 3 cycles: 14/16
" mov %[sclk], #12 \n" // 1 cycle : 15
" b calc \n" // 3 cycles : 18
"c96M: mov %[sclk], #24 \n" // 1 cycle : 17
" b calc \n" // 3 cycles : 20
"low: cmp %[freq], #1 \n" // 1 cycle : 6
" bgt c2M \n" // 1 or 3 cycles: 7/9
" lsr %[usec], %[usec], #2 \n" // 1 cycle : 8
" b loop \n" // 3 cycles : 11
"c2M: cmp %[freq], #2 \n" // 1 cycle : 10
" bgt c3M \n" // 1 or 3 cycles: 11/13
" lsr %[usec], %[usec], #1 \n" // 1 cycle : 12
" b loop \n" // 3 cycles : 15
"c3M: cmp %[freq], #3 \n" // 1 cycle : 14
" bgt c4M \n" // 1 or 3 cycles: 15/17
" lsr %[usec], %[usec], #1 \n" // 1 cycle : 16
" b loop1 \n" // 3 cycles : 19
"c4M: cmp %[freq], #4 \n" // 1 cycle : 18
" bgt c6M \n" // 1 or 3 cycles: 19/21
" b loop \n" // 3 cycles : 22
"c6M: cmp %[freq],#6 \n" // 1 cycle : 22
" bgt c8M \n" // 1 or 3 cycles: 23/25
" b loop1 \n" // 3 cycles : 26
"c8M: cmp %[freq], #8 \n" // 1 cycle : 26
" bgt c12M \n" // 1 or 3 cycles: 27/29
" mov %[sclk], #2 \n" // 1 cycle : 28
" b calc \n" // 3 cycles : 31
"c12M: mov %[sclk], #2 \n" // 1 cycle : 30
" mul %[usec], %[sclk], %[usec] \n" // 1 cycle : 31
/* Error:
* 1MHz: 11 cycles, 11usec
* 2MHz: 15 cycles, 7.5usec
* 3MHz: 19 cycles, 6.33usec
* 4MHz: 22 cycles, 5.5usec
* 6MHz: 26 cycles, 4.33usec
* 8MHz: 31 cycles, 3.875usec
* 12MHz: 31 cycles, 2.584usec
* 16MHz: 8 cycles, 0.5usec
* 24MHz: 11 cycles, 0.459usec
* 32MHz: 13 cycles, 0.406usec
* 48MHz: 19 cycles, 0.396usec
* 96MHz: 21 cycles, 0.219usec
*
* 1 loop of 4 cycles is --- 1 usec is # loops
* 1MHz: 4usec --- divide (usec) by 4 (up to 5usec error)
* 2MHz: 2usec --- divide (usec) by 2 (up to 2usec error)
* 4MHz: 1usec --- 1 loop ( 0*4 + 1*2, 0.5000usec error)
* 8MHz: 500nsec --- 2 loops ( 1*4 + 1*2, 0.2500usec error)
* 16MHz: 250nsec --- 4 loops ( 3*4 + 1*2, 0.5000usec error)
* 24MHz: 167nsec --- 6 loops ( 5*4 + 1*2, 0.0830usec error)
* 32MHz: 125nsec --- 8 loops ( 7*4 + 1*2, 0.0625usec error)
* 48MHz: 84nsec --- 12 loops (11*4 + 1*2, 0.0420usec error)
* 96MHz: 42nsec --- 24 loops (23*4 + 1*2, 0.0210usec error)
*
* 1 loop of 6 cycles is --- 1 usec is # loops
* 3MHz: 2usec --- divide (usec) by 2 (up to 3usec error)
* 6MHz: 1usec --- 1 loop ( 0*6 + 1*7, 0.1670usec error)
* 12MHz: 0.5usec --- 2 loops ( 1*6 + 1*7, 0.0830usec error)
*
* Cumulative error is:
* 1MHz: 11 + 5 = 16usec
* 2MHz: 7.5 + 2 = 9.5usec
* 3MHz: 6.33 + 3 = 9.33usec
* 4MHz: 5.5 + 0.5 = 6usec
* 6MHz: 4.33 + 0.167 = 4.5usec
* 8MHz: 3.875 + 0.25 = 4.125usec
* 12MHz: 2.584 + 0.083 = 2.67usec
* 16MHz: 0.5 + 0.5 = 1usec
* 24MHz: 0.459 + 0.083 = 0.541usec
* 32MHz: 0.406 + 0.0625 = 0.469usec
* 48MHz: 0.396 + 0.042 = 0.438usec
* 96MHz: 0.219 + 0.021 = 0.429usec
*/
"loop1: sub %[usec], %[usec], #1 \n" // 1 cycle
" nop \n" // 1 cycle
" nop \n" // 1 cycle
" bne loop1 \n" // 3 cycles except for the last one which is 1
" b exit \n" // 3 cycles
"calc: mul %[usec], %[sclk], %[usec] \n" // 1 cycle
"loop: sub %[usec], %[usec], #1 \n" // 1 cycle
" bne loop \n" // 3 cycles except for the last one which is 1
"exit: \n"
:
: /* output */
[usec] "r"(usec), [freq] "r"(freq), [sclk] "r"(sclk) : /* inputs (%0, %1, %2) */
"r4"); /* registers that are destroyed */
}
#endif /* dg_configUSE_HW_CPM */
/**
\}
\}
\}
*/
@@ -0,0 +1,337 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup DMA
* \{
*/
/**
****************************************************************************************
*
* @file hw_dma.c
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
*
****************************************************************************************
*/
#if dg_configUSE_HW_DMA
#include <global_io.h>
#include <core_cm0.h>
#include <hw_gpio.h>
#include <hw_dma.h>
#if (dg_configSYSTEMVIEW)
# include "SEGGER_SYSVIEW_FreeRTOS.h"
#else
# define SEGGER_SYSTEMVIEW_ISR_ENTER()
# define SEGGER_SYSTEMVIEW_ISR_EXIT()
#endif
static struct hw_dma_callback_data
{
hw_dma_transfer_cb callback;
void *user_data;
} dma_callbacks_user_data[8];
#define DMA_CHN_REG(reg, chan) ((uint16 *) (((int) &(reg)) + ((chan) << 4)))
/**
* \brief Initialize DMA Channel
*
* \param [in] channel_setup pointer to struct of type DMA_Setup
*
*/
void hw_dma_channel_initialization(DMA_setup *channel_setup)
{
volatile uint16 *dma_x_ctrl_reg;
volatile uint16 *dma_x_a_start_low_reg;
volatile uint16 *dma_x_a_start_high_reg;
volatile uint16 *dma_x_b_start_low_reg;
volatile uint16 *dma_x_b_start_high_reg;
volatile uint16 *dma_x_len_reg;
volatile uint16 *dma_x_int_reg;
uint32 src_address;
uint32 dest_address;
/* Make sure the DMA channel length is not zero */
ASSERT_WARNING(channel_setup->length > 0);
// Look up DMAx_CTRL_REG address
dma_x_ctrl_reg = DMA_CHN_REG(DMA->DMA0_CTRL_REG, channel_setup->channel_number);
// Look up DMAx_A_STARTL_REG address
dma_x_a_start_low_reg = DMA_CHN_REG(DMA->DMA0_A_STARTL_REG, channel_setup->channel_number);
// Look up DMAx_A_STARTH_REG address
dma_x_a_start_high_reg = DMA_CHN_REG(DMA->DMA0_A_STARTH_REG, channel_setup->channel_number);
// Look up DMAx_B_STARTL_REG address
dma_x_b_start_low_reg = DMA_CHN_REG(DMA->DMA0_B_STARTL_REG, channel_setup->channel_number);
// Look up DMAx_B_STARTH_REG address
dma_x_b_start_high_reg = DMA_CHN_REG(DMA->DMA0_B_STARTH_REG, channel_setup->channel_number);
// Look up DMAX_LEN_REG address
dma_x_len_reg = DMA_CHN_REG(DMA->DMA0_LEN_REG, channel_setup->channel_number);
// Look up DMAX_INT
dma_x_int_reg = DMA_CHN_REG(DMA->DMA0_INT_REG, channel_setup->channel_number);
// Make sure DMA channel is disabled first
REG_SET_FIELD(DMA, DMA0_CTRL_REG, DMA_ON, *dma_x_ctrl_reg, HW_DMA_STATE_DISABLED);
// Set DMAx_CTRL_REG width provided settings, but do not start the channel.
// Start the channel with the "dma_channel_enable" function separately.
*dma_x_ctrl_reg =
channel_setup->bus_width |
channel_setup->irq_enable |
channel_setup->dreq_mode |
channel_setup->b_inc |
channel_setup->a_inc |
channel_setup->circular |
channel_setup->dma_prio |
channel_setup->dma_idle |
channel_setup->dma_init;
// Set DMA_REQ_MUX_REG for the requested channel / trigger combination
if (channel_setup->dma_req_mux != HW_DMA_TRIG_NONE)
{
switch (channel_setup->channel_number)
{
case HW_DMA_CHANNEL_0:
case HW_DMA_CHANNEL_1:
REG_SETF(DMA, DMA_REQ_MUX_REG, DMA01_SEL, channel_setup->dma_req_mux);
break;
case HW_DMA_CHANNEL_2:
case HW_DMA_CHANNEL_3:
REG_SETF(DMA, DMA_REQ_MUX_REG, DMA23_SEL, channel_setup->dma_req_mux);
break;
case HW_DMA_CHANNEL_4:
case HW_DMA_CHANNEL_5:
REG_SETF(DMA, DMA_REQ_MUX_REG, DMA45_SEL, channel_setup->dma_req_mux);
break;
case HW_DMA_CHANNEL_6:
case HW_DMA_CHANNEL_7:
REG_SETF(DMA, DMA_REQ_MUX_REG, DMA67_SEL, channel_setup->dma_req_mux);
break;
default:
break;
}
}
src_address = black_orca_phy_addr(channel_setup->src_address);
dest_address = black_orca_phy_addr(channel_setup->dest_address);
// Set source address registers
*dma_x_a_start_low_reg = (src_address & 0xffff);
*dma_x_a_start_high_reg = (src_address >> 16);
// Set destination address registers
*dma_x_b_start_low_reg = (dest_address & 0xffff);
*dma_x_b_start_high_reg = (dest_address >> 16);
// Set IRQ number of transfers
if (channel_setup->irq_nr_of_trans > 0)
{
// If user explicitly set this number use it
*dma_x_int_reg = channel_setup->irq_nr_of_trans - 1;
}
else
{
// If user passed 0, use transfer length to fire interrupt after transfer ends
*dma_x_int_reg = channel_setup->length - 1;
}
// Set the transfer length
*dma_x_len_reg = (channel_setup->length) - 1;
if (channel_setup->irq_enable)
{
dma_callbacks_user_data[channel_setup->channel_number].callback = channel_setup->callback;
}
else
{
dma_callbacks_user_data[channel_setup->channel_number].callback = NULL;
}
dma_callbacks_user_data[channel_setup->channel_number].user_data = channel_setup->user_data;
}
/**
* \brief Enable or disable a DMA channel
*
* \param [in] channel_number DMA channel number to start/stop
* \param [in] dma_on enable/disable DMA channel
*
*/
void hw_dma_channel_enable(HW_DMA_CHANNEL channel_number, HW_DMA_STATE dma_on)
{
volatile uint16 *dma_x_ctrl_reg;
// Look up DMAx_CTRL_REG address
dma_x_ctrl_reg = DMA_CHN_REG(DMA->DMA0_CTRL_REG, channel_number);
if (dma_on == HW_DMA_STATE_ENABLED)
{
uint16_t dma_ctrl = *dma_x_ctrl_reg;
REG_SET_FIELD(DMA, DMA0_CTRL_REG, DMA_ON, dma_ctrl, 1);
if (dma_callbacks_user_data[channel_number].callback)
{
REG_SET_FIELD(DMA, DMA0_CTRL_REG, IRQ_ENABLE, dma_ctrl, 1);
}
// Start the chosen DMA channel
*dma_x_ctrl_reg = dma_ctrl;
NVIC_EnableIRQ(DMA_IRQn);
}
else
{
// Stop the chosen DMA channel
REG_SET_FIELD(DMA, DMA0_CTRL_REG, DMA_ON, *dma_x_ctrl_reg, 0);
REG_SET_FIELD(DMA, DMA0_CTRL_REG, IRQ_ENABLE, *dma_x_ctrl_reg, 0);
}
}
static inline void dma_helper(HW_DMA_CHANNEL channel_number, uint16_t len, bool stop_dma)
{
hw_dma_transfer_cb cb;
NVIC_DisableIRQ(DMA_IRQn);
cb = dma_callbacks_user_data[channel_number].callback;
if (stop_dma)
{
dma_callbacks_user_data[channel_number].callback = NULL;
hw_dma_channel_enable(channel_number, HW_DMA_STATE_DISABLED);
}
if (cb)
{
cb(dma_callbacks_user_data[channel_number].user_data, len);
}
NVIC_EnableIRQ(DMA_IRQn);
}
bool hw_dma_channel_active(void)
{
int dma_on;
dma_on = REG_GETF(DMA, DMA0_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA1_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA2_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA3_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA4_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA5_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA6_CTRL_REG, DMA_ON);
dma_on |= REG_GETF(DMA, DMA7_CTRL_REG, DMA_ON);
return (dma_on == 1);
}
/**
* \brief Capture Timer Interrupt Handler
*
* Calls user interrupt handler
*
*/
void DMA_Handler(void)
{
SEGGER_SYSTEMVIEW_ISR_ENTER();
uint16_t risen;
uint16_t i;
volatile uint16 *dma_x_len_reg;
volatile uint16 *dma_x_int_reg;
volatile uint16 *dma_x_ctrl_reg;
risen = DMA->DMA_INT_STATUS_REG;
for (i = 0; risen != 0 && i < 8; ++i, risen >>= 1)
{
if (risen & 1)
{
bool stop;
/*
* DMAx_INT_REG shows after how many transfers the interrupt
* is generated
*/
dma_x_int_reg = DMA_CHN_REG(DMA->DMA0_INT_REG, i);
/*
* DMAx_LEN_REG shows the length of the DMA transfer
*/
dma_x_len_reg = DMA_CHN_REG(DMA->DMA0_LEN_REG, i);
dma_x_ctrl_reg = DMA_CHN_REG(DMA->DMA0_CTRL_REG, i);
/*
* Stop DMA if:
* - transfer is completed
* - mode is not circular
*/
stop = (*dma_x_int_reg == *dma_x_len_reg)
&& (!REG_GET_FIELD(DMA, DMA0_CTRL_REG, CIRCULAR, *dma_x_ctrl_reg));
DMA->DMA_CLEAR_INT_REG = 1 << i;
dma_helper(i, *dma_x_int_reg + 1, stop);
}
}
SEGGER_SYSTEMVIEW_ISR_EXIT();
}
void hw_dma_channel_stop(HW_DMA_CHANNEL channel_number)
{
// Stopping DMA will clear DMAx_IDX_REG so read it before
uint16 *dma_x_idx_reg = DMA_CHN_REG(DMA->DMA0_IDX_REG, channel_number);
dma_helper(channel_number, *dma_x_idx_reg, true);
}
uint16_t hw_dma_transfered_bytes(HW_DMA_CHANNEL channel_number)
{
uint16 *dma_x_int_reg = dma_x_int_reg = DMA_CHN_REG(DMA->DMA0_IDX_REG, channel_number);
return *dma_x_int_reg;
}
#endif /* dg_configUSE_HW_DMA */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,395 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup FEM
* \{
*/
/**
*****************************************************************************************
*
* @file
*
* @brief FEM Driver for SKYWORKS SKY66112-11 Radio module
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
*****************************************************************************************
*/
#if dg_configFEM == FEM_SKY66112_11
#include "stdint.h"
#include "black_orca.h"
#include "hw_gpio.h"
#include "hw_fem_sky66112-11.h"
static hw_fem_config fem_config __RETAINED;
#if !defined(dg_configFEM_SKY66112_11_CTX_PORT) || !defined(dg_configFEM_SKY66112_11_CTX_PIN)
#error FEM CTX GPIO must be defined!!
#endif
#if !defined(dg_configFEM_SKY66112_11_CRX_PORT) || !defined(dg_configFEM_SKY66112_11_CRX_PIN)
#error FEM CRX GPIO must be defined!!
#endif
int hw_fem_set_bias(uint16_t voltage)
{
uint16_t value;
if (voltage < 1200 || voltage > 1975)
{
return -1;
}
value = (voltage - 1200) / 27.5;
// /* Value is actually one lower than computed */
// if (value > 0)
// value--;
#ifdef dg_configFEM_SKY66112_11_FEM_BIAS_V18P
REG_SETF(DCDC, DCDC_V18P_0_REG, DCDC_V18P_VOLTAGE, value);
return 0;
#elif defined(dg_configFEM_SKY66112_11_FEM_BIAS_V18)
REG_SETF(DCDC, DCDC_V18_0_REG, DCDC_V18_VOLTAGE, value);
return 0;
#else
return -2;
#endif
}
int hw_fem_set_bias2(uint16_t voltage)
{
uint16_t value;
if (voltage < 1200 || voltage > 1975)
{
return -1;
}
value = (voltage - 1200) / 27.5;
// /* Value is actually one lower than computed */
// if (value > 0)
// value--;
#ifdef dg_configFEM_SKY66112_11_FEM_BIAS2_V18P
REG_SETF(DCDC, DCDC_V18P_0_REG, DCDC_V18P_VOLTAGE, value);
#elif defined(dg_configFEM_SKY66112_11_FEM_BIAS2_V18)
REG_SETF(DCDC, DCDC_V18_0_REG, DCDC_V18_VOLTAGE, value);
#else
return -2;
#endif
return 0;
}
void hw_fem_set_txpower(bool high)
{
#if defined(dg_configFEM_SKY66112_11_CHL_PORT) && defined(dg_configFEM_SKY66112_11_CHL_PIN)
GLOBAL_INT_DISABLE();
fem_config.tx_power = high;
if (fem_config.started)
{
if (high == false)
{
/* TX Power low. Stop DCF, set GPIO to low */
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CHL_PORT,
dg_configFEM_SKY66112_11_CHL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
REG_SET_MASKED(RFCU_POWER, RF_PORT_EN_REG,
RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_RX_Msk |
RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk, 0);
}
else
{
/* TX Power high. Configure GPIO for DCF. Enable DCF on TX. */
hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CHL_PORT,
dg_configFEM_SKY66112_11_CHL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT4_DCF);
REG_SET_MASKED(RFCU_POWER, RF_PORT_EN_REG,
RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_RX_Msk |
RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk,
RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk);
}
}
GLOBAL_INT_RESTORE();
#endif
}
static void set_bypass(void)
{
uint16_t m = 0;
if (fem_config.tx_bypass)
{
m = RFCU_POWER_RF_PORT_EN_REG_RF_PORT3_TX_Msk;
}
if (fem_config.rx_bypass)
{
m |= RFCU_POWER_RF_PORT_EN_REG_RF_PORT3_RX_Msk;
}
REG_SET_MASKED(RFCU_POWER, RF_PORT_EN_REG,
RFCU_POWER_RF_PORT_EN_REG_RF_PORT3_RX_Msk |
RFCU_POWER_RF_PORT_EN_REG_RF_PORT3_TX_Msk, m);
if (m == 0)
{
/* No RX/TX bypass. Drive the interface line to low */
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CPS_PORT,
dg_configFEM_SKY66112_11_CPS_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
}
else
{
/* At least one of TX/RX needs bypass */
hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CPS_PORT,
dg_configFEM_SKY66112_11_CPS_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT3_DCF);
}
}
void hw_fem_set_tx_bypass(bool enable)
{
#if defined(dg_configFEM_SKY66112_11_CPS_PORT) && defined(dg_configFEM_SKY66112_11_CPS_PIN)
GLOBAL_INT_DISABLE();
fem_config.tx_bypass = enable;
if (fem_config.started)
{
set_bypass();
}
GLOBAL_INT_RESTORE();
#endif
}
void hw_fem_set_rx_bypass(bool enable)
{
#if defined(dg_configFEM_SKY66112_11_CPS_PORT) && defined(dg_configFEM_SKY66112_11_CPS_PIN)
GLOBAL_INT_DISABLE();
fem_config.rx_bypass = enable;
if (fem_config.started)
{
set_bypass();
}
GLOBAL_INT_RESTORE();
#endif
}
void hw_fem_set_antenna(bool one)
{
#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
GLOBAL_INT_DISABLE();
fem_config.antsel = one;
if (fem_config.started)
{
/* Antenna selection */
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT,
dg_configFEM_SKY66112_11_ANTSEL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, fem_config.antsel);
}
GLOBAL_INT_RESTORE();
#endif
}
bool hw_fem_get_txpower(void)
{
return fem_config.tx_power;
}
bool hw_fem_get_antenna(void)
{
return fem_config.antsel;
}
bool hw_fem_get_tx_bypass(void)
{
return fem_config.tx_bypass;
}
bool hw_fem_get_rx_bypass(void)
{
return fem_config.rx_bypass;
}
void hw_fem_start(void)
{
GLOBAL_INT_DISABLE();
fem_config.started = true;
uint8_t set_delay;
uint8_t reset_delay;
uint16_t rf_port_en;
/******************************************************
* Setup GPIOs
*/
/* CSD GPIO Config */
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
# if dg_configFEM_SKY66112_11_CSD_USE_DCF == 0
/* Manually set CSD (Enable FEM) */
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, true);
# else
/* Use DCF for CSD */
hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT2_DCF);
# endif
#endif
/* Timer 27 GPIO (DCF Port 0). Used for TX EN */
hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CTX_PORT, dg_configFEM_SKY66112_11_CTX_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT0_DCF);
/* Timer 28 (DCF Port 1). Used for RX EN */
hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CRX_PORT, dg_configFEM_SKY66112_11_CRX_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT1_DCF);
/* Antenna selection */
#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT, dg_configFEM_SKY66112_11_ANTSEL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, fem_config.antsel);
#endif
/******************************************************
* Setup DCFs
*/
/* assign values to the timer registers for CTX/CRX (in usec) */
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_27_REG, SET_OFFSET, dg_configFEM_SKY66112_11_TXSET_DCF);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_27_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_TXRESET_DCF);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_28_REG, SET_OFFSET, dg_configFEM_SKY66112_11_RXSET_DCF);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_28_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_RXRESET_DCF);
rf_port_en = 0x6; /* Start with Port 0: TX, Port 1: RX */
/* Compute set/reset delays to use for CSD, CPS, CHL DCFs: For setting delay,
* smaller of TXSET, RXSET, and for resetting delay, larger of TXSET, RXSET
*/
#if dg_configFEM_SKY66112_11_RXSET_DCF > dg_configFEM_SKY66112_11_TXSET_DCF
set_delay = dg_configFEM_SKY66112_11_TXSET_DCF;
#else
set_delay = dg_configFEM_SKY66112_11_RXSET_DCF;
#endif
#if dg_configFEM_SKY66112_11_RXRESET_DCF > dg_configFEM_SKY66112_11_TXRESET_DCF
reset_delay = dg_configFEM_SKY66112_11_RXRESET_DCF;
#else
reset_delay = dg_configFEM_SKY66112_11_TXRESET_DCF;
#endif
/* CSD DCF (if enabled) configuration */
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
# if dg_configFEM_SKY66112_11_CSD_USE_DCF != 0
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_29_REG, SET_OFFSET, set_delay);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_29_REG, RESET_OFFSET, reset_delay);
/* enable DCF Signals for Port 2 (CSD) for both rx/tx */
rf_port_en |= 0x30;
# endif /* dg_configFEM_SKY66112_11_CSD_USE_DCF != 0 */
#endif
/* Set bypass (CPS) DCF timers (but don't enable yet) */
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_30_REG, SET_OFFSET, set_delay);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_30_REG, RESET_OFFSET, reset_delay);
/* Set TX Power (CHL) DCF timers (but don't enable yet) */
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_31_REG, SET_OFFSET, dg_configFEM_SKY66112_11_TXSET_DCF);
REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_31_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_TXRESET_DCF);
/* Enable DCFs */
RFCU_POWER->RF_PORT_EN_REG = rf_port_en;
hw_fem_set_txpower(fem_config.tx_power);
set_bypass();
GLOBAL_INT_RESTORE();
}
void hw_fem_stop(void)
{
GLOBAL_INT_DISABLE();
fem_config.started = false;
/* Stop DCF Timers */
RFCU_POWER->RF_PORT_EN_REG = 0x0;
/* Set all FEM interface outputs to GPIO mode, and value 0, in order to get the minimum
* possible power consumption from FEM
*/
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CTX_PORT, dg_configFEM_SKY66112_11_CTX_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#if defined(dg_configFEM_SKY66112_11_CHL_PORT) && defined(dg_configFEM_SKY66112_11_CHL_PIN)
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CHL_PORT, dg_configFEM_SKY66112_11_CHL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CRX_PORT, dg_configFEM_SKY66112_11_CRX_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#if defined(dg_configFEM_SKY66112_11_CPS_PORT) && defined(dg_configFEM_SKY66112_11_CPS_PIN)
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CPS_PORT, dg_configFEM_SKY66112_11_CPS_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif
#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT, dg_configFEM_SKY66112_11_ANTSEL_PIN,
HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif
GLOBAL_INT_RESTORE();
}
#endif /* dg_configFEM == FEM_SKY66112_11 */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,342 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup GPIO
* \{
*/
/**
****************************************************************************************
*
* @file hw_gpio.c
*
* @brief Implementation of the GPIO Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_GPIO
#include <stdint.h>
#include <hw_gpio.h>
/* Register adresses */
#define PX_DATA_REG_ADDR(_port) ((uint16_t *)(GPIO_BASE + offsetof(GPIO_Type, P0_DATA_REG)) + _port)
#define PX_DATA_REG(_port) *PX_DATA_REG_ADDR(_port)
#define PX_SET_DATA_REG_ADDR(_port) ((uint16_t *)(GPIO_BASE + offsetof(GPIO_Type, P0_SET_DATA_REG)) + _port)
#define PX_SET_DATA_REG(_port) *PX_SET_DATA_REG_ADDR(_port)
#define PX_RESET_DATA_REG_ADDR(_port) ((uint16_t *)(GPIO_BASE + offsetof(GPIO_Type, P0_RESET_DATA_REG)) + _port)
#define PX_RESET_DATA_REG(_port) *PX_RESET_DATA_REG_ADDR(_port)
#define PXX_MODE_REG_ADDR(_port, _pin) ((uint16_t *)(GPIO_BASE + offsetof(GPIO_Type, P00_MODE_REG)) + (_port * 8) + _pin)
#define PXX_MODE_REG(_port, _pin) *PXX_MODE_REG_ADDR(_port, _pin)
#define PX_PADPWR_CTRL_REG_ADDR(_port) ((uint16_t *)(GPIO_BASE + offsetof(GPIO_Type, P0_PADPWR_CTRL_REG)) + _port)
#define PX_PADPWR_CTRL_REG(_port) *PX_PADPWR_CTRL_REG_ADDR(_port)
/* on FPGA we cannot read the state of an output GPIO */
#ifdef FPGA_PAD_LOOPBACK_BROKEN
static uint16_t Px_DATA_REG_cache[5];
#endif
#if (dg_configIMAGE_SETUP == PRODUCTION_MODE) && (DEBUG_GPIO_ALLOC_MONITOR_ENABLED == 1)
#warning "GPIO assignment monitoring is active in PRODUCTION build!"
#endif
static volatile uint8_t GPIO_status[HW_GPIO_NUM_PORTS] = { 0 };
const uint8_t hw_gpio_port_num_pins[HW_GPIO_NUM_PORTS] =
{
HW_GPIO_PORT_0_NUM_PINS, HW_GPIO_PORT_1_NUM_PINS,
HW_GPIO_PORT_2_NUM_PINS, HW_GPIO_PORT_3_NUM_PINS,
HW_GPIO_PORT_4_NUM_PINS
};
/*
* Global Functions
****************************************************************************************
*/
void hw_gpio_configure(const gpio_config cfg[])
{
#if dg_configIMAGE_SETUP == DEVELOPMENT_MODE
int num_pins = 0;
uint8_t set_mask[HW_GPIO_NUM_PORTS]; // = { };
#endif
if (!cfg)
{
return;
}
while (cfg->pin != 0xFF)
{
uint8_t port = cfg->pin >> 4;
uint8_t pin = cfg->pin & 0x0F;
#if dg_configIMAGE_SETUP == DEVELOPMENT_MODE
if (port >= HW_GPIO_NUM_PORTS || pin >= hw_gpio_port_num_pins[port])
{
/*
* invalid port or pin number specified, it was either incorrectly specified
* of cfg was not terminated properly using HW_GPIO_PINCONFIG_END so we're
* reading garbage
*/
__BKPT(0);
}
if (++num_pins > HW_GPIO_NUM_PINS)
{
/*
* trying to set more pins than available, perhaps cfg was not terminated
* properly using HW_GPIO_PINCONFIG_END?
*/
__BKPT(0);
}
if (set_mask[port] & (1 << pin))
{
/*
* trying to set pin which has been already set by this call which means
* there is duplicated pin in configuration - does not make sense
*/
__BKPT(0);
}
set_mask[port] |= (1 << pin);
#endif
if (cfg->reserve)
{
hw_gpio_reserve_and_configure_pin(port, pin, cfg->mode, cfg->func, cfg->high);
}
else
{
hw_gpio_configure_pin(port, pin, cfg->mode, cfg->func, cfg->high);
}
cfg++;
}
}
bool hw_gpio_reserve_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
if ((GPIO_status[port] & (1 << pin)))
{
return false;
}
GPIO_status[port] |= (1 << pin);
return true;
}
bool hw_gpio_reserve_and_configure_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function, bool high)
{
if (!hw_gpio_reserve_pin(port, pin))
{
return false;
}
hw_gpio_configure_pin(port, pin, mode, function, high);
return true;
}
void hw_gpio_unreserve_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
GPIO_status[port] &= ~(1 << pin);
}
static void hw_gpio_verify_reserved(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
#if (DEBUG_GPIO_ALLOC_MONITOR_ENABLED == 1)
if (!(GPIO_status[port] & (1 << pin)))
{
// If debugger stops at this line, there is configuration problem
// pin is used without being reserved first
__BKPT(0); /* this pin has not been previously reserved! */
}
#endif // (DEBUG_GPIO_ALLOC_MONITOR_ENABLED == 1)
}
void hw_gpio_set_pin_function(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function)
{
hw_gpio_verify_reserved(port, pin);
PXX_MODE_REG(port, pin) = mode | function;
}
void hw_gpio_get_pin_function(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE *mode,
HW_GPIO_FUNC *function)
{
uint16_t val;
hw_gpio_verify_reserved(port, pin);
val = PXX_MODE_REG(port, pin);
*mode = val & 0x0700;
*function = val & 0x00ff;
}
void hw_gpio_configure_pin(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_MODE mode,
HW_GPIO_FUNC function, const bool high)
{
hw_gpio_verify_reserved(port, pin);
if (high)
{
hw_gpio_set_active(port, pin);
}
else
{
hw_gpio_set_inactive(port, pin);
}
hw_gpio_set_pin_function(port, pin, mode, function);
}
void hw_gpio_configure_pin_power(HW_GPIO_PORT port, HW_GPIO_PIN pin, HW_GPIO_POWER power)
{
uint16_t padpwr;
padpwr = PX_PADPWR_CTRL_REG(port);
padpwr &= ~(1 << pin);
if (power == HW_GPIO_POWER_VDD1V8P)
{
padpwr |= (1 << pin);
}
PX_PADPWR_CTRL_REG(port) = padpwr;
}
void hw_gpio_set_active(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
hw_gpio_verify_reserved(port, pin);
PX_SET_DATA_REG(port) = 1 << pin;
#ifdef FPGA_PAD_LOOPBACK_BROKEN
Px_DATA_REG_cache[port] |= 1 << pin;
#endif
}
void hw_gpio_set_inactive(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
hw_gpio_verify_reserved(port, pin);
PX_RESET_DATA_REG(port) = 1 << pin;
#ifdef FPGA_PAD_LOOPBACK_BROKEN
Px_DATA_REG_cache[port] &= ~(1 << pin);
#endif
}
bool hw_gpio_get_pin_status(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
#ifdef FPGA_PAD_LOOPBACK_BROKEN
HW_GPIO_MODE mode;
HW_GPIO_FUNC function;
#endif
hw_gpio_verify_reserved(port, pin);
#ifdef FPGA_PAD_LOOPBACK_BROKEN
hw_gpio_get_pin_function(port, pin, &mode, &function);
if (mode != HW_GPIO_MODE_OUTPUT)
{
return !!(PX_DATA_REG(port) & (1 << pin));
}
else
{
return !!(Px_DATA_REG_cache[port] & (1 << pin));
}
#else
return ((PX_DATA_REG(port) & (1 << pin)) != 0);
#endif
}
void hw_gpio_toggle(HW_GPIO_PORT port, HW_GPIO_PIN pin)
{
hw_gpio_verify_reserved(port, pin);
if (hw_gpio_get_pin_status(port, pin))
{
hw_gpio_set_inactive(port, pin);
}
else
{
hw_gpio_set_active(port, pin);
}
}
int hw_gpio_get_pins_with_function(HW_GPIO_FUNC func, uint8_t *buf, int buf_size)
{
int count = 0;
int port;
int pin;
HW_GPIO_MODE mode;
HW_GPIO_FUNC pin_func;
for (port = 0; port < HW_GPIO_NUM_PORTS; ++port)
{
for (pin = 0; pin < hw_gpio_port_num_pins[port]; ++pin)
{
hw_gpio_get_pin_function(port, pin, &mode, &pin_func);
if (pin_func != func)
{
continue;
}
if (count < buf_size && buf != NULL)
{
buf[count] = (uint8_t)((port << 4) | pin);
}
count++;
}
}
return count;
}
#endif /* dg_configUSE_HW_GPIO */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,173 @@
/**
* \addtogroup BSP
* \{
* \addtogroup SYSTEM
* \{
* \addtogroup Exception_Handlers
* \{
*/
/**
****************************************************************************************
*
* @file hw_hard_fault.c
*
* @brief HardFault handler.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdint.h>
#include <stdio.h>
#include "black_orca.h"
#include "hw_hard_fault.h"
#include "hw_watchdog.h"
#include "hw_cpm.h"
/*
* Global variables
*/
uint32_t hardfault_event_data[9] __attribute__((section("hard_fault_info")));
/*
* Local variables
*/
/*
* This is the base address in Retention RAM where the stacked information will be copied.
*/
#define STATUS_BASE (0x7FC5600)
/*
* Compilation switch to enable verbose output on HardFault
*/
#ifndef VERBOSE_HARDFAULT
# define VERBOSE_HARDFAULT 0
#endif
/*
* Function definitions
*/
/**
* \brief HardFault handler implementation. During development it will copy the system's status
* to a predefined location in memory. In release mode, it will cause a system reset.
*
* \param [in] hardfault_args The system's status when the HardFault event occurred.
*
* \return void
*
*/
#if (dg_configCODE_LOCATION == NON_VOLATILE_IS_FLASH)
__attribute__((section("text_retained")))
#endif
void HardFault_HandlerC(unsigned long *hardfault_args)
{
// Stack frame contains:
// r0, r1, r2, r3, r12, r14, the return address and xPSR
// - Stacked R0 = hf_args[0]
// - Stacked R1 = hf_args[1]
// - Stacked R2 = hf_args[2]
// - Stacked R3 = hf_args[3]
// - Stacked R12 = hf_args[4]
// - Stacked LR = hf_args[5]
// - Stacked PC = hf_args[6]
// - Stacked xPSR= hf_args[7]
if (dg_configIMAGE_SETUP == DEVELOPMENT_MODE)
{
hw_watchdog_freeze(); // Stop WDOG
ENABLE_DEBUGGER;
*(volatile unsigned long *)(STATUS_BASE) = hardfault_args[0]; // R0
*(volatile unsigned long *)(STATUS_BASE + 0x04) = hardfault_args[1]; // R1
*(volatile unsigned long *)(STATUS_BASE + 0x08) = hardfault_args[2]; // R2
*(volatile unsigned long *)(STATUS_BASE + 0x0C) = hardfault_args[3]; // R3
*(volatile unsigned long *)(STATUS_BASE + 0x10) = hardfault_args[4]; // R12
*(volatile unsigned long *)(STATUS_BASE + 0x14) = hardfault_args[5]; // LR
*(volatile unsigned long *)(STATUS_BASE + 0x18) = hardfault_args[6]; // PC
*(volatile unsigned long *)(STATUS_BASE + 0x1C) = hardfault_args[7]; // PSR
*(volatile unsigned long *)(STATUS_BASE + 0x20) = (unsigned long)hardfault_args; // Stack Pointer
*(volatile unsigned long *)(STATUS_BASE + 0x24) = (*((volatile unsigned long *)(0xE000ED28))); // CFSR
*(volatile unsigned long *)(STATUS_BASE + 0x28) = (*((volatile unsigned long *)(0xE000ED2C))); // HFSR
*(volatile unsigned long *)(STATUS_BASE + 0x2C) = (*((volatile unsigned long *)(0xE000ED30))); // DFSR
*(volatile unsigned long *)(STATUS_BASE + 0x30) = (*((volatile unsigned long *)(0xE000ED3C))); // AFSR
*(volatile unsigned long *)(STATUS_BASE + 0x34) = (*((volatile unsigned long *)(0xE000ED34))); // MMAR
*(volatile unsigned long *)(STATUS_BASE + 0x38) = (*((volatile unsigned long *)(0xE000ED38))); // BFAR
if (VERBOSE_HARDFAULT)
{
printf("HardFault Handler:\n\r");
printf("- R0 = 0x%08lx\n\r", hardfault_args[0]);
printf("- R1 = 0x%08lx\n\r", hardfault_args[1]);
printf("- R2 = 0x%08lx\n\r", hardfault_args[2]);
printf("- R3 = 0x%08lx\n\r", hardfault_args[3]);
printf("- R12 = 0x%08lx\n\r", hardfault_args[4]);
printf("- LR = 0x%08lx\n\r", hardfault_args[5]);
printf("- PC = 0x%08lx\n\r", hardfault_args[6]);
printf("- xPSR= 0x%08lx\n\r", hardfault_args[7]);
}
hw_cpm_assert_trigger_gpio();
while (1);
}
else
{
# ifdef PRODUCTION_DEBUG_OUTPUT
# if (USE_WDOG)
WDOG->WATCHDOG_REG = 0xC8; // Reset WDOG! 200 * 10.24ms active time for UART to finish printing!
# endif
dbg_prod_output(1, hardfault_args);
# endif // PRODUCTION_DEBUG_OUTPUT
hardfault_event_data[0] = HARDFAULT_MAGIC_NUMBER;
hardfault_event_data[1] = hardfault_args[0]; // R0
hardfault_event_data[2] = hardfault_args[1]; // R1
hardfault_event_data[3] = hardfault_args[2]; // R2
hardfault_event_data[4] = hardfault_args[3]; // R3
hardfault_event_data[5] = hardfault_args[4]; // R12
hardfault_event_data[6] = hardfault_args[5]; // LR
hardfault_event_data[7] = hardfault_args[6]; // PC
hardfault_event_data[8] = hardfault_args[7]; // PSR
hw_cpm_reboot_system(); // Force reset
while (1);
}
}
/**
* \}
* \}
* \}
* */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,329 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup QSPI
* \{
*/
/**
****************************************************************************************
*
* @file hw_qspi.c
*
* @brief Implementation of the QSPI Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_QSPI
#include <stdint.h>
#include <hw_qspi.h>
#define BITS16(base, reg, field, v) \
((uint16) (((uint16) (v) << (base ## _ ## reg ## _ ## field ## _Pos)) & \
(base ## _ ## reg ## _ ## field ## _Msk)))
#define BITS32(base, reg, field, v) \
((uint32) (((uint32) (v) << (base ## _ ## reg ## _ ## field ## _Pos)) & \
(base ## _ ## reg ## _ ## field ## _Msk)))
#define GETBITS16(base, reg, v, field) \
((uint16) (((uint16) (v)) & (base ## _ ## reg ## _ ## field ## _Msk)) >> \
(base ## _ ## reg ## _ ## field ## _Pos))
#define GETBITS32(base, reg, v, field) \
((uint32) (((uint32) (v)) & (base ## _ ## reg ## _ ## field ## _Msk)) >> \
(base ## _ ## reg ## _ ## field ## _Pos))
static const uint8_t dummy_num[] = { 0, 1, 2, 0, 3 };
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
void hw_qspi_set_bus_mode(HW_QSPI_BUS_MODE mode)
{
switch (mode)
{
case HW_QSPI_BUS_MODE_SINGLE:
QSPIC->QSPIC_CTRLBUS_REG = REG_MSK(QSPIC, QSPIC_CTRLBUS_REG, QSPIC_SET_SINGLE);
break;
case HW_QSPI_BUS_MODE_DUAL:
QSPIC->QSPIC_CTRLBUS_REG = REG_MSK(QSPIC, QSPIC_CTRLBUS_REG, QSPIC_SET_DUAL);
break;
case HW_QSPI_BUS_MODE_QUAD:
QSPIC->QSPIC_CTRLBUS_REG = REG_MSK(QSPIC, QSPIC_CTRLBUS_REG, QSPIC_SET_QUAD);
hw_qspi_set_io2_output(false);
hw_qspi_set_io3_output(false);
break;
}
}
#if (dg_configFLASH_POWER_DOWN == 1)
__attribute__((section("text_retained")))
#endif
void hw_qspi_set_automode(bool automode)
{
if (automode)
{
const uint32_t burst_cmd_a = QSPIC->QSPIC_BURSTCMDA_REG;
const uint32_t burst_cmd_b = QSPIC->QSPIC_BURSTCMDB_REG;
const uint32_t status_cmd = QSPIC->QSPIC_STATUSCMD_REG;
const uint32_t erase_cmd_b = QSPIC->QSPIC_ERASECMDB_REG;
const uint32_t burstbrk = QSPIC->QSPIC_BURSTBRK_REG;
if (GETBITS32(QSPIC, QSPIC_BURSTCMDA_REG, burst_cmd_a, QSPIC_INST_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTCMDA_REG, burst_cmd_a, QSPIC_ADR_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTCMDA_REG, burst_cmd_a, QSPIC_DMY_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTCMDA_REG, burst_cmd_a, QSPIC_EXT_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTCMDB_REG, burst_cmd_b, QSPIC_DAT_RX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTCMDB_REG, burst_cmd_b, QSPIC_DAT_RX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_STATUSCMD_REG, status_cmd, QSPIC_RSTAT_RX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_STATUSCMD_REG, status_cmd, QSPIC_RSTAT_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_ERASECMDB_REG, erase_cmd_b, QSPIC_ERS_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_ERASECMDB_REG, erase_cmd_b, QSPIC_WEN_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_ERASECMDB_REG, erase_cmd_b, QSPIC_SUS_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_ERASECMDB_REG, erase_cmd_b, QSPIC_RES_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_ERASECMDB_REG, erase_cmd_b, QSPIC_EAD_TX_MD) == HW_QSPI_BUS_MODE_QUAD ||
GETBITS32(QSPIC, QSPIC_BURSTBRK_REG, burstbrk, QSPIC_BRK_TX_MD) == HW_QSPI_BUS_MODE_QUAD)
{
hw_qspi_set_io2_output(false);
hw_qspi_set_io3_output(false);
}
}
HW_QSPIC_REG_SETF(CTRLMODE, AUTO_MD, automode);
}
void hw_qspi_set_read_instruction(uint8_t inst, uint8_t send_once, uint8_t dummy_count,
HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE addr_phase,
HW_QSPI_BUS_MODE dummy_phase,
HW_QSPI_BUS_MODE data_phase)
{
QSPIC->QSPIC_BURSTCMDA_REG =
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_INST, inst) |
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_INST_TX_MD, inst_phase) |
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_ADR_TX_MD, addr_phase) |
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_DMY_TX_MD, dummy_phase);
QSPIC->QSPIC_BURSTCMDB_REG =
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DAT_RX_MD, data_phase) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_INST_MD, send_once) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DMY_FORCE, (dummy_count == 3 ? 1 : 0)) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DMY_NUM, dummy_num[dummy_count]);
}
void hw_qspi_set_wrapping_burst_instruction(uint8_t inst, HW_QSPI_WRAP_LEN len,
HW_QSPI_WRAP_SIZE size)
{
HW_QSPIC_REG_SETF(BURSTCMDA, INST_WB, inst);
QSPIC->QSPIC_BURSTCMDB_REG =
(QSPIC->QSPIC_BURSTCMDB_REG &
~(REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_WRAP_SIZE) |
REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_WRAP_LEN))) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_WRAP_SIZE, size) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_WRAP_LEN, len) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_WRAP_MD, 1);
}
void hw_qspi_set_extra_byte(uint8_t extra_byte, HW_QSPI_BUS_MODE bus_mode, uint8_t half_disable_out)
{
QSPIC->QSPIC_BURSTCMDA_REG =
(QSPIC->QSPIC_BURSTCMDA_REG &
~(REG_MSK(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_EXT_BYTE) |
REG_MSK(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_EXT_TX_MD))) |
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_EXT_BYTE, extra_byte) |
BITS32(QSPIC, QSPIC_BURSTCMDA_REG, QSPIC_EXT_TX_MD, bus_mode);
QSPIC->QSPIC_BURSTCMDB_REG =
(QSPIC->QSPIC_BURSTCMDB_REG &
~(REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_EXT_BYTE_EN) |
REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_EXT_HF_DS))) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_EXT_BYTE_EN, 1) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_EXT_HF_DS, half_disable_out ? 1 : 0);
}
void hw_qspi_set_dummy_bytes_count(uint8_t count)
{
if (count == 3)
{
HW_QSPIC_REG_SETF(BURSTCMDB, DMY_FORCE, 1);
}
else
{
QSPIC->QSPIC_BURSTCMDB_REG =
(QSPIC->QSPIC_BURSTCMDB_REG &
~(REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DMY_FORCE) |
REG_MSK(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DMY_NUM))) |
BITS32(QSPIC, QSPIC_BURSTCMDB_REG, QSPIC_DMY_NUM,
dummy_num[count]);
}
}
void hw_qspi_set_read_status_instruction(uint8_t inst, HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE receive_phase,
uint8_t busy_pos,
uint8_t busy_val,
uint8_t reset_delay,
uint8_t sts_delay)
{
QSPIC->QSPIC_STATUSCMD_REG =
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_BUSY_VAL, busy_val) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_BUSY_POS , busy_pos) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_RSTAT_RX_MD, receive_phase) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_RSTAT_TX_MD, inst_phase) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_RSTAT_INST, inst) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_STSDLY_SEL, sts_delay) |
BITS32(QSPIC, QSPIC_STATUSCMD_REG, QSPIC_RESSTS_DLY, reset_delay);
}
void hw_qspi_set_erase_instruction(uint8_t inst, HW_QSPI_BUS_MODE inst_phase,
HW_QSPI_BUS_MODE addr_phase, uint8_t hclk_cycles,
uint8_t cs_hi_cycles)
{
HW_QSPIC_REG_SETF(ERASECMDA, ERS_INST, inst);
QSPIC->QSPIC_ERASECMDB_REG =
(QSPIC->QSPIC_ERASECMDB_REG &
~(REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERS_TX_MD) |
REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_EAD_TX_MD) |
REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERSRES_HLD) |
REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERS_CS_HI))) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERS_TX_MD, inst_phase) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_EAD_TX_MD, addr_phase) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERSRES_HLD, hclk_cycles) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_ERS_CS_HI, cs_hi_cycles);
}
void hw_qspi_set_write_enable_instruction(uint8_t write_enable, HW_QSPI_BUS_MODE inst_phase)
{
HW_QSPIC_REG_SETF(ERASECMDA, WEN_INST, write_enable);
HW_QSPIC_REG_SETF(ERASECMDB, WEN_TX_MD, inst_phase);
}
void hw_qspi_set_suspend_resume_instructions(uint8_t erase_suspend_inst,
HW_QSPI_BUS_MODE suspend_inst_phase,
uint8_t erase_resume_inst,
HW_QSPI_BUS_MODE resume_inst_phase,
uint8_t minimum_delay)
{
QSPIC->QSPIC_ERASECMDA_REG =
(QSPIC->QSPIC_ERASECMDA_REG &
~(REG_MSK(QSPIC, QSPIC_ERASECMDA_REG, QSPIC_SUS_INST) |
REG_MSK(QSPIC, QSPIC_ERASECMDA_REG, QSPIC_RES_INST))) |
BITS32(QSPIC, QSPIC_ERASECMDA_REG, QSPIC_SUS_INST, erase_suspend_inst) |
BITS32(QSPIC, QSPIC_ERASECMDA_REG, QSPIC_RES_INST, erase_resume_inst);
QSPIC->QSPIC_ERASECMDB_REG =
(QSPIC->QSPIC_ERASECMDB_REG &
~(REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_SUS_TX_MD) |
REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_RES_TX_MD) |
REG_MSK(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_RESSUS_DLY))) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_SUS_TX_MD, suspend_inst_phase) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_RES_TX_MD, resume_inst_phase) |
BITS32(QSPIC, QSPIC_ERASECMDB_REG, QSPIC_RESSUS_DLY, minimum_delay);
}
void hw_qspi_erase_block(uint32_t addr)
{
if (!hw_qspi_get_automode())
{
hw_qspi_set_automode(true);
}
// Wait for previous erase to end
while (hw_qspi_get_erase_status() != 0)
{
}
if (hw_qspi_get_address_size() == HW_QSPI_ADDR_SIZE_32)
{
addr >>= 12;
}
else
{
addr >>= 4;
}
// Setup erase block page
HW_QSPIC_REG_SETF(ERASECTRL, ERS_ADDR, addr);
// Fire erase
HW_QSPIC_REG_SETF(ERASECTRL, ERASE_EN, 1);
}
void hw_qspi_set_break_sequence(uint16_t sequence, HW_QSPI_BUS_MODE mode,
HW_QSPI_BREAK_SEQ_SIZE size, uint8_t dis_out)
{
QSPIC->QSPIC_BURSTBRK_REG =
BITS32(QSPIC, QSPIC_BURSTBRK_REG, QSPIC_SEC_HF_DS, dis_out) |
BITS32(QSPIC, QSPIC_BURSTBRK_REG, QSPIC_BRK_SZ, size) |
BITS32(QSPIC, QSPIC_BURSTBRK_REG, QSPIC_BRK_TX_MD, mode) |
BITS32(QSPIC, QSPIC_BURSTBRK_REG, QSPIC_BRK_EN, 1) |
BITS32(QSPIC, QSPIC_BURSTBRK_REG, QSPIC_BRK_WRD, sequence);
}
void hw_qspi_set_pads(HW_QSPI_SLEW_RATE rate, HW_QSPI_DRIVE_CURRENT current)
{
QSPIC->QSPIC_GP_REG =
BITS16(QSPIC, QSPIC_GP_REG, QSPIC_PADS_SLEW, rate) |
BITS16(QSPIC, QSPIC_GP_REG, QSPIC_PADS_DRV, current);
}
void hw_qspi_init(const qspi_config *cfg)
{
hw_qspi_enable_clock();
hw_qspi_set_automode(false);
hw_qspi_set_bus_mode(HW_QSPI_BUS_MODE_SINGLE);
hw_qspi_set_io2_output(true);
hw_qspi_set_io2(1);
hw_qspi_set_io3_output(true);
hw_qspi_set_io3(1);
if (cfg)
{
hw_qspi_set_address_size(cfg->address_size);
hw_qspi_set_clock_mode(cfg->idle_clock);
hw_qspi_set_read_sampling_edge(cfg->sampling_edge);
}
}
__RETAINED_CODE void hw_qspi_set_div(HW_QSPI_DIV div)
{
REG_SETF(CRG_TOP, CLK_AMBA_REG, QSPI_DIV, div);
}
#endif /* dg_configUSE_HW_QSPI */
/**
* \}
* \}
* \}
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,121 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Timer0
* \{
*/
/**
****************************************************************************************
*
* @file hw_timer0.c
*
* @brief Implementation of the Timer0 Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_TIMER0
#include <stdio.h>
#include <black_orca.h>
#include <hw_timer0.h>
#if (dg_configSYSTEMVIEW)
# include "SEGGER_SYSVIEW_FreeRTOS.h"
#else
# define SEGGER_SYSTEMVIEW_ISR_ENTER()
# define SEGGER_SYSTEMVIEW_ISR_EXIT()
#endif
static hw_timer0_interrupt_cb intr_cb;
void hw_timer0_init(const timer0_config *cfg)
{
/* Enable clock for peripheral */
uint32_t clk_tmr_reg = CRG_TOP->CLK_TMR_REG;
clk_tmr_reg &= ~CRG_TOP_CLK_TMR_REG_TMR0_DIV_Msk;
clk_tmr_reg &= ~CRG_TOP_CLK_TMR_REG_TMR0_CLK_SEL_Msk;
clk_tmr_reg |= CRG_TOP_CLK_TMR_REG_TMR0_ENABLE_Msk;
CRG_TOP->CLK_TMR_REG = clk_tmr_reg ;
/* Reset control register, i.e. disable timer */
GP_TIMERS->TIMER0_CTRL_REG = 0x0;
/* Disable NVIC interrupt */
NVIC_DisableIRQ(SWTIM0_IRQn);
intr_cb = NULL;
hw_timer0_configure(cfg);
}
void hw_timer0_configure(const timer0_config *cfg)
{
if (cfg)
{
hw_timer0_set_clock_source(cfg->clk_src);
hw_timer0_set_fast_clock_div(cfg->fast_clk_div);
hw_timer0_set_on_clock_div(cfg->on_clock_div);
hw_timer0_set_on_reload(cfg->on_reload);
hw_timer0_set_t0_reload(cfg->t0_reload_m, cfg->t0_reload_n);
}
}
void hw_timer0_register_int(hw_timer0_interrupt_cb handler)
{
intr_cb = handler;
NVIC_EnableIRQ(SWTIM0_IRQn);
}
void hw_timer0_unregister_int(void)
{
NVIC_DisableIRQ(SWTIM0_IRQn);
intr_cb = NULL;
}
void SWTIM0_Handler(void)
{
SEGGER_SYSTEMVIEW_ISR_ENTER();
if (intr_cb)
{
intr_cb();
}
SEGGER_SYSTEMVIEW_ISR_EXIT();
}
#endif /* dg_configUSE_HW_TIMER0 */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,124 @@
/**
****************************************************************************************
*
* @file hw_trng.c
*
* @brief Implementation of the True Random Number Generator Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_TRNG
#include <hw_trng.h>
#if (dg_configSYSTEMVIEW)
# include "SEGGER_SYSVIEW_FreeRTOS.h"
#else
# define SEGGER_SYSTEMVIEW_ISR_ENTER()
# define SEGGER_SYSTEMVIEW_ISR_EXIT()
#endif
#define HW_TRNG_FIFO_DEPTH (32)
#define HW_TRNG_RAM (0x40040000)
static hw_trng_cb trng_cb;
static void hw_disable_trng(void)
{
REG_CLR_BIT(TRNG, TRNG_CTRL_REG, TRNG_ENABLE);
}
static void hw_disable_trng_clk(void)
{
REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, TRNG_CLK_ENABLE);
}
static void hw_trng_clear_pending(void)
{
// read TRNG_FIFOLVL_REG to clear level-sensitive source.
TRNG->TRNG_FIFOLVL_REG;
NVIC_ClearPendingIRQ(TRNG_IRQn);
}
void hw_trng_enable(hw_trng_cb callback)
{
hw_trng_disable();
if (callback != NULL)
{
trng_cb = callback;
hw_trng_clear_pending();
NVIC_EnableIRQ(TRNG_IRQn);
}
REG_SET_BIT(CRG_TOP, CLK_AMBA_REG, TRNG_CLK_ENABLE);
REG_SET_BIT(TRNG, TRNG_CTRL_REG, TRNG_ENABLE);
}
void hw_trng_get_numbers(uint32_t *buffer, uint8_t size)
{
if (size > HW_TRNG_FIFO_DEPTH)
{
size = HW_TRNG_FIFO_DEPTH;
}
for (int i = 0; i < size ; i++)
{
buffer[i] = *((volatile uint32_t *)HW_TRNG_RAM);
}
}
uint8_t hw_trng_get_fifo_level(void)
{
return (TRNG->TRNG_FIFOLVL_REG) & (REG_MSK(TRNG, TRNG_FIFOLVL_REG, TRNG_FIFOLVL) |
REG_MSK(TRNG, TRNG_FIFOLVL_REG, TRNG_FIFOFULL));
}
void hw_trng_disable(void)
{
hw_disable_trng();
NVIC_DisableIRQ(TRNG_IRQn);
hw_trng_clear_pending();
hw_disable_trng_clk();
}
void TRNG_Handler(void)
{
SEGGER_SYSTEMVIEW_ISR_ENTER();
if (trng_cb != NULL)
{
trng_cb();
}
hw_trng_clear_pending();
SEGGER_SYSTEMVIEW_ISR_EXIT();
}
#endif /* dg_configUSE_HW_TRNG */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Watchdog_Timer
* \{
*/
/**
****************************************************************************************
*
* @file hw_watchdog.c
*
* @brief Implementation of the Watchdog timer Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdio.h>
#include "hw_watchdog.h"
#include "hw_cpm.h"
/*
* Global variables
*/
uint32_t nmi_event_data[9] __attribute__((section("nmi_info")));
/*
* Local variables
*/
static hw_watchdog_interrupt_cb int_handler __RETAINED = NULL;
/*
* This is the base address in Retention RAM where the stacked information will be copied.
*/
#define STATUS_BASE (0x7FC5600)
bool hw_watchdog_freeze(void)
{
GPREG->SET_FREEZE_REG = GPREG_SET_FREEZE_REG_FRZ_WDOG_Msk;
return !REG_GETF(WDOG, WATCHDOG_CTRL_REG, NMI_RST);
}
void hw_watchdog_unfreeze(void)
{
GPREG->RESET_FREEZE_REG = GPREG_RESET_FREEZE_REG_FRZ_WDOG_Msk;
}
HW_WDG_RESET hw_watchdog_is_irq_or_rst_gen(void)
{
if (REG_GETF(WDOG, WATCHDOG_CTRL_REG, NMI_RST))
{
return HW_WDG_RESET_RST;
}
return HW_WDG_RESET_NMI;
}
void hw_watchdog_register_int(hw_watchdog_interrupt_cb handler)
{
int_handler = handler;
}
void hw_watchdog_unregister_int(void)
{
int_handler = NULL;
}
__RETAINED_CODE void hw_watchdog_handle_int(unsigned long *exception_args)
{
// Reached this point due to a WDOG timeout
uint16_t pmu_ctrl_reg = CRG_TOP->PMU_CTRL_REG;
pmu_ctrl_reg |= ((1 << CRG_TOP_PMU_CTRL_REG_BLE_SLEEP_Pos) | /* turn off BLE */
(1 << CRG_TOP_PMU_CTRL_REG_FTDF_SLEEP_Pos) | /* turn off FTDF */
(1 << CRG_TOP_PMU_CTRL_REG_RADIO_SLEEP_Pos) | /* turn off radio PD */
(1 << CRG_TOP_PMU_CTRL_REG_PERIPH_SLEEP_Pos)); /* turn off peripheral power domain */
CRG_TOP->PMU_CTRL_REG = pmu_ctrl_reg;
REG_SET_BIT(CRG_TOP, CLK_RADIO_REG, BLE_LP_RESET); /* reset the BLE LP timer */
#if (dg_configIMAGE_SETUP == DEVELOPMENT_MODE)
hw_watchdog_freeze(); // Stop WDOG
ENABLE_DEBUGGER;
if (exception_args != NULL)
{
*(volatile unsigned long *)(STATUS_BASE) = exception_args[0]; // R0
*(volatile unsigned long *)(STATUS_BASE + 0x04) = exception_args[1]; // R1
*(volatile unsigned long *)(STATUS_BASE + 0x08) = exception_args[2]; // R2
*(volatile unsigned long *)(STATUS_BASE + 0x0C) = exception_args[3]; // R3
*(volatile unsigned long *)(STATUS_BASE + 0x10) = exception_args[4]; // R12
*(volatile unsigned long *)(STATUS_BASE + 0x14) = exception_args[5]; // LR
*(volatile unsigned long *)(STATUS_BASE + 0x18) = exception_args[6]; // PC
*(volatile unsigned long *)(STATUS_BASE + 0x1C) = exception_args[7]; // PSR
*(volatile unsigned long *)(STATUS_BASE + 0x20) = (unsigned long)exception_args; // Stack Pointer
*(volatile unsigned long *)(STATUS_BASE + 0x24) = (*((volatile unsigned long *)(0xE000ED28))); // CFSR
*(volatile unsigned long *)(STATUS_BASE + 0x28) = (*((volatile unsigned long *)(0xE000ED2C))); // HFSR
*(volatile unsigned long *)(STATUS_BASE + 0x2C) = (*((volatile unsigned long *)(0xE000ED30))); // DFSR
*(volatile unsigned long *)(STATUS_BASE + 0x30) = (*((volatile unsigned long *)(0xE000ED3C))); // AFSR
*(volatile unsigned long *)(STATUS_BASE + 0x34) = (*((volatile unsigned long *)(0xE000ED34))); // MMAR
*(volatile unsigned long *)(STATUS_BASE + 0x38) = (*((volatile unsigned long *)(0xE000ED38))); // BFAR
}
hw_cpm_assert_trigger_gpio();
if (REG_GETF(CRG_TOP, SYS_STAT_REG, DBG_IS_ACTIVE))
{
__asm("BKPT #0\n");
}
else
{
while (1);
}
#else // dg_configIMAGE_SETUP == DEVELOPMENT_MODE
if (exception_args != NULL)
{
nmi_event_data[0] = NMI_MAGIC_NUMBER;
nmi_event_data[1] = exception_args[0]; // R0
nmi_event_data[2] = exception_args[1]; // R1
nmi_event_data[3] = exception_args[2]; // R2
nmi_event_data[4] = exception_args[3]; // R3
nmi_event_data[5] = exception_args[4]; // R12
nmi_event_data[6] = exception_args[5]; // LR
nmi_event_data[7] = exception_args[6]; // PC
nmi_event_data[8] = exception_args[7]; // PSR
}
// Wait for the reset to occur
while (1);
#endif // dg_configIMAGE_SETUP == DEVELOPMENT_MODE
}
__RETAINED_CODE void NMI_HandlerC(unsigned long *exception_args);
void NMI_HandlerC(unsigned long *exception_args)
{
if (int_handler)
{
int_handler(exception_args);
}
else
{
hw_watchdog_handle_int(exception_args);
}
}
/**
* \}
* \}
* \}
*/
+131
View File
@@ -0,0 +1,131 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup Wakeup_Timer
* \{
*/
/**
****************************************************************************************
*
* @file hw_wkup.c
*
* @brief Implementation of the Wakeup timer Low Level Driver.
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#if dg_configUSE_HW_USB_WKUP
#include <stdio.h>
#include <string.h>
#include <hw_wkup.h>
static hw_wkup_interrupt_cb intr_cb __RETAINED /* = NULL*/;
void hw_wkup_init(const wkup_config *cfg)
{
unsigned int i;
REG_SET_BIT(CRG_TOP, CLK_TMR_REG, WAKEUPCT_ENABLE);
/* reset configuration */
WAKEUP->WKUP_CTRL_REG = 0;
WAKEUP->WKUP_COMPARE_REG = 0;
/* disable all pins */
for (i = 0; i < 5; i++) {
*((volatile uint16_t *)WAKEUP_BASE + 5 + i) = 0;
*((volatile uint16_t *)WAKEUP_BASE + 10 + i) = 0;
}
NVIC_DisableIRQ(WKUP_GPIO_IRQn);
hw_wkup_configure(cfg);
}
void hw_wkup_configure(const wkup_config *cfg)
{
int i;
if (!cfg) {
return;
}
hw_wkup_set_counter_threshold(cfg->threshold);
hw_wkup_set_debounce_time(cfg->debounce);
for (i = 0; i < HW_GPIO_NUM_PORTS; i++) {
hw_wkup_configure_port(i, cfg->pin_state[i], cfg->pin_trigger[i]);
}
}
void hw_wkup_register_interrupt(hw_wkup_interrupt_cb cb, uint32_t prio)
{
intr_cb = cb;
HW_WKUP_REG_SETF(CTRL, WKUP_ENABLE_IRQ, 1);
NVIC_ClearPendingIRQ(WKUP_GPIO_IRQn);
NVIC_SetPriority(WKUP_GPIO_IRQn, prio);
NVIC_EnableIRQ(WKUP_GPIO_IRQn);
}
void hw_wkup_unregister_interrupt(void)
{
intr_cb = NULL;
HW_WKUP_REG_SETF(CTRL, WKUP_ENABLE_IRQ, 0);
NVIC_DisableIRQ(WKUP_GPIO_IRQn);
}
void hw_wkup_handler(void)
{
if (intr_cb) {
intr_cb();
} else {
hw_wkup_reset_interrupt();
}
}
#ifdef OS_BAREMETAL
void WKUP_GPIO_Handler(void)
{
hw_wkup_handler();
}
#endif
#endif /* dg_configUSE_HW_USB_WKUP */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,470 @@
/**
\addtogroup BSP
\{
\addtogroup SYSTEM
\{
\addtogroup TCS_Handling
\{
*/
/**
****************************************************************************************
*
* @file sys_tcs.c
*
* @brief TCS HAndler
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdint.h>
#include "sys_tcs.h"
#define APPEND_TCS_LENGTH (0)
#define RADIO_AREA_SIZE (0x1000)
#define PERIPHERAL_AREA_SIZE (0xC4A)
#define IS_IN_AREA(addr, base, size) ((addr >= base) && (addr <= (base + size)))
/*
* Global and / or retained variables
*/
uint32_t tcs_data[24 * 2 + APPEND_TCS_LENGTH] __RETAINED_UNINIT;
uint8_t tcs_length __RETAINED_UNINIT;
uint8_t area_offset[tcs_system + 1] __RETAINED;
uint8_t area_size_global[tcs_system + 1] __RETAINED;
const uint32_t *tcs_ptr __RETAINED;
bool is_calibrated_chip __RETAINED_UNINIT; // Initial value: false
/*
* Local variables
*/
static const uint32_t uncalibrated_tcs_data[] =
{
/* BANDGAP_REG: (offset 0)
* [14]: BYPASS_COLD_BOOT_DISABLE = 0
* [13:10]: LDO_SLEEP_TRIM = 0x4
* [9:5]: BGR_ITRIM = 0x00
* [4:0]: BGR_TRIM = 0x13 (change until V12 is 1.2V)
*
* Especially for this register, merge the trimmed and preferred settings.
*/
(uint32_t) &CRG_TOP->BANDGAP_REG, 0x1013,
/* CLK_FREQ_TRIM_REG: (offset 2)
* [10:8]: COARSE_ADJ = 0x4
* [7:0]: FINE_ADJ = 0x60
*/
(uint32_t) &CRG_TOP->CLK_FREQ_TRIM_REG, 0x0460,
/* CLK_16M_REG: (offset 4)
* [15]: RC16M_STARTUP_DISABLE = 0
* [14]: XTAL16_HPASS_FLT_EN = 0
* [13]: XTAL16_SPIKE_FLT_BYPASS = 0
* [12:10]: XTAL16_AMP_TRIM = 0x5
* [9]: XTAL16_EXT_CLK_ENABLE = 0
* [8]: XTAL16_MAX_CURRENT = 0
* [7:5]: XTAL16_CUR_SET = 0x5
* [4:1]: RC16M_TRIM = 0x9
* [0]: RC16M_ENABLE = 0
*
* Apply the trimmed and a default preferred value. The correct one is applied
* later.
*/
(uint32_t) &CRG_TOP->CLK_16M_REG, 0x14B2,
/* CLK_32K_REG: (offset 6)
* [15:13]: 0
* [12]: XTAL32K_DISABLE_AMPREG0 = 0
* [11:8]: RC32K_TRIM = 0x07
* [7]: RC32K_ENABLE = 0x1 (reset value)
* [6:3]: XTAL32K_CUR = 0x3 (reset value)
* [2:1]: XTAL32K_RBIAS = 0x2 (reset value)
* [0]: XTAL32K_ENABLE = 0
*/
(uint32_t) &CRG_TOP->CLK_32K_REG, 0x79C,
/* CHARGER_CTRL2_REG: (offset 8)
* [15:13]: 0
* [12:8]: CURRENT_OFFSET_TRIM = 0x0C
* [7:4]: CHARGER_VFLOAT_ADJ = 0x5
* [3:0]: CURRENT_GAIN_TRIM = 0xA
*/
(uint32_t) &ANAMISC->CHARGER_CTRL2_REG, 0x0C5A,
};
#define UNCALIBRATED_DATA_NON_RETAINED_OFFSET (8)
#ifdef CONFIG_USE_BLE
#define UNCALIBRATED_DATA_BLE_SIZE (0)
#define UNCALIBRATED_DATA_BLE_OFFSET (0)
#endif
#ifdef CONFIG_USE_FTDF
#define UNCALIBRATED_DATA_FTDF_SIZE (0)
#define UNCALIBRATED_DATA_FTDF_OFFSET (0)
#endif
#define UNCALIBRATED_DATA_RADIO_SIZE (0)
#define UNCALIBRATED_DATA_RADIO_OFFSET (0)
#define UNCALIBRATED_DATA_CHARGER_SIZE (1 * 2)
#define UNCALIBRATED_DATA_CHARGER_OFFSET (8)
#define UNCALIBRATED_DATA_AUDIO_SIZE (0)
#define UNCALIBRATED_DATA_AUDIO_OFFSET (0)
#define UNCALIBRATED_DATA_SYSTEM_SIZE (0)
#define UNCALIBRATED_DATA_SYSTEM_OFFSET (0)
/*
* Forward declarations
*/
/*
* Function definitions
*/
/**
* \brief Apply a TCS <address, value> pair.
*
* \param [in] address the address of the register
* \param [in] value the value for this register
*
*/
static void apply_pair(uint32_t address, uint32_t value)
{
if (address & 0x2)
{
*(volatile uint16_t *)address = value;
}
else
{
*(volatile uint32_t *)address = value;
}
}
/**
* \brief Apply a TCS <address, value> entry of the TCS array.
*
* \param [in] address the address of the register
* \param [in] value the value for this register
*
*/
static void apply_entry(uint8_t index)
{
uint32_t address = tcs_ptr[index];
uint32_t value = tcs_ptr[index + 1];
if (address & 0x2)
{
*(volatile uint16_t *)address = value;
}
else
{
*(volatile uint32_t *)address = value;
}
}
/**
* \brief Store TCS <address, value> pair in the Global TCS array.
*
* \param [in] address the address of the register
* \param [in] value the value for this register
*
*/
static void store_in_array(uint32_t address, uint32_t value)
{
tcs_data[tcs_length] = address;
tcs_length++;
tcs_data[tcs_length] = value;
tcs_length++;
}
/**
* \brief Swaps the contents of two entries in the TCS array.
*
* \param [in] address the address of the register
* \param [in] value the value for this register
*
* \warning When this function is called, the RC16 must have been set as the system clock!
*
*/
static void swap_entries(uint32_t first_pos, uint32_t second_pos)
{
uint32_t address_stored;
uint32_t value_stored;
address_stored = tcs_data[second_pos];
value_stored = tcs_data[second_pos + 1];
tcs_data[second_pos] = tcs_data[first_pos];
tcs_data[second_pos + 1] = tcs_data[first_pos + 1];
tcs_data[first_pos] = address_stored;
tcs_data[first_pos + 1] = value_stored;
}
/**
* \brief Sort the registers of a specific Memory Map area of the chip to a continuous region in the
* TCS array.
*
* \param [in] area_base the base address of the Memory Map area
* \param [in] area_size the size of the Memory Map region in bytes
* \param [in] array_ptr the current position in the TCS array to start reading from (all previous
* positions have been sorted)
* \param [out] ptr the offset of the beginning of the sorted region in the TCS array
* \param [out] size the size of the sorted region in bytes
*
* \return The updated position in the TCS array to start reading next time
*/
static int sys_tcs_sort_area(uint32_t area_base, uint32_t area_size, uint32_t array_ptr, uint8_t *ptr, uint8_t *size)
{
int i = array_ptr;
int sort_start;
int sort_end;
if (array_ptr == tcs_length)
{
return array_ptr; // Nothing else is left in the array
}
sort_start = array_ptr;
sort_end = array_ptr;
/* Make sure that the values in TCS don't overflow the allocated array */
ASSERT_WARNING(tcs_length <= sizeof(tcs_data) / sizeof(tcs_data[0]));
while (i < tcs_length)
{
if (IS_IN_AREA(tcs_data[i], area_base, area_size))
{
if (i == array_ptr)
{
if (sort_start == array_ptr)
{
sort_start = array_ptr;
sort_end = sort_start + 2;
}
}
else
{
// Copy it to the proper place.
if (i != sort_end)
{
swap_entries(sort_end, i);
}
sort_end += 2;
}
}
i += 2;
}
*ptr = sort_start;
*size = sort_end - sort_start;
return sort_end;
}
void sys_tcs_init(void)
{
tcs_length = 0;
is_calibrated_chip = false;
}
bool sys_tcs_store_pair(uint32_t address, uint32_t value)
{
// If it stops here then tcs_length must become uint16_t.
ASSERT_WARNING((256 * sizeof(tcs_length)) >= (24 * 2 + APPEND_TCS_LENGTH));
// Check if the address is in Always-ON or of a retained register and apply it.
if (IS_IN_AREA(address, CRG_TOP_BASE, sizeof(CRG_TOP_Type))
|| IS_IN_AREA(address, TIMER1_BASE, sizeof(TIMER1_Type))
|| IS_IN_AREA(address, WAKEUP_BASE, sizeof(WAKEUP_Type))
|| IS_IN_AREA(address, DCDC_BASE, sizeof(DCDC_Type))
|| IS_IN_AREA(address, QSPIC_BASE, sizeof(QSPIC_Type))
|| IS_IN_AREA(address, CACHE_BASE, sizeof(CACHE_Type))
|| IS_IN_AREA(address, OTPC_BASE, sizeof(OTPC_Type)))
{
if (address == (uint32_t)&CRG_TOP->BANDGAP_REG)
{
is_calibrated_chip = true;
}
if (address == (uint32_t)&CRG_TOP->CLK_16M_REG)
{
value |= 1; // Make sure that RC16 is enabled!
}
apply_pair(address, value);
}
else
{
store_in_array(address, value);
}
return is_calibrated_chip;
}
void sys_tcs_sort_array(void)
{
int entry_ptr = 0;
int i;
/*
* Apply a default value to CLK_FREQ_TRIM_REG, if not set in TCS.
* [10:8]: COARSE_ADJ = 0x4
* [7:0]: FINE_ADJ = 0x60
*/
if (CRG_TOP->CLK_FREQ_TRIM_REG == 0)
{
CRG_TOP->CLK_FREQ_TRIM_REG = 0x0460;
}
if (is_calibrated_chip)
{
#ifdef CONFIG_USE_BLE
entry_ptr = sys_tcs_sort_area(BLE_BASE, sizeof(BLE_Type), entry_ptr,
&area_offset[tcs_ble], &area_size[tcs_ble]);
#endif
#ifdef CONFIG_USE_FTDF
entry_ptr = sys_tcs_sort_area(FTDF_BASE, sizeof(FTDF_Type), entry_ptr,
&area_offset[tcs_ftdf], &area_size_global[tcs_ftdf]);
#endif
entry_ptr = sys_tcs_sort_area(RFCU_BASE, RADIO_AREA_SIZE, entry_ptr,
&area_offset[tcs_radio], &area_size_global[tcs_radio]);
entry_ptr = sys_tcs_sort_area((uint32_t)&ANAMISC->CHARGER_CTRL2_REG, 1, entry_ptr,
&area_offset[tcs_charger], &area_size_global[tcs_charger]);
entry_ptr = sys_tcs_sort_area(APU_BASE, sizeof(APU_Type), entry_ptr,
&area_offset[tcs_audio], &area_size_global[tcs_audio]);
// The rest should be System. Assert if not!
for (i = entry_ptr; i < tcs_length; i += 2)
{
if (IS_IN_AREA(tcs_data[i], UART_BASE, PERIPHERAL_AREA_SIZE))
{
ASSERT_WARNING(0);
}
if (IS_IN_AREA(tcs_data[i], CRG_TOP_BASE, 0x6100))
{
// It is ok (most probably).
}
else
{
ASSERT_WARNING(0);
}
}
area_offset[tcs_system] = entry_ptr;
area_size_global[tcs_system] = tcs_length - entry_ptr;
tcs_ptr = tcs_data;
}
else
{
tcs_ptr = uncalibrated_tcs_data;
for (i = 0; i < UNCALIBRATED_DATA_NON_RETAINED_OFFSET; i += 2)
{
apply_pair(tcs_ptr[i], tcs_ptr[i + 1]);
}
#ifdef CONFIG_USE_BLE
if (UNCALIBRATED_DATA_BLE_SIZE > 0)
{
area_offset[tcs_ble] = UNCALIBRATED_DATA_BLE_OFFSET;
area_size[tcs_ble] = UNCALIBRATED_DATA_BLE_SIZE;
}
#endif
#ifdef CONFIG_USE_FTDF
if (UNCALIBRATED_DATA_FTDF_SIZE > 0)
{
area_offset[tcs_ftdf] = UNCALIBRATED_DATA_FTDF_OFFSET;
area_size_global[tcs_ftdf] = UNCALIBRATED_DATA_FTDF_SIZE;
}
#endif
if (UNCALIBRATED_DATA_RADIO_SIZE > 0)
{
area_offset[tcs_radio] = UNCALIBRATED_DATA_RADIO_OFFSET;
area_size_global[tcs_radio] = UNCALIBRATED_DATA_RADIO_SIZE;
}
if (UNCALIBRATED_DATA_CHARGER_SIZE > 0)
{
area_offset[tcs_charger] = UNCALIBRATED_DATA_CHARGER_OFFSET;
area_size_global[tcs_charger] = UNCALIBRATED_DATA_CHARGER_SIZE;
}
if (UNCALIBRATED_DATA_AUDIO_SIZE > 0)
{
area_offset[tcs_audio] = UNCALIBRATED_DATA_AUDIO_OFFSET;
area_size_global[tcs_audio] = UNCALIBRATED_DATA_AUDIO_SIZE;
}
if (UNCALIBRATED_DATA_SYSTEM_SIZE > 0)
{
area_offset[tcs_system] = UNCALIBRATED_DATA_SYSTEM_OFFSET;
area_size_global[tcs_system] = UNCALIBRATED_DATA_SYSTEM_SIZE;
}
}
}
void sys_tcs_apply(sys_tcs_area_t area)
{
int i;
for (i = area_offset[area]; i < (area_offset[area] + area_size_global[area]); i += 2)
{
apply_entry(i);
}
}
/**
\}
\}
\}
*/
+118
View File
@@ -0,0 +1,118 @@
/**
\addtogroup INTERFACES
\{
\addtogroup RADIO
\{
\addtogroup FTDF
\{
*/
/**
****************************************************************************************
* @file ad_ftdf_config.h
*
* @brief FTDF Adapter API
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 AD_FTDF_CONFIG_H
#define AD_FTDF_CONFIG_H
#ifndef FTDF_PHY_API
#include "queue.h"
#endif
#include "ftdf.h"
/**
* \brief Sleep When Idle
*
* If set, the block will sleep when Idle
*
*/
#define AD_FTDF_SLEEP_WHEN_IDLE 1
/**
* \brief Idle Timeout
*
* Idle Timeout, in OS scheduler ticks, after which, if still Idle, FTDF will
* be put to sleep. Only applicable if AD_FTDF_SLEEP_WHEN_IDLE 1
*
*/
#define AD_FTDF_IDLE_TIMEOUT 1
/**
* \brief UP Queue size
*
* Defines the UP (UMAC to client app) Queue length, in number of messages
*
*/
#define AD_FTDF_UP_QUEUE_LENGTH 16
/**
* \brief DOWN Queue size
*
* Defines the DOWN (client app to UMAC) Queue length, in number of messages
*
*/
#define AD_FTDF_DOWN_QUEUE_LENGTH 16
/**
* \brief Low Power Clock cycle
*
* Defines the Low Power clock cycle in pico secs. Used for computation needed
* for sleeping / waking up FTDF
*
*/
#define AD_FTDF_LP_CLOCK_CYCLE 30517578
/**
* \brief Wake Up Latency
*
* Defines the Wake Up Latency expressed in Low Power clock cycles, that is
* the number of LP clock cycles needed for the FTDF to be fully operational
* (calculations and FTDF timer synchronization)
*
*/
#define AD_FTDF_WUP_LATENCY 10
/**
* \brief Sleep value compensation
*
* Defines the sleep value compensation expressed in microseconds. This value
* is subtracted from the sleep time returned by FTDF_canSleep( )
*/
#define AD_FTDF_SLEEP_COMPENSATION 1500
#endif /* AD_FTDF_CONFIG_H */
/**
\}
\}
\}
*/
+131
View File
@@ -0,0 +1,131 @@
/**
\addtogroup INTERFACES
\{
\addtogroup RADIO
\{
\addtogroup FTDF
\{
*/
/**
****************************************************************************************
* @file ad_ftdf_phy_api.h
*
* @brief FTDF PHY Adapter API
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 AD_FTDF_PHY_API_H
#define AD_FTDF_PHY_API_H
#include "ftdf.h"
#include "ad_ftdf_config.h"
/**
* \brief Initialize adapter - create queues
*
*/
void ad_ftdf_init(void);
/**
* \brief Set Extended Address
*
* Sets interface extended address. This is thread safe.
*
* \param[in] address - The extended address to set
*/
void ad_ftdf_setExtAddress( FTDF_ExtAddress address);
/**
* \brief Get Extended Address
*
* Gets interface extended address. This is thread safe.
*
* \returns The extended address of the interface
*/
FTDF_ExtAddress ad_ftdf_getExtAddress( void);
/**
* \brief Transmits a frame
*
* Transmits a frame. Params:
*
* \param[in] frameLength - The total length of the frame passed in bytes
* \param[in] frame - a pointer to the passed frame buffer
* \param[in] channel - The channel to use for transmission in [11, 26]
* \param[in] csmaSuppress - If true, csma protocol (i.e. CCA) will not be performed
* \param[in] pti - Packet Traffic Information that will be used for this transaction.
*/
FTDF_Status ad_ftdf_send_frame_simple( FTDF_DataLength frameLength,
FTDF_Octet* frame,
FTDF_ChannelNumber channel,
FTDF_PTI pti,
FTDF_Boolean csmaSuppress);
/**
* \brief Instructs the MAC and PHY to go to sleep
*
* \param[in] allow_deferred_sleep - If true, then if the MAC cannot go to sleep immediately
* (e.g. a transmission is pending), the MAC will go to sleep
* as soon as possible. If false, and the MAC cannot go to sleep
* immediately, sleep will be aborted.
*/
void ad_ftdf_sleep_when_possible( FTDF_Boolean allow_deferred_sleep);
/**
* \brief Instructs the MAC and PHY to wakeup, if sleeping
*
*/
void ad_ftdf_wake_up(void);
#if FTDF_DBG_BUS_ENABLE
/**
* \brief Configures GPIO pins for the FTDF debug bus
*
* Debug bus uses the following (fixed) GPIO pins:
*
* bit 0: HW_GPIO_PORT_1, HW_GPIO_PIN_4
* bit 1: HW_GPIO_PORT_1, HW_GPIO_PIN_5
* bit 2: HW_GPIO_PORT_1, HW_GPIO_PIN_6
* bit 3: HW_GPIO_PORT_1, HW_GPIO_PIN_7
* bit 4: HW_GPIO_PORT_0, HW_GPIO_PIN_6
* bit 5: HW_GPIO_PORT_0, HW_GPIO_PIN_7
* bit 6: HW_GPIO_PORT_1, HW_GPIO_PIN_3
* bit 7: HW_GPIO_PORT_2, HW_GPIO_PIN_3
*/
void ad_ftdf_dbgBusGpioConfig(void);
#endif /* FTDF_DBG_BUS_ENABLE */
#endif /* AD_FTDF_PHY_API_H */
/**
\}
\}
\}
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,150 @@
/**
****************************************************************************************
*
* @file ftdf_config_phy_api.h
*
* @brief FTDF PHY API configuration template file
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 FTDF_CONFIG_PHY_API_H_
#define FTDF_CONFIG_PHY_API_H_
//#include "osal.h" // OS_FREERTOS macro is checked within the header file.
/**
* \remark phy configuration values in microseconds
*/
#define FTDF_PHYTXSTARTUP 0x4c
#define FTDF_PHYTXLATENCY 0x01
#define FTDF_PHYTXFINISH 0x00
#define FTDF_PHYTRXWAIT 0x0f
#define FTDF_PHYRXSTARTUP 0
#define FTDF_PHYRXLATENCY 0
#define FTDF_PHYENABLE 0
#ifndef FTDF_LITE
#define FTDF_LITE
#endif
/**
* \remark See FTDF_GET_MSG_BUFFER in ftdf.h
*/
#define FTDF_GET_MSG_BUFFER ad_ftdf_getMsgBuffer
/**
* \remark See FTDF_REL_MSG_BUFFER in ftdf.h
*/
#define FTDF_REL_MSG_BUFFER ad_ftdf_relMsgBuffer
/**
* \remark See FTDF_REC_MSG in ftdf.h
*/
#define FTDF_RCV_MSG ad_ftdf_rcvMsg
/**
* \remark See FTDF_GET_DATA_BUFFER in ftdf.h
*/
#define FTDF_GET_DATA_BUFFER ad_ftdf_getDataBuffer
/**
* \remark See FTDF_REL_DATA_BUFFER in ftdf.h
*/
#define FTDF_REL_DATA_BUFFER ad_ftdf_relDataBuffer
/**
* \remark See FTDF_GET_EXT_ADDRESS in ftdf.h
*/
#define FTDF_GET_EXT_ADDRESS ad_ftdf_getExtAddress
/**
* \remark See FTDF_RCV_FRAME_TRANSPARENT in ftdf.h
*/
#define FTDF_RCV_FRAME_TRANSPARENT FTDF_rcvFrameTransparent
/**
* \remark See FTDF_SEND_FRAME_TRANSPARENT_CONFIRM in ftdf.h
*/
#define FTDF_SEND_FRAME_TRANSPARENT_CONFIRM FTDF_sendFrameTransparentConfirm
/**
* \remark See FTDF_WAKE_UP_READY in ftdf.h
*/
#define FTDF_WAKE_UP_READY ad_ftdf_wakeUpReady
/**
* \remark See FTDF_SLEEP_CALLBACK in ftdf.h
*/
#define FTDF_SLEEP_CALLBACK ad_ftdf_sleepCb
/* Forward declaration */
void sleep_when_possible( uint8_t explicit_request, uint32_t sleepTime );
#define FTDF_LMACREADY4SLEEP_CB sleep_when_possible
#ifndef OS_FREERTOS
#define portDISABLE_INTERRUPTS() \
do { \
__asm volatile ( " cpsid i " ); \
DBG_CONFIGURE_HIGH(CMN_TIMING_DEBUG, CMNDBG_CRITICAL_SECTION); \
} while (0)
#define portENABLE_INTERRUPTS() \
do { \
DBG_CONFIGURE_LOW(CMN_TIMING_DEBUG, CMNDBG_CRITICAL_SECTION); \
__asm volatile ( " cpsie i " ); \
} while (0)
void vPortEnterCritical( void );
void vPortExitCritical( void );
#endif
/**
* \remark Critical section
*/
#define FTDF_criticalVar( )
#define FTDF_enterCritical( ) vPortEnterCritical()
#define FTDF_exitCritical( ) vPortExitCritical()
#ifndef FTDF_DBG_BUS_ENABLE
/**
* \brief Whether FTDF debug bus will be available or not.
*
* Define to 0 for production software.
*
* Refer to \ref ad_ftdf_dbgBusGpioConfig for the GPIO pins used for the debug bus.
*/
#define FTDF_DBG_BUS_ENABLE 0
#endif
#if FTDF_DBG_BUS_ENABLE
#define FTDF_DBG_BUS_GPIO_CONFIG ad_ftdf_dbgBusGpioConfig
#endif /* FTDF_DBG_BUS_ENABLE */
#endif /* FTDF_CONFIG_PHY_API_H_ */
@@ -0,0 +1,288 @@
/**
****************************************************************************************
*
* @file ftdf.c
*
* @brief FTDF FreeRTOS Adapter
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <string.h>
#include <stdbool.h>
#ifndef FTDF_PHY_API
#include "osal.h"
#include "queue.h"
#include "sys_power_mgr.h"
#endif
#include "ad_rf.h"
#include "sys_tcs.h"
#include "black_orca.h"
#include "ad_ftdf.h"
#include "ad_rf.h"
#include "internal.h"
#include "regmap.h"
#if FTDF_DBG_BUS_ENABLE
#include "hw_gpio.h"
#endif /* FTDF_DBG_BUS_ENABLE */
#define WUP_LATENCY (AD_FTDF_LP_CLOCK_CYCLE * AD_FTDF_WUP_LATENCY)
#ifdef FTDF_PHY_API
#ifndef PRIVILEGED_DATA
#define PRIVILEGED_DATA __attribute__((section("privileged_data_zi")))
#endif
#ifndef INITIALIZED_PRIVILEGED_DATA
#define INITIALIZED_PRIVILEGED_DATA __attribute__((section("privileged_data_rw")))
#endif
#endif
PRIVILEGED_DATA FTDF_Boolean explicit_sleep; /* = FTDF_FALSE; */
PRIVILEGED_DATA eSleepStatus sleep_status;
PRIVILEGED_DATA FTDF_ExtAddress uExtAddress;
static void ad_ftdf_sleep(void)
{
FTDF_criticalVar();
FTDF_enterCritical();
REG_SET_BIT(CRG_TOP, PMU_CTRL_REG, FTDF_SLEEP); // go sleep
FTDF_exitCritical();
while (REG_GETF(CRG_TOP, SYS_STAT_REG, FTDF_IS_DOWN) == 0x0) // don't go-go before I sleep
{
}
}
void ad_ftdf_wake_up_internal(bool sync)
{
if (sleep_status != BLOCK_SLEEPING)
{
return;
}
FTDF_criticalVar();
FTDF_enterCritical();
/* Wake up power domains */
REG_CLR_BIT(CRG_TOP, PMU_CTRL_REG, FTDF_SLEEP); // go wake up
FTDF_exitCritical();
while (REG_GETF(CRG_TOP, SYS_STAT_REG, FTDF_IS_UP) == 0x0) // don't go-go before I sleep
{
}
/* Power on and configure RF */
#if dg_configRF_ADAPTER
ad_rf_request_on(false);
#else
vPortEnterCritical();
hw_rf_request_on(false);
vPortExitCritical();
#endif
/* Apply trim values */
sys_tcs_apply(tcs_ftdf);
#if dg_configRF_ADAPTER
ad_rf_request_recommended_settings();
#else
vPortEnterCritical();
hw_rf_request_recommended_settings();
vPortExitCritical();
#endif
if (sync)
{
FTDF_initLmac();
sleep_status = BLOCK_ACTIVE;
}
else
{
/* Wake up FTDF block */
sleep_status = BLOCK_WAKING_UP;
FTDF_wakeUp();
#if defined(FTDF_NO_CSL) && defined(FTDF_NO_TSCH)
ad_ftdf_wakeUpReady();
#endif
}
}
void ad_ftdf_wake_up_async(void)
{
ad_ftdf_wake_up_internal(false);
}
void ad_ftdf_wake_up_sync(void)
{
ad_ftdf_wake_up_internal(true);
}
void sleep_when_possible(uint8_t explicit_request, uint32_t sleepTime)
{
FTDF_Boolean blockSleep = FTDF_FALSE;
if ((!AD_FTDF_SLEEP_WHEN_IDLE && !explicit_request) || sleep_status != BLOCK_ACTIVE)
{
return;
}
FTDF_USec us;
FTDF_criticalVar();
FTDF_enterCritical();
#ifdef FTDF_PHY_API
if (explicit_request && FTDF_GET_FIELD(ON_OFF_REGMAP_LMACREADY4SLEEP) == 0)
{
volatile uint32_t *lmacCtrlMask = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_LMAC_CONTROL_MASK);
volatile uint32_t *lmacReady4sleepEvent = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_LMACREADY4SLEEP_D);
/* clear a previous interrupt */
*lmacReady4sleepEvent = MSK_F_FTDF_ON_OFF_REGMAP_LMACREADY4SLEEP_D;
/* Enable (unmask) interrupt */
*lmacCtrlMask |= MSK_F_FTDF_ON_OFF_REGMAP_LMACREADY4SLEEP_M;
us = 0;
}
else
{
us = FTDF_canSleep();
}
#else
us = FTDF_canSleep();
#endif
/* Try to sleep as much as needed (if sleepTime is 0, then sleep as much as possible).
* Otherwise, sleep as much as possible. */
if (explicit_request == FTDF_TRUE)
{
if (sleepTime && us > sleepTime)
{
us = sleepTime;
}
}
if (us > (WUP_LATENCY / 1000000) + AD_FTDF_SLEEP_COMPENSATION)
{
// Subtract sleep compensation from the sleep time, compensating for delays
us -= AD_FTDF_SLEEP_COMPENSATION;
blockSleep = FTDF_prepareForSleep(us);
if (blockSleep)
{
// FTDF ready to sleep, disable clocks
sleep_status = BLOCK_SLEEPING;
explicit_sleep = explicit_request;
ad_ftdf_sleep();
}
}
FTDF_exitCritical();
if (blockSleep)
{
#if dg_configRF_ADAPTER
ad_rf_request_off(false);
#else
vPortEnterCritical();
hw_rf_request_off(false);
vPortExitCritical();
#endif
}
}
/**
* @brief Initialization function of FTDF adapter
*/
void ad_ftdf_init(void)
{
/* Wake up power domains */
REG_CLR_BIT(CRG_TOP, PMU_CTRL_REG, FTDF_SLEEP); // go wake up
while (REG_GETF(CRG_TOP, SYS_STAT_REG, FTDF_IS_UP) == 0x0) // don't go-go before I sleep
{
}
REG_SET_BIT(CRG_TOP, CLK_RADIO_REG, FTDF_MAC_ENABLE); // on
REG_SETF(CRG_TOP, CLK_RADIO_REG, FTDF_MAC_DIV, 0); // divide by 1
/* Power on and configure RF */
ad_rf_request_on(false);
/* Apply trim values */
sys_tcs_apply(tcs_ftdf);
ad_rf_request_recommended_settings();
FTDF_setSleepAttributes(AD_FTDF_LP_CLOCK_CYCLE,
AD_FTDF_WUP_LATENCY);
#ifdef FTDF_PHY_API
ad_ftdf_init_phy_api();
#else
ad_ftdf_init_mac_api();
#endif
}
void ad_ftdf_sleepCb(FTDF_USec sleepTime)
{
sleep_when_possible(FTDF_TRUE, sleepTime);
}
#if FTDF_DBG_BUS_ENABLE
void ad_ftdf_dbgBusGpioConfig(void)
{
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_4, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_5, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_6, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_7, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_0, HW_GPIO_PIN_6, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_0, HW_GPIO_PIN_7, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_1, HW_GPIO_PIN_3, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
hw_gpio_set_pin_function(HW_GPIO_PORT_2, HW_GPIO_PIN_3, HW_GPIO_MODE_OUTPUT,
HW_GPIO_FUNC_FTDF_DIAG);
}
#endif /* FTDF_DBG_BUS_ENABLE */
+94
View File
@@ -0,0 +1,94 @@
/**
\addtogroup INTERFACES
\{
\addtogroup RADIO
\{
\addtogroup FTDF
\{
*/
/**
****************************************************************************************
* @file ad_ftdf.h
*
* @brief FTDF Adapter internal header file
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 AD_FTDF_H
#define AD_FTDF_H
#ifndef FTDF_PHY_API
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#endif
#include "ftdf.h"
#include "ad_ftdf_config.h"
typedef enum {
BLOCK_ACTIVE = 0, BLOCK_SLEEPING, BLOCK_WAKING_UP
} eSleepStatus;
extern eSleepStatus sleep_status;
extern FTDF_ExtAddress uExtAddress;
extern FTDF_Boolean explicit_sleep;
void ad_ftdf_init_mac_api(void);
void ad_ftdf_init_phy_api(void);
void ad_ftdf_wake_up_async(void);
void ad_ftdf_wake_up_sync(void);
void sleep_when_possible( uint8_t explicit_request, uint32_t sleepTime );
#if FTDF_DBG_BUS_ENABLE
/**
* \brief Configures GPIO pins for the FTDF debug bus
*
* Debug bus uses the following (fixed) GPIO pins:
*
* bit 0: HW_GPIO_PORT_1, HW_GPIO_PIN_4
* bit 1: HW_GPIO_PORT_1, HW_GPIO_PIN_5
* bit 2: HW_GPIO_PORT_1, HW_GPIO_PIN_6
* bit 3: HW_GPIO_PORT_1, HW_GPIO_PIN_7
* bit 4: HW_GPIO_PORT_0, HW_GPIO_PIN_6
* bit 5: HW_GPIO_PORT_0, HW_GPIO_PIN_7
* bit 6: HW_GPIO_PORT_1, HW_GPIO_PIN_3
* bit 7: HW_GPIO_PORT_2, HW_GPIO_PIN_3
*/
void ad_ftdf_dbgBusGpioConfig(void);
#endif /* FTDF_DBG_BUS_ENABLE */
#endif /* AD_FTDF_H */
/**
\}
\}
\}
*/
@@ -0,0 +1,155 @@
/**
****************************************************************************************
*
* @file ftdf.c
*
* @brief FTDF FreeRTOS Adapter
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <string.h>
#include <stdbool.h>
#include "black_orca.h"
#include "ad_ftdf.h"
#include "ad_ftdf_phy_api.h"
#include "internal.h"
#ifndef OS_FREERTOS
static unsigned long uxCriticalNesting = 0x0 ;//0xaaaaaaaa;
void vPortEnterCritical(void)
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
__asm volatile("dsb");
__asm volatile("isb");
}
/*-----------------------------------------------------------*/
void vPortExitCritical(void)
{
uxCriticalNesting--;
if (uxCriticalNesting == 0)
{
portENABLE_INTERRUPTS();
}
}
#endif /* !OS_FREERTOS */
/**
* @brief ftdf_gen_irq interrupt service routine
*/
void FTDF_GEN_Handler(void)
{
FTDF_confirmLmacInterrupt();
FTDF_eventHandler();
}
/**
* @brief ftdf_wakup_irq interrupt service routine
*/
void FTDF_WAKEUP_Handler(void)
{
ad_ftdf_wake_up_async();
}
void ad_ftdf_setExtAddress(FTDF_ExtAddress address)
{
uExtAddress = address;
}
FTDF_ExtAddress ad_ftdf_getExtAddress(void)
{
return uExtAddress;
}
void ad_ftdf_wakeUpReady(void)
{
}
FTDF_Status ad_ftdf_send_frame_simple(FTDF_DataLength frameLength,
FTDF_Octet *frame,
FTDF_ChannelNumber channel,
FTDF_PTI pti,
FTDF_Boolean csmaSuppress)
{
FTDF_criticalVar();
FTDF_enterCritical();
if (FTDF_txInProgress == FTDF_TRUE)
{
FTDF_exitCritical();
return FTDF_TRANSPARENT_OVERFLOW;
}
FTDF_txInProgress = FTDF_TRUE;
FTDF_exitCritical();
if (sleep_status == BLOCK_SLEEPING)
{
/* Wake-up the block */
ad_ftdf_wake_up_async();
sleep_status = BLOCK_ACTIVE;
}
return FTDF_sendFrameSimple(frameLength, frame, channel, pti, csmaSuppress);
}
void ad_ftdf_sleep_when_possible(FTDF_Boolean allow_deferred_sleep)
{
sleep_when_possible(allow_deferred_sleep, 0);
}
void ad_ftdf_wake_up(void)
{
if (sleep_status == BLOCK_SLEEPING)
{
/* Wake-up the block */
ad_ftdf_wake_up_async();
sleep_status = BLOCK_ACTIVE;
}
}
void ad_ftdf_init_phy_api(void)
{
NVIC_ClearPendingIRQ(FTDF_WAKEUP_IRQn);
NVIC_EnableIRQ(FTDF_WAKEUP_IRQn);
NVIC_ClearPendingIRQ(FTDF_GEN_IRQn);
NVIC_EnableIRQ(FTDF_GEN_IRQn);
sleep_status = BLOCK_ACTIVE;
#ifndef OS_FREERTOS
uxCriticalNesting = 0;
#endif
FTDF_reset(0);
}
File diff suppressed because it is too large Load Diff
+662
View File
@@ -0,0 +1,662 @@
/**
****************************************************************************************
*
* @file data.c
*
* @brief FTDF data send/receive functions
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdlib.h>
#include <ftdf.h>
#include "internal.h"
#include "regmap.h"
#ifndef FTDF_LITE
void FTDF_processDataRequest(FTDF_DataRequest *dataRequest)
{
#ifndef FTDF_NO_TSCH
if (FTDF_pib.tschEnabled &&
FTDF_tschSlotLink->request != dataRequest)
{
FTDF_Status status;
if (dataRequest->dstAddrMode == FTDF_SHORT_ADDRESS &&
!dataRequest->indirectTX)
{
status = FTDF_scheduleTsch((FTDF_MsgBuffer *) dataRequest);
if (status == FTDF_SUCCESS)
{
return;
}
}
else
{
status = FTDF_INVALID_PARAMETER;
}
FTDF_sendDataConfirm(dataRequest,
status,
0,
0,
0,
NULL);
return;
}
#endif /* FTDF_NO_TSCH */
int queue;
FTDF_AddressMode dstAddrMode = dataRequest->dstAddrMode;
FTDF_PANId dstPANId = dataRequest->dstPANId;
FTDF_Address dstAddr = dataRequest->dstAddr;
// Search for an existing indirect queue
for (queue = 0; queue < FTDF_NR_OF_REQ_BUFFERS; queue++)
{
if (dstAddrMode == FTDF_SHORT_ADDRESS)
{
if (FTDF_txPendingList[ queue ].addrMode == dstAddrMode &&
FTDF_txPendingList[ queue ].addr.shortAddress == dstAddr.shortAddress)
{
break;
}
}
else if (dstAddrMode == FTDF_EXTENDED_ADDRESS)
{
if (FTDF_txPendingList[ queue ].addrMode == dstAddrMode &&
FTDF_txPendingList[ queue ].addr.extAddress == dstAddr.extAddress)
{
break;
}
}
}
if (dataRequest->indirectTX)
{
FTDF_Status status = FTDF_SUCCESS;
if (queue < FTDF_NR_OF_REQ_BUFFERS)
{
// Queue request in existing queue
status = FTDF_queueReqHead((FTDF_MsgBuffer *) dataRequest, &FTDF_txPendingList[ queue ].queue);
if (status == FTDF_SUCCESS)
{
FTDF_addTxPendingTimer((FTDF_MsgBuffer *) dataRequest,
queue,
FTDF_pib.transactionPersistenceTime * FTDF_BASE_SUPERFRAME_DURATION,
FTDF_sendTransactionExpired);
return;
}
}
if (dstAddrMode != FTDF_EXTENDED_ADDRESS &&
dstAddrMode != FTDF_SHORT_ADDRESS)
{
status = FTDF_INVALID_PARAMETER;
}
if (status != FTDF_SUCCESS)
{
// Queueing of indirect transfer was successful
FTDF_sendDataConfirm(dataRequest,
status,
0,
0,
0,
NULL);
return;
}
// Search for an empty indirect queue
for (queue = 0; queue < FTDF_NR_OF_REQ_BUFFERS; queue++)
{
if (FTDF_txPendingList[ queue ].addrMode == FTDF_NO_ADDRESS)
{
FTDF_txPendingList[ queue ].addrMode = dstAddrMode;
FTDF_txPendingList[ queue ].PANId = dstPANId;
FTDF_txPendingList[ queue ].addr = dstAddr;
status = FTDF_queueReqHead((FTDF_MsgBuffer *) dataRequest,
&FTDF_txPendingList[ queue ].queue);
if (status == FTDF_SUCCESS)
{
FTDF_addTxPendingTimer((FTDF_MsgBuffer *) dataRequest,
queue,
FTDF_pib.transactionPersistenceTime * FTDF_BASE_SUPERFRAME_DURATION,
FTDF_sendTransactionExpired);
return;
}
else
{
break;
}
}
}
// Did not find an existing or an empty queue
FTDF_sendDataConfirm(dataRequest, FTDF_TRANSACTION_OVERFLOW,
0,
0,
0,
NULL);
return;
}
if (FTDF_reqCurrent == NULL)
{
FTDF_reqCurrent = (FTDF_MsgBuffer *) dataRequest;
}
else
{
if (FTDF_queueReqHead((FTDF_MsgBuffer *) dataRequest, &FTDF_reqQueue) == FTDF_TRANSACTION_OVERFLOW)
{
FTDF_sendDataConfirm(dataRequest, FTDF_TRANSACTION_OVERFLOW,
0,
0,
0,
NULL);
}
return;
}
FTDF_FrameHeader *frameHeader = &FTDF_fh;
FTDF_SecurityHeader *securityHeader = &FTDF_sh;
frameHeader->frameType = dataRequest->sendMultiPurpose ? FTDF_MULTIPURPOSE_FRAME : FTDF_DATA_FRAME;
FTDF_Boolean framePending;
if (queue < FTDF_NR_OF_REQ_BUFFERS)
{
framePending = FTDF_TRUE;
}
else
{
framePending = FTDF_FALSE;
}
frameHeader->options =
(dataRequest->securityLevel > 0 ? FTDF_OPT_SECURITY_ENABLED : 0) |
(dataRequest->ackTX ? FTDF_OPT_ACK_REQUESTED : 0) |
(framePending ? FTDF_OPT_FRAME_PENDING : 0) |
((dataRequest->frameControlOptions & FTDF_PAN_ID_PRESENT) ? FTDF_OPT_PAN_ID_PRESENT : 0) |
((dataRequest->frameControlOptions & FTDF_IES_INCLUDED) ? FTDF_OPT_IES_PRESENT : 0) |
((dataRequest->frameControlOptions & FTDF_SEQ_NR_SUPPRESSED) ? FTDF_OPT_SEQ_NR_SUPPRESSED : 0);
if (FTDF_pib.leEnabled || FTDF_pib.tschEnabled)
{
frameHeader->options |= FTDF_OPT_ENHANCED;
}
frameHeader->srcAddrMode = dataRequest->srcAddrMode;
frameHeader->srcPANId = FTDF_pib.PANId;
frameHeader->dstAddrMode = dataRequest->dstAddrMode;
frameHeader->dstPANId = dataRequest->dstPANId;
frameHeader->dstAddr = dataRequest->dstAddr;
securityHeader->securityLevel = dataRequest->securityLevel;
securityHeader->keyIdMode = dataRequest->keyIdMode;
securityHeader->keyIndex = dataRequest->keyIndex;
securityHeader->keySource = dataRequest->keySource;
securityHeader->frameCounter = FTDF_pib.frameCounter;
securityHeader->frameCounterMode = FTDF_pib.frameCounterMode;
#ifndef FTDF_NO_TSCH
if (FTDF_pib.tschEnabled)
{
frameHeader->SN = FTDF_processTschSN((FTDF_MsgBuffer *)dataRequest,
FTDF_pib.DSN,
&dataRequest->requestSN);
}
else
#endif /* FTDF_NO_TSCH */
{
frameHeader->SN = FTDF_pib.DSN;
}
FTDF_Octet *txPtr = (FTDF_Octet *) FTDF_GET_REG_ADDR(RETENTION_RAM_TX_FIFO) +
(FTDF_BUFFER_LENGTH * FTDF_TX_DATA_BUFFER);
// Skip PHY header (= MAC length)
txPtr++;
FTDF_DataLength msduLength = dataRequest->msduLength;
txPtr = FTDF_addFrameHeader(txPtr,
frameHeader,
msduLength);
txPtr = FTDF_addSecurityHeader(txPtr,
securityHeader);
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
if (dataRequest->frameControlOptions & FTDF_IES_INCLUDED)
{
txPtr = FTDF_addIes(txPtr,
dataRequest->headerIEList,
dataRequest->payloadIEList,
dataRequest->msduLength);
}
#endif /* !FTDF_NO_CSL || !FTDF_NO_TSCH */
FTDF_Status status = FTDF_sendFrame(FTDF_pib.currentChannel,
frameHeader,
securityHeader,
txPtr,
dataRequest->msduLength,
dataRequest->msdu);
if (status != FTDF_SUCCESS)
{
FTDF_sendDataConfirm(dataRequest, status,
0,
0,
0,
NULL);
FTDF_reqCurrent = NULL;
return;
}
FTDF_nrOfRetries = 0;
if (frameHeader->SN == FTDF_pib.DSN)
{
FTDF_pib.DSN++;
}
}
void FTDF_sendDataConfirm(FTDF_DataRequest *dataRequest,
FTDF_Status status,
FTDF_Time timestamp,
FTDF_SN DSN,
FTDF_NumOfBackoffs numOfBackoffs,
FTDF_IEList *ackPayload)
{
FTDF_REL_DATA_BUFFER(dataRequest->msdu);
FTDF_DataConfirm *dataConfirm = (FTDF_DataConfirm *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_DataConfirm));
dataConfirm->msgId = FTDF_DATA_CONFIRM;
dataConfirm->msduHandle = dataRequest->msduHandle;
dataConfirm->status = status;
dataConfirm->timestamp = timestamp;
dataConfirm->numOfBackoffs = numOfBackoffs;
dataConfirm->DSN = DSN;
dataConfirm->ackPayload = ackPayload;
if (FTDF_reqCurrent == (FTDF_MsgBuffer *)dataRequest)
{
FTDF_reqCurrent = NULL;
}
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) dataRequest);
FTDF_RCV_MSG((FTDF_MsgBuffer *) dataConfirm);
FTDF_processNextRequest();
}
void FTDF_sendDataIndication(FTDF_FrameHeader *frameHeader,
FTDF_SecurityHeader *securityHeader,
FTDF_IEList *payloadIEList,
FTDF_DataLength msduLength,
FTDF_Octet *msdu,
FTDF_LinkQuality mpduLinkQuality,
FTDF_Time timestamp)
{
FTDF_DataIndication *dataIndication = (FTDF_DataIndication *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_DataIndication));
FTDF_Octet *msduBuf = FTDF_GET_DATA_BUFFER(msduLength);
FTDF_Octet *bufPtr = msduBuf;
int n;
for (n = 0; n < msduLength; n++)
{
*msduBuf++ = *msdu++;
}
dataIndication->msgId = FTDF_DATA_INDICATION;
dataIndication->srcAddrMode = frameHeader->srcAddrMode;
dataIndication->srcPANId = frameHeader->srcPANId;
dataIndication->srcAddr = frameHeader->srcAddr;
dataIndication->dstAddrMode = frameHeader->dstAddrMode;
dataIndication->dstPANId = frameHeader->dstPANId;
dataIndication->dstAddr = frameHeader->dstAddr;
dataIndication->msduLength = msduLength;
dataIndication->msdu = bufPtr;
dataIndication->mpduLinkQuality = mpduLinkQuality;
dataIndication->DSN = frameHeader->SN;
dataIndication->timestamp = timestamp;
dataIndication->securityLevel = securityHeader->securityLevel;
dataIndication->keyIdMode = securityHeader->keyIdMode;
dataIndication->keyIndex = securityHeader->keyIndex;
dataIndication->payloadIEList = payloadIEList;
if (dataIndication->keyIdMode == 0x2)
{
for (n = 0; n < 4; n++)
{
dataIndication->keySource[ n ] = securityHeader->keySource[ n ];
}
}
else if (dataIndication->keyIdMode == 0x3)
{
for (n = 0; n < 8; n++)
{
dataIndication->keySource[ n ] = securityHeader->keySource[ n ];
}
}
FTDF_RCV_MSG((FTDF_MsgBuffer *) dataIndication);
}
void FTDF_processPollRequest(FTDF_PollRequest *pollRequest)
{
if (FTDF_reqCurrent == NULL)
{
FTDF_reqCurrent = (FTDF_MsgBuffer *) pollRequest;
}
else
{
if (FTDF_queueReqHead((FTDF_MsgBuffer *) pollRequest, &FTDF_reqQueue) == FTDF_TRANSACTION_OVERFLOW)
{
FTDF_sendPollConfirm(pollRequest, FTDF_TRANSACTION_OVERFLOW);
}
return;
}
FTDF_FrameHeader *frameHeader = &FTDF_fh;
FTDF_SecurityHeader *securityHeader = &FTDF_sh;
frameHeader->frameType = FTDF_MAC_COMMAND_FRAME;
frameHeader->options =
(pollRequest->securityLevel > 0 ? FTDF_OPT_SECURITY_ENABLED : 0) | FTDF_OPT_ACK_REQUESTED;
if (FTDF_pib.shortAddress < 0xfffe)
{
frameHeader->srcAddrMode = FTDF_SHORT_ADDRESS;
frameHeader->srcAddr.shortAddress = FTDF_pib.shortAddress;
}
else
{
frameHeader->srcAddrMode = FTDF_EXTENDED_ADDRESS;
frameHeader->srcAddr.extAddress = FTDF_pib.extAddress;
}
frameHeader->srcPANId = FTDF_pib.PANId;
frameHeader->dstAddrMode = pollRequest->coordAddrMode;
frameHeader->dstPANId = pollRequest->coordPANId;
frameHeader->dstAddr = pollRequest->coordAddr;
securityHeader->securityLevel = pollRequest->securityLevel;
securityHeader->keyIdMode = pollRequest->keyIdMode;
securityHeader->keyIndex = pollRequest->keyIndex;
securityHeader->keySource = pollRequest->keySource;
securityHeader->frameCounter = FTDF_pib.frameCounter;
securityHeader->frameCounterMode = FTDF_pib.frameCounterMode;
FTDF_Octet *txPtr = (FTDF_Octet *) FTDF_GET_REG_ADDR(RETENTION_RAM_TX_FIFO) +
(FTDF_BUFFER_LENGTH * FTDF_TX_DATA_BUFFER);
// Skip PHY header (= MAC length)
txPtr++;
frameHeader->SN = FTDF_pib.DSN;
txPtr = FTDF_addFrameHeader(txPtr,
frameHeader,
1);
txPtr = FTDF_addSecurityHeader(txPtr,
securityHeader);
*txPtr++ = FTDF_COMMAND_DATA_REQUEST;
FTDF_Status status = FTDF_sendFrame(FTDF_pib.currentChannel,
frameHeader,
securityHeader,
txPtr,
0,
NULL);
if (status != FTDF_SUCCESS)
{
FTDF_sendPollConfirm(pollRequest, status);
return;
}
FTDF_nrOfRetries = 0;
FTDF_pib.DSN++;
}
void FTDF_sendPollConfirm(FTDF_PollRequest *pollRequest, FTDF_Status status)
{
FTDF_PollConfirm *pollConfirm = (FTDF_PollConfirm *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_PollConfirm));
pollConfirm->msgId = FTDF_POLL_CONFIRM;
pollConfirm->status = status;
if (FTDF_reqCurrent == (FTDF_MsgBuffer *)pollRequest)
{
FTDF_reqCurrent = NULL;
}
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) pollRequest);
FTDF_RCV_MSG((FTDF_MsgBuffer *) pollConfirm);
FTDF_processNextRequest();
}
void FTDF_processPurgeRequest(FTDF_PurgeRequest *purgeRequest)
{
FTDF_Handle msduHandle = purgeRequest->msduHandle;
FTDF_Status status = FTDF_INVALID_HANDLE;
int n;
for (n = 0; n < FTDF_NR_OF_REQ_BUFFERS; n++)
{
FTDF_MsgBuffer *request = FTDF_dequeueByHandle(msduHandle, &FTDF_txPendingList[ n ].queue);
if (request)
{
FTDF_DataRequest *dataRequest = (FTDF_DataRequest *) request;
if (dataRequest->indirectTX == FTDF_TRUE)
{
FTDF_removeTxPendingTimer(request);
if (FTDF_isQueueEmpty(&FTDF_txPendingList[ n ].queue))
{
FTDF_txPendingList[ n ].addrMode = FTDF_NO_ADDRESS;
}
}
FTDF_REL_DATA_BUFFER(dataRequest->msdu);
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) dataRequest);
status = FTDF_SUCCESS;
break;
}
}
FTDF_PurgeConfirm *purgeConfirm = (FTDF_PurgeConfirm *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_PurgeConfirm));
purgeConfirm->msgId = FTDF_PURGE_CONFIRM;
purgeConfirm->msduHandle = msduHandle;
purgeConfirm->status = status;
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) purgeRequest);
FTDF_RCV_MSG((FTDF_MsgBuffer *) purgeConfirm);
}
#endif /* !FTDF_LITE */
#ifdef FTDF_PHY_API
FTDF_Status FTDF_sendFrameSimple(FTDF_DataLength frameLength,
FTDF_Octet *frame,
FTDF_ChannelNumber channel,
FTDF_PTI pti,
FTDF_Boolean csmaSuppress)
{
FTDF_Octet *fp = frame;
if (frameLength > 127 ||
FTDF_transparentMode != FTDF_TRUE)
{
return FTDF_INVALID_PARAMETER;
}
FTDF_Octet *txPtr = (FTDF_Octet *) FTDF_GET_REG_ADDR(RETENTION_RAM_TX_FIFO) +
(FTDF_BUFFER_LENGTH * FTDF_TX_DATA_BUFFER);
/* This data copy could/should be optimized using DMA */
*txPtr++ = frameLength;
int n;
for (n = 0; n < frameLength; n++)
{
*txPtr++ = *fp++;
}
FTDF_criticalVar();
FTDF_enterCritical();
FTDF_nrOfRetries = 0;
FTDF_exitCritical();
FTDF_sendTransparentFrame(frameLength,
frame,
channel,
pti,
csmaSuppress);
return FTDF_SUCCESS;
}
#else /* !FTDF_PHY_API */
void FTDF_processTransparentRequest(FTDF_TransparentRequest *transparentRequest)
{
FTDF_DataLength frameLength = transparentRequest->frameLength;
if (frameLength > 127 ||
FTDF_transparentMode != FTDF_TRUE)
{
FTDF_SEND_FRAME_TRANSPARENT_CONFIRM(transparentRequest->handle,
FTDF_INVALID_PARAMETER);
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) transparentRequest);
return;
}
if (FTDF_reqCurrent == NULL)
{
FTDF_reqCurrent = (FTDF_MsgBuffer *) transparentRequest;
}
else
{
#ifndef FTDF_LITE
if (FTDF_queueReqHead((FTDF_MsgBuffer *) transparentRequest, &FTDF_reqQueue) == FTDF_TRANSACTION_OVERFLOW)
{
#endif /* !FTDF_LITE */
FTDF_SEND_FRAME_TRANSPARENT_CONFIRM(transparentRequest->handle,
FTDF_TRANSPARENT_OVERFLOW);
FTDF_REL_MSG_BUFFER((FTDF_MsgBuffer *) transparentRequest);
#ifndef FTDF_LITE
}
#endif /* !FTDF_LITE */
return;
}
FTDF_Octet *txPtr = (FTDF_Octet *) FTDF_GET_REG_ADDR(RETENTION_RAM_TX_FIFO) +
(FTDF_BUFFER_LENGTH * FTDF_TX_DATA_BUFFER);
*txPtr++ = frameLength;
FTDF_Octet *frame = transparentRequest->frame;
int n;
for (n = 0; n < frameLength; n++)
{
*txPtr++ = *frame++;
}
FTDF_sendTransparentFrame(frameLength,
transparentRequest->frame,
transparentRequest->channel,
transparentRequest->pti,
transparentRequest->cmsaSuppress);
FTDF_nrOfRetries = 0;
}
void FTDF_sendFrameTransparent(FTDF_DataLength frameLength,
FTDF_Octet *frame,
FTDF_ChannelNumber channel,
FTDF_PTI pti,
FTDF_Boolean cmsaSuppress,
void *handle)
{
FTDF_TransparentRequest *transparentRequest =
(FTDF_TransparentRequest *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_TransparentRequest));
transparentRequest->msgId = FTDF_TRANSPARENT_REQUEST;
transparentRequest->frameLength = frameLength;
transparentRequest->frame = frame;
transparentRequest->channel = channel;
transparentRequest->pti = pti;
transparentRequest->cmsaSuppress = cmsaSuppress;
transparentRequest->handle = handle;
FTDF_processTransparentRequest(transparentRequest);
}
#endif /* FTDF_PHY_API */
+15
View File
@@ -0,0 +1,15 @@
#ifndef FTDFINFO_H_
#define FTDFINFO_H_
/*
* The FTDF release name (version) is listed below, and manually maintained.
* The build time is automatically generated.
*/
#define FTDF_ARCHITECTURE_VERSION 1
#define FTDF_BRANCH_VERSION 0
#define FTDF_LOAD_VERSION 32
const char* FTDF_getUmacRelName( void );
const char* FTDF_getUmacBuildTime( void );
#endif /* FTDFINFO_H_ */
+673
View File
@@ -0,0 +1,673 @@
/**
****************************************************************************************
*
* @file internal.h
*
* @brief Internal header file
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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.
*
****************************************************************************************
*/
#define FTDF_TBD 0
#define FTDF_FCS_LENGTH 2
#define FTDF_BUFFER_LENGTH 128
#define FTDF_NR_OF_REQ_BUFFERS 16
#define FTDF_NR_OF_RX_BUFFERS 8
#define FTDF_NR_OF_CHANNELS 16
#define FTDF_NR_OF_SCAN_RESULTS 16
#define FTDF_NR_OF_CSL_PEERS 16
#define FTDF_MAX_HEADER_IES 8
#define FTDF_MAX_PAYLOAD_IES 4
#define FTDF_MAX_SUB_IES 8
#define FTDF_MAX_IE_CONTENT 128
#define FTDF_NR_OF_RX_ADDRS 16
#define FTDF_NR_OF_NEIGHBORS 16
#define FTDF_TX_DATA_BUFFER 0
#define FTDF_TX_WAKEUP_BUFFER 1
#define FTDF_TX_ACK_BUFFER 2
#define FTDF_OPT_SECURITY_ENABLED 0x01
#define FTDF_OPT_FRAME_PENDING 0x02
#define FTDF_OPT_SEQ_NR_SUPPRESSED 0x04
#define FTDF_OPT_ACK_REQUESTED 0x08
#define FTDF_OPT_IES_PRESENT 0x10
#define FTDF_OPT_PAN_ID_PRESENT 0x20
#define FTDF_OPT_ENHANCED 0x40
#define FTDF_MSK_RX_CE 0x00000002
#define FTDF_MSK_SYMBOL_TMR_CE 0x00000008
#define FTDF_MSK_TX_CE 0x00000010
// The maximum time in symbols that is takes to process request. After succesful
// processing a request the TX buffer is fully initialized and ready to be sent.
#define FTDF_TSCH_MAX_PROCESS_REQUEST_TIME 35
// The maximum time in symbols needed to search for the next slot for which a
// TX or RX needs to be done
#define FTDF_TSCH_MAX_SCHEDULE_TIME 30
#define FTDF_GET_FIELD_ADDR( fieldName ) ( (volatile uint32_t*) ( IND_F_FTDF_ ## fieldName ) )
#define FTDF_GET_FIELD_ADDR_INDEXED( fieldName, index ) ( (volatile uint32_t*) ( IND_F_FTDF_ ## fieldName + \
(intptr_t) index * \
FTDF_ ## fieldName ## _INTVL ) )
#define FTDF_GET_REG_ADDR( regName ) ( (volatile uint32_t*) ( IND_R_FTDF_ ## regName ) )
#define FTDF_GET_REG_ADDR_INDEXED( regName, index ) ( (volatile uint32_t*) ( IND_R_FTDF_ ## regName + \
(intptr_t) index * \
FTDF_ ## regName ## _INTVL ) )
#define FTDF_GET_FIELD( fieldName ) ( ( ( *(volatile uint32_t*) ( IND_F_FTDF_ ## fieldName ) ) & \
MSK_F_FTDF_ ## fieldName ) >> OFF_F_FTDF_ ## fieldName )
#define FTDF_GET_FIELD_INDEXED( fieldName, \
index ) ( ( ( *FTDF_GET_FIELD_ADDR_INDEXED( fieldName, \
index ) ) \
& MSK_F_FTDF_ ## fieldName ) >> OFF_F_FTDF_ ## fieldName )
#define FTDF_SET_FIELD( fieldName, value ) do { \
uint32_t tmp = *FTDF_GET_FIELD_ADDR( fieldName ) & ~MSK_F_FTDF_ ## fieldName; \
*FTDF_GET_FIELD_ADDR( fieldName ) = tmp | \
( ( ( value ) << OFF_F_FTDF_ ## fieldName ) & MSK_F_FTDF_ ## fieldName ); \
} \
while ( 0 )
#define FTDF_processRequest FTDF_sndMsg
struct FTDF_Pib
{
FTDF_ExtAddress extAddress;
FTDF_Period ackWaitDuration;
#ifndef FTDF_LITE
FTDF_Boolean associatedPANCoord;
FTDF_Boolean associationPermit;
FTDF_Boolean autoRequest;
FTDF_Boolean battLifeExt;
FTDF_NumOfBackoffs battLifeExtPeriods;
FTDF_Octet beaconPayload[ FTDF_MAX_BEACON_PAYLOAD_LENGTH ];
FTDF_Size beaconPayloadLength;
FTDF_Order beaconOrder;
FTDF_Time beaconTxTime;
FTDF_SN BSN;
FTDF_ExtAddress coordExtAddress;
FTDF_ShortAddress coordShortAddress;
FTDF_SN DSN;
FTDF_Boolean GTSPermit;
#endif /* !FTDF_LITE */
FTDF_BEExponent maxBE;
FTDF_Size maxCSMABackoffs;
FTDF_Period maxFrameTotalWaitTime;
FTDF_Size maxFrameRetries;
FTDF_BEExponent minBE;
#ifndef FTDF_LITE
FTDF_Period LIFSPeriod;
FTDF_Period SIFSPeriod;
#endif /* !FTDF_LITE */
FTDF_PANId PANId;
#ifndef FTDF_LITE
FTDF_Boolean promiscuousMode; /* Not supported. Use transparent mode instead */
FTDF_Size responseWaitTime;
#endif /* !FTDF_LITE */
FTDF_Boolean rxOnWhenIdle;
#ifndef FTDF_LITE
FTDF_Boolean securityEnabled;
#endif /* !FTDF_LITE */
FTDF_ShortAddress shortAddress;
#ifndef FTDF_LITE
FTDF_Size superframeOrder;
FTDF_Period syncSymbolOffset;
FTDF_Boolean timestampSupported;
FTDF_Period transactionPersistenceTime;
FTDF_Period enhAckWaitDuration;
FTDF_Boolean implicitBroadcast;
FTDF_SimpleAddress simpleAddress;
FTDF_Period disconnectTime;
FTDF_Priority joinPriority;
FTDF_ASN ASN;
FTDF_Boolean noHLBuffers;
FTDF_SlotframeTable slotframeTable;
FTDF_LinkTable linkTable;
FTDF_TimeslotTemplate timeslotTemplate;
FTDF_HoppingSequenceId HoppingSequenceId;
FTDF_ChannelPage channelPage;
FTDF_ChannelNumber numberOfChannels;
FTDF_Bitmap32 phyConfiguration;
FTDF_Bitmap8 extendedBitmap;
FTDF_Length hoppingSequenceLength;
FTDF_ChannelNumber hoppingSequenceList[ FTDF_MAX_HOPPING_SEQUENCE_LENGTH ];
FTDF_Length currentHop;
FTDF_Period dwellTime;
FTDF_Period CSLPeriod;
FTDF_Period CSLMaxPeriod;
FTDF_Bitmap32 CSLChannelMask;
FTDF_Period CSLFramePendingWaitT;
FTDF_Boolean lowEnergySuperframeSupported;
FTDF_Boolean lowEnergySuperframeSyncInterval;
#endif /* !FTDF_LITE */
FTDF_PerformanceMetrics performanceMetrics;
#ifndef FTDF_LITE
FTDF_Boolean useEnhancedBecaon;
FTDF_IEList EBIEList;
FTDF_Boolean EBFilteringEnabled;
FTDF_SN EBSN;
FTDF_AutoSA EBAutoSA;
FTDF_IEList EAckIEList;
FTDF_Boolean tschEnabled;
FTDF_Boolean leEnabled;
#endif /* !FTDF_LITE */
FTDF_ChannelNumber currentChannel;
FTDF_TXPowerTolerance TXPowerTolerance;
FTDF_DBm TXPower;
FTDF_CCAMode CCAMode;
#ifndef FTDF_LITE
FTDF_ChannelPage currentPage;
FTDF_Period maxFrameDuration;
FTDF_Period SHRDuration;
FTDF_KeyTable keyTable;
FTDF_DeviceTable deviceTable;
FTDF_SecurityLevelTable securityLevelTable;
FTDF_FrameCounter frameCounter;
FTDF_SecurityLevel mtDataSecurityLevel;
FTDF_KeyIdMode mtDataKeyIdMode;
FTDF_Octet mtDataKeySource[ 8 ];
FTDF_KeyIndex mtDataKeyIndex;
FTDF_Octet defaultKeySource[ 8 ];
FTDF_ExtAddress PANCoordExtAddress;
FTDF_ShortAddress PANCoordShortAddress;
FTDF_FrameCounterMode frameCounterMode;
FTDF_Period CSLSyncTxMargin;
FTDF_Period CSLMaxAgeRemoteInfo;
#endif /* !FTDF_LITE */
FTDF_TrafficCounters trafficCounters;
#ifndef FTDF_LITE
FTDF_Boolean LECapable;
FTDF_Boolean LLCapable;
FTDF_Boolean DSMECapable;
FTDF_Boolean RFIDCapable;
FTDF_Boolean AMCACapable;
#endif /* !FTDF_LITE */
FTDF_Boolean metricsCapable;
#ifndef FTDF_LITE
FTDF_Boolean rangingSupported;
#endif /* !FTDF_LITE */
FTDF_Boolean keepPhyEnabled;
FTDF_Boolean metricsEnabled;
#ifndef FTDF_LITE
FTDF_Boolean beaconAutoRespond;
FTDF_Boolean tschCapable;
FTDF_Period tsSyncCorrectThreshold;
#endif /* !FTDF_LITE */
};
typedef uint8_t FTDF_FrameVersion;
#define FTDF_FRAME_VERSION_2003 0
#define FTDF_FRAME_VERSION_2011 1
#define FTDF_FRAME_VERSION_E 2
#define FTDF_FRAME_VERSION_NOT_SUPPORTED 3
typedef struct
{
FTDF_FrameType frameType;
FTDF_FrameVersion frameVersion;
FTDF_Bitmap8 options;
FTDF_SN SN;
FTDF_AddressMode srcAddrMode;
FTDF_PANId srcPANId;
FTDF_Address srcAddr;
FTDF_AddressMode dstAddrMode;
FTDF_PANId dstPANId;
FTDF_Address dstAddr;
FTDF_CommandFrameId commandFrameId;
} FTDF_FrameHeader;
typedef struct
{
FTDF_SecurityLevel securityLevel;
FTDF_KeyIdMode keyIdMode;
FTDF_KeyIndex keyIndex;
FTDF_FrameCounterMode frameCounterMode;
FTDF_Octet* keySource;
FTDF_FrameCounter frameCounter;
} FTDF_SecurityHeader;
typedef struct
{
FTDF_Boolean fastA;
FTDF_Boolean dataR;
} FTDF_AssocAdmin;
typedef uint8_t FTDF_SNSel;
#define FTDF_SN_SEL_DSN 0
#define FTDF_SN_SEL_BSN 1
#define FTDF_SN_SEL_EBSN 2
typedef struct
{
FTDF_AddressMode addrMode;
FTDF_Address addr;
FTDF_Time timestamp;
FTDF_Boolean dsnValid;
FTDF_SN dsn;
FTDF_Boolean bsnValid;
FTDF_SN bsn;
FTDF_Boolean ebsnValid;
FTDF_SN ebsn;
} FTDF_RxAddressAdmin;
struct FTDF_Buffer_;
typedef struct
{
struct FTDF_Buffer_* next;
struct FTDF_Buffer_* prev;
} FTDF_BufferHeader;
typedef struct FTDF_Buffer_
{
FTDF_BufferHeader header;
FTDF_MsgBuffer* request;
} FTDF_Buffer;
typedef struct
{
FTDF_BufferHeader head;
FTDF_BufferHeader tail;
} FTDF_Queue;
typedef struct
{
FTDF_Address addr;
FTDF_AddressMode addrMode;
FTDF_PANId PANId;
FTDF_Queue queue;
} FTDF_Pending;
typedef struct _FTDF_PendingTL_
{
struct _FTDF_PendingTL_* next;
FTDF_Boolean free;
FTDF_MsgBuffer* request;
FTDF_Time delta;
uint8_t pendListNr;
void ( * func )( struct _FTDF_PendingTL_* );
} FTDF_PendingTL;
typedef uint8_t FTDF_RemoteId;
#define FTDF_REMOTE_DATA_REQUEST 0
#define FTDF_REMOTE_PAN_ID_CONFLICT_NOTIFICATION 1
#define FTDF_REMOTE_BEACON 2
#define FTDF_REMOTE_KEEP_ALIVE 3
typedef struct
{
FTDF_MsgId msgId;
FTDF_RemoteId remoteId;
FTDF_ShortAddress dstAddr;
} FTDF_RemoteRequest;
#ifndef FTDF_NO_CSL
typedef struct
{
FTDF_ShortAddress addr;
FTDF_Time time;
FTDF_Period period;
} FTDF_PeerCslTiming;
#endif /* FTDF_NO_CSL */
typedef uint8_t FTDF_State;
#define FTDF_STATE_UNINITIALIZED 0
#define FTDF_STATE_IDLE 1
#define FTDF_STATE_DATA_REQUEST 2
#define FTDF_STATE_POLL_REQUEST 3
#define FTDF_STATE_SCANNING 4
#ifndef FTDF_NO_TSCH
typedef struct
{
FTDF_ShortAddress nodeAddr;
FTDF_Size nrOfRetries;
FTDF_Size nrOfCcaRetries;
FTDF_BEExponent BE;
} FTDF_TschRetry;
typedef struct
{
FTDF_ShortAddress dstAddr;
FTDF_KeepAlivePeriod period;
FTDF_RemoteRequest msg;
} FTDF_NeighborEntry;
#endif /* FTDF_NO_TSCH */
typedef struct
{
FTDF_Count fcsErrorCnt;
FTDF_Count txStdAckCnt;
FTDF_Count rxStdAckCnt;
} FTDF_LmacCounters;
extern struct FTDF_Pib FTDF_pib;
extern FTDF_State* FTDF_state;
extern FTDF_Boolean FTDF_transparentMode;
extern FTDF_Bitmap32 FTDF_transparentModeOptions;
extern FTDF_Queue FTDF_reqQueue;
extern FTDF_Queue FTDF_freeQueue;
extern FTDF_Pending FTDF_txPendingList[ FTDF_NR_OF_REQ_BUFFERS ];
extern FTDF_PendingTL FTDF_txPendingTimerList[ FTDF_NR_OF_REQ_BUFFERS ];
extern FTDF_PendingTL* FTDF_txPendingTimerHead;
extern FTDF_Time FTDF_txPendingTimerLT;
extern FTDF_Time FTDF_txPendingTimerTime;
extern FTDF_MsgBuffer* FTDF_reqCurrent;
extern FTDF_Size FTDF_nrOfRetries;
extern FTDF_Boolean FTDF_isPANCoordinator;
extern FTDF_SlotframeEntry FTDF_slotframeTable[ FTDF_MAX_SLOTFRAMES ];
extern FTDF_LinkEntry FTDF_linkTable[ FTDF_MAX_LINKS ];
#ifndef FTDF_NO_TSCH
extern FTDF_LinkEntry* FTDF_startLinks[ FTDF_MAX_SLOTFRAMES ];
extern FTDF_LinkEntry* FTDF_endLinks[ FTDF_MAX_SLOTFRAMES ];
extern FTDF_NeighborEntry FTDF_neighborTable[ FTDF_NR_OF_NEIGHBORS ];
extern FTDF_Boolean FTDF_wakeUpEnableTsch;
#endif /* FTDF_NO_TSCH */
#ifndef FTDF_NO_CSL
extern FTDF_Boolean FTDF_wakeUpEnableLe;
#endif /* FTDF_NO_CSL */
extern FTDF_LmacCounters FTDF_lmacCounters;
extern FTDF_FrameHeader FTDF_fh;
extern FTDF_SecurityHeader FTDF_sh;
extern FTDF_AssocAdmin FTDF_aa;
extern FTDF_Boolean FTDF_txInProgress;
#ifndef FTDF_NO_CSL
extern FTDF_Time FTDF_rzTime;
extern FTDF_ShortAddress FTDF_sendFramePending;
#endif /* FTDF_NO_CSL */
extern FTDF_Time FTDF_startCslSampleTime;
#ifndef FTDF_NO_TSCH
extern FTDF_LinkEntry* FTDF_tschSlotLink;
extern FTDF_Time64 FTDF_tschSlotTime;
extern FTDF_ASN FTDF_tschSlotASN;
#endif /* FTDF_NO_TSCH */
void FTDF_processDataRequest( FTDF_DataRequest* req );
void FTDF_processPurgeRequest( FTDF_PurgeRequest* req );
void FTDF_processAssociateRequest( FTDF_AssociateRequest* req );
void FTDF_processAssociateResponse( FTDF_AssociateResponse* req );
void FTDF_processDisassociateRequest( FTDF_DisassociateRequest* req );
void FTDF_processGetRequest( FTDF_GetRequest* req );
void FTDF_processSetRequest( FTDF_SetRequest* req );
void FTDF_processOrphanResponse( FTDF_OrphanResponse* req );
void FTDF_processResetRequest( FTDF_ResetRequest* req );
void FTDF_processRxEnableRequest( FTDF_RxEnableRequest* req );
void FTDF_processScanRequest( FTDF_ScanRequest* req );
void FTDF_processStartRequest( FTDF_StartRequest* req );
void FTDF_processPollRequest( FTDF_PollRequest* req );
#ifndef FTDF_NO_TSCH
void FTDF_processSetSlotframeRequest( FTDF_SetSlotframeRequest* req );
void FTDF_processSetLinkRequest( FTDF_SetLinkRequest* req );
void FTDF_processTschModeRequest( FTDF_TschModeRequest* req );
void FTDF_processKeepAliveRequest( FTDF_KeepAliveRequest* req );
#endif /* FTDF_NO_TSCH */
void FTDF_processBeaconRequest( FTDF_BeaconRequest* req );
void FTDF_processTransparentRequest( FTDF_TransparentRequest* req );
void FTDF_processRemoteRequest( FTDF_RemoteRequest* req );
void FTDF_processNextRequest( void );
void FTDF_processRxEvent( void );
void FTDF_processTxEvent( void );
void FTDF_processSymbolTimerEvent( void );
void FTDF_sendDataConfirm( FTDF_DataRequest* dataRequest,
FTDF_Status status,
FTDF_Time timestamp,
FTDF_SN DSN,
FTDF_NumOfBackoffs numOfBackoffs,
FTDF_IEList* ackPayload );
void FTDF_sendDataIndication( FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader,
FTDF_IEList* payloadIEList,
FTDF_DataLength msduLength,
FTDF_Octet* msdu,
FTDF_LinkQuality mpduLinkQuality,
FTDF_Time timestamp );
void FTDF_sendPollConfirm( FTDF_PollRequest* pollRequest, FTDF_Status status );
void FTDF_sendScanConfirm( FTDF_ScanRequest* scanRequest, FTDF_Status status );
void FTDF_sendBeaconNotifyIndication( FTDF_PANDescriptor* PANDescriptor );
void FTDF_sendBeaconConfirm( FTDF_BeaconRequest* beaconRequest, FTDF_Status status );
void FTDF_sendAssociateConfirm( FTDF_AssociateRequest* associateRequest,
FTDF_Status status,
FTDF_ShortAddress assocShortAddr );
void FTDF_sendAssociateDataRequest( void );
void FTDF_sendDisassociateConfirm( FTDF_DisassociateRequest* disReq, FTDF_Status status );
void FTDF_sendSyncLossIndication( FTDF_LossReason lossReason, FTDF_SecurityHeader* securityHeader );
void FTDF_sendPANIdConflictNotification( FTDF_FrameHeader* frameHeader, FTDF_SecurityHeader* securityHeader );
void FTDF_sendCommStatusIndication( FTDF_MsgBuffer* request,
FTDF_Status status,
FTDF_PANId PANId,
FTDF_AddressMode srcAddrMode,
FTDF_Address srcAddr,
FTDF_AddressMode dstAddrMode,
FTDF_Address dstAddr,
FTDF_SecurityLevel securityLevel,
FTDF_KeyIdMode keyIdMode,
FTDF_Octet* keySource,
FTDF_KeyIndex keyIndex );
void FTDF_startTimer( FTDF_Period period,
void ( * timerFunc )( void* params ),
void* params );
FTDF_Octet* FTDF_getTxBufPtr( FTDF_Buffer* txBuffer );
void FTDF_setTxMetaData( FTDF_Buffer* txBuffer,
FTDF_DataLength frameLength,
FTDF_ChannelNumber channel,
FTDF_FrameType frameType,
FTDF_Boolean ackTX,
FTDF_SN SN );
FTDF_Status FTDF_sendFrame( FTDF_ChannelNumber channel,
FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader,
FTDF_Octet* txPtr,
FTDF_DataLength payloadSize,
FTDF_Octet* payload );
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
FTDF_Status FTDF_sendAckFrame( FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader,
FTDF_Octet* txPtr );
#endif /* !FTDF_NO_CSL || !FTDF_NO_TSCH */
void FTDF_sendTransparentFrame( FTDF_DataLength frameLength,
FTDF_Octet* frame,
FTDF_ChannelNumber channel,
FTDF_PTI pti,
FTDF_Boolean cmsaSuppress );
FTDF_Octet* FTDF_getRxBuffer( void );
void FTDF_processRxEvent( void );
FTDF_Octet* FTDF_addFrameHeader( FTDF_Octet* txPtr,
FTDF_FrameHeader* frameHeader,
FTDF_DataLength msduLength );
FTDF_Octet* FTDF_getFrameHeader( FTDF_Octet* rxPtr,
FTDF_FrameHeader* frameHeader );
FTDF_DataLength FTDF_getMicLength( FTDF_SecurityLevel securityLevel );
FTDF_Octet* FTDF_getSecurityHeader( FTDF_Octet* rxPtr,
uint8_t frameVersion,
FTDF_SecurityHeader* securityHeader );
FTDF_Octet* FTDF_addSecurityHeader( FTDF_Octet* txPtr,
FTDF_SecurityHeader* securityHeader );
FTDF_Status FTDF_secureFrame( FTDF_Octet* bufPtr,
FTDF_Octet* privPtr,
FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader );
FTDF_Status FTDF_unsecureFrame( FTDF_Octet* bufPtr,
FTDF_Octet* privPtr,
FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader );
FTDF_KeyDescriptor* FTDF_lookupKey( FTDF_AddressMode devAddrMode,
FTDF_PANId devPANId,
FTDF_Address devAddr,
FTDF_FrameType frameType,
FTDF_KeyIdMode keyIdMode,
FTDF_KeyIndex keyIndex,
FTDF_Octet* keySource );
FTDF_DeviceDescriptor* FTDF_lookupDevice( FTDF_Size nrOfDeviceDescriptorHandles,
FTDF_DeviceDescriptorHandle* deviceDescriptorHandles,
FTDF_AddressMode devAddrMode,
FTDF_PANId devPANId,
FTDF_Address devAddr );
FTDF_SecurityLevelDescriptor* FTDF_getSecurityLevelDescr( FTDF_FrameType frameType,
FTDF_CommandFrameId commandFrameId );
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
FTDF_Octet* FTDF_addIes( FTDF_Octet* txPtr,
FTDF_IEList* headerIEList,
FTDF_IEList* payloadIEList,
FTDF_Boolean withTerminationIE );
FTDF_Octet* FTDF_getIes( FTDF_Octet* rxPtr,
FTDF_Octet* frameEndPtr,
FTDF_IEList** headerIEList,
FTDF_IEList** payloadIEList );
#endif /* !FTDF_NO_CSL || !FTDF_NO_TSCH */
#ifndef FTDF_NO_CSL
void FTDF_setPeerCslTiming( FTDF_IEList* headerIEList,
FTDF_Time timeStamp );
void FTDF_setCslSampleTime( void );
void FTDF_getWakeupParams( FTDF_ShortAddress dstAddr,
FTDF_Time* wakeupStartTime,
FTDF_Period* wakeupPeriod );
#endif /* FTDF_NO_CSL */
void FTDF_getExtAddress( void );
void FTDF_setExtAddress( void );
void FTDF_getAckWaitDuration( void );
void FTDF_getEnhAckWaitDuration( void );
void FTDF_setEnhAckWaitDuration( void );
void FTDF_getImplicitBroadcast( void );
void FTDF_setImplicitBroadcast( void );
void FTDF_setShortAddress( void );
void FTDF_setSimpleAddress( void );
void FTDF_getRxOnWhenIdle( void );
void FTDF_setRxOnWhenIdle( void );
void FTDF_getPANId( void );
void FTDF_setPANId( void );
void FTDF_getCurrentChannel( void );
void FTDF_setCurrentChannel( void );
void FTDF_getMaxFrameTotalWaitTime( void );
void FTDF_setMaxFrameTotalWaitTime( void );
#ifndef FTDF_NO_CSL
void FTDF_setLeEnabled( void );
void FTDF_getCslFramePendingWaitT( void );
void FTDF_setCslFramePendingWaitT( void );
#endif /* FTDF_NO_CSL */
void FTDF_getLmacPmData( void );
void FTDF_getLmacTrafficCounters( void );
void FTDF_setMaxCSMABackoffs( void );
void FTDF_setMaxBE( void );
void FTDF_setMinBE( void );
void FTDF_getKeepPhyEnabled( void );
void FTDF_setKeepPhyEnabled( void );
#ifndef FTDF_NO_TSCH
void FTDF_setTimeslotTemplate( void );
#endif /* FTDF_NO_TSCH */
void FTDF_initLmac( void );
void FTDF_initQueues( void );
void FTDF_initQueue( FTDF_Queue* queue );
void FTDF_queueBufferHead( FTDF_Buffer* buffer, FTDF_Queue* queue );
FTDF_Status FTDF_queueReqHead( FTDF_MsgBuffer* request, FTDF_Queue* queue );
FTDF_Buffer* FTDF_dequeueBufferTail( FTDF_Queue* queue );
FTDF_MsgBuffer* FTDF_dequeueReqTail( FTDF_Queue* queue );
FTDF_MsgBuffer* FTDF_dequeueByHandle( FTDF_Handle handle, FTDF_Queue* queue );
FTDF_Buffer* FTDF_dequeueByBuffer( FTDF_Buffer* buffer, FTDF_Queue* queue );
FTDF_Boolean FTDF_isQueueEmpty( FTDF_Queue* queue );
void FTDF_addTxPendingTimer( FTDF_MsgBuffer* request, uint8_t pendListNr, FTDF_Time delta, void ( * func )(
FTDF_PendingTL* ) );
void FTDF_removeTxPendingTimer( FTDF_MsgBuffer* request );
void FTDF_restoreTxPendingTimer( void );
FTDF_Boolean FTDF_getTxPendingTimerHead( FTDF_Time* time );
void FTDF_sendTransactionExpired( FTDF_PendingTL* ptr );
#ifndef FTDF_NO_TSCH
void FTDF_processKeepAliveTimerExp( FTDF_PendingTL* ptr );
void FTDF_resetKeepAliveTimer( FTDF_ShortAddress dstAddr );
#endif /* FTDF_NO_TSCH */
void FTDF_processCommandFrame( FTDF_Octet* rxBuffer,
FTDF_FrameHeader* frameHeader,
FTDF_SecurityHeader* securityHeader,
FTDF_IEList* payloadIEList );
void FTDF_scanReady( FTDF_ScanRequest* );
void FTDF_addPANdescriptor( FTDF_PANDescriptor* );
void FTDF_sendBeaconRequest( FTDF_ChannelNumber channel );
void FTDF_sendBeaconRequestIndication( FTDF_FrameHeader* frameHeader,
FTDF_IEList* payloadIEList );
void FTDF_sendOrphanNotification( FTDF_ChannelNumber channel );
#ifndef FTDF_NO_TSCH
void FTDF_setTschEnabled( void );
FTDF_Status FTDF_scheduleTsch( FTDF_MsgBuffer* request );
void FTDF_tschProcessRequest( void );
FTDF_Size FTDF_getTschSyncSubIe( void );
FTDF_Octet* FTDF_addTschSyncSubIe( FTDF_Octet* txPtr );
FTDF_ShortAddress FTDF_getRequestAddress( FTDF_MsgBuffer* request );
FTDF_MsgBuffer* FTDF_tschGetPending( FTDF_MsgBuffer* request );
FTDF_Octet* FTDF_addCorrTimeIE( FTDF_Octet* txPtr, FTDF_Time rxTimestamp );
void FTDF_correctSlotTime( FTDF_Time rxTimestamp );
void FTDF_correctSlotTimeFromAck( FTDF_IEList* headerIEList );
void FTDF_initTschRetries( void );
FTDF_TschRetry* FTDF_getTschRetry( FTDF_ShortAddress nodeAddr );
FTDF_NumOfBackoffs FTDF_getNumOfBackoffs( FTDF_BEExponent BE );
void FTDF_initBackoff( void );
FTDF_SN FTDF_processTschSN( FTDF_MsgBuffer* msg, FTDF_SN sn, uint8_t* priv );
#endif /* FTDF_NO_TSCH */
FTDF_Time64 FTDF_getCurTime64( void );
void FTDF_initCurTime64( void );
+321
View File
@@ -0,0 +1,321 @@
/**
****************************************************************************************
*
* @file main.c
*
* @brief Main FTDF functions
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <ftdf.h>
#include <string.h>
#include "internal.h"
#include "regmap.h"
#include "ftdfInfo.h"
void FTDF_getReleaseInfo(char **lmacRelName, char **lmacBuildTime, char **umacRelName, char **umacBuildTime)
{
static char lrelName[ 16 ];
static char lbldTime[ 16 ];
static char urelName[ 16 ];
static char ubldTime[ 16 ];
uint8_t i;
volatile uint32_t *ptr = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_REL_NAME);
uint32_t *chrPtr = (uint32_t *)lrelName;
for (i = 0; i < FTDF_ON_OFF_REGMAP_REL_NAME_NUM; i++)
{
*chrPtr++ = *ptr++;
}
ptr = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_BUILDTIME);
chrPtr = (uint32_t *)lbldTime;
for (i = 0; i < FTDF_ON_OFF_REGMAP_BUILDTIME_NUM; i++)
{
*chrPtr++ = *ptr++;
}
const char *umacVPtr = FTDF_getUmacRelName();
for (i = 0; i < 16; i++)
{
urelName[ i ] = umacVPtr[ i ];
if (umacVPtr[ i ] == '\0')
{
break;
}
}
umacVPtr = FTDF_getUmacBuildTime();
for (i = 0; i < 16; i++)
{
ubldTime[ i ] = umacVPtr[ i ];
if (umacVPtr[ i ] == '\0')
{
break;
}
}
lrelName[ 15 ] = '\0';
lbldTime[ 15 ] = '\0';
urelName[ 15 ] = '\0';
ubldTime[ 15 ] = '\0';
*lmacRelName = lrelName;
*lmacBuildTime = lbldTime;
*umacRelName = urelName;
*umacBuildTime = ubldTime;
}
void FTDF_confirmLmacInterrupt(void)
{
volatile uint32_t *ftdfCm = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_FTDF_CM);
*ftdfCm = 0;
}
void FTDF_eventHandler(void)
{
volatile uint32_t ftdfCe = *FTDF_GET_REG_ADDR(ON_OFF_REGMAP_FTDF_CE);
if (ftdfCe & FTDF_MSK_RX_CE)
{
FTDF_processRxEvent();
}
if (ftdfCe & FTDF_MSK_TX_CE)
{
FTDF_processTxEvent();
}
if (ftdfCe & FTDF_MSK_SYMBOL_TMR_CE)
{
FTDF_processSymbolTimerEvent();
}
#ifndef FTDF_LITE
#ifndef FTDF_NO_CSL
if (FTDF_pib.leEnabled)
{
FTDF_Time curTime = FTDF_GET_FIELD(ON_OFF_REGMAP_SYMBOLTIMESNAPSHOTVAL);
FTDF_Time delta = curTime - FTDF_rzTime;
if (delta < 0x80000000)
{
// RZ has passed check if a send frame is pending
if (FTDF_sendFramePending != 0xfffe)
{
FTDF_Time wakeupStartTime;
FTDF_Period wakeupPeriod;
FTDF_criticalVar();
FTDF_enterCritical();
FTDF_getWakeupParams(FTDF_sendFramePending, &wakeupStartTime, &wakeupPeriod);
FTDF_txInProgress = FTDF_TRUE;
FTDF_SET_FIELD(ON_OFF_REGMAP_MACCSLSTARTSAMPLETIME, wakeupStartTime);
FTDF_SET_FIELD(ON_OFF_REGMAP_MACWUPERIOD, wakeupPeriod);
volatile uint32_t *txFlagSet = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_TX_FLAG_SET);
*txFlagSet |= ((1 << FTDF_TX_DATA_BUFFER) | (1 << FTDF_TX_WAKEUP_BUFFER));
FTDF_sendFramePending = 0xfffe;
FTDF_exitCritical();
}
if (FTDF_txInProgress == FTDF_FALSE)
{
FTDF_setCslSampleTime();
}
}
}
#endif /* FTDF_NO_CSL */
#endif /* !FTDF_LITE */
volatile uint32_t *ftdfCm = FTDF_GET_REG_ADDR(ON_OFF_REGMAP_FTDF_CM);
*ftdfCm = FTDF_MSK_TX_CE | FTDF_MSK_RX_CE | FTDF_MSK_SYMBOL_TMR_CE;
}
#ifndef FTDF_PHY_API
void FTDF_sndMsg(FTDF_MsgBuffer *msgBuf)
{
switch (msgBuf->msgId)
{
#ifndef FTDF_LITE
case FTDF_DATA_REQUEST:
FTDF_processDataRequest((FTDF_DataRequest *) msgBuf);
break;
case FTDF_PURGE_REQUEST:
FTDF_processPurgeRequest((FTDF_PurgeRequest *) msgBuf);
break;
case FTDF_ASSOCIATE_REQUEST:
FTDF_processAssociateRequest((FTDF_AssociateRequest *) msgBuf);
break;
case FTDF_ASSOCIATE_RESPONSE:
FTDF_processAssociateResponse((FTDF_AssociateResponse *) msgBuf);
break;
case FTDF_DISASSOCIATE_REQUEST:
FTDF_processDisassociateRequest((FTDF_DisassociateRequest *) msgBuf);
break;
#endif /* !FTDF_LITE */
case FTDF_GET_REQUEST:
FTDF_processGetRequest((FTDF_GetRequest *) msgBuf);
break;
case FTDF_SET_REQUEST:
FTDF_processSetRequest((FTDF_SetRequest *) msgBuf);
break;
#ifndef FTDF_LITE
case FTDF_ORPHAN_RESPONSE:
FTDF_processOrphanResponse((FTDF_OrphanResponse *) msgBuf);
break;
#endif /* !FTDF_LITE */
case FTDF_RESET_REQUEST:
FTDF_processResetRequest((FTDF_ResetRequest *) msgBuf);
break;
case FTDF_RX_ENABLE_REQUEST:
FTDF_processRxEnableRequest((FTDF_RxEnableRequest *) msgBuf);
break;
#ifndef FTDF_LITE
case FTDF_SCAN_REQUEST:
FTDF_processScanRequest((FTDF_ScanRequest *) msgBuf);
break;
case FTDF_START_REQUEST:
FTDF_processStartRequest((FTDF_StartRequest *) msgBuf);
break;
case FTDF_POLL_REQUEST:
FTDF_processPollRequest((FTDF_PollRequest *) msgBuf);
break;
#ifndef FTDF_NO_TSCH
case FTDF_SET_SLOTFRAME_REQUEST:
FTDF_processSetSlotframeRequest((FTDF_SetSlotframeRequest *) msgBuf);
break;
case FTDF_SET_LINK_REQUEST:
FTDF_processSetLinkRequest((FTDF_SetLinkRequest *) msgBuf);
break;
case FTDF_TSCH_MODE_REQUEST:
FTDF_processTschModeRequest((FTDF_TschModeRequest *) msgBuf);
break;
case FTDF_KEEP_ALIVE_REQUEST:
FTDF_processKeepAliveRequest((FTDF_KeepAliveRequest *) msgBuf);
break;
#endif /* FTDF_NO_TSCH */
case FTDF_BEACON_REQUEST:
FTDF_processBeaconRequest((FTDF_BeaconRequest *) msgBuf);
break;
#endif /* !FTDF_LITE */
case FTDF_TRANSPARENT_ENABLE_REQUEST:
FTDF_enableTransparentMode(((FTDF_TransparentEnableRequest *) msgBuf)->enable,
((FTDF_TransparentEnableRequest *) msgBuf)->options);
FTDF_REL_MSG_BUFFER(msgBuf);
break;
case FTDF_TRANSPARENT_REQUEST:
FTDF_processTransparentRequest((FTDF_TransparentRequest *) msgBuf);
break;
case FTDF_SLEEP_REQUEST:
FTDF_SLEEP_CALLBACK(((FTDF_SleepRequest *)msgBuf)->sleepTime);
FTDF_REL_MSG_BUFFER(msgBuf);
break;
#ifndef FTDF_LITE
case FTDF_REMOTE_REQUEST:
FTDF_processRemoteRequest((FTDF_RemoteRequest *)msgBuf);
break;
#endif /* !FTDF_LITE */
#if FTDF_DBG_BUS_ENABLE
case FTDF_DBG_MODE_SET_REQUEST:
FTDF_setDbgMode(((FTDF_DbgModeSetRequest *) msgBuf)->dbgMode);
FTDF_REL_MSG_BUFFER(msgBuf);
break;
#endif /* FTDF_DBG_BUS_ENABLE */
default:
// Silenty release the message buffer
FTDF_REL_MSG_BUFFER(msgBuf);
break;
}
}
void FTDF_sendFrameTransparentConfirm(void *handle,
FTDF_Bitmap32 status)
{
FTDF_TransparentConfirm *confirm =
(FTDF_TransparentConfirm *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_TransparentConfirm));
confirm->msgId = FTDF_TRANSPARENT_CONFIRM;
confirm->handle = handle;
confirm->status = status;
FTDF_RCV_MSG((FTDF_MsgBuffer *) confirm);
}
void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength,
FTDF_Octet *frame,
FTDF_Bitmap32 status)
{
FTDF_TransparentIndication *indication =
(FTDF_TransparentIndication *) FTDF_GET_MSG_BUFFER(sizeof(FTDF_TransparentIndication));
indication->msgId = FTDF_TRANSPARENT_INDICATION;
indication->frameLength = frameLength;
indication->status = status;
indication->frame = FTDF_GET_DATA_BUFFER(frameLength);
memcpy(indication->frame, frame, frameLength);
FTDF_RCV_MSG((FTDF_MsgBuffer *) indication);
}
#endif /* !FTDF_PHY_API */
+319
View File
@@ -0,0 +1,319 @@
/**
****************************************************************************************
*
* @file power.c
*
* @brief FTDF power on/off functions
*
* Copyright (c) 2016, Dialog Semiconductor
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the 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 <stdlib.h>
#include <ftdf.h>
#include "internal.h"
#include "regmap.h"
static FTDF_PSec FTDF_lowPowerClockCycle __attribute__((section(".retention")));
static FTDF_PSec FTDF_wakeUpLatency __attribute__((section(".retention")));
/* Pre-calculated value for optimization. */
static FTDF_USec FTDF_lowPowerClockCycleUSec __attribute__((section(".retention")));
/* Pre-calculated value for optimization. */
static FTDF_USec FTDF_wakeUpLatencyUSec __attribute__((section(".retention")));
/* Pre-calculated value for optimization. */
static FTDF_NrLowPowerClockCycles FTDF_csmacaWakeupThr __attribute__((section(".retention")));
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
static uint32_t FTDF_eventCurrVal __attribute__((section(".retention")));
static uint32_t FTDF_timeStampCurrVal __attribute__((section(".retention")));
static uint32_t FTDF_timeStampCurrPhaseVal __attribute__((section(".retention")));
#endif
#ifndef FTDF_NO_CSL
FTDF_Boolean FTDF_wakeUpEnableLe __attribute__((section(".retention")));
#endif /* FTDF_NO_CSL */
#ifndef FTDF_NO_TSCH
FTDF_Boolean FTDF_wakeUpEnableTsch;
#endif /* FTDF_NO_TSCH */
void FTDF_setSleepAttributes(FTDF_PSec lowPowerClockCycle,
FTDF_NrLowPowerClockCycles wakeUpLatency)
{
FTDF_lowPowerClockCycle = lowPowerClockCycle;
FTDF_wakeUpLatency = (uint64_t)wakeUpLatency * lowPowerClockCycle;
FTDF_lowPowerClockCycleUSec = FTDF_lowPowerClockCycle / 1000000;
FTDF_wakeUpLatencyUSec = FTDF_wakeUpLatency / 1000000;
FTDF_csmacaWakeupThr = (FTDF_NrLowPowerClockCycles)
(((FTDF_PSec) 0xffffffff * 1000000 - FTDF_wakeUpLatency) / FTDF_lowPowerClockCycle);
}
FTDF_USec FTDF_canSleep(void)
{
#ifdef FTDF_PHY_API
if (FTDF_txInProgress || FTDF_pib.keepPhyEnabled)
{
return 0;
}
#else
if (FTDF_reqCurrent || FTDF_pib.keepPhyEnabled)
{
return 0;
}
#endif
if (FTDF_GET_FIELD(ON_OFF_REGMAP_LMACREADY4SLEEP) == 0 ||
FTDF_GET_FIELD(ON_OFF_REGMAP_SECBUSY) == 1)
{
return 0;
}
#ifndef FTDF_NO_CSL
if (FTDF_pib.leEnabled)
{
if (FTDF_txInProgress == FTDF_FALSE)
{
FTDF_Time curTime = FTDF_GET_FIELD(ON_OFF_REGMAP_SYMBOLTIMESNAPSHOTVAL);
FTDF_Time delta = curTime - FTDF_startCslSampleTime;
// A delta larger than 0x80000000 is assumed to be negative
// Do not return a sleep value when CSL sample time is in the past
if (delta < 0x80000000)
{
return 0;
}
return (FTDF_startCslSampleTime - curTime) * 16;
}
else
{
return 0;
}
}
#endif /* FTDF_NO_CSL */
#ifndef FTDF_NO_TSCH
if (FTDF_pib.tschEnabled)
{
FTDF_Time64 curTime64 = FTDF_getCurTime64();
FTDF_Time64 delta = curTime64 - FTDF_tschSlotTime;
// A delta larger than 0x8000000000000000 is assumed to be negative
// Do not return a sleep value when TSCH slot time is in the past
if (delta < 0x8000000000000000ULL)
{
return 0;
}
FTDF_USec sleepTime = (FTDF_USec)(FTDF_tschSlotTime - curTime64);
FTDF_Time pendListTime;
FTDF_Time curTime = FTDF_GET_FIELD(ON_OFF_REGMAP_SYMBOLTIMESNAPSHOTVAL);
FTDF_Boolean pending = FTDF_getTxPendingTimerHead(&pendListTime);
if (pending)
{
// A delta larger than 0x80000000 is assumed to be negative
// Do not return a sleep value when pending timer time is in the past
if (curTime - pendListTime < 0x80000000)
{
return 0;
}
FTDF_USec tmpSleepTime = (FTDF_USec)(pendListTime - curTime);
if (tmpSleepTime < sleepTime)
{
sleepTime = tmpSleepTime;
}
}
if (sleepTime < FTDF_TSCH_MAX_PROCESS_REQUEST_TIME + FTDF_TSCH_MAX_SCHEDULE_TIME)
{
return 0;
}
return (sleepTime - (FTDF_TSCH_MAX_PROCESS_REQUEST_TIME + FTDF_TSCH_MAX_SCHEDULE_TIME)) * 16;
}
#endif /* FTDF_NO_TSCH */
#ifndef FTDF_LITE
// Normal mode
int n;
for (n = 0; n < FTDF_NR_OF_REQ_BUFFERS; n++)
{
if (FTDF_txPendingList[ n ].addrMode != FTDF_NO_ADDRESS)
{
return 0;
}
}
#endif /* !FTDF_LITE */
return 0xffffffff;
}
FTDF_Boolean FTDF_prepareForSleep(FTDF_USec sleepTime)
{
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
if (FTDF_pib.leEnabled || FTDF_pib.tschEnabled)
{
if (sleepTime < 2 * FTDF_lowPowerClockCycleUSec)
{
return FTDF_FALSE;
}
// Correct sleeptime with the inaccuracy of this function
sleepTime -= 2 * FTDF_lowPowerClockCycleUSec;
if (sleepTime < FTDF_wakeUpLatencyUSec + 500)
{
return FTDF_FALSE;
}
}
#endif
FTDF_criticalVar();
FTDF_enterCritical();
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
// Capture the current value of both the event generator and the timestamp generator
// and phase on the rising edge of LP_CLK
FTDF_SET_FIELD(ON_OFF_REGMAP_GETGENERATORVAL, 1);
#endif
// Save current LMAC PM counters
FTDF_lmacCounters.fcsErrorCnt += FTDF_GET_FIELD(ON_OFF_REGMAP_MACFCSERRORCOUNT);
FTDF_lmacCounters.txStdAckCnt += FTDF_GET_FIELD(ON_OFF_REGMAP_MACTXSTDACKFRMCNT);
FTDF_lmacCounters.rxStdAckCnt += FTDF_GET_FIELD(ON_OFF_REGMAP_MACRXSTDACKFRMOKCNT);
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
volatile uint32_t *getGeneratorValE = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_GETGENERATORVAL_E);
// Wait until data is ready
while ((*getGeneratorValE & MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E) == 0)
{ }
FTDF_eventCurrVal = FTDF_GET_FIELD(ON_OFF_REGMAP_EVENTCURRVAL);
FTDF_timeStampCurrVal = FTDF_GET_FIELD(ON_OFF_REGMAP_TIMESTAMPCURRVAL);
FTDF_timeStampCurrPhaseVal = FTDF_GET_FIELD(ON_OFF_REGMAP_TIMESTAMPCURRPHASEVAL);
#ifdef SIMULATOR
*getGeneratorValE &= ~MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E;
#else
*getGeneratorValE = MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E;
#endif
uint64_t nextWakeUpThr;
if (FTDF_pib.leEnabled || FTDF_pib.tschEnabled)
{
uint64_t picoSleepTime = (uint64_t)sleepTime * 1000000;
nextWakeUpThr = (picoSleepTime - FTDF_wakeUpLatency) / FTDF_lowPowerClockCycle;
}
else
{
nextWakeUpThr = FTDF_csmacaWakeupThr;
}
// Set wake up threshold
uint32_t wakeUpIntThr = FTDF_eventCurrVal + nextWakeUpThr;
FTDF_SET_FIELD(ALWAYS_ON_REGMAP_WAKEUPINTTHR, wakeUpIntThr);
FTDF_SET_FIELD(ALWAYS_ON_REGMAP_WAKEUPENABLE, 1);
#endif
FTDF_exitCritical();
return FTDF_TRUE;
}
void FTDF_wakeUp(void)
{
#ifndef FTDF_PHY_API
FTDF_criticalVar();
FTDF_enterCritical();
FTDF_SET_FIELD(ALWAYS_ON_REGMAP_WAKEUPENABLE, 0);
#if !defined(FTDF_NO_CSL) || !defined(FTDF_NO_TSCH)
// Capture the current value of both the event generator and the timestamp generator
// and phase on the rising edge of LP_CLK
FTDF_SET_FIELD(ON_OFF_REGMAP_GETGENERATORVAL, 1);
volatile uint32_t *getGeneratorValE = FTDF_GET_FIELD_ADDR(ON_OFF_REGMAP_GETGENERATORVAL_E);
// Wait until data is ready
while ((*getGeneratorValE & MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E) == 0)
{ }
uint32_t eventNewCurrVal = FTDF_GET_FIELD(ON_OFF_REGMAP_EVENTCURRVAL);
#ifdef SIMULATOR
*getGeneratorValE &= ~MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E;
#else
*getGeneratorValE = MSK_F_FTDF_ON_OFF_REGMAP_GETGENERATORVAL_E;
#endif
// Backward calculate the time slept
FTDF_PSec sleepTime = ((uint64_t)(eventNewCurrVal - FTDF_eventCurrVal) * FTDF_lowPowerClockCycle) + FTDF_wakeUpLatency;
// Calculate sync values
uint64_t newSyncVals = ((uint64_t)FTDF_timeStampCurrVal << 8) | (FTDF_timeStampCurrPhaseVal & 0xff);
newSyncVals += (sleepTime / 62500) + 1;
uint32_t syncTimestampThr = FTDF_eventCurrVal + (sleepTime / FTDF_lowPowerClockCycle);
uint32_t syncTimestampVal = (newSyncVals & 0xffffffff00) >> 8;
uint32_t syncTimestampPhaseVal = (newSyncVals & 0xff);
// Set values
FTDF_SET_FIELD(ON_OFF_REGMAP_SYNCTIMESTAMPTHR, syncTimestampThr);
FTDF_SET_FIELD(ON_OFF_REGMAP_SYNCTIMESTAMPVAL, syncTimestampVal);
FTDF_SET_FIELD(ON_OFF_REGMAP_SYNCTIMESTAMPPHASEVAL, syncTimestampPhaseVal);
FTDF_SET_FIELD(ON_OFF_REGMAP_SYNCTIMESTAMPENA, 1);
#endif
FTDF_exitCritical();
#ifndef FTDF_NO_CSL
FTDF_wakeUpEnableLe = FTDF_pib.leEnabled;
FTDF_pib.leEnabled = FTDF_FALSE;
#endif /* FTDF_NO_CSL */
#ifndef FTDF_NO_TSCH
FTDF_wakeUpEnableTsch = FTDF_pib.tschEnabled;
FTDF_pib.tschEnabled = FTDF_FALSE;
#endif /* FTDF_NO_TSCH */
#endif /* ! FTDF_PHY_API */
// Init LMAC
FTDF_initLmac();
}
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
arm-none-eabi-objcopy -O binary ../../../output/bin/arm-none-eabi-ot-cli-ftd ../../../output/bin/arm-none-eabi-ot-cli-ftd.bin
./bin2image qspi_cached ../../../output/bin/arm-none-eabi-ot-cli-ftd.bin ../../../output/bin/arm-none-eabi-ot-cli-ftd.img AD enable_uart
BIN
View File
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
URL: http://www.dialog-semiconductor.com/openthread-sandbox-development-kit
Version: TO BE UPDATED!
License: BSD3
Description:
DialogSDK - contain board support package and radio interface used for build
DialogTools - contain flash tools
imgprep.sh - prepare image from generated binary using bin2image tool
cli_programmer and uartboot - utilities for loading image into the platform
Look into examples/platform/da15000/README.am for DialogTools usage description.