From 1cc659d882bbb07f1bb9c2f993cc4127163c0e9f Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Sat, 24 Oct 2015 18:21:05 +0200 Subject: [PATCH 01/80] Allow for using a fixed frame header length. When SICSLOWPAN_FRAMER_HDRLEN is defined its value is used as a frame header length. This allows for using sicslowpan without calling a framer. This is usefull if framer is not used on a given platform or when header length is always the same. In addition this commit also fixes an inline define. --- core/net/ipv6/sicslowpan.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index d0bf14799..7fbdbefc7 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -169,6 +169,14 @@ void uip_log(char *msg); #define COMPRESSION_THRESHOLD 0 #endif +/** \brief Fixed size of a frame header. This value is + * used in case framer returns an error or if SICSLOWPAN_USE_FIXED_HDRLEN + * is defined. + */ +#ifndef SICSLOWPAN_FIXED_HDRLEN +#define SICSLOWPAN_FIXED_HDRLEN 21 +#endif + /** \name General variables * @{ */ @@ -1345,16 +1353,15 @@ output(const uip_lladdr_t *localdest) /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC. * We calculate it here only to make a better decision of whether the outgoing packet * needs to be fragmented or not. */ -#define USE_FRAMER_HDRLEN 1 -#if USE_FRAMER_HDRLEN +#ifndef SICSLOWPAN_USE_FIXED_HDRLEN packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); framer_hdrlen = NETSTACK_FRAMER.length(); if(framer_hdrlen < 0) { /* Framing failed, we assume the maximum header length */ - framer_hdrlen = 21; + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; } #else /* USE_FRAMER_HDRLEN */ - framer_hdrlen = 21; + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; #endif /* USE_FRAMER_HDRLEN */ max_payload = MAC_MAX_PAYLOAD - framer_hdrlen; From 803d170b55ab8725c8a3733c83ae06afea126bab Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Wed, 23 Dec 2015 21:21:51 +0100 Subject: [PATCH 02/80] Fixed unsused variable warning when SICSLOWPAN_CONF_FRAG is undefined --- core/net/ipv6/sicslowpan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index 7fbdbefc7..5453d9e21 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -1285,11 +1285,6 @@ output(const uip_lladdr_t *localdest) /* The MAC address of the destination of the packet */ linkaddr_t dest; -#if SICSLOWPAN_CONF_FRAG - /* Number of bytes processed. */ - uint16_t processed_ip_out_len; -#endif /* SICSLOWPAN_CONF_FRAG */ - /* init */ uncomp_hdr_len = 0; packetbuf_hdr_len = 0; @@ -1367,6 +1362,9 @@ output(const uip_lladdr_t *localdest) max_payload = MAC_MAX_PAYLOAD - framer_hdrlen; if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) { #if SICSLOWPAN_CONF_FRAG + /* Number of bytes processed. */ + uint16_t processed_ip_out_len; + struct queuebuf *q; uint16_t frag_tag; From 0671640ea285beffb11e8d0f074c194e4d090119 Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Wed, 23 Dec 2015 21:29:03 +0100 Subject: [PATCH 03/80] Extended SOURCEDIRS variable with EXTRALDIRS variable in Makefile.include Directories listed in this variable are added to include and source (vpath) search paths. Contents of this variable aren't automatically prefixed with Contki root. This allows for inclusion of folders that are outside Contiki root. --- Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.include b/Makefile.include index 36b5e06ca..67b0ff595 100644 --- a/Makefile.include +++ b/Makefile.include @@ -182,7 +182,7 @@ CONTIKI_CPU_DIRS_CONCAT = ${addprefix $(CONTIKI_CPU)/, \ $(CONTIKI_CPU_DIRS)} SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) \ - $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDS) ${dir $(target_makefile)} + $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDS) $(EXTERNALDIRS) ${dir $(target_makefile)} vpath %.c $(SOURCEDIRS) vpath %.S $(SOURCEDIRS) From 20f9515ed1b7fdf7cdd097e19ea0821e3f6cd86c Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Sat, 9 Jan 2016 14:44:18 +0100 Subject: [PATCH 04/80] nrf52dk: cpu/nrf52832 support --- cpu/nrf52832/Makefile.nrf52832 | 262 ++++++++++++++++++ cpu/nrf52832/ble/ble-core.c | 238 +++++++++++++++++ cpu/nrf52832/ble/ble-core.h | 61 +++++ cpu/nrf52832/ble/ble-mac.c | 386 +++++++++++++++++++++++++++ cpu/nrf52832/ble/ble-mac.h | 53 ++++ cpu/nrf52832/dev/clock.c | 171 ++++++++++++ cpu/nrf52832/dev/lpm.h | 67 +++++ cpu/nrf52832/dev/random.c | 90 +++++++ cpu/nrf52832/dev/uart0.c | 118 ++++++++ cpu/nrf52832/dev/uart0.h | 57 ++++ cpu/nrf52832/dev/watchdog.c | 93 +++++++ cpu/nrf52832/erase.jlink | 2 + cpu/nrf52832/flash.jlink | 4 + cpu/nrf52832/ld/nrf52-pca10036-sd.ld | 12 + cpu/nrf52832/ld/nrf52-pca10040-sd.ld | 12 + cpu/nrf52832/ld/nrf52.ld | 12 + cpu/nrf52832/mtarch.h | 48 ++++ cpu/nrf52832/putchar.c | 70 +++++ cpu/nrf52832/rtimer-arch.c | 110 ++++++++ cpu/nrf52832/rtimer-arch.h | 52 ++++ 20 files changed, 1918 insertions(+) create mode 100644 cpu/nrf52832/Makefile.nrf52832 create mode 100644 cpu/nrf52832/ble/ble-core.c create mode 100644 cpu/nrf52832/ble/ble-core.h create mode 100644 cpu/nrf52832/ble/ble-mac.c create mode 100644 cpu/nrf52832/ble/ble-mac.h create mode 100644 cpu/nrf52832/dev/clock.c create mode 100644 cpu/nrf52832/dev/lpm.h create mode 100644 cpu/nrf52832/dev/random.c create mode 100644 cpu/nrf52832/dev/uart0.c create mode 100644 cpu/nrf52832/dev/uart0.h create mode 100644 cpu/nrf52832/dev/watchdog.c create mode 100644 cpu/nrf52832/erase.jlink create mode 100644 cpu/nrf52832/flash.jlink create mode 100644 cpu/nrf52832/ld/nrf52-pca10036-sd.ld create mode 100644 cpu/nrf52832/ld/nrf52-pca10040-sd.ld create mode 100644 cpu/nrf52832/ld/nrf52.ld create mode 100644 cpu/nrf52832/mtarch.h create mode 100644 cpu/nrf52832/putchar.c create mode 100644 cpu/nrf52832/rtimer-arch.c create mode 100644 cpu/nrf52832/rtimer-arch.h diff --git a/cpu/nrf52832/Makefile.nrf52832 b/cpu/nrf52832/Makefile.nrf52832 new file mode 100644 index 000000000..f93f063f3 --- /dev/null +++ b/cpu/nrf52832/Makefile.nrf52832 @@ -0,0 +1,262 @@ +ifndef NRF52_SDK_ROOT + $(error NRF52_SDK_ROOT not defined! You must specify where nRF52 SDK resides!) +endif + +ifneq ($(filter %.flash erase,$(MAKECMDGOALS)),) +ifeq ($(NRF52_JLINK_PATH),) +NRF52_JLINK_PATH=$(shell location=$$(which JLinkExe) && dirname $$location) +endif +ifeq ($(NRF52_JLINK_PATH),) + $(error JLink not found in PATH and NRF52_JLINK_PATH path is not defined) +endif +endif + +ifeq ($(CONTIKI_WITH_RIME),1) + $(error Rime stack is not supported!) +endif + +ifneq ($(CONTIKI_WITH_IPV6),1) + $(error Only IPv6 stack is supported!) +endif + +$(info SDK: $(NRF52_SDK_ROOT)) + +ifeq ($(NRF52_DK_REVISION),) +NRF52_DK_REVISION=pca10040 +endif + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) + ifeq ($(NRF52_SOFTDEVICE),) + NRF52_SOFTDEVICE := $(shell find $(NRF52_SDK_ROOT) -name *iot*_softdevice.hex | head -n 1) + endif + $(info SoftDevice: $(NRF52_SOFTDEVICE)) + LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52-$(NRF52_DK_REVISION)-sd.ld +else + LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52.ld +endif + +OUTPUT_FILENAME := $(CONTIKI_PROJECT) +MAKEFILE_NAME := $(MAKEFILE_LIST) +MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) ) + +TEMPLATE_PATH = $(NRF52_SDK_ROOT)/components/toolchain/gcc + +OBJECT_DIRECTORY = $(OBJECTDIR) +LISTING_DIRECTORY := $(OBJECTDIR) +OUTPUT_BINARY_DIRECTORY := bin_$(TARGET) + +MK := mkdir +RM := rm -rf + +# Toolchain commands +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +AR := arm-none-eabi-ar +LD := arm-none-eabi-ld +NM := arm-none-eabi-nm +OBJDUMP := arm-none-eabi-objdump +OBJCOPY := arm-none-eabi-objcopy +SIZE := arm-none-eabi-size + +# JLink +JLINK := $(NRF52_JLINK_PATH)/JLinkExe +JLINK_OPTS = -Device NRF52 -if swd -speed 1000 +ifneq ($(NRF52_JLINK_SN),) +JLINK_OPTS += -SelectEmuBySN $(NRF52_JLINK_SN) +endif + +#function for removing duplicates in a list +remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1)))) + +### CPU-dependent directories +CONTIKI_CPU_DIRS += . dev ble #compat + +### CPU-dependent source files +CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c putchar.c watchdog.c + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +CONTIKI_CPU_SOURCEFILES += ble-core.c ble-mac.c +endif + +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) + +#source common to all targets +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/rtc/nrf_drv_rtc.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/wdt/nrf_drv_wdt.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/rng/nrf_drv_rng.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/delay/nrf_delay.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \ + $(NRF52_SDK_ROOT)/components/libraries/util/app_error.c \ + $(NRF52_SDK_ROOT)/components/toolchain/system_nrf52.c + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/softdevice/common/softdevice_handler/softdevice_handler.c \ + $(NRF52_SDK_ROOT)/components/ble/common/ble_advdata.c +else +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/libraries/fifo/app_fifo.c \ + $(NRF52_SDK_ROOT)/components/libraries/util/app_util_platform.c +endif + +#assembly files common to all targets +ASM_SOURCE_FILES = $(NRF52_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.s + +#includes common to all targets +INC_PATHS += components/drivers_nrf/gpiote +INC_PATHS += components/drivers_nrf/hal +INC_PATHS += components/drivers_nrf/config +INC_PATHS += components/drivers_nrf/delay +INC_PATHS += components/drivers_nrf/uart +INC_PATHS += components/drivers_nrf/common +INC_PATHS += components/drivers_nrf/rtc +INC_PATHS += components/drivers_nrf/wdt +INC_PATHS += components/drivers_nrf/rng +INC_PATHS += components/drivers_nrf/clock +INC_PATHS += components/drivers_nrf/timer +INC_PATHS += components/libraries/util +INC_PATHS += components/libraries/timer +INC_PATHS += components/device +INC_PATHS += components/toolchain/gcc +INC_PATHS += components/toolchain +INC_PATHS += examples/bsp + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +INC_PATHS += components/softdevice/s1xx_iot/headers +INC_PATHS += components/softdevice/s1xx_iot/headers/nrf52 +INC_PATHS += components/softdevice/common/softdevice_handler +INC_PATHS += components/ble/common +INC_PATHS += components/iot/common +INC_PATHS += components/iot/ble_ipsp +else +INC_PATHS += components/drivers_nrf/nrf_soc_nosd +INC_PATHS += components/libraries/fifo +endif + +EXTERNALDIRS += $(addprefix $(NRF52_SDK_ROOT)/, $(INC_PATHS)) + +# Sorting removes duplicates +BUILD_DIRECTORIES := $(sort $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY)) + +# Clean files and directories +CLEAN += bin_$(TARGET) lst_$(TARGET) nrf52832.a *.elf *.hex + +#flags common to all targets +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +CFLAGS += -DSOFTDEVICE_PRESENT +CFLAGS += -DS132 +endif + +ifeq ($(SMALL),1) +CFLAGS += -Os +else +CFLAGS += -O2 +endif + +CFLAGS += -DNRF52 +CFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z) +CFLAGS += -D__HEAP_SIZE=512 +CFLAGS += -DSWI_DISABLE0 +CFLAGS += -DCONFIG_GPIO_AS_PINRESET +CFLAGS += -DBLE_STACK_SUPPORT_REQD +CFLAGS += -mcpu=cortex-m4 +CFLAGS += -mthumb -mabi=aapcs --std=gnu99 +CFLAGS += -Wall -Werror +CFLAGS += -ggdb +CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# keep every function in separate section. This will allow linker to dump unused functions +CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing +CFLAGS += -fno-builtin --short-enums + +# keep every function in separate section. This will allow linker to dump unused functions +LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map +LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) +LDFLAGS += -mcpu=cortex-m4 +LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# let linker to dump unused sections +LDFLAGS += -Wl,--gc-sections +# use newlib in nano version +LDFLAGS += --specs=nano.specs -lc -lnosys + +# Assembler flags +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +ASMFLAGS += -DSOFTDEVICE_PRESENT +ASMFLAGS += -DS132 +endif +ASMFLAGS += -x assembler-with-cpp +ASMFLAGS += -DSWI_DISABLE0 +ASMFLAGS += -DNRF52 +ASMFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z) +ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET +ASMFLAGS += -DBLE_STACK_SUPPORT_REQD + +C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES)) +C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) ) +C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) ) + +ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES)) +ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) )) +ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) ) + +vpath %.c $(C_PATHS) +vpath %.s $(ASM_PATHS) + +OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS) + +TARGET_LIBS= nrf52832.a $(NRF52_SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a + +### Don't treat the .elf as intermediate +.PRECIOUS: %.hex %.bin + +nrf52832.a: $(OBJECTS) + $(TRACE_AR) + $(Q)$(AR) $(AROPTS) $@ $^ + +### Compilation rules +CUSTOM_RULE_LINK=1 + +%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS) + $(TRACE_LD) + $(Q)$(CC) $(LDFLAGS) ${filter %o %.co %.a,$^} -o $@ + +# Assemble files +$(OBJECT_DIRECTORY)/%.o: %.s + @echo Compiling file: $(notdir $<) + $(Q)$(CC) $(ASMFLAGS) $(addprefix -I$(NRF52_SDK_ROOT)/, $(INC_PATHS)) -c -o $@ $< + +# Create binary file from the .out file +%.bin: %.elf + @echo Preparing: $@ + $(Q)$(OBJCOPY) -O binary $^ $@ + +# Create binary .hex file from the .out file +%.hex: %.elf + @echo Preparing: $@ + $(Q)$(OBJCOPY) -O ihex $^ $@ + +### We don't really need the .hex and .bin for the .$(TARGET) but let's make +### sure they get built +%.$(TARGET): %.elf %.hex %.bin + cp $*.elf $@ + $(Q)$(SIZE) $@ + +%.jlink: + sed -e 's/#OUTPUT_FILENAME#/$*.hex/' $(CONTIKI_CPU)/flash.jlink > $@ + +%.flash: %.hex %.jlink + @echo Flashing: $^ + $(JLINK) $(JLINK_OPTS) -CommanderScript $*.jlink + +softdevice.jlink: + sed -e 's,#OUTPUT_FILENAME#,$(NRF52_SOFTDEVICE),' $(CONTIKI_CPU)/flash.jlink > $@ + +softdevice.flash: softdevice.jlink + @echo Flashing: $(notdir $(NRF52_SOFTDEVICE)) + $(JLINK) $(JLINK_OPTS) -CommanderScript $^ + +erase: + $(JLINK) $(JLINK_OPTS) -CommanderScript $(CONTIKI_CPU)/erase.jlink + +.PHONY: softdevice.jlink diff --git a/cpu/nrf52832/ble/ble-core.c b/cpu/nrf52832/ble/ble-core.c new file mode 100644 index 000000000..cb3d4ce66 --- /dev/null +++ b/cpu/nrf52832/ble/ble-core.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup cpu + * @{ + * + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * @{ + * + * \file + * Basic BLE functions. + * \author + * Wojciech Bober + * + */ +#include +#include +#include "boards.h" +#include "nordic_common.h" +#include "nrf_delay.h" +#include "nrf_sdm.h" +#include "ble_advdata.h" +#include "ble_srv_common.h" +#include "ble_ipsp.h" +#include "softdevice_handler.h" +#include "app_error.h" +#include "iot_defines.h" +#include "ble-core.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define IS_SRVC_CHANGED_CHARACT_PRESENT 1 +#define APP_ADV_TIMEOUT 0 /**< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables timeout. */ +#define APP_ADV_ADV_INTERVAL MSEC_TO_UNITS(333, UNIT_0_625_MS) /**< The advertising interval. This value can vary between 100ms to 10.24s). */ + +static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */ + +static void +ble_evt_dispatch(ble_evt_t * p_ble_evt); +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize and enable the BLE stack. + */ +void +ble_stack_init(void) +{ + uint32_t err_code; + + // Enable BLE stack. + ble_enable_params_t ble_enable_params; + memset(&ble_enable_params, 0, sizeof(ble_enable_params)); + ble_enable_params.gatts_enable_params.attr_tab_size = + BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; + ble_enable_params.gatts_enable_params.service_changed = + IS_SRVC_CHANGED_CHARACT_PRESENT; + err_code = sd_ble_enable(&ble_enable_params); + APP_ERROR_CHECK(err_code); + + // Register with the SoftDevice handler module for BLE events. + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + APP_ERROR_CHECK(err_code); + + // Setup address + ble_gap_addr_t ble_addr; + err_code = sd_ble_gap_address_get(&ble_addr); + APP_ERROR_CHECK(err_code); + + ble_addr.addr[5] = 0x00; + ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + + err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &ble_addr); + APP_ERROR_CHECK(err_code); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return device EUI64 MAC address + * \param addr pointer to a buffer to store the address + */ +void +ble_get_mac(uint8_t addr[8]) +{ + uint32_t err_code; + ble_gap_addr_t ble_addr; + + err_code = sd_ble_gap_address_get(&ble_addr); + APP_ERROR_CHECK(err_code); + + IPV6_EUI64_CREATE_FROM_EUI48(addr, ble_addr.addr, ble_addr.addr_type); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize BLE advertising data. + * \param name Human readable device name that will be advertised + */ +void +ble_advertising_init(const char *name) +{ + uint32_t err_code; + ble_advdata_t advdata; + uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)name, + strlen(name)); + APP_ERROR_CHECK(err_code); + + ble_uuid_t adv_uuids[] = {{BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}}; + + // Build and set advertising data. + memset(&advdata, 0, sizeof(advdata)); + + advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.flags = flags; + advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); + advdata.uuids_complete.p_uuids = adv_uuids; + + err_code = ble_advdata_set(&advdata, NULL); + APP_ERROR_CHECK(err_code); + + // Initialize advertising parameters (used when starting advertising). + memset(&m_adv_params, 0, sizeof(m_adv_params)); + + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; + m_adv_params.p_peer_addr = NULL; // Undirected advertisement. + m_adv_params.fp = BLE_GAP_ADV_FP_ANY; + m_adv_params.interval = APP_ADV_ADV_INTERVAL; + m_adv_params.timeout = APP_ADV_TIMEOUT; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start BLE advertising. + */ +void +ble_advertising_start(void) +{ + uint32_t err_code; + + err_code = sd_ble_gap_adv_start(&m_adv_params); + APP_ERROR_CHECK(err_code); + + PRINTF("ble-core: advertising started\n"); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Print GAP address. + * \param addr a pointer to address + */ +void +ble_gap_addr_print(const ble_gap_addr_t *addr) +{ + unsigned int i; + for(i = 0; i < sizeof(addr->addr); i++) { + if(i > 0) { + PRINTF(":"); + }PRINTF("%02x", addr->addr[i]); + }PRINTF(" (%d)", addr->addr_type); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Function for handling the Application's BLE Stack events. + * \param[in] p_ble_evt Bluetooth stack event. + */ +static void +on_ble_evt(ble_evt_t *p_ble_evt) +{ + switch(p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + PRINTF("ble-core: connected [handle:%d, peer: ", p_ble_evt->evt.gap_evt.conn_handle); + ble_gap_addr_print(&(p_ble_evt->evt.gap_evt.params.connected.peer_addr)); + PRINTF("]\n"); + sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_RSSI_THRESHOLD_INVALID, + 0); + break; + + case BLE_GAP_EVT_DISCONNECTED: + PRINTF("ble-core: disconnected [handle:%d]\n", p_ble_evt->evt.gap_evt.conn_handle); + ble_advertising_start(); + break; + default: + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief SoftDevice BLE event callback. + * \param[in] p_ble_evt Bluetooth stack event. + */ +static void +ble_evt_dispatch(ble_evt_t *p_ble_evt) +{ + ble_ipsp_evt_handler(p_ble_evt); + on_ble_evt(p_ble_evt); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/ble/ble-core.h b/cpu/nrf52832/ble/ble-core.h new file mode 100644 index 000000000..84c181d2e --- /dev/null +++ b/cpu/nrf52832/ble/ble-core.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup cpu + * @{ + * + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * @{ + * + * \file + * Basic BLE functions. + * \author + * Wojciech Bober + */ +#ifndef DEV_BLE_H_ +#define DEV_BLE_H_ + +#include + +void ble_stack_init(void); +void ble_advertising_init(const char *name); +void ble_advertising_start(void); +void ble_get_mac(uint8_t addr[8]); + +#endif /* DEV_BLE_H_ */ + +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/ble/ble-mac.c b/cpu/nrf52832/ble/ble-mac.c new file mode 100644 index 000000000..6ffd87a82 --- /dev/null +++ b/cpu/nrf52832/ble/ble-mac.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-ble + * @{ + * + * \file + * A MAC protocol implementation that uses nRF52 IPSP implementation + * as a link layer. + * \author + * Wojciech Bober + */ +#include +#include +#include "app_error.h" +#include "ble_ipsp.h" +#include "nrf_soc.h" +#include "iot_defines.h" + +#include "net/mac/nullmac.h" +#include "net/netstack.h" +#include "net/ip/uip.h" +#include "net/ip/tcpip.h" +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "net/linkaddr.h" + +#include "dev/watchdog.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#ifndef BLE_MAC_MAX_INTERFACE_NUM +#define BLE_MAC_MAX_INTERFACE_NUM 1 /**< Maximum number of interfaces, i.e., connection to master devices */ +#endif + +/*---------------------------------------------------------------------------*/ +process_event_t ble_event_interface_added; /**< This event is broadcast when BLE connection is established */ +process_event_t ble_event_interface_deleted; /**< This event is broadcast when BLE connection is destroyed */ + +/*---------------------------------------------------------------------------*/ +PROCESS(ble_ipsp_process, "BLE IPSP process"); + +/*---------------------------------------------------------------------------*/ +/** + * \brief A structure that binds IPSP connection with a peer address. + */ +typedef struct { + eui64_t peer_addr; + ble_ipsp_handle_t handle; +} ble_mac_interface_t; + +static ble_mac_interface_t interfaces[BLE_MAC_MAX_INTERFACE_NUM]; + +static volatile int busy_tx; /**< Flag is set to 1 when the driver is busy transmitting a packet. */ +static volatile int busy_rx; /**< Flag is set to 1 when there is a received packet pending. */ + +struct { + eui64_t src; + uint8_t payload[PACKETBUF_SIZE]; + uint16_t len; + int8_t rssi; +} input_packet; + +static mac_callback_t mac_sent_cb; +static void *mac_sent_ptr; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Lookup interface by IPSP connection. + * + * \param handle a pointer to IPSP handle. + * \retval a pointer to interface structure + * \retval NULL if no interface has been found for a given handle + */ +static ble_mac_interface_t * +ble_mac_interface_lookup(ble_ipsp_handle_t *handle) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.conn_handle == handle->conn_handle && + interfaces[i].handle.cid == handle->cid) { + return &interfaces[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Add IPSP connection to the interface table. + * + * This function binds IPSP connection with peer address. + * + * \param peer a pointer to eui64 address + * \param handle a pointer to IPSP handle + * + * \retval a pointer to an interface structure on success + * \retval NULL if interface table is full + */ +static ble_mac_interface_t * +ble_mac_interface_add(eui64_t *peer, ble_ipsp_handle_t *handle) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.conn_handle == 0 && interfaces[i].handle.cid == 0) { + memcpy(&interfaces[i].handle, handle, sizeof(ble_ipsp_handle_t)); + memcpy(&interfaces[i].peer_addr, peer, sizeof(eui64_t)); + process_post(PROCESS_BROADCAST, ble_event_interface_added, NULL); + return &interfaces[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Remove interface from the interface table. + * \param interface a pointer to interface + */ +static void +ble_mac_interface_delete(ble_mac_interface_t *interface) +{ + memset(interface, 0, sizeof(ble_mac_interface_t)); + process_post(PROCESS_BROADCAST, ble_event_interface_deleted, NULL); +} + +/*---------------------------------------------------------------------------*/ +/** + * \brief Callback registered with IPSP to receive asynchronous events from the module. + * \note This function is called from SoftDevice interrupt context. + * + * \param[in] p_handle Pointer to IPSP handle. + * \param[in] p_evt Pointer to specific event, generated by IPSP module. + * + * \return NRF_SUCCESS on success, otherwise NRF_ERROR_NO_MEM error. + */ +static uint32_t +ble_mac_ipsp_evt_handler_irq(ble_ipsp_handle_t *p_handle, ble_ipsp_evt_t *p_evt) +{ + uint32_t retval = NRF_SUCCESS; + + ble_mac_interface_t *p_instance = NULL; + p_instance = ble_mac_interface_lookup(p_handle); + + if(p_handle) { + PRINTF("ble-mac: IPSP event [handle:%d CID 0x%04X]\n", p_handle->conn_handle, p_handle->cid); + } + + switch(p_evt->evt_id) { + case BLE_IPSP_EVT_CHANNEL_CONNECTED: { + eui64_t peer_addr; + + PRINTF("ble-mac: channel connected\n"); + + IPV6_EUI64_CREATE_FROM_EUI48( + peer_addr.identifier, + p_evt->evt_param->params.ch_conn_request.peer_addr.addr, + p_evt->evt_param->params.ch_conn_request.peer_addr.addr_type); + + p_instance = ble_mac_interface_add(&peer_addr, p_handle); + + if(p_instance != NULL) { + PRINTF("ble-mac: added new IPSP interface\n"); + } else { + PRINTF("ble-mac: cannot add new interface. Table is full\n"); + ble_ipsp_disconnect(p_handle); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DISCONNECTED: { + PRINTF("ble-mac: channel disconnected\n"); + if(p_instance != NULL) { + PRINTF("ble-mac: removed IPSP interface\n"); + ble_mac_interface_delete(p_instance); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DATA_RX: { + PRINTF("ble-mac: data received\n"); + if(p_instance != NULL) { + if(busy_rx) { + PRINTF("ble-mac: packet dropped as input buffer is busy\n"); + break; + } + + if(p_evt->evt_param->params.ch_rx.len > PACKETBUF_SIZE) { + PRINTF("ble-mac: packet buffer is too small!\n"); + break; + } + + busy_rx = 1; + + input_packet.len = p_evt->evt_param->params.ch_rx.len; + memcpy(input_packet.payload, p_evt->evt_param->params.ch_rx.p_data, input_packet.len); + memcpy(input_packet.src.identifier, p_instance->peer_addr.identifier, sizeof(eui64_t)); + sd_ble_gap_rssi_get(p_handle->conn_handle, &input_packet.rssi); + + process_poll(&ble_ipsp_process); + } else { + PRINTF("ble-mac: got data to unknown interface!\n"); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE: { + PRINTF("ble-mac: data transmitted\n"); + busy_tx = 0; + break; + } + } + + return retval; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ble_ipsp_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == PROCESS_EVENT_POLL) { + packetbuf_copyfrom(input_packet.payload, input_packet.len); + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, input_packet.rssi); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const linkaddr_t *)input_packet.src.identifier); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &linkaddr_node_addr); + busy_rx = 0; + NETSTACK_LLSEC.input(); + } + } + + PROCESS_END(); +} + +/*---------------------------------------------------------------------------*/ +/** + * \brief Lookup IPSP handle by peer address. + * + * \param addr a pointer to eui64 address. + * \retval a pointer to IPSP handle on success + * \retval NULL if an IPSP handle for given address haven't been found + */ +static ble_ipsp_handle_t * +find_handle(const linkaddr_t *addr) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(linkaddr_cmp((const linkaddr_t *)&interfaces[i].peer_addr, addr)) { + return &interfaces[i].handle; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Send packet on a given IPSP handle. + * + * \param handle a pointer to IPSP handle. + * \return 1 on success, 0 otherwise + */ +static int +send_to_peer(ble_ipsp_handle_t *handle) +{ + PRINTF("ble-mac: sending packet[GAP handle:%d CID:0x%04X]\n", handle->conn_handle, handle->cid); + return (ble_ipsp_send(handle, packetbuf_dataptr(), packetbuf_datalen()) == NRF_SUCCESS); +} +/*---------------------------------------------------------------------------*/ +static void +send_packet(mac_callback_t sent, void *ptr) +{ + int i; + const linkaddr_t *dest; + ble_ipsp_handle_t *handle; + int ret = 0; + + mac_sent_cb = sent; + mac_sent_ptr = ptr; + + dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + + if(linkaddr_cmp(dest, &linkaddr_null)) { + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.cid != 0 && interfaces[i].handle.conn_handle != 0) { + ret = send_to_peer(&interfaces[i].handle); + watchdog_periodic(); + } + } + } else if((handle = find_handle(dest)) != NULL) { + ret = send_to_peer(handle); + } else { + PRINTF("ble-mac: no connection found for peer"); + } + + if(ret) { + busy_tx = 1; + while(busy_tx) { + watchdog_periodic(); + sd_app_evt_wait(); + } + mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1); + } else { + mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); + } +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +channel_check_interval(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +// Initialize IPSP service + uint32_t err_code; + ble_ipsp_init_t ipsp_init_params; + + memset(&ipsp_init_params, 0, sizeof(ipsp_init_params)); + ipsp_init_params.evt_handler = ble_mac_ipsp_evt_handler_irq; + err_code = ble_ipsp_init(&ipsp_init_params); + APP_ERROR_CHECK(err_code); + + ble_event_interface_added = process_alloc_event(); + ble_event_interface_deleted = process_alloc_event(); + + process_start(&ble_ipsp_process, NULL); +} +/*---------------------------------------------------------------------------*/ +const struct mac_driver ble_ipsp_mac_driver = { + "nRF52 IPSP driver", + init, + send_packet, + NULL, + on, + off, + channel_check_interval, +}; +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/ble/ble-mac.h b/cpu/nrf52832/ble/ble-mac.h new file mode 100644 index 000000000..3dd9b82af --- /dev/null +++ b/cpu/nrf52832/ble/ble-mac.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-ble + * @{ + * + * \file + * A MAC protocol implementation that uses nRF52 IPSP implementation + * as a link layer. + * \author + * Wojciech Bober + */ +#ifndef BLE_MAC_H_ +#define BLE_MAC_H_ + +#include "sys/process.h" +#include "net/mac/mac.h" + +extern const struct mac_driver ble_ipsp_mac_driver; /**< BLE over IPSP MAC driver structure */ +extern process_event_t ble_event_interface_added; /**< This event is broadcast when a new IPSP connection is established */ +extern process_event_t ble_event_interface_deleted; /**< This event is broadcast when a IPSP connection is deleted */ + +#endif /* BLE_MAC_H_ */ +/** + * @} + */ diff --git a/cpu/nrf52832/dev/clock.c b/cpu/nrf52832/dev/clock.c new file mode 100644 index 000000000..4ee09839d --- /dev/null +++ b/cpu/nrf52832/dev/clock.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + */ + +/** + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-clock Clock driver + * @{ + * + * \file + * Software clock implementation for the nRF52. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#include +#include +#include "nrf.h" +#include "nrf_drv_config.h" +#include "nrf_drv_rtc.h" +#include "nrf_drv_clock.h" +#include "nrf_delay.h" +#include "app_error.h" +#include "contiki.h" +#include "platform-conf.h" + +/*---------------------------------------------------------------------------*/ +const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(PLATFORM_RTC_INSTANCE_ID); /**< RTC instance used for platform clock */ +/*---------------------------------------------------------------------------*/ +static volatile uint32_t ticks; +void clock_update(void); + +#define TICKS (RTC1_CONFIG_FREQUENCY/CLOCK_CONF_SECOND) + +/** + * \brief Function for handling the RTC0 interrupts + * \param int_type Type of interrupt to be handled + */ +static void +rtc_handler(nrf_drv_rtc_int_type_t int_type) +{ + if (int_type == NRF_DRV_RTC_INT_TICK) { + clock_update(); + } +} + +#ifndef SOFTDEVICE_PRESENT +/** \brief Function starting the internal LFCLK XTAL oscillator. + */ +static void +lfclk_config(void) +{ + ret_code_t err_code = nrf_drv_clock_init(NULL); + APP_ERROR_CHECK(err_code); + + nrf_drv_clock_lfclk_request(); +} +#endif + +/** + * \brief Function initialization and configuration of RTC driver instance. + */ +static void +rtc_config(void) +{ + uint32_t err_code; + + //Initialize RTC instance + err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler); + APP_ERROR_CHECK(err_code); + + //Enable tick event & interrupt + nrf_drv_rtc_tick_enable(&rtc, true); + + //Power on RTC instance + nrf_drv_rtc_enable(&rtc); +} +/*---------------------------------------------------------------------------*/ +void +clock_init(void) +{ + ticks = 0; +#ifndef SOFTDEVICE_PRESENT + lfclk_config(); +#endif + rtc_config(); +} +/*---------------------------------------------------------------------------*/ +CCIF clock_time_t +clock_time(void) +{ + return (clock_time_t)(ticks & 0xFFFFFFFF); +} +/*---------------------------------------------------------------------------*/ +void +clock_update(void) +{ + ticks++; + if (etimer_pending()) { + etimer_request_poll(); + } +} +/*---------------------------------------------------------------------------*/ +CCIF unsigned long +clock_seconds(void) +{ + return (unsigned long)ticks/CLOCK_CONF_SECOND; +} +/*---------------------------------------------------------------------------*/ +void +clock_wait(clock_time_t i) +{ + clock_time_t start; + start = clock_time(); + while (clock_time() - start < (clock_time_t)i) { + __WFE(); + } +} +/*---------------------------------------------------------------------------*/ +void +clock_delay_usec(uint16_t dt) +{ + nrf_delay_us(dt); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Obsolete delay function but we implement it here since some code + * still uses it + */ +void +clock_delay(unsigned int i) +{ + clock_delay_usec(i); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/lpm.h b/cpu/nrf52832/dev/lpm.h new file mode 100644 index 000000000..192165a49 --- /dev/null +++ b/cpu/nrf52832/dev/lpm.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-lpm Low power mode functions + * @{ + * + * \file + * A header file for low power mode functions. + * \author + * Wojciech Bober + */ +#ifndef LPM_H +#define LPM_H + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#endif + +/** + * \brief Stop and wait for an event + * + */ +static inline void +lpm_drop(void) +{ +#ifdef SOFTDEVICE_PRESENT + sd_app_evt_wait(); +#else + __WFI(); +#endif +} + +#endif /* DEV_LPM_H_ */ +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/random.c b/cpu/nrf52832/dev/random.c new file mode 100644 index 000000000..d21bf18ff --- /dev/null +++ b/cpu/nrf52832/dev/random.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-rng Hardware random number generator + * @{ + * + * \file + * Random number generator routines exploiting the nRF52 hardware + * capabilities. + * + * This file overrides core/lib/random.c. + * + * \author + * Wojciech Bober + */ +#include +#include +#include "app_error.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Generates a new random number using the nRF52 RNG. + * \return a random number. + */ +unsigned short +random_rand(void) +{ + unsigned short value = 42; + uint8_t available; + ret_code_t err_code; + + do { + nrf_drv_rng_bytes_available(&available); + } while (available < sizeof(value)); + + err_code = nrf_drv_rng_rand((uint8_t *)&value, sizeof(value)); + APP_ERROR_CHECK(err_code); + + return value; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the nRF52 random number generator. + * \param seed Ignored. It's here because the function prototype is in core. + * + */ +void +random_init(unsigned short seed) +{ + (void)seed; + ret_code_t err_code = nrf_drv_rng_init(NULL); + APP_ERROR_CHECK(err_code); +} +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/uart0.c b/cpu/nrf52832/dev/uart0.c new file mode 100644 index 000000000..df9c7b9e3 --- /dev/null +++ b/cpu/nrf52832/dev/uart0.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-uart UART driver + * @{ + * + * \file + * Contiki compatible UART driver. + * \author + * Wojciech Bober + */ +#include +#include "nrf.h" +#include "nrf_drv_config.h" +#include "nrf_drv_uart.h" +#include "app_util_platform.h" +#include "app_error.h" + +#include "contiki.h" +#include "dev/uart0.h" +#include "dev/watchdog.h" +#include "lib/ringbuf.h" + +#define TXBUFSIZE 128 +static uint8_t rx_buffer[1]; + +static int (*uart0_input_handler)(unsigned char c); + +static struct ringbuf txbuf; +static uint8_t txbuf_data[TXBUFSIZE]; + +/*---------------------------------------------------------------------------*/ +static void +uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if (p_event->type == NRF_DRV_UART_EVT_RX_DONE) { + if (uart0_input_handler != NULL) { + uart0_input_handler(p_event->data.rxtx.p_data[0]); + } + (void)nrf_drv_uart_rx(rx_buffer, 1); + } else if (p_event->type == NRF_DRV_UART_EVT_TX_DONE) { + if (ringbuf_elements(&txbuf) > 0) { + uint8_t c = ringbuf_get(&txbuf); + nrf_drv_uart_tx(&c, 1); + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +void +uart0_set_input(int (*input)(unsigned char c)) +{ + uart0_input_handler = input; +} +/*---------------------------------------------------------------------------*/ +void +uart0_writeb(unsigned char c) +{ + if (nrf_drv_uart_tx(&c, 1) == NRF_ERROR_BUSY) { + while (ringbuf_put(&txbuf, c) == 0) { + __WFE(); + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * Initialize the RS232 port. + * + */ +void +uart0_init(unsigned long ubr) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + ret_code_t retcode = nrf_drv_uart_init(&config, uart_event_handler); + APP_ERROR_CHECK(retcode); + + ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data)); + + nrf_drv_uart_rx_enable(); + nrf_drv_uart_rx(rx_buffer, 1); +} +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/uart0.h b/cpu/nrf52832/dev/uart0.h new file mode 100644 index 000000000..c6b3938ea --- /dev/null +++ b/cpu/nrf52832/dev/uart0.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-uart UART driver + * @{ + * + * \file + * A header file for Contiki compatible UART driver. + * \author + * Wojciech Bober + */ +#ifndef UART_0_H +#define UART_0_H + +#include +#include "contiki-conf.h" + +void uart0_init(); +void uart0_writeb(uint8_t byte); + +void uart0_set_input(int (* input)(unsigned char c)); + +#endif /* UART_0_H */ +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/watchdog.c b/cpu/nrf52832/dev/watchdog.c new file mode 100644 index 000000000..50e26d72b --- /dev/null +++ b/cpu/nrf52832/dev/watchdog.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-watchdog Watchdog driver + * @{ + * + * \file + * Contiki compatible watchdog driver implementation. + * \author + * Wojciech Bober + */ +#include +#include "app_error.h" +#include "contiki-conf.h" + +static nrf_drv_wdt_channel_id wdt_channel_id; +static uint8_t wdt_initialized = 0; + +/** + * \brief WDT events handler. + */ +static void wdt_event_handler(void) +{ + LEDS_OFF(LEDS_MASK); +} + +/*---------------------------------------------------------------------------*/ +void +watchdog_init(void) +{ + ret_code_t err_code; + err_code = nrf_drv_wdt_init(NULL, &wdt_event_handler); + APP_ERROR_CHECK(err_code); + err_code = nrf_drv_wdt_channel_alloc(&wdt_channel_id); + APP_ERROR_CHECK(err_code); + wdt_initialized = 1; +} +/*---------------------------------------------------------------------------*/ +void +watchdog_start(void) +{ + if(wdt_initialized) { + nrf_drv_wdt_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +watchdog_periodic(void) +{ + if(wdt_initialized) { + nrf_drv_wdt_channel_feed(wdt_channel_id); + } +} +/*---------------------------------------------------------------------------*/ +void +watchdog_reboot(void) +{ + NVIC_SystemReset(); +} +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/erase.jlink b/cpu/nrf52832/erase.jlink new file mode 100644 index 000000000..5f08d8d86 --- /dev/null +++ b/cpu/nrf52832/erase.jlink @@ -0,0 +1,2 @@ +erase +q \ No newline at end of file diff --git a/cpu/nrf52832/flash.jlink b/cpu/nrf52832/flash.jlink new file mode 100644 index 000000000..787670d55 --- /dev/null +++ b/cpu/nrf52832/flash.jlink @@ -0,0 +1,4 @@ +loadfile #OUTPUT_FILENAME# +r +g +q \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52-pca10036-sd.ld b/cpu/nrf52832/ld/nrf52-pca10036-sd.ld new file mode 100644 index 000000000..455749e29 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52-pca10036-sd.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 + RAM (rwx) : ORIGIN = 0x08000000, LENGTH = 0x8000 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52-pca10040-sd.ld b/cpu/nrf52832/ld/nrf52-pca10040-sd.ld new file mode 100644 index 000000000..f30aad455 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52-pca10040-sd.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 + RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0xD800 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52.ld b/cpu/nrf52832/ld/nrf52.ld new file mode 100644 index 000000000..268794d04 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/mtarch.h b/cpu/nrf52832/mtarch.h new file mode 100644 index 000000000..4f696669d --- /dev/null +++ b/cpu/nrf52832/mtarch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 + * Stub header file for multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * + * \author + * George Oikonomou - + */ +#ifndef __MTARCH_H__ +#define __MTARCH_H__ + +struct mtarch_thread { + unsigned char *sp; +}; + +#endif /* __MTARCH_H__ */ diff --git a/cpu/nrf52832/putchar.c b/cpu/nrf52832/putchar.c new file mode 100644 index 000000000..c4163ba3d --- /dev/null +++ b/cpu/nrf52832/putchar.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 + * @{ + * + * \file + * Hardware specific implementation of putchar() and puts() functions. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#include +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + uart0_writeb(c); + return c; +} +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + int i; + + if (str == NULL) { + return 0; + } + + for (i = 0; i < strlen(str); i++) { + uart0_writeb(str[i]); + } + + uart0_writeb('\n'); + return i; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/rtimer-arch.c b/cpu/nrf52832/rtimer-arch.c new file mode 100644 index 000000000..78f4790f2 --- /dev/null +++ b/cpu/nrf52832/rtimer-arch.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + */ + +/** + * \addtogroup nrf52832 + * @{ + * + * \file + * Implementation of the architecture dependent rtimer functions for the nRF52 + * + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include +#include "nrf.h" +#include "nrf_drv_timer.h" +#include "app_error.h" +#include "contiki.h" +#include "platform-conf.h" + +static const nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(PLATFORM_TIMER_INSTANCE_ID); /**< Timer instance used for rtimer */ + +/** + * \brief Handler for timer events. + * + * \param event_type type of an event that should be handled + * \param p_context opaque data pointer passed from nrf_drv_timer_init() + */ +static void +timer_event_handler(nrf_timer_event_t event_type, void* p_context) +{ + switch (event_type) { + case NRF_TIMER_EVENT_COMPARE1: + rtimer_run_next(); + break; + + default: + //Do nothing. + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize platform rtimer + */ +void +rtimer_arch_init(void) +{ + ret_code_t err_code = nrf_drv_timer_init(&timer, NULL, timer_event_handler); + APP_ERROR_CHECK(err_code); + nrf_drv_timer_enable(&timer); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Schedules an rtimer task to be triggered at time t + * \param t The time when the task will need executed. + * + * \e t is an absolute time, in other words the task will be executed AT + * time \e t, not IN \e t rtimer ticks. + * + * This function schedules a one-shot event with the nRF RTC. + */ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + nrf_drv_timer_compare(&timer, NRF_TIMER_CC_CHANNEL1, t, true); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current real-time clock time + * \return The current rtimer time in ticks + * + */ +rtimer_clock_t +rtimer_arch_now() +{ + return nrf_drv_timer_capture(&timer, NRF_TIMER_CC_CHANNEL0); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/rtimer-arch.h b/cpu/nrf52832/rtimer-arch.h new file mode 100644 index 000000000..da709dae2 --- /dev/null +++ b/cpu/nrf52832/rtimer-arch.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 nRF52832 + * @{ + * + * \file + * Architecture dependent rtimer implementation header file. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef RTIMER_ARCH_H_ +#define RTIMER_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +rtimer_clock_t rtimer_arch_now(void); +/*---------------------------------------------------------------------------*/ +#endif /* RTIMER_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ From d39ad95db5f1625dac61b91a1d0a6d16c0b43938 Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Sat, 9 Jan 2016 14:44:39 +0100 Subject: [PATCH 05/80] nrf52dk: platform support --- platform/nrf52dk/Makefile.nrf52dk | 34 + platform/nrf52dk/README-BLE-6LoWPAN.md | 100 ++ platform/nrf52dk/README.md | 254 +++++ platform/nrf52dk/config/nrf_drv_config.h | 329 ++++++ platform/nrf52dk/config/pstorage_platform.h | 74 ++ platform/nrf52dk/contiki-conf.h | 153 +++ platform/nrf52dk/contiki-main.c | 203 ++++ platform/nrf52dk/dbg-io/dbg.c | 72 ++ platform/nrf52dk/dbg-io/dbg.h | 67 ++ platform/nrf52dk/dbg-io/debug-uart.h | 54 + platform/nrf52dk/dev/button-sensor.c | 330 ++++++ platform/nrf52dk/dev/button-sensor.h | 72 ++ platform/nrf52dk/dev/leds-arch.c | 77 ++ platform/nrf52dk/dev/nrf52dk-sensors.c | 66 ++ platform/nrf52dk/dev/temperature-sensor.c | 109 ++ platform/nrf52dk/dev/temperature-sensor.h | 59 + platform/nrf52dk/platform-conf.h | 145 +++ platform/nrf52dk/rtt/rtt-printf.c | 24 + platform/nrf52dk/rtt/segger-rtt-conf.h | 135 +++ platform/nrf52dk/rtt/segger-rtt-printf.c | 510 +++++++++ platform/nrf52dk/rtt/segger-rtt.c | 1102 +++++++++++++++++++ platform/nrf52dk/rtt/segger-rtt.h | 204 ++++ 22 files changed, 4173 insertions(+) create mode 100644 platform/nrf52dk/Makefile.nrf52dk create mode 100644 platform/nrf52dk/README-BLE-6LoWPAN.md create mode 100644 platform/nrf52dk/README.md create mode 100644 platform/nrf52dk/config/nrf_drv_config.h create mode 100644 platform/nrf52dk/config/pstorage_platform.h create mode 100644 platform/nrf52dk/contiki-conf.h create mode 100644 platform/nrf52dk/contiki-main.c create mode 100644 platform/nrf52dk/dbg-io/dbg.c create mode 100644 platform/nrf52dk/dbg-io/dbg.h create mode 100644 platform/nrf52dk/dbg-io/debug-uart.h create mode 100644 platform/nrf52dk/dev/button-sensor.c create mode 100644 platform/nrf52dk/dev/button-sensor.h create mode 100644 platform/nrf52dk/dev/leds-arch.c create mode 100644 platform/nrf52dk/dev/nrf52dk-sensors.c create mode 100644 platform/nrf52dk/dev/temperature-sensor.c create mode 100644 platform/nrf52dk/dev/temperature-sensor.h create mode 100644 platform/nrf52dk/platform-conf.h create mode 100644 platform/nrf52dk/rtt/rtt-printf.c create mode 100644 platform/nrf52dk/rtt/segger-rtt-conf.h create mode 100644 platform/nrf52dk/rtt/segger-rtt-printf.c create mode 100644 platform/nrf52dk/rtt/segger-rtt.c create mode 100644 platform/nrf52dk/rtt/segger-rtt.h diff --git a/platform/nrf52dk/Makefile.nrf52dk b/platform/nrf52dk/Makefile.nrf52dk new file mode 100644 index 000000000..8fa911cc4 --- /dev/null +++ b/platform/nrf52dk/Makefile.nrf52dk @@ -0,0 +1,34 @@ +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +### Include the board-specific makefile +PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET) + +CONTIKI_TARGET_DIRS += . dev config +CONTIKI_SOURCEFILES += contiki-main.c leds-arch.c nrf52dk-sensors.c button-sensor.c temperature-sensor.c + +ifeq ($(NRF52_USE_RTT),1) +### Use the existing debug I/O in cpu/arm/common +CONTIKI_TARGET_DIRS += rtt +CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c +else +CONTIKI_TARGET_DIRS += dbg-io +CONTIKI_SOURCEFILES += dbg.c +CONTIKI_CPU_DIRS += ../arm/common/dbg-io +CONTIKI_CPU_SOURCEFILES += dbg-printf.c dbg-putchar.c dbg-snprintf.c dbg-sprintf.c strformat.c +endif + +CLEAN += *.nrf52dk + +### Unless the example dictates otherwise, build with code size optimisations switched +### off +ifndef SMALL + SMALL = 0 +endif + +### Define the CPU directory and pull in the correct CPU makefile. +CONTIKI_CPU=$(CONTIKI)/cpu/nrf52832 +include $(CONTIKI_CPU)/Makefile.nrf52832 + +MODULES += core/net core/net/mac core/net/llsec diff --git a/platform/nrf52dk/README-BLE-6LoWPAN.md b/platform/nrf52dk/README-BLE-6LoWPAN.md new file mode 100644 index 000000000..e4c9ef5f6 --- /dev/null +++ b/platform/nrf52dk/README-BLE-6LoWPAN.md @@ -0,0 +1,100 @@ +This README contains information how to establish an IPv6 connecton between +Linux BLE router and an IPSP enabled BLE device. + +Prerequisites +============= +In general, any device capable of running Linux operating system, can be used +as a BLE router provided the following conditions are met: + +* Linux Kernel >3.18 is used +* bluez, libcap-ng0, radvd tools are present. + +If a built-in Bluetooth device is not available then Bluetooth 4.0 compatible +USB dongle can be used. + +The following procedures have been tested on Ubuntu 15.10. + +Establishing an IPv6 connection +=============================== +Use the following procedure to establish a connection between an nRF52 device +and Linux router: + +First enable 6LoWPAN module. This is neccessary only once per session: + + # Log in as a root user. + sudo su + + # Mount debugfs file system. + mount -t debugfs none /sys/kernel/debug + + # Load 6LoWPAN module. + modprobe bluetooth_6lowpan + + # Enable the bluetooth 6lowpan module. + echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable + + # Look for available HCI devices. + hciconfig + + # Reset HCI device - for example hci0 device. + hciconfig hci0 reset + + # Read 00:AA:BB:XX:YY:ZZ address of the nRF5x device. + hcitool lescan + +If you see device name and address in lescan output then you can connect to the +device: + + echo "connect 00:AA:BB:XX:YY:ZZ 1" > /sys/kernel/debug/bluetooth/6lowpan_control + +If above is successful then LED1 will stop blinking and LED2 will switch on. +You can then check the connection using the following commands: + + # Check if bt0 interface is present and up + ifconfig + + # Try to ping the device using its link-local address, for example, on bt0 interface. + ping6 -I bt0 fe80::2aa:bbff:fexx:yyzz + +If you'd like to learn more about the procedure please refer to +[Connecting devices to the router]. + +Distributing routable IPv6 prefix +================================= +In Linux, Router Advertisement Daemon (RADVD) can be used to distribute prefixes +in the network, hance configure routable IPv6 address. + +To configure RADVD create `/etc/radvd.conf` file and paste the following contents: + + interface bt0 + { + AdvSendAdvert on; + prefix 2001:db8::/64 + { + AdvOnLink off; + AdvAutonomous on; + AdvRouterAddr on; + }; + }; + +Next, start RADVD daemon: + + # Set IPv6 forwarding (must be present). + sudo echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + # Run radvd daemon. + sudo service radvd restart + +If successfull then all devices connected to the host will receive +a routable `2001:db8` prefix. + +This can be verified by sending echo request to the full address: + + ping6 -I bt0 2001:db8::2aa:bbff:fexx:yyzz + +where `aa:bbff:fexx:yyzz` is device Bluetooth address. + +If you'd like to learn more about the procedure please refer to +[Distributing a global IPv6 prefix]. + +* [Connecting devices to the router]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00089.html +* [Distributing a global IPv6 prefix]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00090.html \ No newline at end of file diff --git a/platform/nrf52dk/README.md b/platform/nrf52dk/README.md new file mode 100644 index 000000000..236892858 --- /dev/null +++ b/platform/nrf52dk/README.md @@ -0,0 +1,254 @@ +Contiki for nRF52 Development Kit +================================= +This guide's aim is to help you with using Contiki for +Nordic Semiconductor's nRF52 DK. + +The port depends on Nordic Semiconductor IoT SDK for nRF52. +The IoT SDK contains source code and libraries which are +required for successfull port compilation. It also contains +SoftDevice binary driver which is required for BLE operation. +See prerequisites section for details on how to set up the SDK. + +For more information about SoftDevice please refer to the SDK +docummentation [nRF52 Datasheet and SDK documentation]. + +This port supports DK versions PCA10040 and PCA10036. + +Port Features +============= +The following features have been implemented: +* Support for IPv6 over BLE using Contiki 6LoWPAN implementation +* Contiki system clock and rtimers (using 32kHz and 1MHz timers) +* UART driver +* Watchdog driver +* Hardware RNG +* Temperature sensor driver +* DK LED driver +* DK Buttons driver +* Real Time Transfer (RTT) I/O support + +Note that this port supports only IPv6 network stack. + +The port is organized as follows: +* nRF52832 CPU and BLE drivers are located in `cpu/nrf52832` folder +* nRF52 Development Kit drivers are located in `platform/nrf52dk` folder +* Platform examples are located in `examples/nrf52dk` folder + +Prerequisites and Setup +======================= +In order to compile for the nRF52 DK platform you'll need: + +* nRF5 IOT SDK + https://developer.nordicsemi.com + + Download nRF5 IOT SDK, extract it to a folder of your choice, + and point `NRF52_SDK_ROOT` environmental variable to it, e.g.,: + + ``` + wget https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip + unzip nrf5_iot_sdk_3288530.zip -d /path/to/sdk + export NRF52_SDK_ROOT=/path/to/sdk + ``` + +* An ARM compatible toolchain + The port has been tested with GNU Tools for ARM Embedded Processors + version 5.2.1. + + For Ubuntu you can use package version provided by your distribution: + ``` + sudo apt-get install gcc-arm-none-eabi + ``` + + Alternatively, install the toolchain from PPA to get the latest version + of the compiler: https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa + + For other systems please download and install toolchain available at + https://launchpad.net/gcc-arm-embedded + +* GNU make + +* Segger JLink Software for Linux + https://www.segger.com/jlink-software.html + + This package contains tools necessary for programming and debugging nRF52 DK. + + For Ubuntu you can download and install a .deb package. Alternatively download + tar.gz archive and extract it to a folder of your choice. In this case you + need to set `NRF52_JLINK_PATH` environmental variable to point to the + JLink tools location: + + ``` + export NRF52_JLINK_PATH=/path/to/jlink/tools + ``` + + To keep this variable set between sessions please add the above line to your + `rc.local` file. + + In order to access the DK as a regular Linux user create a `99-jlink.rules` + file in your udev rules folder (e.g., `/etc/udev/rules.d/`) and add the + following line to it: + + ``` + ATTRS{idProduct}=="1015", ATTRS{idVendor}=="1366", MODE="0666" + ``` + When installing from a deb package, the `99-jlink.rules` file is added + automatically to /etc/udev/rules.d folder. However, the syntax of the file + doesn't work on newer udev versions. To fix this problem edit this file and + replace ATTR keyword with ATTRS. + +To fully use the platform a BLE enabled router device is needed. Please refer +to `Preqrequisites` section in `README-BLE-6LoWPAN.md` for details. + +Getting Started +=============== +Once all tools are installed it is recommended to start by compiling +and flashing `examples/hello-word` application. This allows to verify +that toolchain setup is correct. + +To compile the example, go to `examples/hello-world` and execute: + + make TARGET=nrf52dk + +If you haven't used the device with Contiki before we advise to +erase the device and flash new SoftDevice: + + make TARGET=nrf52dk erase + make TARGET=nrf52dk softdevice.flash + +If the compilation is completed without errors flash the board: + + make TARGET=nrf52dk hello-world.flash + +The device will start BLE advertising as soon as initialized. By +default the device name is set to 'Contiki nRF52 DK'. To verify +that the device is advertising properly run: + + sudo hcitool lescan + +And observe if the device name appears in the output. Also, observe +if LED1 is blinking what indicates that device is waiting for a connection +from BLE master. + +If device is functioning as expected you can test IPv6 connection +to the device. Please refer to `README-BLE-6LoWPAN.md` on details how to do +this. + +Examples +======== +Examples specific for nRF52 DK can be found in `examples/nrf52dk` folder. Please +refer to README.md in respective examples for detailed description. + +The DK has also been tested with the `examples/hello-world` and `examples/webserver-ipv6` +generic examples. + +Compilation Options +=================== +The Contiki TARGET name for this port is `nrf52dk`, so in order to compile +an application you need to invoke GNU make as follows: + + make TARGET=nrf52dk + +In addition to this port supports the following variables which can be +set on the compilation command line: + +* `NRF52_SDK_ROOT=` + This variable allows to specify a path to the nRF52 SDK which should + be used for the build. + +* `NRF52_WITHOUT_SOFTDEVICE={0|1}` + Disables SoftDevice support if set to 1. By default, SoftDevice support + is used. Note that SoftDevice must be present (flashed) in the device + before you run an application that requires it's presence. + +* `NRF52_USE_RTT={0|1}` + Enables RealTime Terminal I/O. See VCOM and RTT for details. By default, + RTT is disabled and IO is done using Virtual COM port. + +* `NRF52_JLINK_SN=` + Allows to choose a particular DK by its serial number (printed on the + label). This is useful if you have more than one DK connected to your + PC and whish to flash a particular device. + +* `NRF52_DK_REVISION={pca10040|pca10036}` + Allows to specify DK revision. By default, pca10040 is used. + +Compilation Targets +=================== +Invoking make solely with the `TARGET` variable set will build all +applications in a given folder. A particular application can be built +by invoking make with its name as a compilation target: + + make TARGET=nrf52dk hello-world + +In order to flash the application binary to the device use `.flash` +as make target, e.g.: + + make TARGET=nrf52dk hello-world.flash + +In addition, the SoftDevice binary can be flashed to the DK by invoking: + + make TARGET=nrf52dk softdevice.flash + +To remove all build results invoke: + + make TARGET=nrf52dk clean + +The device memory can be erased using: + + make TARGET=nrf52dk erase + +Note, that once the device is erased, the SoftDevice must be programmed again. + +Virtual COM and Real Time Transfer +================================== +By default, the nRF52 DK uses a Virtual COM port to output logs. Once +the DK is plugged in a `/tty/ACM` or `/ttyUSB` device should appear in +your filesystem. A terminal emulator, such as picocom or minicom, can be +used to connect to the device. Default serial port speed is 38400 bps. + +To connect to serial port using picocom invoke: + + picocom -fh -b 38400 --imap lfcrlf /dev/ttyACM0 + +Note, that if you have not fixed file permissions for `/dev/ttyACM0` +according to section `Segger JLink Software for Linux` you'll need to use +root or sudo to open the port with `picocom`. + +In addition to Virtual COM the port supports SEGGER's Real Time Transfer +for low overhead I/O support. This allows for outputting debugging information +at much higher rate with significantly lower overhead than regular I/O. + +To compile an application with RTT rather that VCOM set `NRF52_USE_RTT` to 1 on +the compilation command line: + + make TARGET=nrf52dk NRF52_USE_RTT=1 hello-world + +You can then connect to the device terminal using `JLinkRTTClient`. Note that +a JLlink gdb or commander must be connected to the target for the RTT to work. + +More details regarding RTT can be found at https://www.segger.com/jlink-rtt.html + +Docummentation +============== +This port provides doxygen source code docummentation. To build the +docummentation please run: + + sudo apt-get install doxygen + cd \doc + make + +Support +======= +This port is officially supported by Nordic Semiconductor. Please send bug +reports or/and suggestions to . + +License +======= +All files in the port are under BSD license. nRF52 SDK and SoftDevice are +licensed on a separate terms. + +Resources +========= +* nRF52 Datasheet and SDK documentation (http://infocenter.nordicsemi.com) +* nRF52 SDK Downloads (https://developer.nordicsemi.com/) +* JLink Tools (https://www.segger.com/) \ No newline at end of file diff --git a/platform/nrf52dk/config/nrf_drv_config.h b/platform/nrf52dk/config/nrf_drv_config.h new file mode 100644 index 000000000..cfc3595b2 --- /dev/null +++ b/platform/nrf52dk/config/nrf_drv_config.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \defgroup nrf52dk-config nRF52 SDK configuration + * @{ + */ + +#ifndef NRF_DRV_CONFIG_H +#define NRF_DRV_CONFIG_H + +/* CLOCK */ +#define CLOCK_CONFIG_XTAL_FREQ NRF_CLOCK_XTALFREQ_Default +#define CLOCK_CONFIG_LF_SRC NRF_CLOCK_LF_SRC_Xtal +#define CLOCK_CONFIG_LF_RC_CAL_INTERVAL RC_2000MS_CALIBRATION_INTERVAL +#define CLOCK_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +/* GPIOTE */ +#define GPIOTE_ENABLED 1 + +#if (GPIOTE_ENABLED == 1) +#define GPIOTE_CONFIG_USE_SWI_EGU false +#define GPIOTE_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +/* TIMER */ +#define TIMER0_ENABLED 0 + +#if (TIMER0_ENABLED == 1) +#define TIMER0_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER0_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER0_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER0_INSTANCE_INDEX 0 +#endif + +#define TIMER1_ENABLED 1 + +#if (TIMER1_ENABLED == 1) +#define TIMER1_CONFIG_FREQUENCY NRF_TIMER_FREQ_62500Hz +#define TIMER1_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER1_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER1_INSTANCE_INDEX (TIMER0_ENABLED) +#endif + +#define TIMER2_ENABLED 0 + +#if (TIMER2_ENABLED == 1) +#define TIMER2_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER2_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER2_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER2_INSTANCE_INDEX (TIMER1_ENABLED+TIMER0_ENABLED) +#endif + +#define TIMER3_ENABLED 0 + +#if (TIMER3_ENABLED == 1) +#define TIMER3_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER3_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER3_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER3_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER3_INSTANCE_INDEX (TIMER2_ENABLED+TIMER2_INSTANCE_INDEX) +#endif + +#define TIMER4_ENABLED 0 + +#if (TIMER4_ENABLED == 1) +#define TIMER4_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER4_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER4_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER4_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER4_INSTANCE_INDEX (TIMER3_ENABLED+TIMER3_INSTANCE_INDEX) +#endif + + +#define TIMER_COUNT (TIMER0_ENABLED + TIMER1_ENABLED + TIMER2_ENABLED + TIMER3_ENABLED + TIMER4_ENABLED) + +/* RTC */ +#define RTC0_ENABLED 0 + +#if (RTC0_ENABLED == 1) +#define RTC0_CONFIG_FREQUENCY 32678 +#define RTC0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC0_CONFIG_RELIABLE false + +#define RTC0_INSTANCE_INDEX 0 +#endif + +#define RTC1_ENABLED 1 + +#if (RTC1_ENABLED == 1) +#define RTC1_CONFIG_FREQUENCY 128 +#define RTC1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC1_CONFIG_RELIABLE false + +#define RTC1_INSTANCE_INDEX (RTC0_ENABLED) +#endif + +#define RTC_COUNT (RTC0_ENABLED+RTC1_ENABLED) + +#define NRF_MAXIMUM_LATENCY_US 2000 + +/* RNG */ +#define RNG_ENABLED 1 + +#if (RNG_ENABLED == 1) +#define RNG_CONFIG_ERROR_CORRECTION true +#define RNG_CONFIG_POOL_SIZE 8 +#define RNG_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* SPI */ +#define SPI0_ENABLED 0 + +#if (SPI0_ENABLED == 1) +#define SPI0_USE_EASY_DMA 0 + +#define SPI0_CONFIG_SCK_PIN 2 +#define SPI0_CONFIG_MOSI_PIN 3 +#define SPI0_CONFIG_MISO_PIN 4 +#define SPI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI0_INSTANCE_INDEX 0 +#endif + +#define SPI1_ENABLED 0 + +#if (SPI1_ENABLED == 1) +#define SPI1_USE_EASY_DMA 0 + +#define SPI1_CONFIG_SCK_PIN 2 +#define SPI1_CONFIG_MOSI_PIN 3 +#define SPI1_CONFIG_MISO_PIN 4 +#define SPI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI1_INSTANCE_INDEX (SPI0_ENABLED) +#endif + +#define SPI2_ENABLED 0 + +#if (SPI2_ENABLED == 1) +#define SPI2_USE_EASY_DMA 0 + +#define SPI2_CONFIG_SCK_PIN 2 +#define SPI2_CONFIG_MOSI_PIN 3 +#define SPI2_CONFIG_MISO_PIN 4 +#define SPI2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI2_INSTANCE_INDEX (SPI0_ENABLED + SPI1_ENABLED) +#endif + +#define SPI_COUNT (SPI0_ENABLED + SPI1_ENABLED + SPI2_ENABLED) + +/* UART */ +#define UART0_ENABLED 1 + +#if (UART0_ENABLED == 1) +#define UART0_CONFIG_HWFC NRF_UART_HWFC_DISABLED +#define UART0_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED +#define UART0_CONFIG_BAUDRATE NRF_UART_BAUDRATE_38400 +#define UART0_CONFIG_PSEL_TXD 6 +#define UART0_CONFIG_PSEL_RXD 8 +#define UART0_CONFIG_PSEL_CTS 7 +#define UART0_CONFIG_PSEL_RTS 5 +#define UART0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#ifdef NRF52 +#define UART0_CONFIG_USE_EASY_DMA false +//Compile time flag +#define UART_EASY_DMA_SUPPORT 1 +#define UART_LEGACY_SUPPORT 1 +#endif //NRF52 +#endif + +#define TWI0_ENABLED 0 + +#if (TWI0_ENABLED == 1) +#define TWI0_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI0_CONFIG_SCL 0 +#define TWI0_CONFIG_SDA 1 +#define TWI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI0_INSTANCE_INDEX 0 +#endif + +#define TWI1_ENABLED 0 + +#if (TWI1_ENABLED == 1) +#define TWI1_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI1_CONFIG_SCL 0 +#define TWI1_CONFIG_SDA 1 +#define TWI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI1_INSTANCE_INDEX (TWI0_ENABLED) +#endif + +#define TWI_COUNT (TWI0_ENABLED+TWI1_ENABLED) + +/* TWIS */ +#define TWIS0_ENABLED 0 + +#if (TWIS0_ENABLED == 1) + #define TWIS0_CONFIG_ADDR0 0 + #define TWIS0_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS0_CONFIG_SCL 0 + #define TWIS0_CONFIG_SDA 1 + #define TWIS0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS0_INSTANCE_INDEX 0 +#endif + +#define TWIS1_ENABLED 0 + +#if (TWIS1_ENABLED == 1) + #define TWIS1_CONFIG_ADDR0 0 + #define TWIS1_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS1_CONFIG_SCL 0 + #define TWIS1_CONFIG_SDA 1 + #define TWIS1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS1_INSTANCE_INDEX (TWIS0_ENABLED) +#endif + +#define TWIS_COUNT (TWIS0_ENABLED + TWIS1_ENABLED) +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_NO_SYNC_MODE 0 +/** + * \brief Definition for patching PAN problems + * + * Set this definition to nonzero value to patch anomalies + * from MPW3 - first lunch microcontroller. + * + * Concerns: + * - PAN-29: TWIS: incorrect bits in ERRORSRC + * - PAN-30: TWIS: STOP task does not work as expected + */ +#define NRF_TWIS_PATCH_FOR_MPW3 1 + + +/* QDEC */ +#define QDEC_ENABLED 0 + +#if (QDEC_ENABLED == 1) +#define QDEC_CONFIG_REPORTPER NRF_QDEC_REPORTPER_10 +#define QDEC_CONFIG_SAMPLEPER NRF_QDEC_SAMPLEPER_16384us +#define QDEC_CONFIG_PIO_A 1 +#define QDEC_CONFIG_PIO_B 2 +#define QDEC_CONFIG_PIO_LED 3 +#define QDEC_CONFIG_LEDPRE 511 +#define QDEC_CONFIG_LEDPOL NRF_QDEC_LEPOL_ACTIVE_HIGH +#define QDEC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define QDEC_CONFIG_DBFEN false +#define QDEC_CONFIG_SAMPLE_INTEN false +#endif + +/* SAADC */ +#define SAADC_ENABLED 0 + +#if (SAADC_ENABLED == 1) +#define SAADC_CONFIG_RESOLUTION NRF_SAADC_RESOLUTION_10BIT +#define SAADC_CONFIG_OVERSAMPLE NRF_SAADC_OVERSAMPLE_DISABLED +#define SAADC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* LPCOMP */ +#define LPCOMP_ENABLED 0 + +#if (LPCOMP_ENABLED == 1) +#define LPCOMP_CONFIG_REFERENCE NRF_LPCOMP_REF_SUPPLY_4_8 +#define LPCOMP_CONFIG_DETECTION NRF_LPCOMP_DETECT_DOWN +#define LPCOMP_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define LPCOMP_CONFIG_INPUT NRF_LPCOMP_INPUT_0 +#endif + +/* WDT */ +#define WDT_ENABLED 1 + +#if (WDT_ENABLED == 1) +#define WDT_CONFIG_BEHAVIOUR NRF_WDT_BEHAVIOUR_RUN_SLEEP +#define WDT_CONFIG_RELOAD_VALUE 2000 +#define WDT_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#endif + +#include "nrf_drv_config_validation.h" +#endif // NRF_DRV_CONFIG_H + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/config/pstorage_platform.h b/platform/nrf52dk/config/pstorage_platform.h new file mode 100644 index 000000000..3102b2097 --- /dev/null +++ b/platform/nrf52dk/config/pstorage_platform.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + /** @cond To make doxygen skip this file */ + +/** @file + * This header contains defines with respect persistent storage that are specific to + * persistent storage implementation and application use case. + */ +#ifndef PSTORAGE_PL_H__ +#define PSTORAGE_PL_H__ + +#include +#include "nrf.h" + +static __INLINE uint16_t pstorage_flash_page_size() +{ + return (uint16_t)NRF_FICR->CODEPAGESIZE; +} + +#define PSTORAGE_FLASH_PAGE_SIZE pstorage_flash_page_size() /**< Size of one flash page. */ +#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */ + +#ifdef NRF51 +#define BOOTLOADER_ADDRESS (NRF_UICR->BOOTLOADERADDR) +#elif defined NRF52 +#define BOOTLOADER_ADDRESS (PSTORAGE_FLASH_EMPTY_MASK) +#endif + +#define PSTORAGE_FLASH_PAGE_END \ + ((BOOTLOADER_ADDRESS != PSTORAGE_FLASH_EMPTY_MASK) \ + ? (BOOTLOADER_ADDRESS / PSTORAGE_FLASH_PAGE_SIZE) \ + : NRF_FICR->CODESIZE) + + +#define PSTORAGE_NUM_OF_PAGES 2 /**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */ +#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */ + +#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES - 1) \ + * PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */ + +#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */ +#define PSTORAGE_CMD_QUEUE_SIZE 30 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */ + + +/** Abstracts persistently memory block identifier. */ +typedef uint32_t pstorage_block_t; + +typedef struct +{ + uint32_t module_id; /**< Module ID.*/ + pstorage_block_t block_id; /**< Block ID.*/ +} pstorage_handle_t; + +typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */ + +/**\brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */ +void pstorage_sys_event_handler (uint32_t sys_evt); + +#endif // PSTORAGE_PL_H__ + +/** @} */ +/** @endcond */ diff --git a/platform/nrf52dk/contiki-conf.h b/platform/nrf52dk/contiki-conf.h new file mode 100644 index 000000000..6303c90db --- /dev/null +++ b/platform/nrf52dk/contiki-conf.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-contikic-conf Contiki configuration + * @{ + * + * \file + * Contiki configuration for the nRF52 DK + */ +#ifndef CONTIKI_CONF_H +#define CONTIKI_CONF_H + +#include +/*---------------------------------------------------------------------------*/ +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif /* PROJECT_CONF_H */ +/*---------------------------------------------------------------------------*/ +/* Include platform peripherals configuration */ +#include "platform-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_NETWORK +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#endif /* NETSTACK_CONF_NETWORK */ + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC ble_ipsp_mac_driver +#endif /* NETSTACK_CONF_MAC */ + +/* 6LoWPAN */ +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /**< Always compress IPv6 packets. */ +#define SICSLOWPAN_CONF_FRAG 0 /**< We don't use 6LoWPAN fragmentation as IPSP takes care of that for us.*/ +#define SICSLOWPAN_FRAMER_HDRLEN 0 /**< Use fixed header len rather than framer.length() function */ + +/* Packet buffer */ +#define PACKETBUF_CONF_SIZE 1280 /**< Required IPv6 MTU size */ +/** @} */ + +/** + * \name BLE configuration + * @{ + */ +#ifndef DEVICE_NAME +#define DEVICE_NAME "Contiki nRF52dk" /**< Device name used in BLE undirected advertisement. */ +#endif +/** + * @} + */ + +/** + * \name IPv6 network buffer configuration + * + * @{ + */ +/* Don't let contiki-default-conf.h decide if we are an IPv6 build */ +#ifndef NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_WITH_IPV6 0 +#endif + +#if NETSTACK_CONF_WITH_IPV6 +/*---------------------------------------------------------------------------*/ +/* Addresses, Sizes and Interfaces */ +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* The size of the uIP main buffer */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1280 +#endif + +/* ND and Routing */ +#define UIP_CONF_ROUTER 0 /**< BLE master role, which allows for routing, isn't supported. */ +#define UIP_CONF_ND6_SEND_NA 1 +#define UIP_CONF_IP_FORWARD 0 /**< No packet forwarding. */ + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#endif + +#ifndef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 20 +#endif + +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif + +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS 64 +#endif + +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_ICMP6 1 +#endif /* NETSTACK_CONF_WITH_IPV6 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Generic Configuration directives + * + * @{ + */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 1 /**< Energest Module */ +#endif +/** @} */ +#endif /* CONTIKI_CONF_H */ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/contiki-main.c b/platform/nrf52dk/contiki-main.c new file mode 100644 index 000000000..50fcfcd28 --- /dev/null +++ b/platform/nrf52dk/contiki-main.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + */ +#include +#include + +#include "nordic_common.h" +#include "nrf_drv_config.h" +#include "nrf_drv_gpiote.h" +#ifdef SOFTDEVICE_PRESENT +#include "softdevice_handler.h" +#include "ble/ble-core.h" +#include "ble/ble-mac.h" +#endif + +#include "contiki.h" +#include "contiki-net.h" +#include "leds.h" +#include "lib/sensors.h" + +#include "dev/watchdog.h" +#include "dev/serial-line.h" +#include "dev/uart0.h" +#include "dev/lpm.h" + +#define DEBUG 0 + +#if NETSTACK_CONF_WITH_IPV6 +#include "uip-debug.h" +#include "net/ipv6/uip-ds6.h" +#else +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +#endif + +#if defined(SOFTDEVICE_PRESENT) && PLATFORM_INDICATE_BLE_STATE +PROCESS(ble_iface_observer, "BLE interface observer"); + +/** + * \brief A process that handles adding/removing + * BLE IPSP interfaces. + */ +PROCESS_THREAD(ble_iface_observer, ev, data) +{ + static struct etimer led_timer; + + PROCESS_BEGIN(); + + etimer_set(&led_timer, CLOCK_SECOND/2); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == ble_event_interface_added) { + etimer_stop(&led_timer); + leds_off(LEDS_1); + leds_on(LEDS_2); + } else if(ev == ble_event_interface_deleted) { + etimer_set(&led_timer, CLOCK_SECOND/2); + leds_off(LEDS_2); + } else if(ev == PROCESS_EVENT_TIMER && etimer_expired(&led_timer)) { + etimer_reset(&led_timer); + leds_toggle(LEDS_1); + } + } + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific initialization + * + * This function will enable SoftDevice is present. + */ +static void +board_init(void) +{ +#ifdef SOFTDEVICE_PRESENT + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); +#endif +#ifdef PLATFORM_HAS_BUTTON + if (!nrf_drv_gpiote_is_init()) { + nrf_drv_gpiote_init(); + } +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Main function for nRF52dk platform. + * \note This function doesn't return. + */ +int +main(void) +{ + board_init(); + leds_init(); + + clock_init(); + rtimer_init(); + + watchdog_init(); + process_init(); + + // Seed value is ignored since hardware RNG is used. + random_init(0); + +#ifdef UART0_ENABLED + uart0_init(); +#if SLIP_ARCH_CONF_ENABLE + slip_arch_init(0); +#else + uart0_set_input(serial_line_input_byte); + serial_line_init(); +#endif +#endif + + PRINTF("Starting " CONTIKI_VERSION_STRING "\n"); + + process_start(&etimer_process, NULL); + ctimer_init(); + +#if ENERGEST_CONF_ON + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); +#endif + +#ifdef SOFTDEVICE_PRESENT + ble_stack_init(); + ble_advertising_init(DEVICE_NAME); + +#if NETSTACK_CONF_WITH_IPV6 + netstack_init(); + linkaddr_t linkaddr; + ble_get_mac(linkaddr.u8); + // Set link layer address + linkaddr_set_node_addr(&linkaddr); + // Set device link layer address in uip stack. + memcpy(&uip_lladdr.addr, &linkaddr, sizeof(uip_lladdr.addr)); + uip_debug_lladdr_print(&uip_lladdr); + PRINTF("\n"); + process_start(&ble_iface_observer, NULL); + process_start(&tcpip_process, NULL); +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* SOFTDEVICE_PRESENT */ + + process_start(&sensors_process, NULL); + autostart_start(autostart_processes); + + watchdog_start(); + +#ifdef SOFTDEVICE_PRESENT + ble_advertising_start(); + PRINTF("Advertising name [%s]\n", DEVICE_NAME); +#endif + + while(1) { + uint8_t r; + do { + r = process_run(); + watchdog_periodic(); + } while(r > 0); + + lpm_drop(); + } +} +/** + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.c b/platform/nrf52dk/dbg-io/dbg.c new file mode 100644 index 000000000..db9bb63c0 --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Function implementations for debug io module. + * \author + * Wojciech Bober + * + */ +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while (s && *s != 0) { + if (i >= len) { + break; + } + uart0_writeb(*s++); + i++; + } + + return i; +} +/*---------------------------------------------------------------------------*/ +int +dbg_putchar(int c) +{ + uart0_writeb(c); + return c; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.h b/platform/nrf52dk/dbg-io/dbg.h new file mode 100644 index 000000000..7c623336b --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * +3 * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Header file for the debug module. + * \author + * Wojciech Bober + * + */ +#ifndef DBG_H_ +#define DBG_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Print a stream of bytes + * \param seq A pointer to the stream + * \param len The number of bytes to print + * \return The number of printed bytes + */ +unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/** + * \brief Print a character to debug output + * \param c Character to print + * \return Printed character + */ +int dbg_putchar(int c); +/*---------------------------------------------------------------------------*/ +#endif /* DBG_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/debug-uart.h b/platform/nrf52dk/dbg-io/debug-uart.h new file mode 100644 index 000000000..b52d2fb50 --- /dev/null +++ b/platform/nrf52dk/dbg-io/debug-uart.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * A header file to maintain compatibility with DBG I/O. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef DEBUG_UART_H_ +#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "dbg.h" +/*---------------------------------------------------------------------------*/ +#endif /* DEBUG_UART_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.c b/platform/nrf52dk/dev/button-sensor.c new file mode 100644 index 000000000..3c218a439 --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``as-is'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Driver for nRF52 DK buttons. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "nordic_common.h" +#include "nrf_drv_gpiote.h" +#include "nrf_assert.h" +#include "boards.h" +#include "contiki.h" +#include "lib/sensors.h" +#include "button-sensor.h" + +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) /**< Delay before button state is assumed to be stable */ + +/*---------------------------------------------------------------------------*/ +struct btn_timer +{ + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer btn_timer[BUTTONS_NUMBER]; +static int btn_state = 0; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Button toggle handler + * \param pin GPIO pin which has been triggered + * \param action toggle direction + * + */ +static void +gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) +{ + int id = pin - BUTTON_START; + + if(!timer_expired(&(btn_timer[id].debounce))) { + return; + } + + /* Set timer to ignore consecutive changes for + * DEBOUNCE_DURATION. + */ + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + + /* + * Start measuring duration on falling edge, stop on rising edge. + */ + if(nrf_drv_gpiote_in_is_set(pin) == 0) { + btn_timer[id].start = clock_time(); + btn_timer[id].duration = 0; + } else { + btn_timer[id].duration = clock_time() - btn_timer[id].start; + } + sensors_changed(&buttons[id]); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type if \a SENSORS_HW_INIT is passed the function will initialize + * given button + * if \a SENSORS_ACTIVE is passed then \p c parameter defines + * whether button should be set active or inactive + * \param c 0 to disable the button, non-zero: enable + * \param pin GPIOE pin number + */ +static int +config(int type, int c, nrf_drv_gpiote_pin_t pin) +{ + int id = pin - BUTTON_START; + + switch(type) { + case SENSORS_HW_INIT: { + nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); + config.pull = NRF_GPIO_PIN_PULLUP; + nrf_drv_gpiote_in_init(pin, &config, gpiote_event_handler); + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + return 1; + } + case SENSORS_ACTIVE: { + if(c) { + nrf_drv_gpiote_in_event_enable(pin, true); + btn_state |= (1 << id); + } else { + nrf_drv_gpiote_in_event_disable(pin); + btn_state &= ~(1 << id); + } + return 1; + } + default: + return 0; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 1 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_1(int type, int value) +{ + return config(type, value, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 2 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_2(int type, int value) +{ + return config(type, value, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 3 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_3(int type, int value) +{ + return config(type, value, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 4 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_4(int type, int value) +{ + return config(type, value, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button + * \param type pass \ref BUTTON_SENSOR_VALUE_STATE to get current button state + * or \ref BUTTON_SENSOR_VALUE_DURATION to get active state duration + * \param pin GPIOE pin number + * + * \retval BUTTON_SENSOR_VALUE_PRESSED + * \retval BUTTON_SENSOR_VALUE_RELEASED when \a type is \ref BUTTON_SENSOR_VALUE_STATE + * \retval duration Active state duration in clock ticks + */ +static int +value(int type, nrf_drv_gpiote_pin_t pin) +{ + + if(type == BUTTON_SENSOR_VALUE_STATE) { + return nrf_drv_gpiote_in_is_set(pin) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return btn_timer[pin - BUTTON_START].duration; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 1 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_1(int type) +{ + return value(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 2 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_2(int type) +{ + return value(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 3 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_3(int type) +{ + return value(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 4 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_4(int type) +{ + return value(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Get status of a given button + * \param type \a SENSORS_ACTIVE or \a SENSORS_READY + * \param pin GPIOE pin number + * \return 1 if the button's port interrupt is enabled + */ +static int +status(int type, nrf_drv_gpiote_pin_t pin) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return (btn_state & (1 << (pin - BUTTON_START))); + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 1 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_1(int type) +{ + return status(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 2 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_2(int type) +{ + return status(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_3(int type) +{ + return status(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_4(int type) +{ + return status(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +const struct sensors_sensor buttons[BUTTONS_NUMBER] = { + {BUTTON_SENSOR, value_button_1, config_button_1, status_button_1}, + {BUTTON_SENSOR, value_button_2, config_button_2, status_button_2}, + {BUTTON_SENSOR, value_button_3, config_button_3, status_button_3}, + {BUTTON_SENSOR, value_button_4, config_button_4, status_button_4}, }; +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.h b/platform/nrf52dk/dev/button-sensor.h new file mode 100644 index 000000000..ababb1c1c --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Header file for the nRF52dk button driver. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 /**< Can be passed to value() function + to get current button state */ +#define BUTTON_SENSOR_VALUE_DURATION 1 /**< Can be passed to value() function + to get low state duration */ + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor buttons[]; +/*---------------------------------------------------------------------------*/ +#define button_1 buttons[0] +#define button_2 buttons[1] +#define button_3 buttons[2] +#define button_4 buttons[3] +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/leds-arch.c b/platform/nrf52dk/dev/leds-arch.c new file mode 100644 index 000000000..019589493 --- /dev/null +++ b/platform/nrf52dk/dev/leds-arch.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-led LED driver + * @{ + * + * \file + * Architecture specific LED driver implementation for nRF52 DK. + * \author + * Wojciech Bober + */ +#include "boards.h" +#include "contiki.h" +#include "dev/leds.h" + +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + LEDS_CONFIGURE(LEDS_MASK); + LEDS_OFF(LEDS_MASK); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return (unsigned char)(LED_IS_ON(LEDS_MASK) >> LED_START); +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + unsigned int mask = (unsigned int)leds << LED_START; + LEDS_OFF(LEDS_MASK); + LEDS_ON(mask); +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/nrf52dk-sensors.c b/platform/nrf52dk/dev/nrf52dk-sensors.c new file mode 100644 index 000000000..3d56e91d1 --- /dev/null +++ b/platform/nrf52dk/dev/nrf52dk-sensors.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-sensors Sensors + * The nRF52 DK exports 4 button sensors and an internal temperature sensor. + * @{ + * + * \file + * This file exports a global sensors table. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/temperature-sensor.h" +/*---------------------------------------------------------------------------*/ +SENSORS( + &button_1, + &button_2, + &button_3, + &button_4, + &temperature_sensor +); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.c b/platform/nrf52dk/dev/temperature-sensor.c new file mode 100644 index 000000000..5aac8b3ef --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * This is a driver for nRF52832 hardware sensor. + * + * @{ + * + * \file + * Temperature sensor implementation. + * \author + * Wojciech Bober + * + */ +#ifndef SOFTDEVICE_PRESENT +#include "nrf_temp.h" +#else +#include "nrf_soc.h" +#endif +#include "contiki.h" +#include "dev/temperature-sensor.h" + + +const struct sensors_sensor temperature_sensor; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns device temperature + * \param type ignored + * \return Device temperature in degrees Celsius + */ +static int +value(int type) +{ +#ifndef SOFTDEVICE_PRESENT + return nrf_temp_read(); +#else + int32_t temp; + sd_temp_get(&temp); + return temp >> 2; +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configures temperature sensor + * \param type initializes the hardware sensor when \a type is set to + * \a SENSORS_HW_INIT + * \param c ignored + * \return 1 + * \note This function does nothing when SoftDevice is present + */ +static int +configure(int type, int c) +{ +#ifndef SOFTDEVICE_PRESENT + if (type == SENSORS_HW_INIT) { + nrf_temp_init(); + } +#endif + return 1; +} +/** + * \brief Return temperature sensor status + * \param type ignored + * \return 1 + */ +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR, value, configure, status); +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.h b/platform/nrf52dk/dev/temperature-sensor.h new file mode 100644 index 000000000..27b246b2d --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * @{ + * + * \file + * Temperature sensor header file. + * \author + * Wojciech Bober + * + */ + +#ifndef TEMPERATURE_SENSOR_H_ +#define TEMPERATURE_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor temperature_sensor; + +#define TEMPERATURE_SENSOR "Temperature" + +#endif /* TEMPERATURE_SENSOR_H_ */ + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/platform-conf.h b/platform/nrf52dk/platform-conf.h new file mode 100644 index 000000000..931a3c275 --- /dev/null +++ b/platform/nrf52dk/platform-conf.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup platform + * @{ + * + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + * + * \addtogroup nrf52dk-platform-conf Platform configuration + * @{ + * \file + * Platform features configuration. + * \author + * Wojciech Bober + * + */ +#ifndef PLATFORM_CONF_H_ +#define PLATFORM_CONF_H_ + +#include "boards.h" + +#define PLATFORM_HAS_BATTERY 0 +#define PLATFORM_HAS_RADIO 0 +#define PLATFORM_HAS_TEMPERATURE 1 + +/** + * \name Leds configurations + * + * On nRF52dk all leds are green. + * + * @{ + */ +#define PLATFORM_HAS_LEDS 1 + +#define LEDS_1 (1 << (LED_1 - LED_START)) // 1 +#define LEDS_2 (1 << (LED_2 - LED_START)) // 2 +#define LEDS_3 (1 << (LED_3 - LED_START)) // 4 +#define LEDS_4 (1 << (LED_4 - LED_START)) // 8 + +#define LEDS_GREEN LEDS_1 +#define LEDS_YELLOW LEDS_2 +#define LEDS_RED LEDS_3 +#define LEDS_BLUE LEDS_4 + +#define LEDS_CONF_ALL (LEDS_1 | LEDS_2 | LEDS_3 | LEDS_4) + +/** + * \brief If set to 1 then LED1 and LED2 are used by the + * platform to indicate BLE connection state. + */ +#define PLATFORM_INDICATE_BLE_STATE 1 +/** @} */ + +/** + * \name Button configurations + * + * @{ + */ +/* Notify various examples that we have Buttons */ +#define PLATFORM_HAS_BUTTON 1 + +/* + * Override button symbols from dev/button-sensor.h, for the examples that + * include it + */ +#define button_sensor button_1 +#define button_sensor2 button_2 + +/** + * \brief nRF52 RTC instance to be used for Contiki clock driver. + * \note RTC 0 is used by the SoftDevice. + */ +#define PLATFORM_RTC_INSTANCE_ID 1 + +/** + * \brief nRF52 timer instance to be used for Contiki rtimer driver. + * \note Timer 0 is used by the SoftDevice. + */ +#define PLATFORM_TIMER_INSTANCE_ID 1 + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Compiler configuration and platform-specific type definitions + * + * Those values are not meant to be modified by the user + * @{ + */ +#define CLOCK_CONF_SECOND 128 + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +/* Clock (time) comparison macro */ +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) + +#define RTIMER_ARCH_SECOND 62500 +/* + * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define + * RTIMER_CLOCK_LT to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** @} + * @} + * @} + */ +#endif /* PLATFORM_CONF_H_ */ diff --git a/platform/nrf52dk/rtt/rtt-printf.c b/platform/nrf52dk/rtt/rtt-printf.c new file mode 100644 index 000000000..416fff0ab --- /dev/null +++ b/platform/nrf52dk/rtt/rtt-printf.c @@ -0,0 +1,24 @@ +#include +#include "segger-rtt.h" + +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +int +putchar(int c) +{ + SEGGER_RTT_Write(0, &c, 1); + return c; +} + +int +printf(const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = SEGGER_RTT_vprintf(0, fmt, &ap); + va_end(ap); + return res; +} + + diff --git a/platform/nrf52dk/rtt/segger-rtt-conf.h b/platform/nrf52dk/rtt/segger-rtt-conf.h new file mode 100644 index 000000000..ac996644f --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-conf.h @@ -0,0 +1,135 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +---------------------------------------------------------------------- +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +---------------------------END-OF-HEADER------------------------------ +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __ICCARM__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, $128 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + #else + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_PRIMASK(); \ + __set_PRIMASK(1); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_PRIMASK(SavedState); \ + } + #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_BASEPRI(); \ + __set_BASEPRI(128); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_BASEPRI(SavedState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt-printf.c b/platform/nrf52dk/rtt/segger-rtt-printf.c new file mode 100644 index 000000000..e992e7a36 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-printf.c @@ -0,0 +1,510 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +---------------------------------------------------------------------- +*/ +#include "segger-rtt.h" +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if (c == '*') { + sFormat++; + v = va_arg(*pParamList, int); + NumDigits = (unsigned)v; + break; + } + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + c = *sFormat; + sFormat++; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + if (NumDigits > 0) { + do { + c = *s; + s++; + if (NumDigits == 0) { + break; + } + NumDigits--; + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } else { + do { + c = *s; + s++; + if (c == '\0' || NumDigits == 0) { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + va_list ParamList; + + va_start(ParamList, sFormat); + return SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); +} +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.c b/platform/nrf52dk/rtt/segger-rtt.c new file mode 100644 index 000000000..453a6a0e4 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.c @@ -0,0 +1,1102 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + +---------------------------------------------------------------------- +*/ + +#include "segger-rtt.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef MEMCPY + #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// Allocate buffers for channel 0 +// +static char _acUpBuffer [BUFFER_SIZE_UP]; +static char _acDownBuffer[BUFFER_SIZE_DOWN]; +// +// Initialize SEGGER Real-time-Terminal control block (CB) +// +SEGGER_RTT_CB _SEGGER_RTT; + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_RING_BUFFER *pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); + memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_RING_BUFFER *pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + NumBytesAtOnce = Rem; + memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_RING_BUFFER *pRing, char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[(int)TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_RING_BUFFER *pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_RING_BUFFER* pRing; + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + volatile unsigned SavedState; + // + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_RING_BUFFER* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, Rem); + memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_RING_BUFFER *pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + volatile unsigned SavedState; + // + INIT(); + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, depending on configuration, +* remaining characters may be dropped or RTT module waits until there is more space in the buffer. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_RING_BUFFER *pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + INIT(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(int)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(SavedState); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(SavedState); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = strlen(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(SavedState); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.h b/platform/nrf52dk/rtt/segger-rtt.h new file mode 100644 index 000000000..e3436c462 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.h @@ -0,0 +1,204 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up- (T->H) or down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by either host (down-buffer) or target (up-buffer). Must be volatile since it may be modified by host (down-buffer) + volatile unsigned RdOff; // Position of next item to be read by target (down-buffer) or host (up-buffer). Must be volatile since it may be modified by host (up-buffer) + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_RING_BUFFER; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_RING_BUFFER aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_RING_BUFFER aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "\e[0m" // Reset to default colors +#define RTT_CTRL_CLEAR "\e[2J" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "\e[2;30m" +#define RTT_CTRL_TEXT_RED "\e[2;31m" +#define RTT_CTRL_TEXT_GREEN "\e[2;32m" +#define RTT_CTRL_TEXT_YELLOW "\e[2;33m" +#define RTT_CTRL_TEXT_BLUE "\e[2;34m" +#define RTT_CTRL_TEXT_MAGENTA "\e[2;35m" +#define RTT_CTRL_TEXT_CYAN "\e[2;36m" +#define RTT_CTRL_TEXT_WHITE "\e[2;37m" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "\e[1;30m" +#define RTT_CTRL_TEXT_BRIGHT_RED "\e[1;31m" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "\e[1;32m" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\e[1;33m" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "\e[1;34m" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\e[1;35m" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "\e[1;36m" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "\e[1;37m" + +#define RTT_CTRL_BG_BLACK "\e[24;40m" +#define RTT_CTRL_BG_RED "\e[24;41m" +#define RTT_CTRL_BG_GREEN "\e[24;42m" +#define RTT_CTRL_BG_YELLOW "\e[24;43m" +#define RTT_CTRL_BG_BLUE "\e[24;44m" +#define RTT_CTRL_BG_MAGENTA "\e[24;45m" +#define RTT_CTRL_BG_CYAN "\e[24;46m" +#define RTT_CTRL_BG_WHITE "\e[24;47m" + +#define RTT_CTRL_BG_BRIGHT_BLACK "\e[4;40m" +#define RTT_CTRL_BG_BRIGHT_RED "\e[4;41m" +#define RTT_CTRL_BG_BRIGHT_GREEN "\e[4;42m" +#define RTT_CTRL_BG_BRIGHT_YELLOW "\e[4;43m" +#define RTT_CTRL_BG_BRIGHT_BLUE "\e[4;44m" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "\e[4;45m" +#define RTT_CTRL_BG_BRIGHT_CYAN "\e[4;46m" +#define RTT_CTRL_BG_BRIGHT_WHITE "\e[4;47m" + + +#endif + +/*************************** End of file ****************************/ From 38481c513d3f7222a738973ccbbd17e012f0a898 Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Sat, 9 Jan 2016 14:44:58 +0100 Subject: [PATCH 06/80] nrf52dk: added examples --- examples/nrf52dk/blink-hello/Makefile | 9 + examples/nrf52dk/blink-hello/README.md | 14 + examples/nrf52dk/blink-hello/blink-hello.c | 182 +++++ examples/nrf52dk/coap-demo/Makefile | 35 + examples/nrf52dk/coap-demo/README.md | 63 ++ examples/nrf52dk/coap-demo/coap-client.c | 185 +++++ examples/nrf52dk/coap-demo/coap-server.c | 130 ++++ examples/nrf52dk/coap-demo/project-conf.h | 85 +++ .../nrf52dk/coap-demo/resources/res-leds.c | 106 +++ examples/nrf52dk/mqtt-demo/Makefile | 11 + examples/nrf52dk/mqtt-demo/README.md | 74 ++ examples/nrf52dk/mqtt-demo/mqtt-demo.c | 721 ++++++++++++++++++ examples/nrf52dk/mqtt-demo/project-conf.h | 51 ++ examples/nrf52dk/timer-test/Makefile | 9 + examples/nrf52dk/timer-test/README.md | 20 + examples/nrf52dk/timer-test/timer-test.c | 131 ++++ 16 files changed, 1826 insertions(+) create mode 100644 examples/nrf52dk/blink-hello/Makefile create mode 100644 examples/nrf52dk/blink-hello/README.md create mode 100644 examples/nrf52dk/blink-hello/blink-hello.c create mode 100644 examples/nrf52dk/coap-demo/Makefile create mode 100644 examples/nrf52dk/coap-demo/README.md create mode 100644 examples/nrf52dk/coap-demo/coap-client.c create mode 100644 examples/nrf52dk/coap-demo/coap-server.c create mode 100644 examples/nrf52dk/coap-demo/project-conf.h create mode 100644 examples/nrf52dk/coap-demo/resources/res-leds.c create mode 100644 examples/nrf52dk/mqtt-demo/Makefile create mode 100644 examples/nrf52dk/mqtt-demo/README.md create mode 100644 examples/nrf52dk/mqtt-demo/mqtt-demo.c create mode 100644 examples/nrf52dk/mqtt-demo/project-conf.h create mode 100644 examples/nrf52dk/timer-test/Makefile create mode 100644 examples/nrf52dk/timer-test/README.md create mode 100644 examples/nrf52dk/timer-test/timer-test.c diff --git a/examples/nrf52dk/blink-hello/Makefile b/examples/nrf52dk/blink-hello/Makefile new file mode 100644 index 000000000..5b056a518 --- /dev/null +++ b/examples/nrf52dk/blink-hello/Makefile @@ -0,0 +1,9 @@ +CONTIKI_PROJECT = blink-hello + +CONTIKI_WITH_RPL=0 +NRF52_WITHOUT_SOFTDEVICE=1 + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/blink-hello/README.md b/examples/nrf52dk/blink-hello/README.md new file mode 100644 index 000000000..00064f993 --- /dev/null +++ b/examples/nrf52dk/blink-hello/README.md @@ -0,0 +1,14 @@ +Blink Hello example +=================== +This example shows basic usage of DK's buttons and LEDs. It also shows basic +usage of Contiki's processes. The application autostarts 5 processes: 4 processes +for button and LED control and 1 to display current temperature to the console. + +A process reacts to a press of a respective button (process 1 reacts to button 1, etc.) +and doubles the current blinking frequency. The cycle restarts for beginning when blinking +frequency is greater than 8Hz. + +The example requires one DK and it doesn't use SoftDevice. To compile and flash the +example run: + + make TARGET=nrf52dk blink-hello.flash \ No newline at end of file diff --git a/examples/nrf52dk/blink-hello/blink-hello.c b/examples/nrf52dk/blink-hello/blink-hello.c new file mode 100644 index 000000000..ebc1e451c --- /dev/null +++ b/examples/nrf52dk/blink-hello/blink-hello.c @@ -0,0 +1,182 @@ +/* This is a very simple hello_world program. + * It aims to demonstrate the co-existence of two processes: + * One of them prints a hello world message and the other blinks the LEDs + * + * It is largely based on hello_world in $(CONTIKI)/examples/sensinode + * + * Author: George Oikonomou - + */ + +/** + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + * + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-blink-hello Basic sensors and LEDs demo + * @{ + * + * This demo demonstrates use of Contiki processes, sensors, and LEDs + * on nRF52 DK. Pressing a button will start a timer that blinks a + * respective LED (e.g., button 1 controls LED 1). Each time the button + * is pressed blinking frequency is doubled. On 4th press the LED is + * switched off and the sequence can be started from the beginning. + * + * \file Main file for Basic sensors and LEDs demo. + */ +#include /* For printf() */ +#include +#include "contiki.h" +#include "dev/leds.h" +#include "dev/temperature-sensor.h" +#include "lib/sensors.h" +#include "button-sensor.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(blink_process_1, "LED1 blink process"); +PROCESS(blink_process_2, "LED2 blink process"); +PROCESS(blink_process_3, "LED3 blink process"); +PROCESS(blink_process_4, "LED4 blink process"); +PROCESS(temp, "Temperautre"); + +AUTOSTART_PROCESSES( + &blink_process_1, + &blink_process_2, + &blink_process_3, + &blink_process_4, + &temp +); + +struct blink_process_ctx { + struct etimer et_blink; + unsigned char c; + const struct sensors_sensor *button; + unsigned char led; +}; + +static void handle_event(process_event_t ev, process_data_t data, struct blink_process_ctx *ctx) +{ + if (ev == PROCESS_EVENT_TIMER && etimer_expired(&ctx->et_blink)) { + leds_toggle(ctx->led); + etimer_set(&ctx->et_blink, CLOCK_SECOND / ctx->c); + printf("Blink %d\n", ctx->led); + } else if (ev == sensors_event && data == ctx->button) { + if (ctx->button->value(BUTTON_SENSOR_VALUE_STATE) == 0) { + if (ctx->c == 0) { + ctx->c = 1; + } else if (ctx->c < 8){ + ctx->c <<= 1; + } else { + ctx->c = 0; + leds_off(ctx->led); + } + if (ctx->c) { + etimer_set(&ctx->et_blink, CLOCK_SECOND / ctx->c); + } else { + etimer_stop(&ctx->et_blink); + } + } + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_1, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_1; + ctx.c = 0; + ctx.led = LEDS_1; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_2, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_2; + ctx.c = 0; + ctx.led = LEDS_2; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_3, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_3; + ctx.c = 0; + ctx.led = LEDS_3; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_4, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_4; + ctx.c = 0; + ctx.led = LEDS_4; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(temp, ev, data) +{ + static struct etimer tick; + PROCESS_BEGIN(); + + etimer_set(&tick, CLOCK_SECOND); + + while (1) { + PROCESS_WAIT_EVENT(); + if (ev == PROCESS_EVENT_TIMER && etimer_expired(&tick)) { + int32_t temp = temperature_sensor.value(0); + printf("temp: %"PRId32".%02"PRId32"\n", temp >> 2, (temp & 0x03)*25); + etimer_reset(&tick); + } + } + + PROCESS_END(); +} +/** + * @} + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/Makefile b/examples/nrf52dk/coap-demo/Makefile new file mode 100644 index 000000000..077e469be --- /dev/null +++ b/examples/nrf52dk/coap-demo/Makefile @@ -0,0 +1,35 @@ +CONTIKI=../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +ifeq ($(MAKECMDGOALS),) +$(error Please specify whether coap-client or coap-server should be built) +endif + +ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),) +ifeq ($(SERVER_IPV6_ADDR),) +$(error Please define SERVER_IPV6_ADDR=) +else +CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\" +CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" +endif +else +CFLAGS += -DDEVICE_NAME=\"nRF52-DK-CoAP-Server\" +endif + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) + +PROJECTDIRS += $(REST_RESOURCES_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# linker optimizations +SMALL=1 + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine + +CONTIKI_WITH_RPL = 0 + +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/coap-demo/README.md b/examples/nrf52dk/coap-demo/README.md new file mode 100644 index 000000000..1262ce114 --- /dev/null +++ b/examples/nrf52dk/coap-demo/README.md @@ -0,0 +1,63 @@ +A CoAP demo for nRF52 DK +======================== +This demo contains two applications: coap-server and coap-client which are similar to +[Coap Observable Server] and [Coap Observer Client] examples provided by the nRF5 IoT SDK. + +Note that before any CoAP requests can be made you'll need to configure an IPv6 connection +to the device and assign a routable IPv6 address. + +For details how to do this please refer to sections 'Establishing an IPv6 connection' +and 'Distributing routable IPv6 prefix' in `platform/nrf52dk/README-BLE-6LoWPAN.md`. + +CoAP Server +=========== +The server exposes the following resources: + + host + |-- .well-known + | `-- core + `-- lights + `-- led3 + +The state of LED 3 can be set and queried via CoAP through the observable resource `lights/led3`. Current +state of LED 3 is returned as a text string in the payload. The value 0 means that LED 3 is off, 1 otherwise. + +Button 1 can be used to toggle state of the LED 3. This will cause a notification to be sent to +any subscriber observing `lights/led3`. The state of the resource can also be changed by using POST/PUT to +the resource with desired state encoded as a text in the payload. Send 1 to switch on and 0 to switch off. + +In order to compile and flash the CoAP server to a DK execute: + + make TARGET=nrf52dk coap-server.flash + +Note, if you haven't previously used a given device with Contiki it is recommended +to erase the device and flash SoftDevice before flashing CoAP application, i.e., + + make TARGET=nrf52dk erase + make TARGET=nrf52dk softdevice.flash + +Please refer to the *Testing* and *Python Example* sections of [Coap Observable Server] tutorial for detailed description how to query the Coap Server using a PC. + +CoAP Client +=========== +CoAP client compliments the CoAP server application. When Button 1 on the DK is pressed the the +client subscribes to `lights/led3` resource. If successful the LED 4 will blink briefly. From this moment +any change of the `lights/led3` resource will be automatically reflected by the client's LED 3. + +Note that the client must know the server's IPv6 address. The address is specified as a make variable +during compliation. + +In order to compile and flash the CoAP client to DK execute: + + make TARGET=nrf52dk SERVER_IPV6_ADDR= coap-client.flash + +Note, that you can use `NRF52_JLINK_SN=` to select a particular devkit in a case when +you have more than one boards connected to PC. Please refer to `platform/README.md` for +details. + +Please refer to the *Testing* and *Python Server Example* sections of [Coap Observer Client] tutorial for detailed description how to use CoAP client demo with a PC. + +Resources +========= +[Coap Observable Server] http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00054.html +[Coap Observer Client] http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00051.html diff --git a/examples/nrf52dk/coap-demo/coap-client.c b/examples/nrf52dk/coap-demo/coap-client.c new file mode 100644 index 000000000..2ec1f5ab1 --- /dev/null +++ b/examples/nrf52dk/coap-demo/coap-client.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2014, Daniele Alessandrelli. + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52 DK + * @{ + * + * \file + * Erbium (Er) CoAP observe client example. + * \author + * Daniele Alessandrelli + * \author + * Wojciech Bober + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "er-coap-engine.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*----------------------------------------------------------------------------*/ +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define OBS_RESOURCE_URI "lights/led3" +#define SUBS_LED LEDS_4 +#define OBS_LED LEDS_3 + +/*----------------------------------------------------------------------------*/ +static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ +static coap_observee_t *obs; +static struct ctimer ct; +/*----------------------------------------------------------------------------*/ +PROCESS(er_example_observe_client, "nRF52 DK Coap Observer Client"); +AUTOSTART_PROCESSES(&er_example_observe_client); +/*----------------------------------------------------------------------------*/ +static void +observe_led_off(void *d) +{ + leds_off(SUBS_LED); +} +/*----------------------------------------------------------------------------*/ +/* + * Handle the response to the observe request and the following notifications + */ +static void +notification_callback(coap_observee_t *obs, void *notification, + coap_notification_flag_t flag) +{ + int len = 0; + const uint8_t *payload = NULL; + + + PRINTF("Notification handler\n"); + PRINTF("Observee URI: %s\n", obs->url); + + if (notification) { + len = coap_get_payload(notification, &payload); + } + + (void)len; + + switch (flag) { + case NOTIFICATION_OK: + PRINTF("NOTIFICATION OK: %*s\n", len, (char *)payload); + if (*payload == '1') { + leds_on(OBS_LED); + } else { + leds_off(OBS_LED); + } + break; + case OBSERVE_OK: /* server accepeted observation request */ + PRINTF("OBSERVE_OK: %*s\n", len, (char *)payload); + if (*payload == '1') { + leds_on(OBS_LED); + } else { + leds_off(OBS_LED); + } + leds_on(SUBS_LED); + ctimer_set(&ct, CLOCK_SECOND, observe_led_off, NULL); + break; + case OBSERVE_NOT_SUPPORTED: + PRINTF("OBSERVE_NOT_SUPPORTED: %*s\n", len, (char *)payload); + obs = NULL; + break; + case ERROR_RESPONSE_CODE: + PRINTF("ERROR_RESPONSE_CODE: %*s\n", len, (char *)payload); + obs = NULL; + break; + case NO_REPLY_FROM_SERVER: + PRINTF("NO_REPLY_FROM_SERVER: " + "removing observe registration with token %x%x\n", + obs->token[0], obs->token[1]); + obs = NULL; + break; + } +} +/*----------------------------------------------------------------------------*/ +/* + * The main (proto-)thread. It starts/stops the observation of the remote + * resource every time the timer elapses or the button (if available) is + * pressed + */ +PROCESS_THREAD(er_example_observe_client, ev, data) +{ + PROCESS_BEGIN(); + + uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr); + + /* receives all CoAP messages */ + coap_init_engine(); + +#if PLATFORM_HAS_BUTTON + SENSORS_ACTIVATE(button_1); + SENSORS_ACTIVATE(button_2); +#endif + + /* toggle observation every time the timer elapses or the button is pressed */ + while (1) { + PROCESS_YIELD(); +#if PLATFORM_HAS_BUTTON + if (ev == sensors_event) { + if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + PRINTF("Starting observation\n"); + obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + OBS_RESOURCE_URI, notification_callback, + NULL); + } + if (data == &button_2 && button_2.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + PRINTF("Stopping observation\n"); + coap_obs_remove_observee(obs); + obs = NULL; + } + } +#endif + } + PROCESS_END(); +} + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/coap-server.c b/examples/nrf52dk/coap-demo/coap-server.c new file mode 100644 index 000000000..9bab7e60d --- /dev/null +++ b/examples/nrf52dk/coap-demo/coap-server.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * Copyright (c) 2015, Nordic Semiconductor + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52dk + * @{ + * + * \file + * Erbium (Er) REST Engine example. + * \author + * Matthias Kovatsch + * \author + * Wojciech Bober + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "rest-engine.h" +#include "uip.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +/* + * Resources to be activated need to be imported through the extern keyword. + * The build system automatically compiles the resources in the corresponding sub-directory. + */ +extern resource_t res_led3; + +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if(state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} + +PROCESS(er_example_server, "nRF52 DK Coap Server"); +AUTOSTART_PROCESSES(&er_example_server); + +PROCESS_THREAD(er_example_server, ev, data) +{ + PROCESS_BEGIN(); + PROCESS_PAUSE(); + + PRINTF("Starting Erbium Example Server\n"); + + PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); + PRINTF("LL header: %u\n", UIP_LLH_LEN); + PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); + PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + + print_local_addresses(); + + /* Initialize the REST engine. */ + rest_init_engine(); + rest_activate_resource(&res_led3, "lights/led3"); + + SENSORS_ACTIVATE(button_1); + + /* Define application-specific events here. */ + while (1) { + PROCESS_WAIT_EVENT(); + + if (ev == sensors_event) { + if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + leds_toggle(LEDS_3); + res_led3.trigger(); + } + } + } + + PROCESS_END(); +} + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/project-conf.h b/examples/nrf52dk/coap-demo/project-conf.h new file mode 100644 index 000000000..2b097e8a8 --- /dev/null +++ b/examples/nrf52dk/coap-demo/project-conf.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52dk + * @{ + * + * \file + * Erbium (Er) example project configuration. + * \author + * Matthias Kovatsch + */ + +#ifndef __PROJECT_ERBIUM_CONF_H__ +#define __PROJECT_ERBIUM_CONF_H__ + +/* Disabling TCP on CoAP nodes. */ +#undef UIP_CONF_TCP +#define UIP_CONF_TCP 0 + +/* Increase rpl-border-router IP-buffer when using more than 64. */ +#undef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE 48 + +/* Estimate your header size, especially when using Proxy-Uri. */ +/* + #undef COAP_MAX_HEADER_SIZE + #define COAP_MAX_HEADER_SIZE 70 + */ + +/* Multiplies with chunk size, be aware of memory constraints. */ +#undef COAP_MAX_OPEN_TRANSACTIONS +#define COAP_MAX_OPEN_TRANSACTIONS 4 + +/* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ +/* + #undef COAP_MAX_OBSERVERS + #define COAP_MAX_OBSERVERS 2 + */ + +/* Filtering .well-known/core per query can be disabled to save space. */ +#undef COAP_LINK_FORMAT_FILTERING +#define COAP_LINK_FORMAT_FILTERING 0 +#undef COAP_PROXY_OPTION_PROCESSING +#define COAP_PROXY_OPTION_PROCESSING 0 + +/* Enable client-side support for COAP observe */ +#define COAP_OBSERVE_CLIENT 1 +#endif /* __PROJECT_ERBIUM_CONF_H__ */ + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/resources/res-leds.c b/examples/nrf52dk/coap-demo/resources/res-leds.c new file mode 100644 index 000000000..468a165bf --- /dev/null +++ b/examples/nrf52dk/coap-demo/resources/res-leds.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example resource + * \author + * Matthias Kovatsch + * \author + * Wojciech Bober + */ + +#include +#include "contiki.h" +#include "rest-engine.h" +#include "dev/leds.h" + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset); + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset); + +static void +res_event_handler(); + +/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +EVENT_RESOURCE(res_led3, + "title=\"LED3\"; obs", + res_get_handler, + res_post_put_handler, + res_post_put_handler, + NULL, + res_event_handler + ); + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + const uint8_t *payload; + REST.get_request_payload(request, &payload); + + if (*payload == '0' || *payload == '1') { + if (*payload == '1') { + leds_on(LEDS_3); + } else { + leds_off(LEDS_3); + } + REST.notify_subscribers(&res_led3); + REST.set_response_status(response, REST.status.CHANGED); + } else { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); +} + +/* + * Additionally, res_event_handler must be implemented for each EVENT_RESOURCE. + * It is called through .trigger(), usually from the server process. + */ +static void +res_event_handler() +{ + /* Notify the registered observers which will trigger the res_get_handler to create the response. */ + REST.notify_subscribers(&res_led3); +} diff --git a/examples/nrf52dk/mqtt-demo/Makefile b/examples/nrf52dk/mqtt-demo/Makefile new file mode 100644 index 000000000..bfdeccfb7 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/Makefile @@ -0,0 +1,11 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +all: mqtt-demo + +CONTIKI_WITH_IPV6 = 1 +CONTIKI_WITH_RPL = 0 + +APPS += mqtt + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/mqtt-demo/README.md b/examples/nrf52dk/mqtt-demo/README.md new file mode 100644 index 000000000..a4a9a6ff1 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/README.md @@ -0,0 +1,74 @@ +MQTT Demo +========= +The MQTT client can be used to: + +* Publish sensor readings to an MQTT broker. +* Subscribe to a topic and receive commands from an MQTT broker + +The demo will give some visual feedback with the green LED: +* Very fast blinking: Searching for a network +* Fast blinking: Connecting to broker +* Slow, long blinking: Sending a publish message + +Note that before any MQTT messages can be sent or received you'll +need to configure an IPv6 connection to the device and assign a routable +IPv6 address. + +For details how to do this please refer to sections 'Establishing an IPv6 connection' +and 'Distributing routable IPv6 prefix' in `platform/nrf52dk/README-BLE-6LoWPAN.md`. + +Broker setup +------------ +By default the example will attempt to publish readings to an MQTT broker +running on the IPv6 address specified as `MQTT_DEMO_BROKER_IP_ADDR` in +`project-conf.h`. This functionality was tested successfully with +[mosquitto](http://mosquitto.org/). + +On Ubuntu you can install and run mosquitto broker using the following +commands: + + apt-get install mosquitto mosquitto_clients + killall mosquitto + mosquitto -p 1883 -v + +Publishing +---------- +The publish messages include sensor readings but also some other information, +such as device uptime in seconds and a message sequence number. The demo will +publish to topic `iot-2/evt/status/fmt/json`. The device will connect using +client-id `d:quickstart:cc2538:`, where `` gets +constructed from the device's IEEE address. + +Subscribing +----------- +You can also subscribe to topics and receive commands, but this will only +work if you use "Org ID" != 'quickstart'. To achieve this, you will need to +change 'Org ID' (`DEFAULT_ORG_ID`). In this scenario, the device will subscribe +to: + +`iot-2/cmd/+/fmt/json` + +You can then use this to toggle LEDs. To do this, you can for example +use mosquitto client to publish to `iot-2/cmd/leds/fmt/json`. So, to change +the state of an LED, you would do this: + +`mosquitto_pub -h -m "1" -t iot-2/cmd/leds/fmt/json` + +Where `broker IP` should be replaced with the IP address of your mosquitto +broker (the one where you device has subscribed). Replace `-m "1'` with `-m "0"` +to turn the LED back off. + +Bear in mind that, even though the topic suggests that messages are of json +format, they are in fact not. This was done in order to avoid linking a json +parser into the firmware. This comment only applies to parsing incoming +messages, outgoing publish messages use proper json payload. + +IBM Quickstart Service +---------------------- +It is also possible to publish to IBM's quickstart service. To do so, you need +to undefine `MQTT_DEMO_BROKER_IP_ADDR`. + +If you want to use IBM's cloud service with a registered device, change +'Org ID' (`DEFAULT_ORG_ID`) and provide the 'Auth Token' (`DEFAULT_AUTH_TOKEN`), +which acts as a 'password', but bear in mind that it gets transported in clear +text. \ No newline at end of file diff --git a/examples/nrf52dk/mqtt-demo/mqtt-demo.c b/examples/nrf52dk/mqtt-demo/mqtt-demo.c new file mode 100644 index 000000000..6a3482073 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/mqtt-demo.c @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-mqtt-demo nRF52 DK MQTT Demo Project + * + * Demonstrates MQTT functionality. Works with mosquitto. + * @{ + * + * \file + * An MQTT example for the nrf52dk platform + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "mqtt.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-icmp6.h" +#include "net/ipv6/sicslowpan.h" +#include "sys/etimer.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/temperature-sensor.h" +#include "dev/leds.h" + +#include +/*---------------------------------------------------------------------------*/ +/* + * IBM server: quickstart.messaging.internetofthings.ibmcloud.com + * (184.172.124.189) mapped in an NAT64 (prefix 64:ff9b::/96) IPv6 address + * Note: If not able to connect; lookup the IP address again as it may change. + * + * Alternatively, publish to a local MQTT broker (e.g. mosquitto) running on + * the node that hosts your border router + */ +#ifdef MQTT_DEMO_BROKER_IP_ADDR +static const char *broker_ip = MQTT_DEMO_BROKER_IP_ADDR; +#define DEFAULT_ORG_ID "mqtt-demo" +#else +static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; +#define DEFAULT_ORG_ID "quickstart" +#endif +/*---------------------------------------------------------------------------*/ +/* + * A timeout used when waiting for something to happen (e.g. to connect or to + * disconnect) + */ +#define STATE_MACHINE_PERIODIC (CLOCK_SECOND >> 1) +/*---------------------------------------------------------------------------*/ +/* Provide visible feedback via LEDS during various states */ +/* When connecting to broker */ +#define CONNECTING_LED_DURATION (CLOCK_SECOND >> 2) + +/* Each time we try to publish */ +#define PUBLISH_LED_ON_DURATION (CLOCK_SECOND) +/*---------------------------------------------------------------------------*/ +/* Connections and reconnections */ +#define RETRY_FOREVER 0xFF +#define RECONNECT_INTERVAL (CLOCK_SECOND * 2) + +/* + * Number of times to try reconnecting to the broker. + * Can be a limited number (e.g. 3, 10 etc) or can be set to RETRY_FOREVER + */ +#define RECONNECT_ATTEMPTS RETRY_FOREVER +#define CONNECTION_STABLE_TIME (CLOCK_SECOND * 5) +static struct timer connection_life; +static uint8_t connect_attempt; +/*---------------------------------------------------------------------------*/ +/* Various states */ +static uint8_t state; +#define STATE_INIT 0 +#define STATE_REGISTERED 1 +#define STATE_CONNECTING 2 +#define STATE_CONNECTED 3 +#define STATE_PUBLISHING 4 +#define STATE_DISCONNECTED 5 +#define STATE_NEWCONFIG 6 +#define STATE_CONFIG_ERROR 0xFE +#define STATE_ERROR 0xFF +/*---------------------------------------------------------------------------*/ +#define CONFIG_ORG_ID_LEN 32 +#define CONFIG_TYPE_ID_LEN 32 +#define CONFIG_AUTH_TOKEN_LEN 32 +#define CONFIG_EVENT_TYPE_ID_LEN 32 +#define CONFIG_CMD_TYPE_LEN 8 +#define CONFIG_IP_ADDR_STR_LEN 64 +/*---------------------------------------------------------------------------*/ +#define RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */ +#define RSSI_MEASURE_INTERVAL_MIN 5 /* secs */ +#define PUBLISH_INTERVAL_MAX 86400 /* secs: 1 day */ +#define PUBLISH_INTERVAL_MIN 5 /* secs */ +/*---------------------------------------------------------------------------*/ +/* A timeout used when waiting to connect to a network */ +#define NET_CONNECT_PERIODIC CLOCK_SECOND +#define NO_NET_LED_DURATION (NET_CONNECT_PERIODIC >> 1) +/*---------------------------------------------------------------------------*/ +/* Default configuration values */ +#define DEFAULT_TYPE_ID "nrf52dk" +#define DEFAULT_AUTH_TOKEN "AUTHZ" +#define DEFAULT_EVENT_TYPE_ID "status" +#define DEFAULT_SUBSCRIBE_CMD_TYPE "+" +#define DEFAULT_BROKER_PORT 1883 +#define DEFAULT_PUBLISH_INTERVAL (30 * CLOCK_SECOND) +#define DEFAULT_KEEP_ALIVE_TIMER 60 +#define DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30) +/*---------------------------------------------------------------------------*/ +/* Take a sensor reading on button press */ +#define PUBLISH_TRIGGER (&button_sensor) + +/* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */ +#define ECHO_REQ_PAYLOAD_LEN 20 +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(mqtt_demo_process); +AUTOSTART_PROCESSES(&mqtt_demo_process); +/*---------------------------------------------------------------------------*/ +/** + * \brief Data structure declaration for the MQTT client configuration + */ +typedef struct mqtt_client_config { + char org_id[CONFIG_ORG_ID_LEN]; + char type_id[CONFIG_TYPE_ID_LEN]; + char auth_token[CONFIG_AUTH_TOKEN_LEN]; + char event_type_id[CONFIG_EVENT_TYPE_ID_LEN]; + char broker_ip[CONFIG_IP_ADDR_STR_LEN]; + char cmd_type[CONFIG_CMD_TYPE_LEN]; + clock_time_t pub_interval; + int def_rt_ping_interval; + uint16_t broker_port; +} mqtt_client_config_t; +/*---------------------------------------------------------------------------*/ +/* Maximum TCP segment size for outgoing segments of our socket */ +#define MAX_TCP_SEGMENT_SIZE 32 +/*---------------------------------------------------------------------------*/ +#define STATUS_LED LEDS_GREEN +/*---------------------------------------------------------------------------*/ +/* + * Buffers for Client ID and Topic. + * Make sure they are large enough to hold the entire respective string + * + * d:quickstart:status:EUI64 is 32 bytes long + * iot-2/evt/status/fmt/json is 25 bytes + * We also need space for the null termination + */ +#define BUFFER_SIZE 64 +static char client_id[BUFFER_SIZE]; +static char pub_topic[BUFFER_SIZE]; +static char sub_topic[BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +/* + * The main MQTT buffers. + * We will need to increase if we start publishing more data. + */ +#define APP_BUFFER_SIZE 128 +static struct mqtt_connection conn; +static char app_buffer[APP_BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +#define QUICKSTART "quickstart" +/*---------------------------------------------------------------------------*/ +static struct mqtt_message *msg_ptr = 0; +static struct etimer publish_periodic_timer; +static struct ctimer ct; +static char *buf_ptr; +static uint16_t seq_nr_value = 0; +/*---------------------------------------------------------------------------*/ +/* Parent RSSI functionality */ +static struct uip_icmp6_echo_reply_notification echo_reply_notification; +static struct etimer echo_request_timer; +static int def_rt_rssi = 0; +/*---------------------------------------------------------------------------*/ +static mqtt_client_config_t conf; +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_demo_process, "MQTT Demo"); +/*---------------------------------------------------------------------------*/ +int +ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr) +{ + uint16_t a; + uint8_t len = 0; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + len += snprintf(&buf[len], buf_len - len, "::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + len += snprintf(&buf[len], buf_len - len, ":"); + } + len += snprintf(&buf[len], buf_len - len, "%x", a); + } + } + + return len; +} +/*---------------------------------------------------------------------------*/ +static void +echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, + uint16_t datalen) +{ + if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) { + def_rt_rssi = sicslowpan_get_last_rssi(); + } +} +/*---------------------------------------------------------------------------*/ +static void +publish_led_off(void *d) +{ + leds_off(STATUS_LED); +} +/*---------------------------------------------------------------------------*/ +static void +pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk, + uint16_t chunk_len) +{ + DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len, + chunk_len); + + /* If we don't like the length, ignore */ + if(topic_len != 23 || chunk_len != 1) { + printf("Incorrect topic or chunk len. Ignored\n"); + return; + } + + /* If the format != json, ignore */ + if(strncmp(&topic[topic_len - 4], "json", 4) != 0) { + printf("Incorrect format\n"); + } + + if(strncmp(&topic[10], "leds", 4) == 0) { + if(chunk[0] == '1') { + leds_on(LEDS_RED); + } else if(chunk[0] == '0') { + leds_off(LEDS_RED); + } + return; + } +} +/*---------------------------------------------------------------------------*/ +static void +mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data) +{ + switch(event) { + case MQTT_EVENT_CONNECTED: { + DBG("APP - Application has a MQTT connection\n"); + timer_set(&connection_life, CONNECTION_STABLE_TIME); + state = STATE_CONNECTED; + break; + } + case MQTT_EVENT_DISCONNECTED: { + DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data)); + + state = STATE_DISCONNECTED; + process_poll(&mqtt_demo_process); + break; + } + case MQTT_EVENT_PUBLISH: { + msg_ptr = data; + + /* Implement first_flag in publish message? */ + if(msg_ptr->first_chunk) { + msg_ptr->first_chunk = 0; + DBG("APP - Application received a publish on topic '%s'. Payload " + "size is %i bytes. Content:\n\n", + msg_ptr->topic, msg_ptr->payload_length); + } + + pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk, + msg_ptr->payload_length); + break; + } + case MQTT_EVENT_SUBACK: { + DBG("APP - Application is subscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_UNSUBACK: { + DBG("APP - Application is unsubscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_PUBACK: { + DBG("APP - Publishing complete\n"); + break; + } + default: + DBG("APP - Application got a unhandled MQTT event: %i\n", event); + break; + } +} +/*---------------------------------------------------------------------------*/ +static int +construct_pub_topic(void) +{ + int len = snprintf(pub_topic, BUFFER_SIZE, "iot-2/evt/%s/fmt/json", + conf.event_type_id); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_sub_topic(void) +{ + int len = snprintf(sub_topic, BUFFER_SIZE, "iot-2/cmd/%s/fmt/json", + conf.cmd_type); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_client_id(void) +{ + int len = snprintf(client_id, BUFFER_SIZE, "d:%s:%s:%02x%02x%02x%02x%02x%02x", + conf.org_id, conf.type_id, + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +update_config(void) +{ + if(construct_client_id() == 0) { + /* Fatal error. Client ID larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + if(construct_sub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + if(construct_pub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + /* Reset the counter */ + seq_nr_value = 0; + + state = STATE_INIT; + + /* + * Schedule next timer event ASAP + * + * If we entered an error state then we won't do anything when it fires. + * + * Since the error at this stage is a config error, we will only exit this + * error state if we get a new config. + */ + etimer_set(&publish_periodic_timer, 0); + + return; +} +/*---------------------------------------------------------------------------*/ +static int +init_config() +{ + /* Populate configuration with default values */ + memset(&conf, 0, sizeof(mqtt_client_config_t)); + + memcpy(conf.org_id, DEFAULT_ORG_ID, strlen(DEFAULT_ORG_ID)); + memcpy(conf.type_id, DEFAULT_TYPE_ID, strlen(DEFAULT_TYPE_ID)); + memcpy(conf.auth_token, DEFAULT_AUTH_TOKEN, strlen(DEFAULT_AUTH_TOKEN)); + memcpy(conf.event_type_id, DEFAULT_EVENT_TYPE_ID, + strlen(DEFAULT_EVENT_TYPE_ID)); + memcpy(conf.broker_ip, broker_ip, strlen(broker_ip)); + memcpy(conf.cmd_type, DEFAULT_SUBSCRIBE_CMD_TYPE, 1); + + conf.broker_port = DEFAULT_BROKER_PORT; + conf.pub_interval = DEFAULT_PUBLISH_INTERVAL; + conf.def_rt_ping_interval = DEFAULT_RSSI_MEAS_INTERVAL; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +subscribe(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + mqtt_status_t status; + + status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0); + + DBG("APP - Subscribing!\n"); + if(status == MQTT_STATUS_OUT_QUEUE_FULL) { + DBG("APP - Tried to subscribe but command queue was full!\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +publish(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + int len; + int remaining = APP_BUFFER_SIZE; + + seq_nr_value++; + + buf_ptr = app_buffer; + + len = snprintf(buf_ptr, remaining, + "{" + "\"d\":{" + "\"Seq #\":%d," + "\"Uptime (sec)\":%lu", seq_nr_value, clock_seconds()); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + remaining -= len; + buf_ptr += len; + + /* Put our Default route's string representation in a buffer */ + char def_rt_str[64]; + memset(def_rt_str, 0, sizeof(def_rt_str)); + ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); + + len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", + def_rt_str, def_rt_rssi); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + + len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (deg.C)\":%d", + temperature_sensor.value(0)); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + + len = snprintf(buf_ptr, remaining, "}}"); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer, + strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF); + + DBG("APP - Publish!\n"); +} +/*---------------------------------------------------------------------------*/ +static void +connect_to_broker(void) +{ + /* Connect to MQTT server */ + mqtt_connect(&conn, conf.broker_ip, conf.broker_port, + conf.pub_interval * 3); + + state = STATE_CONNECTING; +} +/*---------------------------------------------------------------------------*/ +static void +ping_parent(void) +{ + if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { + return; + } + + uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0, + ECHO_REQ_PAYLOAD_LEN); +} +/*---------------------------------------------------------------------------*/ +static void +state_machine(void) +{ + switch(state) { + case STATE_INIT: + /* If we have just been configured register MQTT connection */ + mqtt_register(&conn, &mqtt_demo_process, client_id, mqtt_event, + MAX_TCP_SEGMENT_SIZE); + + /* + * If we are not using the quickstart service (thus we are an IBM + * registered device), we need to provide user name and password + */ + if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) != 0) { + if(strlen(conf.auth_token) == 0) { + printf("User name set, but empty auth token\n"); + state = STATE_ERROR; + break; + } else { + mqtt_set_username_password(&conn, "use-token-auth", + conf.auth_token); + } + } + + /* _register() will set auto_reconnect. We don't want that. */ + conn.auto_reconnect = 0; + connect_attempt = 1; + + state = STATE_REGISTERED; + DBG("Init\n"); + /* Continue */ + case STATE_REGISTERED: + if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) { + /* Registered and with a public IP. Connect */ + DBG("Registered. Connect attempt %u\n", connect_attempt); + ping_parent(); + connect_to_broker(); + } else { + leds_on(STATUS_LED); + ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL); + } + etimer_set(&publish_periodic_timer, NET_CONNECT_PERIODIC); + return; + break; + case STATE_CONNECTING: + leds_on(STATUS_LED); + ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL); + /* Not connected yet. Wait */ + DBG("Connecting (%u)\n", connect_attempt); + break; + case STATE_CONNECTED: + /* Don't subscribe unless we are a registered device */ + if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) == 0) { + DBG("Using 'quickstart': Skipping subscribe\n"); + state = STATE_PUBLISHING; + } + /* Continue */ + case STATE_PUBLISHING: + /* If the timer expired, the connection is stable. */ + if(timer_expired(&connection_life)) { + /* + * Intentionally using 0 here instead of 1: We want RECONNECT_ATTEMPTS + * attempts if we disconnect after a successful connect + */ + connect_attempt = 0; + } + + if(mqtt_ready(&conn) && conn.out_buffer_sent) { + /* Connected. Publish */ + if(state == STATE_CONNECTED) { + subscribe(); + state = STATE_PUBLISHING; + } else { + leds_on(STATUS_LED); + ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL); + publish(); + } + etimer_set(&publish_periodic_timer, conf.pub_interval); + + DBG("Publishing\n"); + /* Return here so we don't end up rescheduling the timer */ + return; + } else { + /* + * Our publish timer fired, but some MQTT packet is already in flight + * (either not sent at all, or sent but not fully ACKd). + * + * This can mean that we have lost connectivity to our broker or that + * simply there is some network delay. In both cases, we refuse to + * trigger a new message and we wait for TCP to either ACK the entire + * packet after retries, or to timeout and notify us. + */ + DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state, + conn.out_queue_full); + } + break; + case STATE_DISCONNECTED: + DBG("Disconnected\n"); + if(connect_attempt < RECONNECT_ATTEMPTS || + RECONNECT_ATTEMPTS == RETRY_FOREVER) { + /* Disconnect and backoff */ + clock_time_t interval; + mqtt_disconnect(&conn); + connect_attempt++; + + interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt : + RECONNECT_INTERVAL << 3; + + DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval); + + etimer_set(&publish_periodic_timer, interval); + + state = STATE_REGISTERED; + return; + } else { + /* Max reconnect attempts reached. Enter error state */ + state = STATE_ERROR; + DBG("Aborting connection after %u attempts\n", connect_attempt - 1); + } + break; + case STATE_CONFIG_ERROR: + /* Idle away. The only way out is a new config */ + printf("Bad configuration\n"); + return; + case STATE_ERROR: + default: + leds_on(STATUS_LED); + /* + * 'default' should never happen. + * + * If we enter here it's because of some error. Stop timers. The only thing + * that can bring us out is a new config event + */ + printf("Default case: State=0x%02x\n", state); + return; + } + + /* If we didn't return so far, reschedule ourselves */ + etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_demo_process, ev, data) +{ + + PROCESS_BEGIN(); + + printf("MQTT Demo Process\n"); + + if(init_config() != 1) { + PROCESS_EXIT(); + } + + update_config(); + + def_rt_rssi = 0x8000000; + uip_icmp6_echo_reply_callback_add(&echo_reply_notification, + echo_reply_handler); + etimer_set(&echo_request_timer, conf.def_rt_ping_interval); + + PUBLISH_TRIGGER->configure(SENSORS_ACTIVE, 1); + + /* Main loop */ + while(1) { + + PROCESS_YIELD(); + + if(ev == sensors_event && data == PUBLISH_TRIGGER) { + if(state == STATE_ERROR) { + connect_attempt = 1; + state = STATE_REGISTERED; + } + } + + if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) || + ev == PROCESS_EVENT_POLL || + (ev == sensors_event && data == PUBLISH_TRIGGER && PUBLISH_TRIGGER->value(BUTTON_SENSOR_VALUE_STATE) == 0)) { + state_machine(); + } + + if(ev == PROCESS_EVENT_TIMER && data == &echo_request_timer) { + ping_parent(); + etimer_set(&echo_request_timer, conf.def_rt_ping_interval); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/mqtt-demo/project-conf.h b/examples/nrf52dk/mqtt-demo/project-conf.h new file mode 100644 index 000000000..b52e1a48f --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * 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. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-mqtt-demo + * @{ + * + * \file + * Project specific configuration defines for the MQTT demo + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +/* User configuration */ +#define MQTT_DEMO_STATUS_LED LEDS_GREEN + +/* If undefined, the demo will attempt to connect to IBM's quickstart */ +#define MQTT_DEMO_BROKER_IP_ADDR "fd00::215:83ff:fed2:dbd7" +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/nrf52dk/timer-test/Makefile b/examples/nrf52dk/timer-test/Makefile new file mode 100644 index 000000000..ac89a34a4 --- /dev/null +++ b/examples/nrf52dk/timer-test/Makefile @@ -0,0 +1,9 @@ +CONTIKI_PROJECT = timer-test + +CONTIKI_WITH_RPL=0 +NRF52_WITHOUT_SOFTDEVICE=1 + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/timer-test/README.md b/examples/nrf52dk/timer-test/README.md new file mode 100644 index 000000000..9ce7cad94 --- /dev/null +++ b/examples/nrf52dk/timer-test/README.md @@ -0,0 +1,20 @@ +Timers test +=========== +Timers test is an application allows for testing clocks implementation for nRF52 DK. +The results of different tests are output to the console. + +There are 4 tests performed: + + 1) TEST clock_delay_usec() - measures duration of a NOP delay using rtimer. It's expected + that difference is close to 0. + + 2) TEST rtimer - schedules an rtimer callback after 1 second. Prints actual time difference + in rtimer and clock ticks. It's expected that both values are close to 0. + + 3) TEST etimer - schedules an event timer and measures time difference. It is expected that + the value is close to 0. + +The example requires one DK and it doesn't use SoftDevice. To compile and flash the +example run: + + make TARGET=nrf52dk timer-test.flash \ No newline at end of file diff --git a/examples/nrf52dk/timer-test/timer-test.c b/examples/nrf52dk/timer-test/timer-test.c new file mode 100644 index 000000000..e0ced7293 --- /dev/null +++ b/examples/nrf52dk/timer-test/timer-test.c @@ -0,0 +1,131 @@ +/** + * \file + * Tests related to clocks and timers + * This is based on clock_test.c from the original sensinode port + * + * \author + * Zach Shelby (Original) + * George Oikonomou - (rtimer code) + * Wojciech Bober (nRF52 DK adaptation) + * + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + */ +#include "contiki.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "dev/leds.h" + +#include "nrf_delay.h" + +#include +/*---------------------------------------------------------------------------*/ +#define TEST_CLOCK_DELAY_USEC 1 +#define TEST_RTIMER 1 +#define TEST_ETIMER 1 +/*---------------------------------------------------------------------------*/ +static struct etimer et; + +#if TEST_CLOCK_DELAY_USEC +static rtimer_clock_t start_count, end_count, diff; +#endif + +#if TEST_ETIMER +static clock_time_t count; +#endif + +#if TEST_RTIMER +static struct rtimer rt; +static clock_time_t ct_now; +rtimer_clock_t rt_now, rt_until; + +static volatile rtimer_clock_t rt_now_cb; +static volatile clock_time_t ct_cb; +#endif + +static uint8_t i; +/*---------------------------------------------------------------------------*/ +PROCESS(clock_test_process, "Clock test process"); +AUTOSTART_PROCESSES(&clock_test_process); +/*---------------------------------------------------------------------------*/ +#if TEST_RTIMER +void +rt_callback(struct rtimer *t, void *ptr) +{ + rt_now_cb = RTIMER_NOW(); + ct_cb = clock_time(); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(clock_test_process, ev, data) +{ + + PROCESS_BEGIN(); + etimer_set(&et, 2 * CLOCK_SECOND); + PROCESS_YIELD(); + + printf("RTIMER_SECOND=%d CLOCK_SECOND=%d\n", RTIMER_SECOND, CLOCK_SECOND); + +#if TEST_CLOCK_DELAY_USEC + printf("=======================\n"); + printf("TEST clock_delay_usec()\n"); + printf("=======================\n"); + i = 1; + while(i < 7) { + start_count = RTIMER_NOW(); + clock_delay_usec(10000 * i); + end_count = RTIMER_NOW(); + diff = end_count - start_count; + printf("difference [usec]: %ld\n", 10000 * i - (diff*(1000000/RTIMER_SECOND))); + i++; + } +#endif + +#if TEST_RTIMER + printf("=======================\n"); + printf("TEST rtimer\n"); + printf("=======================\n"); + i = 0; + while(i < 5) { + etimer_set(&et, 2 * CLOCK_SECOND); + rt_now = RTIMER_NOW(); + ct_now = clock_time(); + rt_until = rt_now + RTIMER_SECOND; + printf("now [ticks]: %lu until[ticks]: %lu\n", rt_now, rt_until); + if (rtimer_set(&rt, rt_until, 1, rt_callback, NULL) != RTIMER_OK) { + printf("Error setting\n"); + } + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + printf("rtimer difference [ticks]: %ld\n", RTIMER_SECOND - (rt_now_cb - rt_now)); + printf("clock difference [ticks]: %ld\n", CLOCK_SECOND - (ct_cb - ct_now)); + i++; + } +#endif + +#if TEST_ETIMER + printf("=======================\n"); + printf("TEST etimer\n"); + printf("=======================\n"); + i = 0; + while(i < 5) { + etimer_set(&et, i*CLOCK_SECOND); + count = clock_time(); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + printf("difference [ticks]: %lu\n", i*CLOCK_SECOND - (clock_time() - count)); + leds_toggle(LEDS_RED); + i++; + } +#endif + + printf("Done!\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ From 2d45a4207a57c6a523436911cac65b192c75f127 Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Fri, 22 Jan 2016 11:13:07 +0100 Subject: [PATCH 07/80] nrf52dk: regression tests --- .travis.yml | 13 +++++++++++++ .../23-compile-nrf52-ports/Makefile | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 regression-tests/23-compile-nrf52-ports/Makefile diff --git a/.travis.yml b/.travis.yml index 1814ee6fa..74ce552e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,6 +89,18 @@ before_script: rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* && ba-elf-gcc --version ; fi + + ## Install mainline ARM toolchain and download nRF52 SDK + - if [ ${BUILD_ARCH:-0} = nrf52dk ] ; then + sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded && + sudo apt-get -qq update && + sudo apt-get -qq install gcc-arm-none-eabi srecord && + arm-none-eabi-gcc --version && + $WGET https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip && + mkdir /tmp/nrf52-sdk && + unzip nrf5_iot_sdk_3288530.zip -d /tmp/nrf52-sdk && + export NRF52_SDK_ROOT=/tmp/nrf52-sdk ; + fi ## Compile cooja.jar only when it's going to be needed - if [ ${BUILD_CATEGORY:-sim} = sim ] ; then @@ -138,5 +150,6 @@ env: - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs' - BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x' + - BUILD_TYPE='compile-nrf52-ports' BUILD_CATEGORY='compile' BUILD_ARCH='nrf52dk' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/regression-tests/23-compile-nrf52-ports/Makefile b/regression-tests/23-compile-nrf52-ports/Makefile new file mode 100644 index 000000000..5e9ee19de --- /dev/null +++ b/regression-tests/23-compile-nrf52-ports/Makefile @@ -0,0 +1,19 @@ +EXAMPLESDIR=../../examples +TOOLSDIR=../../tools + +# Note, that SERVER_IPV6_ADDR variable is set to ffff on purpose +# even though it's not a valid IPV6 address. This is due to limitation +# of the testing framework which splits compliation arguments using +# a colon. + +EXAMPLES = \ +hello-world/nrf52dk \ +nrf52dk/blink-hello/nrf52dk \ +nrf52dk/coap-demo/nrf52dk:coap-server \ +nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ +nrf52dk/mqtt-demo/nrf52dk \ +nrf52dk/timer-test/nrf52dk + +TOOLS= + +include ../Makefile.compile-test From 943e5268601e3efba24dd9a19412b2235145c5e1 Mon Sep 17 00:00:00 2001 From: Wojciech Bober Date: Fri, 22 Jan 2016 12:42:45 +0100 Subject: [PATCH 08/80] nrf52dk: added build artifacts to git ignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index c166681da..304d18b7b 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,7 @@ platform/galileo/bsp/grub/bin/ *.galileo.dll *.galileo.efi LOG_OPENOCD + +# nRF52 build artifacts +*.jlink +*.nrf52dk From b4c2cd9619aac07bce4eefc706ef443b8b58c3c2 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 7 Mar 2016 17:25:40 +0100 Subject: [PATCH 09/80] Macros for TSCH US_TO_RTIMERTICKS(US) and RTIMERTICKS_TO_US(T) --- cpu/cc2538/rtimer-arch.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cpu/cc2538/rtimer-arch.h b/cpu/cc2538/rtimer-arch.h index ddb020af1..45ebc5c5d 100644 --- a/cpu/cc2538/rtimer-arch.h +++ b/cpu/cc2538/rtimer-arch.h @@ -65,6 +65,20 @@ #define RTIMER_ARCH_SECOND 32768 +/* Do the math in 32bits to save precision. + * Round to nearest integer rather than truncate. */ +#define US_TO_RTIMERTICKS(US) ((US) >= 0 ? \ + (((int32_t)(US) * (RTIMER_ARCH_SECOND) + 500000) / 1000000L) : \ + ((int32_t)(US) * (RTIMER_ARCH_SECOND) - 500000) / 1000000L) + +#define RTIMERTICKS_TO_US(T) ((T) >= 0 ? \ + (((int32_t)(T) * 1000000L + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) : \ + ((int32_t)(T) * 1000000L - ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) + +/* A 64-bit version because the 32-bit one cannot handle T >= 4295 ticks. + Intended only for positive values of T. */ +#define RTIMERTICKS_TO_US_64(T) ((uint32_t)(((uint64_t)(T) * 1000000 + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND))) + /** \sa RTIMER_NOW() */ rtimer_clock_t rtimer_arch_now(void); From b0a673ca5c24155bc95b6b7faacef3f99da6b2f2 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 7 Mar 2016 17:46:53 +0100 Subject: [PATCH 10/80] Changes to enable TSCH poll mode for TSCH including SFD timestamps and send_on_cca --- cpu/cc2538/dev/cc2538-rf.c | 137 ++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 26 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 58b464fc5..a76c1c356 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -120,6 +120,17 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #define CC2538_RF_AUTOACK 1 #endif /*---------------------------------------------------------------------------*/ +#if CC2538_RF_CONF_SFD_TIMESTAMPS +static rtimer_clock_t cc2538_sfd_rtime; +#endif + +/* Are we currently in poll mode? Disabled by default */ +static uint8_t volatile poll_mode = 0; +/* Do we perform a CCA before sending? Enabled by default. */ +static uint8_t send_on_cca = 1; +static int8_t cc2538_last_rssi; +static uint8_t cc2538_last_crc_corr_lqi; +/*---------------------------------------------------------------------------*/ static uint8_t rf_flags; static uint8_t rf_channel = CC2538_RF_CHANNEL; @@ -329,6 +340,29 @@ set_frame_filtering(uint8_t enable) } /*---------------------------------------------------------------------------*/ static void +set_poll_mode(uint8_t enable) +{ + poll_mode = enable; + + if(enable) { + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source + REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt + REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_SFD; // enable SFD interrupt source + } else { + REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // mask out SFD interrupt source + REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_SFD; // clear pending SFD interrupt + } + nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts +} +/*---------------------------------------------------------------------------*/ +static void +set_send_on_cca(uint8_t enable) +{ + send_on_cca = enable; +} +/*---------------------------------------------------------------------------*/ +static void set_auto_ack(uint8_t enable) { if(enable) { @@ -395,7 +429,9 @@ off(void) /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); - CC2538_RF_CSP_ISFLUSHRX(); + if (!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP)) { + CC2538_RF_CSP_ISFLUSHRX(); + } /* Don't turn off if we are off as this will trigger a Strobe Error */ if(REG(RFCORE_XREG_RXENABLE) != 0) { @@ -459,10 +495,6 @@ init(void) set_channel(rf_channel); - /* Acknowledge RF interrupts, FIFOP only */ - REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; - nvic_interrupt_enable(NVIC_INT_RF_RXTX); - /* Acknowledge all RF Error interrupts */ REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM; nvic_interrupt_enable(NVIC_INT_RF_ERR); @@ -488,6 +520,8 @@ init(void) */ udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA); } + + set_poll_mode(poll_mode); process_start(&cc2538_rf_process, NULL); @@ -700,15 +734,15 @@ read(void *buf, unsigned short bufsize) } /* Read the RSSI and CRC/Corr bytes */ - rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; - crc_corr = REG(RFCORE_SFR_RFDATA); + cc2538_last_rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; + cc2538_last_crc_corr_lqi = REG(RFCORE_SFR_RFDATA); - PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr); + PRINTF("%02x%02x\n", (uint8_t)cc2538_last_rssi, cc2538_last_crc_corr_lqi); /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ - if(crc_corr & CRC_BIT_MASK) { - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); + if(cc2538_last_crc_corr_lqi & CRC_BIT_MASK) { + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2538_last_rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2538_last_crc_corr_lqi & LQI_BIT_MASK); RIMESTATS_ADD(llrx); } else { RIMESTATS_ADD(badcrc); @@ -731,14 +765,18 @@ read(void *buf, unsigned short bufsize) flush(); #endif - /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ - if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) { - if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) { - process_poll(&cc2538_rf_process); - } else { - CC2538_RF_CSP_ISFLUSHRX(); + if(!poll_mode) { + /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ + if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) { + if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) { + process_poll(&cc2538_rf_process); + } else { + CC2538_RF_CSP_ISFLUSHRX(); + } } } + + CC2538_RF_CSP_ISFLUSHRX(); return (len); } @@ -796,6 +834,15 @@ get_value(radio_param_t param, radio_value_t *value) if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) { *value |= RADIO_RX_MODE_AUTOACK; } + if(poll_mode) { + *value |= RADIO_RX_MODE_POLL_MODE; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TX_MODE: + *value = 0; + if(send_on_cca) { + *value |= RADIO_TX_MODE_SEND_ON_CCA; + } return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: *value = get_tx_power(); @@ -806,6 +853,12 @@ get_value(radio_param_t param, radio_value_t *value) case RADIO_PARAM_RSSI: *value = get_rssi(); return RADIO_RESULT_OK; + case RADIO_PARAM_LAST_RSSI: + *value = cc2538_last_rssi; + return RADIO_RESULT_OK; + case RADIO_PARAM_LAST_LINK_QUALITY: + *value = cc2538_last_crc_corr_lqi & LQI_BIT_MASK; + return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: *value = CC2538_RF_CHANNEL_MIN; return RADIO_RESULT_OK; @@ -854,13 +907,21 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_OK; case RADIO_PARAM_RX_MODE: if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | - RADIO_RX_MODE_AUTOACK)) { + RADIO_RX_MODE_AUTOACK | + RADIO_RX_MODE_POLL_MODE)) { return RADIO_RESULT_INVALID_VALUE; } set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0); set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0); + set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0); + return RADIO_RESULT_OK; + case RADIO_PARAM_TX_MODE: + if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) { + return RADIO_RESULT_INVALID_VALUE; + } + set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0); return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { @@ -895,6 +956,19 @@ get_object(radio_param_t param, void *dest, size_t size) return RADIO_RESULT_OK; } + + if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) { +#if CC2538_RF_CONF_SFD_TIMESTAMPS + if(size != sizeof(rtimer_clock_t) || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + *(rtimer_clock_t*)dest = cc2538_sfd_rtime; + return RADIO_RESULT_OK; +#else + return RADIO_RESULT_NOT_SUPPORTED; +#endif + } + return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ @@ -950,15 +1024,18 @@ PROCESS_THREAD(cc2538_rf_process, ev, data) PROCESS_BEGIN(); while(1) { - PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + /* Only if we are not in poll mode oder we are in poll mode and transceiver has to be reset */ + PROCESS_YIELD_UNTIL((!poll_mode || (poll_mode && (rf_flags & RF_MUST_RESET))) && (ev == PROCESS_EVENT_POLL)); - packetbuf_clear(); - len = read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(!poll_mode) { + packetbuf_clear(); + len = read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len > 0) { - packetbuf_set_datalen(len); + if(len > 0) { + packetbuf_set_datalen(len); - NETSTACK_RDC.input(); + NETSTACK_RDC.input(); + } } /* If we were polled due to an RF error, reset the transceiver */ @@ -995,10 +1072,18 @@ void cc2538_rf_rx_tx_isr(void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); + +#if CC2538_RF_CONF_SFD_TIMESTAMPS + if(poll_mode) { + cc2538_sfd_rtime = RTIMER_NOW(); + } +#endif - process_poll(&cc2538_rf_process); + if(!poll_mode) { + process_poll(&cc2538_rf_process); + } - /* We only acknowledge FIFOP so we can safely wipe out the entire SFR */ + /* We only acknowledge FIFOP or SFD so we can safely wipe out the entire SFR */ REG(RFCORE_SFR_RFIRQF0) = 0; ENERGEST_OFF(ENERGEST_TYPE_IRQ); From 73d36ebb6b9d7291fdb43592b271dd8b161ccad9 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 7 Mar 2016 18:34:54 +0100 Subject: [PATCH 11/80] SFD timestamp Only save SFD timestamp when we are actually receiving. --- cpu/cc2538/dev/cc2538-rf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index a76c1c356..fda88ceed 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -1075,7 +1075,9 @@ cc2538_rf_rx_tx_isr(void) #if CC2538_RF_CONF_SFD_TIMESTAMPS if(poll_mode) { - cc2538_sfd_rtime = RTIMER_NOW(); + if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_RX_ACTIVE) { + cc2538_sfd_rtime = RTIMER_NOW(); + } } #endif From b32ad0dbbdf77b0bf5c2c738694e40ffb3fe478c Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 7 Mar 2016 18:37:03 +0100 Subject: [PATCH 12/80] define for SFD timestamp on cc2538 --- examples/ipv6/rpl-tsch/project-conf.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 7ecfb74c1..13595f333 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -67,6 +67,11 @@ #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network #define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network +/* Needed for cc2538 platform only */ +/* Enable SFD timestamp (uses SFD interrupt) */ +#undef CC2538_RF_CONF_SFD_TIMESTAMPS +#define CC2538_RF_CONF_SFD_TIMESTAMPS 1 + /* Needed for cc2420 platforms only */ /* Disable DCO calibration (uses timerB) */ #undef DCOSYNCH_CONF_ENABLED From 9ac14d1c7bf1d831de885fc139010411c7eba222 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 7 Mar 2016 18:39:13 +0100 Subject: [PATCH 13/80] defines needed for TSCH --- platform/cc2538dk/contiki-conf.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index 34a7f1673..380288f02 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -40,6 +40,12 @@ typedef uint32_t rtimer_clock_t; #define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) /** @} */ /*---------------------------------------------------------------------------*/ +#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 + +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(300)) +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(100)) +#define RADIO_DELAY_BEFORE_DETECT 0 +/*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration * From 6e5e1d05cdc9e6fb6dddaf95da5608d5687a808c Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 8 Mar 2016 15:48:16 +0100 Subject: [PATCH 14/80] TSCH: define to enable/disable HW frame filtering --- core/net/mac/tsch/tsch-conf.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/net/mac/tsch/tsch-conf.h b/core/net/mac/tsch/tsch-conf.h index bd9726042..b23355539 100644 --- a/core/net/mac/tsch/tsch-conf.h +++ b/core/net/mac/tsch/tsch-conf.h @@ -175,4 +175,11 @@ #define TSCH_ADAPTIVE_TIMESYNC 0 #endif +/* HW frame filtering enabled */ +#ifdef TSCH_CONF_HW_FRAME_FILTERING +#define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING +#else /* TSCH_CONF_HW_FRAME_FILTERING */ +#define TSCH_HW_FRAME_FILTERING 1 +#endif + #endif /* __TSCH_CONF_H__ */ From 38348b8703b7f914cf892ef71b4969de0b7c8851 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 8 Mar 2016 15:50:37 +0100 Subject: [PATCH 15/80] enable/disable HW frame filtering enable/disable HW frame filtering as defined in TSCH_CONF_HW_FRAME_FILTERING --- core/net/mac/tsch/tsch-slot-operation.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index 3174787c2..be1885bc7 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -514,9 +514,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) TSCH_DEBUG_TX_EVENT(); NETSTACK_RADIO.off(); +#if TSCH_HW_FRAME_FILTERING /* Leaving promiscuous mode */ NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode); NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode | RADIO_RX_MODE_ADDRESS_FILTER); +#endif /* TSCH_HW_FRAME_FILTERING */ /* Read ack frame */ ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf)); From 0e0dba932ffcfcf7d08857cb5f500403ee2116e6 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 8 Mar 2016 15:52:40 +0100 Subject: [PATCH 16/80] disable TSCH HW frame filtering --- platform/cc2538dk/contiki-conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index 380288f02..c91338849 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -40,7 +40,7 @@ typedef uint32_t rtimer_clock_t; #define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) /** @} */ /*---------------------------------------------------------------------------*/ -#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 +#define TSCH_CONF_HW_FRAME_FILTERING 0 #define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(300)) #define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(100)) From a4ccce8dac213de5b581cddbf2d861a908309ff6 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 8 Mar 2016 15:54:03 +0100 Subject: [PATCH 17/80] enable 32 kHz crystal oscillator for TSCH --- examples/ipv6/rpl-tsch/project-conf.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 13595f333..71a8e5425 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -71,6 +71,10 @@ /* Enable SFD timestamp (uses SFD interrupt) */ #undef CC2538_RF_CONF_SFD_TIMESTAMPS #define CC2538_RF_CONF_SFD_TIMESTAMPS 1 +/* For TSCH we have to use the more accurate crystal oscillator + * by default the RC oscillator is activated */ +#undef SYS_CTRL_CONF_OSC32K_USE_XTAL +#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 /* Needed for cc2420 platforms only */ /* Disable DCO calibration (uses timerB) */ From 1b185392e444d2f22559db60d1f1a0f0a31f6a61 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 8 Mar 2016 16:17:40 +0100 Subject: [PATCH 18/80] make cc2538_sfd_rtime volatile --- cpu/cc2538/dev/cc2538-rf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index fda88ceed..f889a373d 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -121,7 +121,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #endif /*---------------------------------------------------------------------------*/ #if CC2538_RF_CONF_SFD_TIMESTAMPS -static rtimer_clock_t cc2538_sfd_rtime; +static rtimer_clock_t volatile cc2538_sfd_rtime; #endif /* Are we currently in poll mode? Disabled by default */ From 217e623337620c3e463f91ed4994668a9dc93cb4 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Thu, 10 Mar 2016 18:09:00 +0100 Subject: [PATCH 19/80] remove unused variables --- cpu/cc2538/dev/cc2538-rf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index f889a373d..9a1957fe0 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -664,8 +664,6 @@ read(void *buf, unsigned short bufsize) { uint8_t i; uint8_t len; - uint8_t crc_corr; - int8_t rssi; PRINTF("RF: Read\n"); From 57a47bb12f6639c1cccb87b06bd6862ed693a8e7 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Thu, 10 Mar 2016 18:36:47 +0100 Subject: [PATCH 20/80] node_id on cc2538dk --- examples/ipv6/rpl-tsch/node.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index 2aee41d81..beceff326 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -38,6 +38,7 @@ #include "contiki.h" #include "node-id.h" +#include "linkaddr.h" #include "net/rpl/rpl.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" @@ -131,6 +132,7 @@ net_init(uip_ipaddr_t *br_prefix) PROCESS_THREAD(node_process, ev, data) { static struct etimer et; + static unsigned short node_id; PROCESS_BEGIN(); /* 3 possible roles: @@ -142,6 +144,8 @@ PROCESS_THREAD(node_process, ev, data) static enum { role_6ln, role_6dr, role_6dr_sec } node_role; node_role = role_6ln; + node_id = linkaddr_node_addr.u8[LINKADDR_SIZE - 2] | linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; + /* Set node with ID == 1 as coordinator, convenient in Cooja. */ if(node_id == 1) { if(LLSEC802154_CONF_SECURITY_LEVEL) { From 45c7477650a19c2cbee5162c652e33786aa86b4d Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Fri, 11 Mar 2016 11:02:43 +0100 Subject: [PATCH 21/80] original node.c --- examples/ipv6/rpl-tsch/node.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index beceff326..2aee41d81 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -38,7 +38,6 @@ #include "contiki.h" #include "node-id.h" -#include "linkaddr.h" #include "net/rpl/rpl.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" @@ -132,7 +131,6 @@ net_init(uip_ipaddr_t *br_prefix) PROCESS_THREAD(node_process, ev, data) { static struct etimer et; - static unsigned short node_id; PROCESS_BEGIN(); /* 3 possible roles: @@ -144,8 +142,6 @@ PROCESS_THREAD(node_process, ev, data) static enum { role_6ln, role_6dr, role_6dr_sec } node_role; node_role = role_6ln; - node_id = linkaddr_node_addr.u8[LINKADDR_SIZE - 2] | linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; - /* Set node with ID == 1 as coordinator, convenient in Cooja. */ if(node_id == 1) { if(LLSEC802154_CONF_SECURITY_LEVEL) { From 400a09e82ceb8e77464bf072748ba42f18ed38e6 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Fri, 11 Mar 2016 11:05:04 +0100 Subject: [PATCH 22/80] comment --- platform/cc2538dk/contiki-conf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index c91338849..ae7c3275d 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -42,6 +42,7 @@ typedef uint32_t rtimer_clock_t; /*---------------------------------------------------------------------------*/ #define TSCH_CONF_HW_FRAME_FILTERING 0 +/* TODO: measure the delays, this are only estimations */ #define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(300)) #define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(100)) #define RADIO_DELAY_BEFORE_DETECT 0 From 2d9b53667fdd49573a703bbf226c73115bcca817 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 16 Mar 2016 12:24:49 +0100 Subject: [PATCH 23/80] not leaving promiscuous mode anymore if TSCH_HW_FRAME_FILTERING disabled --- core/net/mac/tsch/tsch-slot-operation.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index be1885bc7..7deccaa92 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -493,9 +493,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) uint8_t ack_hdrlen; frame802154_t frame; +#if TSCH_HW_FRAME_FILTERING /* Entering promiscuous mode so that the radio accepts the enhanced ACK */ NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode); NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER)); +#endif /* TSCH_HW_FRAME_FILTERING */ /* Unicast: wait for ack after tx: sleep until ack time */ TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck"); From 66a0bbcd24dbd529586de9400e0e045c5744f63d Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 16 Mar 2016 16:38:04 +0100 Subject: [PATCH 24/80] renaming variables back to their original name --- cpu/cc2538/dev/cc2538-rf.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 9a1957fe0..a07108e8b 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -128,8 +128,8 @@ static rtimer_clock_t volatile cc2538_sfd_rtime; static uint8_t volatile poll_mode = 0; /* Do we perform a CCA before sending? Enabled by default. */ static uint8_t send_on_cca = 1; -static int8_t cc2538_last_rssi; -static uint8_t cc2538_last_crc_corr_lqi; +static int8_t rssi; +static uint8_t crc_corr; /*---------------------------------------------------------------------------*/ static uint8_t rf_flags; static uint8_t rf_channel = CC2538_RF_CHANNEL; @@ -732,15 +732,15 @@ read(void *buf, unsigned short bufsize) } /* Read the RSSI and CRC/Corr bytes */ - cc2538_last_rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; - cc2538_last_crc_corr_lqi = REG(RFCORE_SFR_RFDATA); + rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; + crc_corr = REG(RFCORE_SFR_RFDATA); - PRINTF("%02x%02x\n", (uint8_t)cc2538_last_rssi, cc2538_last_crc_corr_lqi); + PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr); /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ - if(cc2538_last_crc_corr_lqi & CRC_BIT_MASK) { - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2538_last_rssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2538_last_crc_corr_lqi & LQI_BIT_MASK); + if(crc_corr & CRC_BIT_MASK) { + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); RIMESTATS_ADD(llrx); } else { RIMESTATS_ADD(badcrc); @@ -852,10 +852,10 @@ get_value(radio_param_t param, radio_value_t *value) *value = get_rssi(); return RADIO_RESULT_OK; case RADIO_PARAM_LAST_RSSI: - *value = cc2538_last_rssi; + *value = rssi; return RADIO_RESULT_OK; case RADIO_PARAM_LAST_LINK_QUALITY: - *value = cc2538_last_crc_corr_lqi & LQI_BIT_MASK; + *value = crc_corr & LQI_BIT_MASK; return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: *value = CC2538_RF_CHANNEL_MIN; From fb6e6d9ea3ae763c8a3a60a0bb868732a7d5be0c Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 22 Mar 2016 18:51:05 +0100 Subject: [PATCH 25/80] macros for MAC timer --- cpu/cc2538/dev/cc2538-rf.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpu/cc2538/dev/cc2538-rf.h b/cpu/cc2538/dev/cc2538-rf.h index 5edb478ba..287147a92 100644 --- a/cpu/cc2538/dev/cc2538-rf.h +++ b/cpu/cc2538/dev/cc2538-rf.h @@ -129,6 +129,15 @@ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \ } while(0) +/*--------------------------------------------------------------------------- + * MAC timer + *---------------------------------------------------------------------------*/ +/* Timer conversion */ +#define RADIO_TO_RTIMER(X) ((X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ) + +#define CLOCK_STABLE() do { \ + while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \ + } while(0) /*---------------------------------------------------------------------------*/ /** The NETSTACK data structure for the cc2538 RF driver */ extern const struct radio_driver cc2538_rf_driver; From a4f575b8f03fca1f297409598fad1c5e05fea0a7 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 23 Mar 2016 09:08:54 +0100 Subject: [PATCH 26/80] use MAC timer instead of SFD interrupt --- cpu/cc2538/dev/cc2538-rf.c | 65 ++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index a07108e8b..0ecf7cb59 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -120,16 +120,15 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #define CC2538_RF_AUTOACK 1 #endif /*---------------------------------------------------------------------------*/ -#if CC2538_RF_CONF_SFD_TIMESTAMPS -static rtimer_clock_t volatile cc2538_sfd_rtime; -#endif - /* Are we currently in poll mode? Disabled by default */ static uint8_t volatile poll_mode = 0; /* Do we perform a CCA before sending? Enabled by default. */ static uint8_t send_on_cca = 1; static int8_t rssi; static uint8_t crc_corr; + +void mac_timer_init(void); +uint32_t get_sfd_timestamp(void); /*---------------------------------------------------------------------------*/ static uint8_t rf_flags; static uint8_t rf_channel = CC2538_RF_CHANNEL; @@ -347,13 +346,14 @@ set_poll_mode(uint8_t enable) if(enable) { REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt - REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_SFD; // enable SFD interrupt source + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // disable SFD interrupt source + nvic_interrupt_disable(NVIC_INT_RF_RXTX); } else { REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source - REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // mask out SFD interrupt source - REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_SFD; // clear pending SFD interrupt + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // mask out SFD interrupt source + REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_SFD; // clear pending SFD interrupt + nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts } - nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts } /*---------------------------------------------------------------------------*/ static void @@ -521,6 +521,8 @@ init(void) udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA); } + mac_timer_init(); + set_poll_mode(poll_mode); process_start(&cc2538_rf_process, NULL); @@ -956,15 +958,11 @@ get_object(radio_param_t param, void *dest, size_t size) } if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) { -#if CC2538_RF_CONF_SFD_TIMESTAMPS if(size != sizeof(rtimer_clock_t) || !dest) { return RADIO_RESULT_INVALID_VALUE; } *(rtimer_clock_t*)dest = cc2538_sfd_rtime; return RADIO_RESULT_OK; -#else - return RADIO_RESULT_NOT_SUPPORTED; -#endif } return RADIO_RESULT_NOT_SUPPORTED; @@ -1071,14 +1069,6 @@ cc2538_rf_rx_tx_isr(void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); -#if CC2538_RF_CONF_SFD_TIMESTAMPS - if(poll_mode) { - if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_RX_ACTIVE) { - cc2538_sfd_rtime = RTIMER_NOW(); - } - } -#endif - if(!poll_mode) { process_poll(&cc2538_rf_process); } @@ -1130,4 +1120,39 @@ cc2538_rf_set_promiscous_mode(char p) set_frame_filtering(p); } /*---------------------------------------------------------------------------*/ +uint32_t get_sfd_timestamp(void) +{ + uint32_t sfd, timer_val; + + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000000; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; + timer_val = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0; + timer_val |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8); + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000000; + timer_val |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); + timer_val |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000001; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; + sfd = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0; + sfd |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8); + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000010; + sfd |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); + sfd |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + + return (RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd)); +} +/*---------------------------------------------------------------------------*/ +void mac_timer_init(void) +{ + CLOCK_STABLE(); + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_RUN; + while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); + REG(RFCORE_SFR_MTCTRL) &= ~RFCORE_SFR_MTCTRL_RUN; + while(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE); + REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN | RFCORE_SFR_MTCTRL_SYNC); + while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); +} +/*---------------------------------------------------------------------------*/ /** @} */ From 199b1b531649b6276d07c96aaf13e4bab1f9e444 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 23 Mar 2016 09:10:19 +0100 Subject: [PATCH 27/80] remove define for SFD interrupt not needed anymore when using MAC timer --- examples/ipv6/rpl-tsch/project-conf.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 71a8e5425..81f7a01b6 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -67,10 +67,6 @@ #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network #define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network -/* Needed for cc2538 platform only */ -/* Enable SFD timestamp (uses SFD interrupt) */ -#undef CC2538_RF_CONF_SFD_TIMESTAMPS -#define CC2538_RF_CONF_SFD_TIMESTAMPS 1 /* For TSCH we have to use the more accurate crystal oscillator * by default the RC oscillator is activated */ #undef SYS_CTRL_CONF_OSC32K_USE_XTAL From 4e446bc178c82b60ebc5fc6882f2ff52c0df6cca Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 23 Mar 2016 10:16:06 +0100 Subject: [PATCH 28/80] fix error --- cpu/cc2538/dev/cc2538-rf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 0ecf7cb59..a9ea369d6 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -961,7 +961,7 @@ get_object(radio_param_t param, void *dest, size_t size) if(size != sizeof(rtimer_clock_t) || !dest) { return RADIO_RESULT_INVALID_VALUE; } - *(rtimer_clock_t*)dest = cc2538_sfd_rtime; + *(rtimer_clock_t*)dest = get_sfd_timestamp(); return RADIO_RESULT_OK; } From bc2f1b5a2ac2f83594b587d1efa6bbff2ee48206 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 29 Mar 2016 10:24:38 +0200 Subject: [PATCH 29/80] update delay constants --- platform/cc2538dk/contiki-conf.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index ae7c3275d..22891f5ba 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -42,9 +42,10 @@ typedef uint32_t rtimer_clock_t; /*---------------------------------------------------------------------------*/ #define TSCH_CONF_HW_FRAME_FILTERING 0 -/* TODO: measure the delays, this are only estimations */ -#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(300)) -#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(100)) +/* 352us from calling transmit() until the SFD byte has been sent */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) +/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) #define RADIO_DELAY_BEFORE_DETECT 0 /*---------------------------------------------------------------------------*/ /** From 871c725144210b0d85c153e64fa6f19403aba5cd Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Thu, 31 Mar 2016 11:24:57 +0200 Subject: [PATCH 30/80] spaces instead of tabs --- core/net/mac/tsch/tsch-conf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/net/mac/tsch/tsch-conf.h b/core/net/mac/tsch/tsch-conf.h index b23355539..43e50d7c3 100644 --- a/core/net/mac/tsch/tsch-conf.h +++ b/core/net/mac/tsch/tsch-conf.h @@ -177,9 +177,9 @@ /* HW frame filtering enabled */ #ifdef TSCH_CONF_HW_FRAME_FILTERING -#define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING +#define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING #else /* TSCH_CONF_HW_FRAME_FILTERING */ #define TSCH_HW_FRAME_FILTERING 1 -#endif +#endif /* TSCH_CONF_HW_FRAME_FILTERING */ #endif /* __TSCH_CONF_H__ */ From 2a6999921497172f94fa2237aea3d4e052857c32 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Tue, 5 Apr 2016 17:12:48 +0200 Subject: [PATCH 31/80] space instead of tab --- core/net/mac/tsch/tsch-conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/mac/tsch/tsch-conf.h b/core/net/mac/tsch/tsch-conf.h index 43e50d7c3..0cbce5913 100644 --- a/core/net/mac/tsch/tsch-conf.h +++ b/core/net/mac/tsch/tsch-conf.h @@ -179,7 +179,7 @@ #ifdef TSCH_CONF_HW_FRAME_FILTERING #define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING #else /* TSCH_CONF_HW_FRAME_FILTERING */ -#define TSCH_HW_FRAME_FILTERING 1 +#define TSCH_HW_FRAME_FILTERING 1 #endif /* TSCH_CONF_HW_FRAME_FILTERING */ #endif /* __TSCH_CONF_H__ */ From a7b43de535956178260c22d56eeb3046b2b920e6 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Wed, 6 Apr 2016 16:54:45 +0200 Subject: [PATCH 32/80] add comment, use spaces --- examples/ipv6/rpl-tsch/project-conf.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 81f7a01b6..1d3ad605d 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -67,18 +67,19 @@ #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network #define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network +/* Needed for CC2538 platforms only */ /* For TSCH we have to use the more accurate crystal oscillator * by default the RC oscillator is activated */ #undef SYS_CTRL_CONF_OSC32K_USE_XTAL -#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 +#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 /* Needed for cc2420 platforms only */ /* Disable DCO calibration (uses timerB) */ #undef DCOSYNCH_CONF_ENABLED -#define DCOSYNCH_CONF_ENABLED 0 +#define DCOSYNCH_CONF_ENABLED 0 /* Enable SFD timestamps (uses timerB) */ #undef CC2420_CONF_SFD_TIMESTAMPS -#define CC2420_CONF_SFD_TIMESTAMPS 1 +#define CC2420_CONF_SFD_TIMESTAMPS 1 /*******************************************************/ /******************* Configure TSCH ********************/ From 9ac859a2af439cfea168a44c66cc25f2e198118d Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Thu, 7 Apr 2016 15:17:44 +0200 Subject: [PATCH 33/80] add send_on_cca if query --- cpu/cc2538/dev/cc2538-rf.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index a9ea369d6..3f79f2bb8 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -607,9 +607,11 @@ transmit(unsigned short transmit_len) while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); } - if(channel_clear() == CC2538_RF_CCA_BUSY) { - RIMESTATS_ADD(contentiondrop); - return RADIO_TX_COLLISION; + if(send_on_cca) { + if(channel_clear() == CC2538_RF_CCA_BUSY) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } } /* From 5753fb5173501e1b4f1c2be440e7ad1d63a23848 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Thu, 7 Apr 2016 15:41:15 +0200 Subject: [PATCH 34/80] Clean up the driver Move mac_timer_init() into set_poll_mode() and remove now unneccesary clear outs and mask outs of interrupt sources and pending interrupts --- cpu/cc2538/dev/cc2538-rf.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 3f79f2bb8..12fe9ffae 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -344,14 +344,12 @@ set_poll_mode(uint8_t enable) poll_mode = enable; if(enable) { - REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source - REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt - REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // disable SFD interrupt source - nvic_interrupt_disable(NVIC_INT_RF_RXTX); + mac_timer_init(); + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source + REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt + nvic_interrupt_disable(NVIC_INT_RF_RXTX); // disable RF interrupts } else { - REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source - REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_SFD; // mask out SFD interrupt source - REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_SFD; // clear pending SFD interrupt + REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts } } @@ -521,8 +519,6 @@ init(void) udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA); } - mac_timer_init(); - set_poll_mode(poll_mode); process_start(&cc2538_rf_process, NULL); From b3f2bba3ecd4d0284dc57467164762ac5c1521ee Mon Sep 17 00:00:00 2001 From: Hardy Date: Wed, 13 Apr 2016 18:12:47 +0200 Subject: [PATCH 35/80] Removed some unnecessary statics in do_event() and process_post(). This allows the optimizer to put the corresponding variables into registers. See also discussion about other static variables: https://sourceforge.net/p/contiki/mailman/message/35010460/ --- core/sys/process.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/sys/process.c b/core/sys/process.c index b2ed5701c..f98057cd3 100644 --- a/core/sys/process.c +++ b/core/sys/process.c @@ -245,10 +245,10 @@ do_poll(void) static void do_event(void) { - static process_event_t ev; - static process_data_t data; - static struct process *receiver; - static struct process *p; + process_event_t ev; + process_data_t data; + struct process *receiver; + struct process *p; /* * If there are any events in the queue, take the first one and walk @@ -321,7 +321,7 @@ process_nevents(void) int process_post(struct process *p, process_event_t ev, process_data_t data) { - static process_num_events_t snum; + process_num_events_t snum; if(PROCESS_CURRENT() == NULL) { PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n", From 3bf05d664e77b6e6e43b3f7bd34e3b1f4d3fc715 Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Fri, 15 Apr 2016 15:50:01 +0200 Subject: [PATCH 36/80] moving macros to .c --- cpu/cc2538/dev/cc2538-rf.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.h b/cpu/cc2538/dev/cc2538-rf.h index 287147a92..5edb478ba 100644 --- a/cpu/cc2538/dev/cc2538-rf.h +++ b/cpu/cc2538/dev/cc2538-rf.h @@ -129,15 +129,6 @@ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \ } while(0) -/*--------------------------------------------------------------------------- - * MAC timer - *---------------------------------------------------------------------------*/ -/* Timer conversion */ -#define RADIO_TO_RTIMER(X) ((X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ) - -#define CLOCK_STABLE() do { \ - while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \ - } while(0) /*---------------------------------------------------------------------------*/ /** The NETSTACK data structure for the cc2538 RF driver */ extern const struct radio_driver cc2538_rf_driver; From 6262025ef3befe7afc0b653444c3d7276d6c5aaa Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Fri, 15 Apr 2016 15:50:20 +0200 Subject: [PATCH 37/80] code style fixes and insert macros from .h --- cpu/cc2538/dev/cc2538-rf.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 12fe9ffae..652480a9e 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -119,6 +119,15 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #else #define CC2538_RF_AUTOACK 1 #endif +/*--------------------------------------------------------------------------- + * MAC timer + *---------------------------------------------------------------------------*/ +/* Timer conversion */ +#define RADIO_TO_RTIMER(X) ((X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ) + +#define CLOCK_STABLE() do { \ + while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \ + } while(0) /*---------------------------------------------------------------------------*/ /* Are we currently in poll mode? Disabled by default */ static uint8_t volatile poll_mode = 0; @@ -427,7 +436,7 @@ off(void) /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); - if (!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP)) { + if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP)) { CC2538_RF_CSP_ISFLUSHRX(); } @@ -1071,7 +1080,7 @@ cc2538_rf_rx_tx_isr(void) process_poll(&cc2538_rf_process); } - /* We only acknowledge FIFOP or SFD so we can safely wipe out the entire SFR */ + /* We only acknowledge FIFOP so we can safely wipe out the entire SFR */ REG(RFCORE_SFR_RFIRQF0) = 0; ENERGEST_OFF(ENERGEST_TYPE_IRQ); @@ -1149,7 +1158,8 @@ void mac_timer_init(void) while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); REG(RFCORE_SFR_MTCTRL) &= ~RFCORE_SFR_MTCTRL_RUN; while(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE); - REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN | RFCORE_SFR_MTCTRL_SYNC); + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC; + REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN); while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); } /*---------------------------------------------------------------------------*/ From 3a76207b5958d34c587ee83b7a46d54cf7cd4a3e Mon Sep 17 00:00:00 2001 From: thomas-ha Date: Mon, 18 Apr 2016 11:40:52 +0200 Subject: [PATCH 38/80] Use 64 bit values for MAC timer --- cpu/cc2538/dev/cc2538-rf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 652480a9e..52708e0ca 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -123,7 +123,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ * MAC timer *---------------------------------------------------------------------------*/ /* Timer conversion */ -#define RADIO_TO_RTIMER(X) ((X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ) +#define RADIO_TO_RTIMER(X) ((uint32_t)((uint64_t)(X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ)) #define CLOCK_STABLE() do { \ while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \ @@ -1129,7 +1129,7 @@ cc2538_rf_set_promiscous_mode(char p) /*---------------------------------------------------------------------------*/ uint32_t get_sfd_timestamp(void) { - uint32_t sfd, timer_val; + uint64_t sfd, timer_val, buffer; REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000000; REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; @@ -1138,6 +1138,8 @@ uint32_t get_sfd_timestamp(void) REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000000; timer_val |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); timer_val |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2; + timer_val |= (buffer << 32); REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000001; REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; @@ -1146,6 +1148,8 @@ uint32_t get_sfd_timestamp(void) REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000010; sfd |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); sfd |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2; + sfd |= (buffer << 32); return (RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd)); } From 510fc9e51edf1f8818e0ed488f88f7983b714b5d Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 24 Nov 2015 11:35:20 +0100 Subject: [PATCH 39/80] removed memcpy that cause inconsistency in nbr-table when adding nd6 neighbor with NS/NA. --- core/net/ipv6/uip-nd6.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 107e66369..a6b8931ad 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -492,10 +492,11 @@ na_input(void) } else { uip_lladdr_t *lladdr; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); - lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(nbr == NULL) { goto discard; } + lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + if(nd6_opt_llao != 0) { is_llchange = memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr, @@ -505,8 +506,16 @@ na_input(void) if(nd6_opt_llao == NULL) { goto discard; } - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + + /* Remove this neighbor - since it has a NULL MAC address */ + uip_ds6_nbr_rm(nbr); + /* Re-add this neighbor - now with a correct MAC address */ + nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, + (const uip_lladdr_t *) &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], + is_router, NBR_STALE); + if(nbr == NULL) { + goto discard; + } if(is_solicited) { nbr->state = NBR_REACHABLE; nbr->nscount = 0; From b2f72fc99634a28258d98078c3a7a228cd818bdf Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 24 Nov 2015 23:00:50 +0100 Subject: [PATCH 40/80] replaces with aligned lladdress and also fixed the second memcpy to avoid risk of inconsistency when nodes change MAC address --- core/net/ipv6/uip-nd6.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index a6b8931ad..1d354d384 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -490,16 +490,16 @@ na_input(void) PRINTF("NA received is bad\n"); goto discard; } else { - uip_lladdr_t *lladdr; + uip_lladdr_t lladdr_aligned; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); if(nbr == NULL) { goto discard; } - lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + extract_lladdr_aligned(&lladdr_aligned); if(nd6_opt_llao != 0) { is_llchange = - memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr, + memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)&lladdr_aligned, UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { @@ -511,7 +511,7 @@ na_input(void) uip_ds6_nbr_rm(nbr); /* Re-add this neighbor - now with a correct MAC address */ nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, - (const uip_lladdr_t *) &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], + &lladdr_aligned, is_router, NBR_STALE); if(nbr == NULL) { goto discard; @@ -537,8 +537,15 @@ na_input(void) if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) || nd6_opt_llao == 0) { if(nd6_opt_llao != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + /* Remove this neighbor - since it has updated its MAC address */ + uip_ds6_nbr_rm(nbr); + /* Re-add this neighbor - now with a correct (new) MAC address */ + nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, + &lladdr_aligned, + is_router, NBR_STALE); + if(nbr == NULL) { + goto discard; + } } if(is_solicited) { nbr->state = NBR_REACHABLE; From 6f271bf8531aca07383e6cb8221963d9a073db59 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 25 Nov 2015 15:01:46 +0100 Subject: [PATCH 41/80] fixed so that the comparison of old lladdr and llao lladdr is compared instead of two llaos - and improved code style on surrounding code --- core/net/ipv6/uip-nd6.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 1d354d384..0eac94c4f 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -490,22 +490,22 @@ na_input(void) PRINTF("NA received is bad\n"); goto discard; } else { - uip_lladdr_t lladdr_aligned; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); if(nbr == NULL) { goto discard; } - extract_lladdr_aligned(&lladdr_aligned); - if(nd6_opt_llao != 0) { + if(nd6_opt_llao != NULL) { is_llchange = - memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)&lladdr_aligned, + memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { + uip_lladdr_t lladdr_aligned; if(nd6_opt_llao == NULL) { goto discard; } + extract_lladdr_aligned(&lladdr_aligned); /* Remove this neighbor - since it has a NULL MAC address */ uip_ds6_nbr_rm(nbr); @@ -534,9 +534,12 @@ na_input(void) } goto discard; } else { - if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) - || nd6_opt_llao == 0) { - if(nd6_opt_llao != 0) { + if(is_override || (!is_override && nd6_opt_llao != NULL && !is_llchange) + || nd6_opt_llao == NULL) { + if(nd6_opt_llao != NULL) { + uip_lladdr_t lladdr_aligned; + extract_lladdr_aligned(&lladdr_aligned); + /* Remove this neighbor - since it has updated its MAC address */ uip_ds6_nbr_rm(nbr); /* Re-add this neighbor - now with a correct (new) MAC address */ @@ -552,7 +555,7 @@ na_input(void) /* reachable time is stored in ms */ stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); } else { - if(nd6_opt_llao != 0 && is_llchange) { + if(nd6_opt_llao != NULL && is_llchange) { nbr->state = NBR_STALE; } } From 223f002676829f6df15f6aa10e35f39b8de5d1d1 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Nov 2015 14:10:16 +0100 Subject: [PATCH 42/80] fixed the case when the lladdr did not change but the LLAO is there and it is not an override. --- core/net/ipv6/uip-nd6.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 0eac94c4f..316172fb2 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -534,9 +534,12 @@ na_input(void) } goto discard; } else { - if(is_override || (!is_override && nd6_opt_llao != NULL && !is_llchange) - || nd6_opt_llao == NULL) { - if(nd6_opt_llao != NULL) { + /** + * If this is an cache override, or same lladdr, or no llao - + * do updates of nbr states. + */ + if(is_override || !is_llchange || nd6_opt_llao == NULL) { + if(nd6_opt_llao != NULL && is_llchange) { uip_lladdr_t lladdr_aligned; extract_lladdr_aligned(&lladdr_aligned); @@ -554,10 +557,6 @@ na_input(void) nbr->state = NBR_REACHABLE; /* reachable time is stored in ms */ stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); - } else { - if(nd6_opt_llao != NULL && is_llchange) { - nbr->state = NBR_STALE; - } } } } From 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Nov 2015 14:19:12 +0100 Subject: [PATCH 43/80] added a null check on the lladdr before the memcmp. --- core/net/ipv6/uip-nd6.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 316172fb2..62b3a64cb 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -490,14 +490,16 @@ na_input(void) PRINTF("NA received is bad\n"); goto discard; } else { + const uip_lladdr_t *lladdr; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); if(nbr == NULL) { goto discard; } + lladdr = uip_ds6_nbr_get_ll(nbr); if(nd6_opt_llao != NULL) { - is_llchange = - memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], uip_ds6_nbr_get_ll(nbr), + is_llchange = lladdr == NULL || + memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { From e9e31e9fd11070d04cec5e37fd47c3c145bb82df Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Nov 2015 20:26:10 +0100 Subject: [PATCH 44/80] replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information --- core/net/ipv6/uip-nd6.c | 77 ++++++++++++++++++++++++++--------------- core/net/nbr-table.c | 69 ++++++++++++++++++++++++++++-------- core/net/nbr-table.h | 1 + 3 files changed, 104 insertions(+), 43 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 62b3a64cb..d160392ed 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -136,7 +136,7 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ /*------------------------------------------------------------------*/ /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */ static void -extract_lladdr_aligned(uip_lladdr_t *dest) { +extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) { if(dest != NULL && nd6_opt_llao != NULL) { memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); } @@ -199,17 +199,29 @@ ns_input(void) goto discard; } else { #endif /*UIP_CONF_IPV6_CHECKS */ + uip_lladdr_t lladdr_aligned; + extract_lladdr_from_llao_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { +<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a uip_lladdr_t lladdr_aligned; extract_lladdr_aligned(&lladdr_aligned); uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); +======= + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); +>>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } else { if(nbr->state == NBR_INCOMPLETE) { @@ -495,10 +507,12 @@ na_input(void) if(nbr == NULL) { goto discard; } - lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(nd6_opt_llao != NULL) { - is_llchange = lladdr == NULL || + is_llchange = memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN); } @@ -507,17 +521,13 @@ na_input(void) if(nd6_opt_llao == NULL) { goto discard; } - extract_lladdr_aligned(&lladdr_aligned); - /* Remove this neighbor - since it has a NULL MAC address */ - uip_ds6_nbr_rm(nbr); - /* Re-add this neighbor - now with a correct MAC address */ - nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, - &lladdr_aligned, - is_router, NBR_STALE); - if(nbr == NULL) { + extract_lladdr_from_llao_aligned(&lladdr_aligned); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ goto discard; } + if(is_solicited) { nbr->state = NBR_REACHABLE; nbr->nscount = 0; @@ -529,7 +539,7 @@ na_input(void) nbr->state = NBR_STALE; } nbr->isrouter = is_router; - } else { + } else { /* NBR is not INCOMPLETE */ if(!is_override && is_llchange) { if(nbr->state == NBR_REACHABLE) { nbr->state = NBR_STALE; @@ -543,15 +553,9 @@ na_input(void) if(is_override || !is_llchange || nd6_opt_llao == NULL) { if(nd6_opt_llao != NULL && is_llchange) { uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); - - /* Remove this neighbor - since it has updated its MAC address */ - uip_ds6_nbr_rm(nbr); - /* Re-add this neighbor - now with a correct (new) MAC address */ - nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, - &lladdr_aligned, - is_router, NBR_STALE); - if(nbr == NULL) { + extract_lladdr_from_llao_aligned(&lladdr_aligned); + if(nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ goto discard; } } @@ -652,15 +656,19 @@ rs_input(void) } else { #endif /*UIP_CONF_IPV6_CHECKS */ uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); + extract_lladdr_from_llao_aligned(&lladdr_aligned); if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { /* we need to add the neighbor */ uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { /* If LL address changed, set neighbor state to stale */ + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) { + lladdr, UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_t nbr_data = *nbr; uip_ds6_nbr_rm(nbr); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, @@ -892,18 +900,31 @@ ra_input(void) nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { uip_lladdr_t lladdr_aligned; +<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a extract_lladdr_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); +======= + extract_lladdr_from_llao_aligned(&lladdr_aligned); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE); +>>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + uip_lladdr_t lladdr_aligned; + extract_lladdr_from_llao_aligned(&lladdr_aligned); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + /* change of link layer address */ + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } nbr->isrouter = 1; diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index ddae06fca..4a3518475 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -178,6 +178,26 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val return 0; } /*---------------------------------------------------------------------------*/ +static void +remove_key(nbr_table_key_t *least_used_key) +{ + int i; + for(i = 0; i < MAX_NUM_TABLES; i++) { + if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { + /* Call table callback for each table that uses this item */ + nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); + if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { + all_tables[i]->callback(removed_item); + } + } + } + /* Empty used map */ + used_map[index_from_key(least_used_key)] = 0; + /* Remove neighbor from list */ + list_remove(nbr_table_keys, least_used_key); + /* Return associated key */ +} + static nbr_table_key_t * nbr_table_allocate(nbr_table_reason_t reason, void *data) { @@ -253,21 +273,7 @@ nbr_table_allocate(nbr_table_reason_t reason, void *data) return NULL; } else { /* Reuse least used item */ - int i; - for(i = 0; icallback != NULL) { - /* Call table callback for each table that uses this item */ - nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); - if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { - all_tables[i]->callback(removed_item); - } - } - } - /* Empty used map */ - used_map[index_from_key(least_used_key)] = 0; - /* Remove neighbor from list */ - list_remove(nbr_table_keys, least_used_key); - /* Return associated key */ + remove_key(least_used_key); return least_used_key; } } @@ -416,6 +422,39 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item) return key != NULL ? &key->lladdr : NULL; } /*---------------------------------------------------------------------------*/ +/* Update link-layer address of an item */ +int +nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, + int remove_if_duplicate) +{ + int index; + int new_index; + nbr_table_key_t *key; + index = index_from_lladdr(old_addr); + if(index == -1) { + /* Failure to change since there is nothing to change. */ + return 0; + } + if((new_index = index_from_lladdr(new_addr)) != -1) { + /* check if it is a change or not - do not remove / fail if same */ + if(new_index == index) { + return 1; + } + /* This new entry already exists - failure! - remove if requested. */ + if(remove_if_duplicate) { + remove_key(key_from_index(index)); + } + return 0; + } + key = key_from_index(index); + /** + * Copy the new lladdr into the key - since we know that there is no + * conflicting entry. + */ + memcpy(&key->lladdr, new_addr, sizeof(linkaddr_t)); + return 1; +} +/*---------------------------------------------------------------------------*/ #if DEBUG static void print_table() diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index 88a90a46c..c797a44ec 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -109,6 +109,7 @@ int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item); /** \name Neighbor tables: address manipulation */ /** @{ */ linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item); +int nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, int remove_if_duplicate); /** @} */ #endif /* NBR_TABLE_H_ */ From d9f4d97a41496d0bd7f92cc6e5856adcceffc87d Mon Sep 17 00:00:00 2001 From: Pere Tuset Date: Tue, 19 Apr 2016 22:35:31 +0200 Subject: [PATCH 45/80] Adapted OpenMote-CC2538 sensor drivers to Contiki sensor API. --- examples/openmote-cc2538/openmote-demo.c | 55 +++++------ platform/openmote-cc2538/dev/adxl346.c | 111 ++++++++++++--------- platform/openmote-cc2538/dev/adxl346.h | 36 ++----- platform/openmote-cc2538/dev/max44009.c | 97 ++++++++++++++++--- platform/openmote-cc2538/dev/max44009.h | 31 ++---- platform/openmote-cc2538/dev/sht21.c | 117 +++++++++++++++++++---- platform/openmote-cc2538/dev/sht21.h | 43 +++------ 7 files changed, 304 insertions(+), 186 deletions(-) diff --git a/examples/openmote-cc2538/openmote-demo.c b/examples/openmote-cc2538/openmote-demo.c index f36c3a0b4..46a301511 100644 --- a/examples/openmote-cc2538/openmote-demo.c +++ b/examples/openmote-cc2538/openmote-demo.c @@ -83,31 +83,29 @@ static struct broadcast_conn bc; PROCESS_THREAD(openmote_demo_process, ev, data) { static struct etimer et; - static unsigned int raw, counter; - static uint8_t adxl346_present, max44009_present, sht21_present; - static float light, temperature, humidity; + static int16_t counter; + static uint16_t adxl346_present, sht21_present, max44009_present; + static uint16_t accel, light, temperature, humidity; PROCESS_EXITHANDLER(broadcast_close(&bc)) PROCESS_BEGIN(); - adxl346_init(); - adxl346_present = adxl346_is_present(); - if(!adxl346_present) { + /* Initialize and activate the ADXL346 sensor */ + adxl346_present = SENSORS_ACTIVATE(adxl346); + if(adxl346_present == ADXL346_ERROR) { printf("ADXL346 sensor is NOT present!\n"); leds_on(LEDS_YELLOW); } - max44009_init(); - max44009_present = max44009_is_present(); - if(!max44009_present) { + max44009_present = SENSORS_ACTIVATE(max44009); + if(max44009_present == MAX44009_ERROR) { printf("MAX44009 sensor is NOT present!\n"); leds_on(LEDS_ORANGE); } - sht21_init(); - sht21_present = sht21_is_present(); - if(!sht21_present) { + sht21_present = SENSORS_ACTIVATE(sht21); + if(sht21_present == SHT21_ERROR) { printf("SHT21 sensor is NOT present!\n"); leds_on(LEDS_RED); } @@ -123,33 +121,30 @@ PROCESS_THREAD(openmote_demo_process, ev, data) PROCESS_YIELD(); if(ev == PROCESS_EVENT_TIMER) { - if(adxl346_present) { + if(adxl346_present != ADXL346_ERROR) { leds_on(LEDS_YELLOW); - raw = adxl346_read_x(); - printf("X Acceleration: %u\n", raw); - raw = adxl346_read_y(); - printf("Y Acceleration: %u\n", raw); - raw = adxl346_read_z(); - printf("Z Acceleration: %u\n", raw); + accel = adxl346.value(ADXL346_READ_X); + printf("X Acceleration: %u\n", accel); + accel = adxl346.value(ADXL346_READ_Y); + printf("Y Acceleration: %u\n", accel); + accel = adxl346.value(ADXL346_READ_Z); + printf("Z Acceleration: %u\n", accel); leds_off(LEDS_YELLOW); } - if(max44009_present) { + if(max44009_present != MAX44009_ERROR) { leds_on(LEDS_ORANGE); - raw = max44009_read_light(); - light = max44009_convert_light(raw); - printf("Light: %u.%ulux\n", (unsigned int)light, (unsigned int)(light * 100) % 100); + light = max44009.value(MAX44009_READ_LIGHT); + printf("Light: %u.%ulux\n", light / 100, light % 100); leds_off(LEDS_ORANGE); } - if(sht21_present) { + if(sht21_present != SHT21_ERROR) { leds_on(LEDS_RED); - raw = sht21_read_temperature(); - temperature = sht21_convert_temperature(raw); - printf("Temperature: %u.%uC\n", (unsigned int)temperature, (unsigned int)(temperature * 100) % 100); - raw = sht21_read_humidity(); - humidity = sht21_convert_humidity(raw); - printf("Rel. humidity: %u.%u%%\n", (unsigned int)humidity, (unsigned int)(humidity * 100) % 100); + temperature = sht21.value(SHT21_READ_TEMP); + printf("Temperature: %u.%uC\n", temperature / 100, temperature % 100); + humidity = sht21.value(SHT21_READ_RHUM); + printf("Rel. humidity: %u.%u%%\n", humidity / 100, humidity % 100); leds_off(LEDS_RED); } diff --git a/platform/openmote-cc2538/dev/adxl346.c b/platform/openmote-cc2538/dev/adxl346.c index 650b7cfda..7fb406051 100644 --- a/platform/openmote-cc2538/dev/adxl346.c +++ b/platform/openmote-cc2538/dev/adxl346.c @@ -43,6 +43,14 @@ /*---------------------------------------------------------------------------*/ #include "dev/i2c.h" #include "dev/adxl346.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif /*---------------------------------------------------------------------------*/ /** * \name ADXL346 address and device identifier @@ -147,7 +155,9 @@ #define ADXL346_DATA_FORMAT_RANGE_PM_16g (3) /** @} */ /*---------------------------------------------------------------------------*/ -void +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void adxl346_init(void) { uint8_t config[2]; @@ -167,12 +177,7 @@ adxl346_init(void) i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); } /*---------------------------------------------------------------------------*/ -void -adxl346_reset(void) -{ -} -/*---------------------------------------------------------------------------*/ -uint8_t +static uint8_t adxl346_is_present(void) { uint8_t is_present; @@ -183,47 +188,15 @@ adxl346_is_present(void) return is_present == ADXL346_DEVID_VALUE; } /*---------------------------------------------------------------------------*/ -uint16_t -adxl346_read_x(void) -{ - uint8_t acceleration[2]; - uint16_t x; - - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAX0_ADDR); - i2c_single_receive(ADXL346_ADDRESS, &acceleration[0]); - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAX1_ADDR); - i2c_single_receive(ADXL346_ADDRESS, &acceleration[1]); - - x = (acceleration[0] << 8) | acceleration[1]; - - return x; -} -/*---------------------------------------------------------------------------*/ -uint16_t -adxl346_read_y(void) -{ - uint8_t acceleration[2]; - uint16_t y; - - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAY0_ADDR); - i2c_single_receive(ADXL346_ADDRESS, &acceleration[0]); - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAY1_ADDR); - i2c_single_receive(ADXL346_ADDRESS, &acceleration[1]); - - y = (acceleration[0] << 8) | acceleration[1]; - - return y; -} -/*---------------------------------------------------------------------------*/ -uint16_t -adxl346_read_z(void) +static uint16_t +adxl346_read_accel(uint8_t addr1, uint8_t addr2) { uint8_t acceleration[2]; uint16_t z; - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAZ0_ADDR); + i2c_single_send(ADXL346_ADDRESS, addr1); i2c_single_receive(ADXL346_ADDRESS, &acceleration[0]); - i2c_single_send(ADXL346_ADDRESS, ADXL346_DATAZ1_ADDR); + i2c_single_send(ADXL346_ADDRESS, addr2); i2c_single_receive(ADXL346_ADDRESS, &acceleration[1]); z = (acceleration[0] << 8) | acceleration[1]; @@ -231,4 +204,56 @@ adxl346_read_z(void) return z; } /*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if(!enabled) { + PRINTF("ADXL346: sensor not started\n"); + return ADXL346_ERROR; + } + + if(type == ADXL346_READ_X) { + return adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + } else if(type == ADXL346_READ_Y) { + return adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + } else if(type == ADXL346_READ_Z) { + return adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + } else { + PRINTF("ADXL346: invalid value requested\n"); + return ADXL346_ERROR; + } + + return ADXL346_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == ADXL346_ACTIVATE) { + if(!adxl346_is_present()) { + PRINTF("ADXL346: is not present\n"); + return ADXL346_ERROR; + } else { + adxl346_init(); + enabled = 1; + return ADXL346_SUCCESS; + } + } + + return ADXL346_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adxl346, ADXL346_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/openmote-cc2538/dev/adxl346.h b/platform/openmote-cc2538/dev/adxl346.h index d5751ce70..acd0d21f5 100644 --- a/platform/openmote-cc2538/dev/adxl346.h +++ b/platform/openmote-cc2538/dev/adxl346.h @@ -47,35 +47,17 @@ #ifndef ADXL346_H_ #define ADXL346_H_ /*---------------------------------------------------------------------------*/ -/** - * \brief Initialize the ADXL346 sensor - */ -void adxl346_init(void); +#define ADXL346_ERROR (-1) +#define ADXL346_SUCCESS (0) +#define ADXL346_ACTIVATE (SENSORS_ACTIVE) +#define ADXL346_READ_X (2) +#define ADXL346_READ_Y (3) +#define ADXL346_READ_Z (4) +#define ADXL346_NONE (5) /*---------------------------------------------------------------------------*/ -/** - * \brief Reset the ADXL346 sensor - */ -void adxl346_reset(void); +#define ADXL346_SENSOR "ADXL346 Sensor" /*---------------------------------------------------------------------------*/ -/** - * \brief Check if the ADXL346 sensor is present - */ -uint8_t adxl346_is_present(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the x-axis from the ADXL346 sensor - */ -uint16_t adxl346_read_x(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the y-axis from the ADXL346 sensor - */ -uint16_t adxl346_read_y(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the z-axis from the ADXL346 sensor - */ -uint16_t adxl346_read_z(void); +extern const struct sensors_sensor adxl346; /*---------------------------------------------------------------------------*/ #endif /* ADXL346_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/openmote-cc2538/dev/max44009.c b/platform/openmote-cc2538/dev/max44009.c index 233b07d13..d7f4e90d9 100644 --- a/platform/openmote-cc2538/dev/max44009.c +++ b/platform/openmote-cc2538/dev/max44009.c @@ -43,6 +43,14 @@ /*---------------------------------------------------------------------------*/ #include "dev/i2c.h" #include "dev/max44009.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif /*---------------------------------------------------------------------------*/ /** * \name MAX44009 address and device identifier @@ -94,9 +102,17 @@ MAX44009_CONFIG_AUTO | \ MAX44009_CONFIG_CDR_NORMAL | \ MAX44009_CONFIG_INTEGRATION_100ms) + +#define MAX44009_USER_CONFIGURATION (MAX44009_CONFIG_DEFAULT | \ + MAX44009_CONFIG_AUTO | \ + MAX44009_CONFIG_CDR_NORMAL | \ + MAX44009_CONFIG_INTEGRATION_800ms) + /** @} */ /*---------------------------------------------------------------------------*/ -void +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void max44009_init(void) { uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \ @@ -106,8 +122,8 @@ max44009_init(void) uint8_t max44009_data[2]; uint8_t i; - max44009_value[0] = (MAX44009_INT_STATUS_ON); - max44009_value[1] = (MAX44009_DEFAULT_CONFIGURATION); + max44009_value[0] = (MAX44009_INT_STATUS_OFF); + max44009_value[1] = (MAX44009_USER_CONFIGURATION); max44009_value[2] = (0xFF); max44009_value[3] = (0x00); max44009_value[4] = (0xFF); @@ -119,7 +135,7 @@ max44009_init(void) } } /*---------------------------------------------------------------------------*/ -void +static void max44009_reset(void) { uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \ @@ -136,7 +152,7 @@ max44009_reset(void) } } /*---------------------------------------------------------------------------*/ -uint8_t +static uint8_t max44009_is_present(void) { uint8_t status; @@ -151,12 +167,12 @@ max44009_is_present(void) return is_present != MAX44009_NOT_FOUND; } /*---------------------------------------------------------------------------*/ -uint16_t +static uint16_t max44009_read_light(void) { uint8_t exponent, mantissa; uint8_t max44009_data[2]; - uint16_t result; + uint32_t result; i2c_single_send(MAX44009_ADDRESS, MAX44009_LUX_HIGH_ADDR); i2c_single_receive(MAX44009_ADDRESS, &max44009_data[0]); @@ -171,20 +187,77 @@ max44009_read_light(void) return result; } /*---------------------------------------------------------------------------*/ -float +static uint16_t max44009_convert_light(uint16_t lux) { uint8_t exponent, mantissa; - float result = 0.045; + uint32_t result; exponent = (lux >> 8) & 0xFF; exponent = (exponent == 0x0F ? exponent & 0x0E : exponent); - mantissa = (lux >> 0) & 0xFF; - result *= 2 ^ exponent * mantissa; + result = 45 * (2 ^ exponent * mantissa) / 10; - return result; + return (uint16_t)result; } /*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t value; + + if(!enabled) { + PRINTF("MAX44009: sensor not started\n"); + return MAX44009_ERROR; + } + + if(type == MAX44009_READ_RAW_LIGHT) { + return max44009_read_light(); + } else if(type == MAX44009_READ_LIGHT) { + value = max44009_read_light(); + return max44009_convert_light(value); + } else { + PRINTF("MAX44009: invalid value requested\n"); + return MAX44009_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == MAX44009_ACTIVATE) { + if(!max44009_is_present()) { + return MAX44009_ERROR; + } else { + max44009_init(); + enabled = 1; + return MAX44009_SUCCESS; + } + } + + if((type == MAX44009_RESET) && enabled) { + max44009_reset(); + return MAX44009_SUCCESS; + } else { + PRINTF("MAX44009: is not enabled\n"); + return MAX44009_ERROR; + } + + return MAX44009_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(max44009, MAX44009_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/openmote-cc2538/dev/max44009.h b/platform/openmote-cc2538/dev/max44009.h index e94a91fca..32ba101e8 100644 --- a/platform/openmote-cc2538/dev/max44009.h +++ b/platform/openmote-cc2538/dev/max44009.h @@ -47,30 +47,17 @@ #ifndef MAX44009_H_ #define MAX44009_H_ /*---------------------------------------------------------------------------*/ -/** - * \brief Initialize the MAX44009 sensor - */ -void max44009_init(void); +#define MAX44009_ERROR (-1) +#define MAX44009_SUCCESS (0) +#define MAX44009_ACTIVATE (SENSORS_ACTIVE) +#define MAX44009_READ_RAW_LIGHT (2) +#define MAX44009_READ_LIGHT (3) +#define MAX44009_RESET (4) +#define MAX44009_NONE (5) /*---------------------------------------------------------------------------*/ -/** - * \brief Reset the MAX44009 sensor - */ -void max44009_reset(void); +#define MAX44009_SENSOR "MAX44009 Sensor" /*---------------------------------------------------------------------------*/ -/** - * \brief Check if the MAX44009 sensor is present - */ -uint8_t max44009_is_present(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the light from the MAX44009 sensor - */ -uint16_t max44009_read_light(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Convert the light from the MAX44009 sensor - */ -float max44009_convert_light(uint16_t light); +extern const struct sensors_sensor max44009; /*---------------------------------------------------------------------------*/ #endif /* MAX44009_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/openmote-cc2538/dev/sht21.c b/platform/openmote-cc2538/dev/sht21.c index 989fe2905..4fd577e01 100644 --- a/platform/openmote-cc2538/dev/sht21.c +++ b/platform/openmote-cc2538/dev/sht21.c @@ -41,8 +41,16 @@ * Pere Tuset */ /*---------------------------------------------------------------------------*/ -#include "i2c.h" -#include "sht21.h" +#include "dev/i2c.h" +#include "dev/sht21.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif /*---------------------------------------------------------------------------*/ /** * \name SHT21 address @@ -87,13 +95,15 @@ SHT21_BATTERY_ABOVE_2V25 | \ SHT21_OTP_RELOAD_DISABLE) -#define SHT21_USER_CONFIG (SHT21_RESOLUTION_8b_12b | \ +#define SHT21_USER_CONFIG (SHT21_RESOLUTION_12b_14b | \ SHT21_ONCHIP_HEATER_DISABLE | \ SHT21_BATTERY_ABOVE_2V25 | \ SHT21_OTP_RELOAD_DISABLE) /** @} */ /*---------------------------------------------------------------------------*/ -void +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void sht21_init(void) { uint8_t config[2]; @@ -116,14 +126,14 @@ sht21_init(void) i2c_burst_send(SHT21_ADDRESS, config, sizeof(config)); } /*---------------------------------------------------------------------------*/ -void +static void sht21_reset(void) { /* Send a soft-reset command according to the datasheet (pag. 9, fig. 17) */ i2c_single_send(SHT21_ADDRESS, SHT21_RESET_CMD); } /*---------------------------------------------------------------------------*/ -uint8_t +static uint8_t sht21_is_present(void) { uint8_t status; @@ -142,7 +152,7 @@ sht21_is_present(void) return (is_present == SHT21_USER_CONFIG) || (is_present == SHT21_DEFAULT_CONFIG); } /*---------------------------------------------------------------------------*/ -uint16_t +static uint32_t sht21_read_temperature(void) { uint8_t sht21_temperature[2]; @@ -152,23 +162,24 @@ sht21_read_temperature(void) i2c_single_send(SHT21_ADDRESS, SHT21_TEMPERATURE_HM_CMD); i2c_burst_receive(SHT21_ADDRESS, sht21_temperature, sizeof(sht21_temperature)); - temperature = (sht21_temperature[0] << 8) | (sht21_temperature[1] & SHT21_STATUS_MASK); + temperature = (sht21_temperature[0] << 8) | ((sht21_temperature[1] & SHT21_STATUS_MASK)); return temperature; } /*---------------------------------------------------------------------------*/ -float -sht21_convert_temperature(uint16_t temperature) +static int16_t +sht21_convert_temperature(uint32_t temperature) { - float result; + int16_t result; - result = -46.85; - result += 175.72 * (float)temperature / 65536.0; + temperature *= 17572; + temperature = temperature >> 16; + result = (int16_t)temperature - 4685; return result; } /*---------------------------------------------------------------------------*/ -uint16_t +static uint32_t sht21_read_humidity(void) { uint8_t sht21_humidity[2]; @@ -178,20 +189,86 @@ sht21_read_humidity(void) i2c_single_send(SHT21_ADDRESS, SHT21_HUMIDITY_HM_CMD); i2c_burst_receive(SHT21_ADDRESS, sht21_humidity, sizeof(sht21_humidity)); - humidity = (sht21_humidity[0] << 8) | (sht21_humidity[1] & SHT21_STATUS_MASK); + humidity = (sht21_humidity[0] << 8) | ((sht21_humidity[1] & SHT21_STATUS_MASK)); return humidity; } /*---------------------------------------------------------------------------*/ -float -sht21_convert_humidity(uint16_t humidity) +static int16_t +sht21_convert_humidity(uint32_t humidity) { - float result; + int16_t result; - result = -6.0; - result += 125.0 * (float)humidity / 65536.0; + humidity *= 12500; + humidity = humidity >> 16; + result = (int16_t)humidity - 600; + result = (result > 10000) ? 10000 : result; return result; } /*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint32_t value; + + if(!enabled) { + PRINTF("SHT21: sensor not started\n"); + return SHT21_ERROR; + } + + if(type == SHT21_READ_RAW_TEMP) { + return sht21_read_temperature(); + } else if(type == SHT21_READ_RAW_RHUM) { + return sht21_read_humidity(); + } else if(type == SHT21_READ_TEMP) { + value = sht21_read_temperature(); + return sht21_convert_temperature(value); + } else if(type == SHT21_READ_RHUM) { + value = sht21_read_humidity(); + return sht21_convert_humidity(value); + } else { + PRINTF("SHT21: invalid value requested\n"); + return SHT21_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == SHT21_ACTIVATE) { + if(!sht21_is_present()) { + PRINTF("SHT21: is not present\n"); + return SHT21_ERROR; + } else { + sht21_init(); + enabled = 1; + return SHT21_SUCCESS; + } + } + + if(type == SHT21_RESET && enabled) { + sht21_reset(); + return SHT21_SUCCESS; + } else { + PRINTF("SHT21: is not enabled\n"); + return SHT21_ERROR; + } + + return SHT21_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(sht21, SHT21_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/openmote-cc2538/dev/sht21.h b/platform/openmote-cc2538/dev/sht21.h index 1483a70a9..3304d915e 100644 --- a/platform/openmote-cc2538/dev/sht21.h +++ b/platform/openmote-cc2538/dev/sht21.h @@ -47,40 +47,19 @@ #ifndef SHT21_H_ #define SHT21_H_ /*---------------------------------------------------------------------------*/ -/** - * \brief Initialize the SHT21 sensor - */ -void sht21_init(void); +#define SHT21_ERROR (-1) +#define SHT21_SUCCESS (0) +#define SHT21_ACTIVATE (SENSORS_ACTIVE) +#define SHT21_READ_RAW_TEMP (2) +#define SHT21_READ_RAW_RHUM (3) +#define SHT21_READ_TEMP (4) +#define SHT21_READ_RHUM (5) +#define SHT21_RESET (6) +#define SHT21_NONE (7) /*---------------------------------------------------------------------------*/ -/** - * \brief Reset the SHT21 sensor - */ -void sht21_reset(void); +#define SHT21_SENSOR "SHT21 Sensor" /*---------------------------------------------------------------------------*/ -/** - * \brief Check if the SHT21 sensor is present - */ -uint8_t sht21_is_present(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the temperature from the SHT21 sensor - */ -uint16_t sht21_read_temperature(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Convert the temperature from the SHT21 sensor - */ -float sht21_convert_temperature(uint16_t temperature); -/*---------------------------------------------------------------------------*/ -/** - * \brief Read the relative humidity from the SHT21 sensor - */ -uint16_t sht21_read_humidity(void); -/*---------------------------------------------------------------------------*/ -/** - * \brief Convert the relative humidity from the SHT21 sensor - */ -float sht21_convert_humidity(uint16_t humidity); +extern const struct sensors_sensor sht21; /*---------------------------------------------------------------------------*/ #endif /* SHT21_H_ */ /*---------------------------------------------------------------------------*/ From 186138f6af940877dea8e6824f9e24d2247ef8f4 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 4 Mar 2016 14:20:23 +0100 Subject: [PATCH 46/80] added error check for extraction of aligned llao --- core/net/ipv6/uip-nd6.c | 36 +++++++++++++----------------------- core/net/nbr-table.c | 3 +-- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index d160392ed..218507228 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -135,11 +135,13 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER /*------------------------------------------------------------------*/ /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */ -static void +static int extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) { if(dest != NULL && nd6_opt_llao != NULL) { memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); + return 1; } + return 0; } #endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ /*------------------------------------------------------------------*/ @@ -203,14 +205,8 @@ ns_input(void) extract_lladdr_from_llao_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { -<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a - uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); -======= - uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); ->>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); if(lladdr == NULL) { @@ -440,6 +436,7 @@ na_input(void) uint8_t is_router; uint8_t is_solicited; uint8_t is_override; + uip_lladdr_t lladdr_aligned; PRINTF("Received NA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); @@ -517,12 +514,9 @@ na_input(void) UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { - uip_lladdr_t lladdr_aligned; - if(nd6_opt_llao == NULL) { + if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) { goto discard; } - - extract_lladdr_from_llao_aligned(&lladdr_aligned); if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { /* failed to update the lladdr */ goto discard; @@ -552,9 +546,8 @@ na_input(void) */ if(is_override || !is_llchange || nd6_opt_llao == NULL) { if(nd6_opt_llao != NULL && is_llchange) { - uip_lladdr_t lladdr_aligned; - extract_lladdr_from_llao_aligned(&lladdr_aligned); - if(nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) { + if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) || + nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) { /* failed to update the lladdr */ goto discard; } @@ -854,6 +847,8 @@ uip_nd6_rs_output(void) void ra_input(void) { + uip_lladdr_t lladdr_aligned; + PRINTF("Received RA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); @@ -898,19 +893,14 @@ ra_input(void) PRINTF("Processing SLLAO option in RA\n"); nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF; nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); + if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) { + /* failed to extract llao - discard packet */ + goto discard; + } if(nbr == NULL) { - uip_lladdr_t lladdr_aligned; -<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a - extract_lladdr_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); -======= - extract_lladdr_from_llao_aligned(&lladdr_aligned); - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE); ->>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { - uip_lladdr_t lladdr_aligned; - extract_lladdr_from_llao_aligned(&lladdr_aligned); const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); if(lladdr == NULL) { goto discard; diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index 4a3518475..4893a99ca 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -195,9 +195,8 @@ remove_key(nbr_table_key_t *least_used_key) used_map[index_from_key(least_used_key)] = 0; /* Remove neighbor from list */ list_remove(nbr_table_keys, least_used_key); - /* Return associated key */ } - +/*---------------------------------------------------------------------------*/ static nbr_table_key_t * nbr_table_allocate(nbr_table_reason_t reason, void *data) { From 70d94133ea2fc6b3050932886aacd53a6d9514e4 Mon Sep 17 00:00:00 2001 From: Pere Tuset Date: Mon, 25 Apr 2016 01:50:23 +0200 Subject: [PATCH 47/80] Updated OpenMote example and platform. --- examples/openmote-cc2538/openmote-demo.c | 20 +++-- platform/openmote-cc2538/dev/adxl346.c | 100 ++++++++++++++++++++--- platform/openmote-cc2538/dev/adxl346.h | 10 ++- 3 files changed, 109 insertions(+), 21 deletions(-) diff --git a/examples/openmote-cc2538/openmote-demo.c b/examples/openmote-cc2538/openmote-demo.c index 46a301511..393203a0c 100644 --- a/examples/openmote-cc2538/openmote-demo.c +++ b/examples/openmote-cc2538/openmote-demo.c @@ -85,25 +85,29 @@ PROCESS_THREAD(openmote_demo_process, ev, data) static struct etimer et; static int16_t counter; static uint16_t adxl346_present, sht21_present, max44009_present; - static uint16_t accel, light, temperature, humidity; + static int16_t accel, light, temperature, humidity; PROCESS_EXITHANDLER(broadcast_close(&bc)) PROCESS_BEGIN(); - /* Initialize and activate the ADXL346 sensor */ + /* Initialize and calibrate the ADXL346 sensor */ adxl346_present = SENSORS_ACTIVATE(adxl346); if(adxl346_present == ADXL346_ERROR) { printf("ADXL346 sensor is NOT present!\n"); leds_on(LEDS_YELLOW); + } else { + adxl346.configure(ADXL346_CALIB_OFFSET, 0); } + /* Initialize the MAX44009 sensor */ max44009_present = SENSORS_ACTIVATE(max44009); if(max44009_present == MAX44009_ERROR) { printf("MAX44009 sensor is NOT present!\n"); leds_on(LEDS_ORANGE); } + /* Initialize the SHT21 sensor */ sht21_present = SENSORS_ACTIVATE(sht21); if(sht21_present == SHT21_ERROR) { printf("SHT21 sensor is NOT present!\n"); @@ -123,12 +127,12 @@ PROCESS_THREAD(openmote_demo_process, ev, data) if(ev == PROCESS_EVENT_TIMER) { if(adxl346_present != ADXL346_ERROR) { leds_on(LEDS_YELLOW); - accel = adxl346.value(ADXL346_READ_X); - printf("X Acceleration: %u\n", accel); - accel = adxl346.value(ADXL346_READ_Y); - printf("Y Acceleration: %u\n", accel); - accel = adxl346.value(ADXL346_READ_Z); - printf("Z Acceleration: %u\n", accel); + accel = adxl346.value(ADXL346_READ_X_mG); + printf("X Acceleration: %d.%u G\n", accel / 1000, accel % 1000); + accel = adxl346.value(ADXL346_READ_Y_mG); + printf("Y Acceleration: %d.%u G\n", accel / 1000, accel % 1000); + accel = adxl346.value(ADXL346_READ_Z_mG); + printf("Z Acceleration: %d.%u G\n", accel / 1000, accel % 1000); leds_off(LEDS_YELLOW); } diff --git a/platform/openmote-cc2538/dev/adxl346.c b/platform/openmote-cc2538/dev/adxl346.c index 7fb406051..09d725474 100644 --- a/platform/openmote-cc2538/dev/adxl346.c +++ b/platform/openmote-cc2538/dev/adxl346.c @@ -153,6 +153,9 @@ #define ADXL346_DATA_FORMAT_RANGE_PM_4g (1) #define ADXL346_DATA_FORMAT_RANGE_PM_8g (2) #define ADXL346_DATA_FORMAT_RANGE_PM_16g (3) + +#define ADXL346_USER_CONFIGURATION (ADXL346_DATA_FORMAT_RANGE_PM_2g) + /** @} */ /*---------------------------------------------------------------------------*/ static uint8_t enabled; @@ -163,13 +166,11 @@ adxl346_init(void) uint8_t config[2]; config[0] = ADXL346_BW_RATE_ADDR; - config[1] = (ADXL346_BW_RATE_RATE(11)); + config[1] = (ADXL346_BW_RATE_RATE(6)); i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); config[0] = ADXL346_DATA_FORMAT_ADDR; - config[1] = (ADXL346_DATA_FORMAT_SELF_TEST | - ADXL346_DATA_FORMAT_FULL_RES | - ADXL346_DATA_FORMAT_RANGE_PM_16g); + config[1] = (ADXL346_USER_CONFIGURATION); i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); config[0] = ADXL346_POWER_CTL_ADDR; @@ -185,23 +186,86 @@ adxl346_is_present(void) i2c_single_send(ADXL346_ADDRESS, ADXL346_DEVID_ADDR); i2c_single_receive(ADXL346_ADDRESS, &is_present); - return is_present == ADXL346_DEVID_VALUE; + return (is_present == ADXL346_DEVID_VALUE); } /*---------------------------------------------------------------------------*/ -static uint16_t +static int16_t adxl346_read_accel(uint8_t addr1, uint8_t addr2) { uint8_t acceleration[2]; - uint16_t z; + int16_t result; i2c_single_send(ADXL346_ADDRESS, addr1); i2c_single_receive(ADXL346_ADDRESS, &acceleration[0]); i2c_single_send(ADXL346_ADDRESS, addr2); i2c_single_receive(ADXL346_ADDRESS, &acceleration[1]); - z = (acceleration[0] << 8) | acceleration[1]; + result = (acceleration[1] << 8) | acceleration[0]; + + return result; +} +/*---------------------------------------------------------------------------*/ +static int16_t +adxl346_convert_accel(int16_t accel) +{ + int32_t result; + + result = (1000 * accel) / 256; + + return (int16_t) result; +} +/*---------------------------------------------------------------------------*/ +static void +adxl346_calibrate_offset(void) +{ + int32_t accum_x = 0; + int32_t accum_y = 0; + int32_t accum_z = 0; + uint8_t config[2]; + int8_t offset; + + config[0] = ADXL346_OFSX_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + config[0] = ADXL346_OFSY_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + config[0] = ADXL346_OFSZ_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + + uint16_t i; + for (i = 0; i < 100; i++) { + uint16_t x, y, z; + + x = adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + accum_x += x; + + y = adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + accum_y += y; + + z = adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + accum_z += z; + } + + offset = (64 * accum_x) / 25600; + config[0] = ADXL346_OFSX_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: X calibration offset is %d\n", offset); + + offset = (64 * accum_y) / 25600; + config[0] = ADXL346_OFSY_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: Y calibration offset is %d\n", offset); + + offset = (64 * accum_z) / 25600; + config[0] = ADXL346_OFSZ_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: Z calibration offset is %d\n", offset); - return z; } /*---------------------------------------------------------------------------*/ static int @@ -218,6 +282,7 @@ status(int type) static int value(int type) { + int16_t accel; if(!enabled) { PRINTF("ADXL346: sensor not started\n"); return ADXL346_ERROR; @@ -225,10 +290,19 @@ value(int type) if(type == ADXL346_READ_X) { return adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); - } else if(type == ADXL346_READ_Y) { + } else if(type == ADXL346_READ_Y) { return adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); } else if(type == ADXL346_READ_Z) { return adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + } else if(type == ADXL346_READ_X_mG) { + accel = adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + return adxl346_convert_accel(accel); + } else if(type == ADXL346_READ_Y_mG) { + accel = adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + return adxl346_convert_accel(accel); + } else if(type == ADXL346_READ_Z_mG) { + accel = adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + return adxl346_convert_accel(accel); } else { PRINTF("ADXL346: invalid value requested\n"); return ADXL346_ERROR; @@ -243,6 +317,7 @@ configure(int type, int value) if(type == ADXL346_ACTIVATE) { if(!adxl346_is_present()) { PRINTF("ADXL346: is not present\n"); + enabled = 0; return ADXL346_ERROR; } else { adxl346_init(); @@ -251,6 +326,11 @@ configure(int type, int value) } } + if(type == ADXL346_CALIB_OFFSET && enabled) { + adxl346_calibrate_offset(); + return ADXL346_SUCCESS; + } + return ADXL346_ERROR; } /*---------------------------------------------------------------------------*/ diff --git a/platform/openmote-cc2538/dev/adxl346.h b/platform/openmote-cc2538/dev/adxl346.h index acd0d21f5..401e601d1 100644 --- a/platform/openmote-cc2538/dev/adxl346.h +++ b/platform/openmote-cc2538/dev/adxl346.h @@ -51,9 +51,13 @@ #define ADXL346_SUCCESS (0) #define ADXL346_ACTIVATE (SENSORS_ACTIVE) #define ADXL346_READ_X (2) -#define ADXL346_READ_Y (3) -#define ADXL346_READ_Z (4) -#define ADXL346_NONE (5) +#define ADXL346_READ_X_mG (3) +#define ADXL346_READ_Y (4) +#define ADXL346_READ_Y_mG (5) +#define ADXL346_READ_Z (6) +#define ADXL346_READ_Z_mG (7) +#define ADXL346_CALIB_OFFSET (8) +#define ADXL346_NONE (9) /*---------------------------------------------------------------------------*/ #define ADXL346_SENSOR "ADXL346 Sensor" /*---------------------------------------------------------------------------*/ From abf08a71676f2f2935dfb3515db2246a9483b07e Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Wed, 20 Apr 2016 11:45:54 +0200 Subject: [PATCH 48/80] Added net-debug.[ch] to provide debug functions even in the non-IP case --- core/net/ip/uip-debug.c | 18 +----- core/net/ip/uip-debug.h | 38 ++--------- core/net/mac/frame802154e-ie.c | 2 +- core/net/mac/tsch/tsch-log.c | 2 +- core/net/mac/tsch/tsch-packet.c | 2 +- core/net/mac/tsch/tsch-queue.c | 2 +- core/net/mac/tsch/tsch-rpl.c | 2 +- core/net/mac/tsch/tsch-schedule.c | 2 +- core/net/mac/tsch/tsch-security.c | 2 +- core/net/mac/tsch/tsch-slot-operation.c | 2 +- core/net/mac/tsch/tsch.c | 2 +- core/net/net-debug.c | 65 +++++++++++++++++++ core/net/net-debug.h | 86 +++++++++++++++++++++++++ platform/cc2530dk/uip-debug.c | 12 ---- platform/mbxxx/contiki-main.c | 2 +- 15 files changed, 166 insertions(+), 73 deletions(-) create mode 100644 core/net/net-debug.c create mode 100644 core/net/net-debug.h diff --git a/core/net/ip/uip-debug.c b/core/net/ip/uip-debug.c index ab3ba0765..7804ba4db 100644 --- a/core/net/ip/uip-debug.c +++ b/core/net/ip/uip-debug.c @@ -30,7 +30,7 @@ /** * \file - * A set of debugging tools + * A set of debugging tools for the IP stack * \author * Nicolas Tsiftes * Niclas Finne @@ -92,19 +92,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr) #endif /* NETSTACK_CONF_WITH_IPV6 */ } /*---------------------------------------------------------------------------*/ -void -uip_debug_lladdr_print(const uip_lladdr_t *addr) -{ - unsigned int i; - if(addr == NULL) { - PRINTA("(NULL LL addr)"); - return; - } - for(i = 0; i < sizeof(uip_lladdr_t); i++) { - if(i > 0) { - PRINTA(":"); - } - PRINTA("%02x", addr->addr[i]); - } -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip/uip-debug.h b/core/net/ip/uip-debug.h index 6ffc1e638..d8e238fe4 100644 --- a/core/net/ip/uip-debug.h +++ b/core/net/ip/uip-debug.h @@ -31,57 +31,27 @@ */ /** * \file - * A set of debugging macros. + * A set of debugging macros for the IP stack * * \author Nicolas Tsiftes * Niclas Finne * Joakim Eriksson + * Simon Duquennoy */ #ifndef UIP_DEBUG_H #define UIP_DEBUG_H +#include "net/net-debug.h" #include "net/ip/uip.h" #include void uip_debug_ipaddr_print(const uip_ipaddr_t *addr); -void uip_debug_lladdr_print(const uip_lladdr_t *addr); - -#define DEBUG_NONE 0 -#define DEBUG_PRINT 1 -#define DEBUG_ANNOTATE 2 -#define DEBUG_FULL DEBUG_ANNOTATE | DEBUG_PRINT - -/* PRINTA will always print if the debug routines are called directly */ -#ifdef __AVR__ -#include -#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define PRINTA(...) printf(__VA_ARGS__) -#endif - -#if (DEBUG) & DEBUG_ANNOTATE -#ifdef __AVR__ -#define ANNOTATE(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define ANNOTATE(...) printf(__VA_ARGS__) -#endif -#else -#define ANNOTATE(...) -#endif /* (DEBUG) & DEBUG_ANNOTATE */ #if (DEBUG) & DEBUG_PRINT -#ifdef __AVR__ -#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define PRINTF(...) printf(__VA_ARGS__) -#endif #define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) -#define PRINTLLADDR(lladdr) uip_debug_lladdr_print(lladdr) #else -#define PRINTF(...) #define PRINT6ADDR(addr) -#define PRINTLLADDR(lladdr) #endif /* (DEBUG) & DEBUG_PRINT */ -#endif +#endif /* UIP_DEBUG_H */ diff --git a/core/net/mac/frame802154e-ie.c b/core/net/mac/frame802154e-ie.c index 55c397631..db0118889 100644 --- a/core/net/mac/frame802154e-ie.c +++ b/core/net/mac/frame802154e-ie.c @@ -41,7 +41,7 @@ #include "net/mac/frame802154e-ie.h" #define DEBUG DEBUG_NONE -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* c.f. IEEE 802.15.4e Table 4b */ enum ieee802154e_header_ie_id { diff --git a/core/net/mac/tsch/tsch-log.c b/core/net/mac/tsch/tsch-log.c index bfb033e9d..8473648a6 100644 --- a/core/net/mac/tsch/tsch-log.c +++ b/core/net/mac/tsch/tsch-log.c @@ -56,7 +56,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" #if TSCH_LOG_LEVEL >= 2 /* Skip this file for log levels 0 or 1 */ diff --git a/core/net/mac/tsch/tsch-packet.c b/core/net/mac/tsch/tsch-packet.c index 9f9a8e107..17601d054 100644 --- a/core/net/mac/tsch/tsch-packet.c +++ b/core/net/mac/tsch/tsch-packet.c @@ -60,7 +60,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /*---------------------------------------------------------------------------*/ /* Construct enhanced ACK packet and return ACK length */ diff --git a/core/net/mac/tsch/tsch-queue.c b/core/net/mac/tsch/tsch-queue.c index 1fdf04232..e3f60f45c 100644 --- a/core/net/mac/tsch/tsch-queue.c +++ b/core/net/mac/tsch/tsch-queue.c @@ -61,7 +61,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */ #if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0 diff --git a/core/net/mac/tsch/tsch-rpl.c b/core/net/mac/tsch/tsch-rpl.c index 772c886b3..960f757f6 100644 --- a/core/net/mac/tsch/tsch-rpl.c +++ b/core/net/mac/tsch/tsch-rpl.c @@ -51,7 +51,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /*---------------------------------------------------------------------------*/ /* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */ diff --git a/core/net/mac/tsch/tsch-schedule.c b/core/net/mac/tsch/tsch-schedule.c index e0028c492..0a61b5f12 100644 --- a/core/net/mac/tsch/tsch-schedule.c +++ b/core/net/mac/tsch/tsch-schedule.c @@ -60,7 +60,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Pre-allocated space for links */ MEMB(link_memb, struct tsch_link, TSCH_SCHEDULE_MAX_LINKS); diff --git a/core/net/mac/tsch/tsch-security.c b/core/net/mac/tsch/tsch-security.c index e7439c519..6d862e19e 100644 --- a/core/net/mac/tsch/tsch-security.c +++ b/core/net/mac/tsch/tsch-security.c @@ -58,7 +58,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* The two keys K1 and K2 from 6TiSCH minimal configuration * K1: well-known, used for EBs diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index 03905617e..e7100c0ed 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -59,7 +59,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH * timeslot events */ diff --git a/core/net/mac/tsch/tsch.c b/core/net/mac/tsch/tsch.c index 442323abc..2085f39ff 100644 --- a/core/net/mac/tsch/tsch.c +++ b/core/net/mac/tsch/tsch.c @@ -64,7 +64,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Use to collect link statistics even on Keep-Alive, even though they were * not sent from an upper layer and don't have a valid packet_sent callback */ diff --git a/core/net/net-debug.c b/core/net/net-debug.c new file mode 100644 index 000000000..8dd630666 --- /dev/null +++ b/core/net/net-debug.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A set of debugging tools for the IP stack + * \author + * Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + * Simon Duquennoy + */ + +#include "net/net-debug.h" + +/*---------------------------------------------------------------------------*/ +void +net_debug_lladdr_print(const uip_lladdr_t *addr) +{ + if(addr == NULL) { + PRINTA("(NULL LL addr)"); + return; + } else { +#if NETSTACK_CONF_WITH_RIME + /* Rime uses traditionally a %u.%u format */ + PRINTA("%u.%u", addr->addr[0], addr->addr[1]); +#else /* NETSTACK_CONF_WITH_RIME */ + unsigned int i; + for(i = 0; i < LINKADDR_SIZE; i++) { + if(i > 0) { + PRINTA(":"); + } + PRINTA("%02x", addr->addr[i]); + } +#endif /* NETSTACK_CONF_WITH_RIME */ + } +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/net-debug.h b/core/net/net-debug.h new file mode 100644 index 000000000..a4c6a3313 --- /dev/null +++ b/core/net/net-debug.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/** + * \file + * A set of debugging macros for the netstack + * + * \author Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + * Simon Duquennoy + */ + +#ifndef NET_DEBUG_H +#define NET_DEBUG_H + +#include "net/ip/uip.h" +#include "net/linkaddr.h" +#include + +void net_debug_lladdr_print(const uip_lladdr_t *addr); + +#define DEBUG_NONE 0 +#define DEBUG_PRINT 1 +#define DEBUG_ANNOTATE 2 +#define DEBUG_FULL DEBUG_ANNOTATE | DEBUG_PRINT + +/* PRINTA will always print if the debug routines are called directly */ +#ifdef __AVR__ +#include +#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) printf(__VA_ARGS__) +#endif + +#if (DEBUG) & DEBUG_ANNOTATE +#ifdef __AVR__ +#define ANNOTATE(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define ANNOTATE(...) printf(__VA_ARGS__) +#endif +#else +#define ANNOTATE(...) +#endif /* (DEBUG) & DEBUG_ANNOTATE */ + +#if (DEBUG) & DEBUG_PRINT +#ifdef __AVR__ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTF(...) printf(__VA_ARGS__) +#endif +#define PRINTLLADDR(lladdr) net_debug_lladdr_print(lladdr) +#else +#define PRINTF(...) +#define PRINTLLADDR(lladdr) +#endif /* (DEBUG) & DEBUG_PRINT */ + +#endif /* NET_DEBUG_H */ diff --git a/platform/cc2530dk/uip-debug.c b/platform/cc2530dk/uip-debug.c index 5f5b23ca8..1a1660e65 100644 --- a/platform/cc2530dk/uip-debug.c +++ b/platform/cc2530dk/uip-debug.c @@ -68,15 +68,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr) #endif /* NETSTACK_CONF_WITH_IPV6 */ } /*---------------------------------------------------------------------------*/ -void -uip_debug_lladdr_print(const uip_lladdr_t *addr) -{ - unsigned int i; - for(i = 0; i < sizeof(uip_lladdr_t); i++) { - if(i > 0) { - putstring(":"); - } - puthex(addr->addr[i]); - } -} -/*---------------------------------------------------------------------------*/ diff --git a/platform/mbxxx/contiki-main.c b/platform/mbxxx/contiki-main.c index 700fbb5cc..f1ad1d8d4 100644 --- a/platform/mbxxx/contiki-main.c +++ b/platform/mbxxx/contiki-main.c @@ -179,7 +179,7 @@ main(void) NETSTACK_RDC.channel_check_interval())); printf("802.15.4 PAN ID 0x%x, EUI-%d:", IEEE802154_CONF_PANID, UIP_CONF_LL_802154?64:16); - uip_debug_lladdr_print((const uip_lladdr_t *)&linkaddr_node_addr); + net_debug_lladdr_print((const uip_lladdr_t *)&linkaddr_node_addr); printf(", radio channel %u\n", RF_CHANNEL); procinit_init(); From bb5e5d5c6bdb23c7baf28e981bcdf140f57d0447 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Sat, 23 Apr 2016 00:19:21 +0200 Subject: [PATCH 49/80] TSCH: use RTIMER_CLOCK_DIFF to compute estimated drift, fixing a bug that would occur on 16-bit rtimer platforms --- core/net/mac/tsch/tsch-slot-operation.c | 2 +- core/sys/rtimer.h | 8 +++++--- cpu/arm/aducrf101/aducrf101-contiki.h | 2 +- cpu/mc1322x/contiki-mc1322x-conf.h | 4 ++-- platform/cc2538dk/contiki-conf.h | 4 ++-- platform/cooja/contiki-conf.h | 2 +- platform/galileo/contiki-conf.h | 2 +- platform/jn516x/platform-conf.h | 4 ++-- platform/mbxxx/platform-conf.h | 2 +- platform/openmote-cc2538/contiki-conf.h | 4 ++-- platform/seedeye/contiki-conf.h | 2 +- platform/srf06-cc26xx/contiki-conf.h | 4 ++-- platform/stm32nucleo-spirit1/platform-conf.h | 2 +- platform/zoul/contiki-conf.h | 4 ++-- 14 files changed, 24 insertions(+), 22 deletions(-) diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index 03905617e..55fc06a24 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -737,7 +737,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) if(linkaddr_cmp(&destination_address, &linkaddr_node_addr) || linkaddr_cmp(&destination_address, &linkaddr_null)) { int do_nack = 0; - estimated_drift = ((int32_t)expected_rx_time - (int32_t)rx_start_time); + estimated_drift = RTIMER_CLOCK_DIFF(expected_rx_time, rx_start_time); #if TSCH_TIMESYNC_REMOVE_JITTER /* remove jitter due to measurement errors */ diff --git a/core/sys/rtimer.h b/core/sys/rtimer.h index 91c23b932..a89ed8299 100644 --- a/core/sys/rtimer.h +++ b/core/sys/rtimer.h @@ -55,10 +55,12 @@ #include "contiki-conf.h" -#ifndef RTIMER_CLOCK_LT +#ifndef RTIMER_CLOCK_DIFF typedef unsigned short rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0) -#endif /* RTIMER_CLOCK_LT */ +#define RTIMER_CLOCK_DIFF(a,b) ((signed short)((a)-(b))) +#endif /* RTIMER_CLOCK_DIFF */ + +#define RTIMER_CLOCK_LT(a, b) (RTIMER_CLOCK_DIFF((a),(b)) < 0) #include "rtimer-arch.h" diff --git a/cpu/arm/aducrf101/aducrf101-contiki.h b/cpu/arm/aducrf101/aducrf101-contiki.h index 00fd8765d..4610c49d6 100644 --- a/cpu/arm/aducrf101/aducrf101-contiki.h +++ b/cpu/arm/aducrf101/aducrf101-contiki.h @@ -46,7 +46,7 @@ typedef uint32_t clock_time_t; typedef uint16_t uip_stats_t; typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) rtimer_clock_t rtimer_arch_now(void); #endif diff --git a/cpu/mc1322x/contiki-mc1322x-conf.h b/cpu/mc1322x/contiki-mc1322x-conf.h index e6c65df56..2dfb7e0f1 100644 --- a/cpu/mc1322x/contiki-mc1322x-conf.h +++ b/cpu/mc1322x/contiki-mc1322x-conf.h @@ -55,8 +55,8 @@ typedef unsigned short uip_stats_t; typedef uint32_t clock_time_t; -/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ +/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_DIFF is defined */ typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #endif diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index ad9aafeeb..9d18ec344 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -34,10 +34,10 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/cooja/contiki-conf.h b/platform/cooja/contiki-conf.h index 04f1c4d43..d021ff547 100644 --- a/platform/cooja/contiki-conf.h +++ b/platform/cooja/contiki-conf.h @@ -201,7 +201,7 @@ typedef unsigned short uip_stats_t; #define CLOCK_CONF_SECOND 1000L typedef unsigned long clock_time_t; typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #define AODV_COMPLIANCE #define AODV_NUM_RT_ENTRIES 32 diff --git a/platform/galileo/contiki-conf.h b/platform/galileo/contiki-conf.h index dca42b8de..2d64c440f 100644 --- a/platform/galileo/contiki-conf.h +++ b/platform/galileo/contiki-conf.h @@ -46,7 +46,7 @@ typedef unsigned long clock_time_t; typedef uint64_t rtimer_clock_t; #define RTIMER_ARCH_SECOND 1024 -#define RTIMER_CLOCK_LT(a, b) ((int64_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int64_t)((a) - (b))) /* We define the following macros and types otherwise Contiki does not * compile. diff --git a/platform/jn516x/platform-conf.h b/platform/jn516x/platform-conf.h index c1c372b64..408b4957e 100644 --- a/platform/jn516x/platform-conf.h +++ b/platform/jn516x/platform-conf.h @@ -80,9 +80,9 @@ #define JN516X_EXTERNAL_CRYSTAL_OSCILLATOR (RTIMER_USE_32KHZ || JN516X_SLEEP_ENABLED) #endif /* JN516X_EXTERNAL_CRYSTAL_OSCILLATOR */ -/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ +/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_DIFF is defined */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /* 8ms timer tick */ #define CLOCK_CONF_SECOND 125 diff --git a/platform/mbxxx/platform-conf.h b/platform/mbxxx/platform-conf.h index 6b811ec96..98870980d 100644 --- a/platform/mbxxx/platform-conf.h +++ b/platform/mbxxx/platform-conf.h @@ -87,7 +87,7 @@ typedef unsigned long clock_time_t; typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #define LEDS_CONF_RED_PIN boardDescription->io->leds[1].gpioPin #define LEDS_CONF_GREEN_PIN boardDescription->io->leds[0].gpioPin diff --git a/platform/openmote-cc2538/contiki-conf.h b/platform/openmote-cc2538/contiki-conf.h index 6c0349025..87b58f299 100644 --- a/platform/openmote-cc2538/contiki-conf.h +++ b/platform/openmote-cc2538/contiki-conf.h @@ -73,10 +73,10 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/seedeye/contiki-conf.h b/platform/seedeye/contiki-conf.h index 69c788381..d58ff686d 100644 --- a/platform/seedeye/contiki-conf.h +++ b/platform/seedeye/contiki-conf.h @@ -60,7 +60,7 @@ typedef uint16_t uip_stats_t; typedef uint32_t clock_time_t; typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) #define RF_CHANNEL 13 diff --git a/platform/srf06-cc26xx/contiki-conf.h b/platform/srf06-cc26xx/contiki-conf.h index 79c1d479a..6e52b5c0c 100644 --- a/platform/srf06-cc26xx/contiki-conf.h +++ b/platform/srf06-cc26xx/contiki-conf.h @@ -325,10 +325,10 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /** @} */ /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ diff --git a/platform/stm32nucleo-spirit1/platform-conf.h b/platform/stm32nucleo-spirit1/platform-conf.h index dede0bdeb..0f2a0077b 100644 --- a/platform/stm32nucleo-spirit1/platform-conf.h +++ b/platform/stm32nucleo-spirit1/platform-conf.h @@ -78,7 +78,7 @@ #define CLOCK_CONF_SECOND 128 /* One tick: 62.5 ms */ -#define RTIMER_CLOCK_LT(a, b) ((signed short)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((signed short)((a) - (b))) /*---------------------------------------------------------------------------*/ typedef unsigned long clock_time_t; typedef unsigned long long rtimer_clock_t; diff --git a/platform/zoul/contiki-conf.h b/platform/zoul/contiki-conf.h index 52cd22dfd..50d781832 100644 --- a/platform/zoul/contiki-conf.h +++ b/platform/zoul/contiki-conf.h @@ -71,10 +71,10 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /** @} */ /*---------------------------------------------------------------------------*/ /** From cd5a0ef29156e959f0124edbfe225721f85ec468 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sat, 14 May 2016 19:16:43 +0100 Subject: [PATCH 50/80] Consolidate .upload for all CC26xx/CC13xx boards The block that controls the `.upload` target is unnecessarily replicated in multiple sub-board Makefiles. This was originally done because the SmartRF and the Launchpad can be programmed with the c2538-bsl script, whereas the sensortag cannot. This commit moves the `cc2538-bsl` / `.upload` target logic to the top level cpu Makefile (`cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx`). Board makefiles simply set the make variable `BOARD_SUPPORTS_BSL` to 1 to signal that they can be programmed by the BSL script. If `BOARD_SUPPORTS_BSL` is not equal to 1, trying to use the `.upload` target will return an error message. For example: ``` $ make BOARD=sensortag/cc2650 cc26xx-demo.upload using saved target 'srf06-cc26xx' This board cannot be programmed with the ROM bootloader and therefore does not support the .upload target. ``` --- cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx | 20 +++++++++++++++++++ .../srf06-cc26xx/launchpad/Makefile.launchpad | 17 ++-------------- platform/srf06-cc26xx/srf06/Makefile.srf06 | 17 ++-------------- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index f6ac275da..d0cf1cf31 100644 --- a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -81,6 +81,15 @@ CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) TARGET_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS) TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES))) +PYTHON = python +BSL_FLAGS += -e -w -v + +ifdef PORT + BSL_FLAGS += -p $(PORT) +endif + +BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py + ### Don't treat the .elf as intermediate .PRECIOUS: %.elf %.hex %.bin @@ -125,3 +134,14 @@ STACK_SIZE = 0 @$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM] used %6d, free %6d\n",s,f;}' @$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}' +ifeq ($(BOARD_SUPPORTS_BSL),1) +%.upload: %.bin +ifeq ($(wildcard $(BSL)), ) + @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" +else + $(PYTHON) $(BSL) $(BSL_FLAGS) $< +endif +else +%.upload: + @echo "This board cannot be programmed through the ROM bootloader and therefore does not support the .upload target." +endif diff --git a/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/platform/srf06-cc26xx/launchpad/Makefile.launchpad index 853450142..54bd81ced 100644 --- a/platform/srf06-cc26xx/launchpad/Makefile.launchpad +++ b/platform/srf06-cc26xx/launchpad/Makefile.launchpad @@ -5,18 +5,5 @@ CONTIKI_TARGET_DIRS += launchpad common BOARD_SOURCEFILES += board.c launchpad-sensors.c leds-arch.c button-sensor.c BOARD_SOURCEFILES += ext-flash.c board-spi.c -PYTHON = python -BSL_FLAGS += -e -w -v - -ifdef PORT - BSL_FLAGS += -p $(PORT) -endif - -BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py - -%.upload: %.bin -ifeq ($(wildcard $(BSL)), ) - @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" -else - $(PYTHON) $(BSL) $(BSL_FLAGS) $< -endif +### Signal that we can be programmed with cc2538-bsl +BOARD_SUPPORTS_BSL=1 diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 index 3459cbadc..afdeeddec 100644 --- a/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -4,18 +4,5 @@ CONTIKI_TARGET_DIRS += srf06 BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c -PYTHON = python -BSL_FLAGS += -e -w -v - -ifdef PORT - BSL_FLAGS += -p $(PORT) -endif - -BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py - -%.upload: %.bin -ifeq ($(wildcard $(BSL)), ) - @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" -else - $(PYTHON) $(BSL) $(BSL_FLAGS) $< -endif +### Signal that we can be programmed with cc2538-bsl +BOARD_SUPPORTS_BSL=1 From 099a933c90c27f3b533692db8c3c860a6f393a48 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 13 Mar 2016 13:02:41 +0000 Subject: [PATCH 51/80] Add support for the CC1310 LaunchPad --- .../launchpad/cc1310/Makefile.cc1310 | 8 + .../srf06-cc26xx/launchpad/cc1310/board.h | 189 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 create mode 100644 platform/srf06-cc26xx/launchpad/cc1310/board.h diff --git a/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 b/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 new file mode 100644 index 000000000..8d3d2abd4 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 @@ -0,0 +1,8 @@ +### Will allow the inclusion of the correct CPU makefile +CPU_FAMILY = cc13xx + +### Add to the source dirs +CONTIKI_TARGET_DIRS += launchpad/cc1310 + +### Include the common launchpad makefile +include $(PLATFORM_ROOT_DIR)/launchpad/Makefile.launchpad diff --git a/platform/srf06-cc26xx/launchpad/cc1310/board.h b/platform/srf06-cc26xx/launchpad/cc1310/board.h new file mode 100644 index 000000000..d6cfeeedb --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc1310/board.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/ + * 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. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup launchpad-peripherals + * @{ + * + * \defgroup launchpad-cc1310-specific CC1310 LaunchPad Peripherals + * + * Defines related to the CC1310 LaunchPad + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other peripherals + * + * This file is not meant to be modified by the user. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the TI + * CC1310 LaunchPad + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +/*---------------------------------------------------------------------------*/ +/** + * \name LED configurations + * + * Those values are not meant to be modified by the user + * @{ + */ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 1 +#define LEDS_GREEN 2 +#define LEDS_YELLOW LEDS_GREEN +#define LEDS_ORANGE LEDS_RED + +#define LEDS_CONF_ALL 3 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LED IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LED_1 IOID_6 +#define BOARD_IOID_LED_2 IOID_7 +#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) +#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) +#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name UART IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_UART_RX IOID_2 +#define BOARD_IOID_UART_TX IOID_3 +#define BOARD_IOID_UART_RTS IOID_18 +#define BOARD_IOID_UART_CTS IOID_19 +#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) +#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) +#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) +#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_KEY_LEFT IOID_13 +#define BOARD_IOID_KEY_RIGHT IOID_14 +#define BOARD_KEY_LEFT (1 << BOARD_IOID_KEY_LEFT) +#define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SPI_MOSI IOID_9 +#define BOARD_IOID_SPI_MISO IOID_8 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name External flash IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_FLASH_CS IOID_20 +#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) +#define BOARD_IOID_SPI_CLK_FLASH IOID_10 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief I2C IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SCL IOID_4 +#define BOARD_IOID_SDA IOID_5 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Remaining pins + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_CS IOID_11 +#define BOARD_IOID_TDO IOID_16 +#define BOARD_IOID_TDI IOID_17 +#define BOARD_IOID_DIO12 IOID_12 +#define BOARD_IOID_DIO15 IOID_15 +#define BOARD_IOID_DIO21 IOID_21 +#define BOARD_IOID_DIO22 IOID_22 +#define BOARD_IOID_DIO23 IOID_23 +#define BOARD_IOID_DIO24 IOID_24 +#define BOARD_IOID_DIO25 IOID_25 +#define BOARD_IOID_DIO26 IOID_26 +#define BOARD_IOID_DIO27 IOID_27 +#define BOARD_IOID_DIO28 IOID_28 +#define BOARD_IOID_DIO29 IOID_29 +#define BOARD_IOID_DIO30 IOID_30 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "TI CC1310 LaunchPad" + +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ From 06f446399634219bc90199ad219025efa73bbcba Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 13 Mar 2016 13:03:02 +0000 Subject: [PATCH 52/80] Extend documentation to include the CC1310 LaunchPad --- platform/srf06-cc26xx/README.md | 4 +++- platform/srf06-cc26xx/contiki-main.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/srf06-cc26xx/README.md b/platform/srf06-cc26xx/README.md index 4e709ca7d..04d66a0d4 100644 --- a/platform/srf06-cc26xx/README.md +++ b/platform/srf06-cc26xx/README.md @@ -8,6 +8,7 @@ platform supports two different boards: (relevant files and drivers are under `srf06/`) * CC2650 SensorTag 2.0 (relevant drivers under `sensortag/cc2650`) * CC2650 LaunchPad (relevant drivers under `launchpad/cc2650`) +* CC1310 LaunchPad (relevant drivers under `launchpad/cc1310`) The CPU code, common for both platforms, can be found under `$(CONTIKI)/cpu/cc26xx-cc13xx`. The port was developed and tested with CC2650s, but the intention is for it to @@ -45,7 +46,7 @@ In terms of hardware support, the following drivers have been implemented: * OPT3001 sensor * Buzzer * External SPI flash -* Launchpad +* LaunchPads * LEDs * Buttons * External SPI flash @@ -99,6 +100,7 @@ Other options for the `BOARD` make variable are: * Srf06+CC13xxEM: Set `BOARD=srf06/cc13xx` * CC2650 tag: Set `BOARD=sensortag/cc2650` * CC2650 Launchpad: Set `BOARD=launchpad/cc2650` +* CC1310 Launchpad: Set `BOARD=launchpad/cc1310` If the `BOARD` variable is unspecified, an image for the Srf06 CC26XXEM will be built. diff --git a/platform/srf06-cc26xx/contiki-main.c b/platform/srf06-cc26xx/contiki-main.c index b103918e7..9e91cec5d 100644 --- a/platform/srf06-cc26xx/contiki-main.c +++ b/platform/srf06-cc26xx/contiki-main.c @@ -32,13 +32,14 @@ * \addtogroup cc26xx-platforms * @{ * - * \defgroup cc26xx-srf-tag SmartRF+CC13xx/CC26xx EM, CC2650 SensorTag and LaunchPad + * \defgroup cc26xx-srf-tag SmartRF+CC13xx/CC26xx EM, CC2650 SensorTag and LaunchPads * * This platform supports a number of different boards: * - A standard TI SmartRF06EB with a CC26xx EM mounted on it * - A standard TI SmartRF06EB with a CC1310 EM mounted on it * - The new TI SensorTag2.0 * - The TI CC2650 LaunchPad + * - The TI CC1310 LaunchPad * @{ */ #include "ti-lib.h" From 18f67dade263b9d4c7e9c89258199d3e32888275 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 13 Mar 2016 13:03:17 +0000 Subject: [PATCH 53/80] Compile-test CC1310 LaunchPad sources --- regression-tests/18-compile-arm-ports/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/regression-tests/18-compile-arm-ports/Makefile b/regression-tests/18-compile-arm-ports/Makefile index 4222eb7f6..55924037d 100644 --- a/regression-tests/18-compile-arm-ports/Makefile +++ b/regression-tests/18-compile-arm-ports/Makefile @@ -12,6 +12,7 @@ cc26xx/very-sleepy-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=srf06/cc13xx \ cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc2650 \ +cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1310 \ cc26xx/very-sleepy-demo/srf06-cc26xx \ hello-world/cc2538dk \ ipv6/rpl-border-router/cc2538dk \ From 80efd730ae889b0911df1b8097634ae7eb9bf12c Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sat, 14 May 2016 20:22:11 +0100 Subject: [PATCH 54/80] Extend the flash driver to support the MX25R1635F According to the CC1310LP design files, the flash on it is the same as the flash on the CC2650 LP (MX25R8035F 8Mbit). However, the flash on some CC1310 LPs reportedly identifies itself as the 16Mbit one (MX25R1635F). Instruction sets are identical, we simply need to tell the driver to recognise this part's Device ID. --- platform/srf06-cc26xx/common/ext-flash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/srf06-cc26xx/common/ext-flash.c b/platform/srf06-cc26xx/common/ext-flash.c index 721a36424..62fea2288 100644 --- a/platform/srf06-cc26xx/common/ext-flash.c +++ b/platform/srf06-cc26xx/common/ext-flash.c @@ -40,6 +40,9 @@ #include "ext-flash.h" #include "ti-lib.h" #include "board-spi.h" + +#include +#include /*---------------------------------------------------------------------------*/ /* Instruction codes */ @@ -73,6 +76,7 @@ #define BLS_DEVICE_ID_W25X20CL 0x11 #define BLS_DEVICE_ID_W25X40CL 0x12 #define BLS_DEVICE_ID_MX25R8035F 0x14 +#define BLS_DEVICE_ID_MX25R1635F 0x15 #define BLS_WINBOND_MID 0xEF #define BLS_MACRONIX_MID 0xC2 @@ -179,7 +183,8 @@ verify_part(void) if((rbuf[0] != BLS_WINBOND_MID && rbuf[0] != BLS_MACRONIX_MID) || (rbuf[1] != BLS_DEVICE_ID_W25X20CL && rbuf[1] != BLS_DEVICE_ID_W25X40CL - && rbuf[1] != BLS_DEVICE_ID_MX25R8035F)) { + && rbuf[1] != BLS_DEVICE_ID_MX25R8035F + && rbuf[1] != BLS_DEVICE_ID_MX25R1635F)) { return VERIFY_PART_POWERED_DOWN; } return VERIFY_PART_OK; From b608b837c239cdc59e3adb4f4f4eb9a6645fc09a Mon Sep 17 00:00:00 2001 From: Atis Elsts Date: Wed, 18 May 2016 17:40:20 +0300 Subject: [PATCH 55/80] Add login target to Makefile.cc26xx-cc13xx --- cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index d0cf1cf31..15d971004 100644 --- a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -145,3 +145,20 @@ else %.upload: @echo "This board cannot be programmed through the ROM bootloader and therefore does not support the .upload target." endif + +# Check if we are running under Windows +ifeq ($(HOST_OS),Windows) + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-windows +else +ifeq ($(HOST_OS),Darwin) + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-macos +else + # Else assume Linux + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-linux +endif +endif + +UART_BAUDRATE = 115200 + +login: + $(SERIALDUMP) -b$(UART_BAUDRATE) $(PORT) From f5919a2a459a75b711d6295b0d0797a565c66970 Mon Sep 17 00:00:00 2001 From: "Kitty(chun hua) Jiang" Date: Wed, 25 May 2016 10:25:43 +0800 Subject: [PATCH 56/80] fix the bug about chalemeon raw hdrsize --- core/net/rime/chameleon-raw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) mode change 100644 => 100755 core/net/rime/chameleon-raw.c diff --git a/core/net/rime/chameleon-raw.c b/core/net/rime/chameleon-raw.c old mode 100644 new mode 100755 index 8efcf8a1f..16b17fb5d --- a/core/net/rime/chameleon-raw.c +++ b/core/net/rime/chameleon-raw.c @@ -205,10 +205,7 @@ hdrsize(const struct packetbuf_attrlist *a) continue; } #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ - len = a->len; - if(len < 8) { - len = 8; - } + len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0); size += len; } return size / 8; From e8edb6b1a0914e5872053293c801ee2d43148e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 4 May 2016 20:39:08 +0200 Subject: [PATCH 57/80] oma-lwm2m: Add JSON writer --- apps/oma-lwm2m/Makefile.oma-lwm2m | 16 ++- apps/oma-lwm2m/lwm2m-engine.c | 5 + apps/oma-lwm2m/lwm2m-json.c | 162 ++++++++++++++++++++++++++++++ apps/oma-lwm2m/lwm2m-json.h | 51 ++++++++++ 4 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 apps/oma-lwm2m/lwm2m-json.c create mode 100644 apps/oma-lwm2m/lwm2m-json.h diff --git a/apps/oma-lwm2m/Makefile.oma-lwm2m b/apps/oma-lwm2m/Makefile.oma-lwm2m index 8445530ed..000147939 100644 --- a/apps/oma-lwm2m/Makefile.oma-lwm2m +++ b/apps/oma-lwm2m/Makefile.oma-lwm2m @@ -1,5 +1,13 @@ -oma-lwm2m_src = lwm2m-object.c lwm2m-engine.c \ - lwm2m-device.c lwm2m-server.c lwm2m-security.c \ - oma-tlv.c oma-tlv-reader.c oma-tlv-writer.c \ - lwm2m-plain-text.c +oma-lwm2m_src = \ + lwm2m-object.c \ + lwm2m-engine.c \ + lwm2m-device.c \ + lwm2m-server.c \ + lwm2m-security.c \ + oma-tlv.c \ + oma-tlv-reader.c \ + oma-tlv-writer.c \ + lwm2m-plain-text.c \ + lwm2m-json.c \ + # CFLAGS += -DHAVE_OMA_LWM2M=1 diff --git a/apps/oma-lwm2m/lwm2m-engine.c b/apps/oma-lwm2m/lwm2m-engine.c index 3728e3505..0fe86bbbb 100644 --- a/apps/oma-lwm2m/lwm2m-engine.c +++ b/apps/oma-lwm2m/lwm2m-engine.c @@ -46,6 +46,7 @@ #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-plain-text.h" +#include "lwm2m-json.h" #include "rest-engine.h" #include "er-coap-constants.h" #include "er-coap-engine.h" @@ -727,6 +728,10 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) case TEXT_PLAIN: context->writer = &lwm2m_plain_text_writer; break; + case LWM2M_JSON: + case APPLICATION_JSON: + context->writer = &lwm2m_json_writer; + break; default: PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); context->writer = &lwm2m_plain_text_writer; diff --git a/apps/oma-lwm2m/lwm2m-json.c b/apps/oma-lwm2m/lwm2m-json.c new file mode 100644 index 000000000..8924ceb8c --- /dev/null +++ b/apps/oma-lwm2m/lwm2m-json.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016, Eistec AB. + * 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 HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M JSON writer + * \author + * Joakim Nohlgård + */ + +#include "lwm2m-object.h" +#include "lwm2m-json.h" +#include "lwm2m-plain-text.h" +#include +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int value) +{ + int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"bv\":%s}]}\n", ctx->resource_id, value ? "true" : "false"); + if((len < 0) || (len >= outlen)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value) +{ + int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":%" PRId32 "}]}\n", ctx->resource_id, value); + if((len < 0) || (len >= outlen)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value, int bits) +{ + size_t len = 0; + int res; + res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":", ctx->resource_id); + if(res <= 0 || res >= outlen) { + return 0; + } + len += res; + outlen -= res; + res = lwm2m_plain_text_write_float32fix(&outbuf[len], outlen, value, bits); + if((res <= 0) || (res >= outlen)) { + return 0; + } + len += res; + outlen -= res; + res = snprintf((char *)&outbuf[len], outlen, "}]}\n"); + if((res <= 0) || (res >= outlen)) { + return 0; + } + len += res; + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + const char *value, size_t stringlen) +{ + size_t i; + size_t len = 0; + int res; + PRINTF("{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + if(res < 0 || res >= outlen) { + return 0; + } + len += res; + for (i = 0; i < stringlen && len < outlen; ++i) { + /* Escape special characters */ + /* TODO: Handle UTF-8 strings */ + if(value[i] < '\x20') { + PRINTF("\\x%x", value[i]); + res = snprintf((char *)&outbuf[len], outlen - len, "\\x%x", value[i]); + if((res < 0) || (res >= (outlen - len))) { + return 0; + } + len += res; + continue; + } else if(value[i] == '"' || value[i] == '\\') { + PRINTF("\\"); + outbuf[len] = '\\'; + ++len; + if(len >= outlen) { + return 0; + } + } + PRINTF("%c", value[i]); + outbuf[len] = value[i]; + ++len; + if(len >= outlen) { + return 0; + } + } + PRINTF("\"}]}\n"); + res = snprintf((char *)&outbuf[len], outlen - len, "\"}]}\n"); + if((res < 0) || (res >= (outlen - len))) { + return 0; + } + len += res; + return len; +} +/*---------------------------------------------------------------------------*/ +const lwm2m_writer_t lwm2m_json_writer = { + write_int, + write_string, + write_float32fix, + write_boolean +}; +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/apps/oma-lwm2m/lwm2m-json.h b/apps/oma-lwm2m/lwm2m-json.h new file mode 100644 index 000000000..bc1a1e32a --- /dev/null +++ b/apps/oma-lwm2m/lwm2m-json.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Eistec AB. + * 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 HOLDER 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. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M JSON writer + * \author + * Joakim Nohlgård + */ + +#ifndef LWM2M_JSON_H_ +#define LWM2M_JSON_H_ + +#include "lwm2m-object.h" + +extern const lwm2m_writer_t lwm2m_json_writer; + +#endif /* LWM2M_JSON_H_ */ +/** @} */ From 334e38339eba2607c6560c09cb914d01cd0e7986 Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Thu, 3 Mar 2016 20:42:27 +0100 Subject: [PATCH 58/80] Fixed rssi-scanner example --- examples/rssi-scanner/rssi-scanner-cc2420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rssi-scanner/rssi-scanner-cc2420.c b/examples/rssi-scanner/rssi-scanner-cc2420.c index fbbfddf00..94c9056b9 100644 --- a/examples/rssi-scanner/rssi-scanner-cc2420.c +++ b/examples/rssi-scanner/rssi-scanner-cc2420.c @@ -77,7 +77,7 @@ do_rssi(void) printf("RSSI:"); for(channel = 0; channel <= 85; ++channel) { set_frq(channel); - printf("%d ", cc2420_rssi() + 55); + printf("%d ", cc2420_rssi() + 100); } printf("\n"); } From d70c75914aed2499d95eba9ba8cb0f7f0a09d4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sat, 28 May 2016 22:47:58 +0200 Subject: [PATCH 59/80] cfs-coffee: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this build warning, which is generated if micro logs are enabled: In file included from ../../core/cfs/cfs-coffee.c:59:0: ../../core/cfs/cfs-coffee.c: In function 'read_log_page': ../../cpu/cc2538/./cfs-coffee-arch.h:145:24: warning: passing argument 1 of 'cfs_coffee_arch_read' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] cfs_coffee_arch_read((buf), (size), (offset)) ^ ../../core/cfs/cfs-coffee.c:757:3: note: in expansion of macro 'COFFEE_READ' COFFEE_READ(lp->buf, lp->size, base); ^ ../../cpu/cc2538/./cfs-coffee-arch.h:176:6: note: expected 'void *' but argument is of type 'const char *' void cfs_coffee_arch_read(void *buf, unsigned int size, cfs_offset_t offset); ^ COFFEE_READ() needs to write to lp->buf, so the target type of this pointer cannot be qualified as "const". Signed-off-by: Benoît Thébaudeau --- core/cfs/cfs-coffee.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index 37b1a707e..374b3419f 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -196,7 +196,7 @@ struct file_header { /* This is needed because of a buggy compiler. */ struct log_param { cfs_offset_t offset; - const char *buf; + char *buf; uint16_t size; }; @@ -1198,7 +1198,7 @@ cfs_write(int fd, const void *buf, unsigned size) need_dummy_write = 0; for(bytes_left = size; bytes_left > 0;) { lp.offset = fdp->offset; - lp.buf = buf; + lp.buf = (void *)buf; lp.size = bytes_left; i = write_log_page(file, &lp); if(i < 0) { From 4ed5c50a4e81006ebcbba930a1ef4585bd034e63 Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Fri, 29 Jan 2016 20:56:34 +0100 Subject: [PATCH 60/80] Make CFS and Coffee examples platform-independent Move the CFS and Coffee examples from sky to a common cfs-coffee folder in order to have unified examples for multiple platforms. --- examples/cfs-coffee/Makefile | 11 +++ examples/cfs-coffee/README.md | 26 +++++++ examples/{sky => cfs-coffee}/example-coffee.c | 2 +- examples/{sky => cfs-coffee}/test-cfs.c | 0 examples/{sky => cfs-coffee}/test-coffee.c | 74 +++++++++---------- examples/sky/Makefile | 2 +- regression-tests/01-compile-base/Makefile | 7 +- regression-tests/03-base/02-sky-coffee.csc | 4 +- 8 files changed, 83 insertions(+), 43 deletions(-) create mode 100644 examples/cfs-coffee/Makefile create mode 100644 examples/cfs-coffee/README.md rename examples/{sky => cfs-coffee}/example-coffee.c (99%) rename examples/{sky => cfs-coffee}/test-cfs.c (100%) rename examples/{sky => cfs-coffee}/test-coffee.c (91%) diff --git a/examples/cfs-coffee/Makefile b/examples/cfs-coffee/Makefile new file mode 100644 index 000000000..543cb8c3d --- /dev/null +++ b/examples/cfs-coffee/Makefile @@ -0,0 +1,11 @@ +CONTIKI = ../.. + +all: test-cfs test-coffee example-coffee + +CONTIKI_WITH_RIME = 1 + +ifeq ($(TARGET),avr-raven) + COFFEE_FILES = 4 +endif + +include $(CONTIKI)/Makefile.include diff --git a/examples/cfs-coffee/README.md b/examples/cfs-coffee/README.md new file mode 100644 index 000000000..672376ef8 --- /dev/null +++ b/examples/cfs-coffee/README.md @@ -0,0 +1,26 @@ +Contiki File System (CFS) and Coffee Examples +============================================= + +Coffee is a very simple, relatively small and easy to use file system that you +are most likely going to be very familiar with if you have done any C file +access in the past. The notion is the same as on a normal PC: you open a file, +read and write to it and close it. Contiki will take care of the underlying +flash memory, giving you more time to focus on the real issues. + +Coffee is a full implementation of the CFS API. + +An extended explanation on CFS and Coffee internals and how they work can be +found at the [CFS](https://github.com/contiki-os/contiki/wiki/File-systems) and +[Coffee](https://github.com/contiki-os/contiki/wiki/Coffee-filesystem-example) +wiki pages. + +Supported Hardware (tested or known to work) +-------------------------------------------- +* sky +* z1 +* wismote +* avr-raven + +The examples are known to build for the 'avr-raven' platform. However, +some of them currently fail at runtime due to file system overflow. +Tweaking the file sizes in the examples is necessary. diff --git a/examples/sky/example-coffee.c b/examples/cfs-coffee/example-coffee.c similarity index 99% rename from examples/sky/example-coffee.c rename to examples/cfs-coffee/example-coffee.c index ee77849e4..998afa4de 100644 --- a/examples/sky/example-coffee.c +++ b/examples/cfs-coffee/example-coffee.c @@ -37,7 +37,7 @@ */ #include - +#include #include "contiki.h" #include "cfs/cfs.h" #include "cfs/cfs-coffee.h" diff --git a/examples/sky/test-cfs.c b/examples/cfs-coffee/test-cfs.c similarity index 100% rename from examples/sky/test-cfs.c rename to examples/cfs-coffee/test-cfs.c diff --git a/examples/sky/test-coffee.c b/examples/cfs-coffee/test-coffee.c similarity index 91% rename from examples/sky/test-coffee.c rename to examples/cfs-coffee/test-coffee.c index b4152b2a8..4ec06f3cd 100644 --- a/examples/sky/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -49,7 +49,7 @@ PROCESS(testcoffee_process, "Test CFS/Coffee process"); AUTOSTART_PROCESSES(&testcoffee_process); -#define FAIL(x) error = (x); goto end; +#define TEST_FAIL(x) error = (x); goto end; #define FILE_SIZE 4096 @@ -73,64 +73,64 @@ coffee_test_basic(void) /* Test 1: Open for writing. */ wfd = cfs_open("T1", CFS_WRITE); if(wfd < 0) { - FAIL(1); + TEST_FAIL(1); } /* Test 2 and 3: Write buffer. */ r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(2); + TEST_FAIL(2); } else if(r < sizeof(buf)) { - FAIL(3); + TEST_FAIL(3); } /* Test 4: Deny reading. */ r = cfs_read(wfd, buf, sizeof(buf)); if(r >= 0) { - FAIL(4); + TEST_FAIL(4); } /* Test 5: Open for reading. */ rfd = cfs_open("T1", CFS_READ); if(rfd < 0) { - FAIL(5); + TEST_FAIL(5); } /* Test 6: Write to read-only file. */ r = cfs_write(rfd, buf, sizeof(buf)); if(r >= 0) { - FAIL(6); + TEST_FAIL(6); } /* Test 7 and 8: Read the buffer written in Test 2. */ memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(7); + TEST_FAIL(7); } else if(r < sizeof(buf)) { printf("r=%d\n", r); - FAIL(8); + TEST_FAIL(8); } /* Test 9: Verify that the buffer is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != r) { printf("r=%d. buf[r]=%d\n", r, buf[r]); - FAIL(9); + TEST_FAIL(9); } } /* Test 10: Seek to beginning. */ if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { - FAIL(10); + TEST_FAIL(10); } /* Test 11 and 12: Write to the log. */ r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(11); + TEST_FAIL(11); } else if(r < sizeof(buf)) { - FAIL(12); + TEST_FAIL(12); } /* Test 13 and 14: Read the data from the log. */ @@ -138,15 +138,15 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(14); + TEST_FAIL(14); } else if(r < sizeof(buf)) { - FAIL(15); + TEST_FAIL(15); } /* Test 16: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != r) { - FAIL(16); + TEST_FAIL(16); } } @@ -155,16 +155,16 @@ coffee_test_basic(void) buf[r] = sizeof(buf) - r - 1; } if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { - FAIL(17); + TEST_FAIL(17); } r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(18); + TEST_FAIL(18); } else if(r < sizeof(buf)) { - FAIL(19); + TEST_FAIL(19); } if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) { - FAIL(20); + TEST_FAIL(20); } /* Test 21 and 22: Read the reversed buffer. */ @@ -172,16 +172,16 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(21); + TEST_FAIL(21); } else if(r < sizeof(buf)) { printf("r = %d\n", r); - FAIL(22); + TEST_FAIL(22); } /* Test 23: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != sizeof(buf) - r - 1) { - FAIL(23); + TEST_FAIL(23); } } @@ -208,14 +208,14 @@ coffee_test_append(void) for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) { afd = cfs_open("T3", CFS_WRITE | CFS_APPEND); if(afd < 0) { - FAIL(1); + TEST_FAIL(1); } for(j = 0; j < BULK_SIZE; j++) { buf[j] = 1 + ((i + j) & 0x7f); } if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) { printf("r=%d\n", r); - FAIL(2); + TEST_FAIL(2); } cfs_close(afd); } @@ -224,22 +224,22 @@ coffee_test_append(void) is correct. */ afd = cfs_open("T3", CFS_READ); if(afd < 0) { - FAIL(3); + TEST_FAIL(3); } total_read = 0; while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) { for(j = 0; j < r; j++) { if(buf2[j] != 1 + ((total_read + j) & 0x7f)) { - FAIL(4); + TEST_FAIL(4); } } total_read += r; } if(r < 0) { - FAIL(5); + TEST_FAIL(5); } if(total_read != APPEND_BYTES) { - FAIL(6); + TEST_FAIL(6); } cfs_close(afd); @@ -262,18 +262,18 @@ coffee_test_modify(void) wfd = -1; if(cfs_coffee_reserve("T3", FILE_SIZE) < 0) { - FAIL(1); + TEST_FAIL(1); } if(cfs_coffee_configure_log("T3", FILE_SIZE / 2, 11) < 0) { - FAIL(2); + TEST_FAIL(2); } /* Test 16: Test multiple writes at random offset. */ for(r = 0; r < 100; r++) { wfd = cfs_open("T2", CFS_WRITE | CFS_READ); if(wfd < 0) { - FAIL(3); + TEST_FAIL(3); } offset = random_rand() % FILE_SIZE; @@ -283,26 +283,26 @@ coffee_test_modify(void) } if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { - FAIL(4); + TEST_FAIL(4); } if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) { - FAIL(5); + TEST_FAIL(5); } if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { - FAIL(6); + TEST_FAIL(6); } memset(buf, 0, sizeof(buf)); if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) { - FAIL(7); + TEST_FAIL(7); } for(i = 0; i < sizeof(buf); i++) { if(buf[i] != i) { printf("buf[%d] != %d\n", i, buf[i]); - FAIL(8); + TEST_FAIL(8); } } } diff --git a/examples/sky/Makefile b/examples/sky/Makefile index dd09f0792..6d17fd421 100644 --- a/examples/sky/Makefile +++ b/examples/sky/Makefile @@ -3,7 +3,7 @@ ifndef TARGET TARGET=sky endif -all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0 +all: blink sky-collect #rt-leds test-button tcprudolph0 %.tgz: %.ihex mkdir $(basename $<) ; \ diff --git a/regression-tests/01-compile-base/Makefile b/regression-tests/01-compile-base/Makefile index bbfbd0c6b..bc38a9777 100644 --- a/regression-tests/01-compile-base/Makefile +++ b/regression-tests/01-compile-base/Makefile @@ -37,8 +37,11 @@ settings-example/avr-raven \ ipv6/multicast/sky \ ipv6/rpl-tsch/z1 \ ipv6/rpl-tsch/z1:MAKE_WITH_ORCHESTRA=1 \ -ipv6/rpl-tsch/z1:MAKE_WITH_SECURITY=1 - +ipv6/rpl-tsch/z1:MAKE_WITH_SECURITY=1 \ +cfs-coffee/sky \ +cfs-coffee/z1 \ +cfs-coffee/wismote \ +cfs-coffee/avr-raven TOOLS= diff --git a/regression-tests/03-base/02-sky-coffee.csc b/regression-tests/03-base/02-sky-coffee.csc index f017a3e7d..035f72843 100644 --- a/regression-tests/03-base/02-sky-coffee.csc +++ b/regression-tests/03-base/02-sky-coffee.csc @@ -24,10 +24,10 @@ org.contikios.cooja.mspmote.SkyMoteType sky1 Sky Mote Type #1 - [CONTIKI_DIR]/examples/sky/test-coffee.c + [CONTIKI_DIR]/examples/cfs-coffee/test-coffee.c make clean TARGET=sky make test-coffee.sky TARGET=sky - [CONTIKI_DIR]/examples/sky/test-coffee.sky + [CONTIKI_DIR]/examples/cfs-coffee/test-coffee.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.IPAddress org.contikios.cooja.interfaces.Mote2MoteRelations From e23c1756990cba162f6db9f8e2ab685d541fa22e Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Fri, 29 Jan 2016 20:56:34 +0100 Subject: [PATCH 61/80] cfs-coffee: examples: Fix coding style --- examples/cfs-coffee/example-coffee.c | 28 ++++++++++++++-------------- examples/cfs-coffee/test-cfs.c | 7 +++---- examples/cfs-coffee/test-coffee.c | 14 ++++++-------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/examples/cfs-coffee/example-coffee.c b/examples/cfs-coffee/example-coffee.c index 998afa4de..7adc8d62c 100644 --- a/examples/cfs-coffee/example-coffee.c +++ b/examples/cfs-coffee/example-coffee.c @@ -28,31 +28,31 @@ * * This file is part of the Contiki operating system. */ - +/*---------------------------------------------------------------------------*/ /** * \file * Example on how to use CFS/Coffee. * \author * Nicolas Tsiftes */ - +/*---------------------------------------------------------------------------*/ #include #include #include "contiki.h" #include "cfs/cfs.h" #include "cfs/cfs-coffee.h" - +/*---------------------------------------------------------------------------*/ PROCESS(example_coffee_process, "Coffee example"); AUTOSTART_PROCESSES(&example_coffee_process); - +/*---------------------------------------------------------------------------*/ #define FILENAME "test" -/* Formatting is needed if the storage device is in an unknown state; +/* Formatting is needed if the storage device is in an unknown state; e.g., when using Coffee on the storage device for the first time. */ #ifndef NEED_FORMATTING #define NEED_FORMATTING 0 #endif - +/*---------------------------------------------------------------------------*/ static int file_test(const char *filename, char *msg) { @@ -65,12 +65,12 @@ file_test(const char *filename, char *msg) } record; /* - * Coffee determines the file length by finding the last non-zero byte - * of the file. This I/O semantic requires that each record should end - * with a non-zero, if we are writing multiple records and closing the + * Coffee determines the file length by finding the last non-zero byte + * of the file. This I/O semantic requires that each record should end + * with a non-zero, if we are writing multiple records and closing the * file descriptor in between. * - * In this example, in which the file_test function can be called + * In this example, in which the file_test function can be called * multiple times, we ensure that the sequence counter starts at 1. */ @@ -84,7 +84,7 @@ file_test(const char *filename, char *msg) record.message[sizeof(record.message) - 1] = '\0'; record.sequence = sequence; - /* Obtain a file descriptor for the file, capable of handling both + /* Obtain a file descriptor for the file, capable of handling both reads and writes. */ fd = cfs_open(FILENAME, CFS_WRITE | CFS_APPEND | CFS_READ); if(fd < 0) { @@ -103,7 +103,7 @@ file_test(const char *filename, char *msg) printf("Wrote message \"%s\", sequence %u\n", record.message, record.sequence); - /* To read back the message, we need to move the file pointer to the + /* To read back the message, we need to move the file pointer to the beginning of the file. */ if(cfs_seek(fd, 0, CFS_SEEK_SET) != 0) { printf("seek failed\n"); @@ -133,7 +133,7 @@ file_test(const char *filename, char *msg) return 1; } - +/*---------------------------------------------------------------------------*/ static int dir_test(void) { @@ -156,7 +156,7 @@ dir_test(void) return 1; } - +/*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_coffee_process, ev, data) { PROCESS_BEGIN(); diff --git a/examples/cfs-coffee/test-cfs.c b/examples/cfs-coffee/test-cfs.c index 68c91e720..b5068aaa2 100644 --- a/examples/cfs-coffee/test-cfs.c +++ b/examples/cfs-coffee/test-cfs.c @@ -29,19 +29,18 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * A quick program for testing the CFS xmem driver * \author * Adam Dunkels */ - +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "cfs/cfs.h" - #include - +/*---------------------------------------------------------------------------*/ PROCESS(cfs_process, "Test CFS process"); AUTOSTART_PROCESSES(&cfs_process); /*---------------------------------------------------------------------------*/ diff --git a/examples/cfs-coffee/test-coffee.c b/examples/cfs-coffee/test-coffee.c index 4ec06f3cd..c274e5b81 100644 --- a/examples/cfs-coffee/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -29,14 +29,14 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * Basic test for CFS/Coffee. * \author * Nicolas Tsiftes */ - +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "cfs/cfs.h" #include "cfs/cfs-coffee.h" @@ -45,14 +45,12 @@ #include #include - +/*---------------------------------------------------------------------------*/ PROCESS(testcoffee_process, "Test CFS/Coffee process"); AUTOSTART_PROCESSES(&testcoffee_process); - +/*---------------------------------------------------------------------------*/ #define TEST_FAIL(x) error = (x); goto end; - #define FILE_SIZE 4096 - /*---------------------------------------------------------------------------*/ static int coffee_test_basic(void) @@ -220,7 +218,7 @@ coffee_test_append(void) cfs_close(afd); } - /* Test 3-6: Read back the data written previously and verify that it + /* Test 3-6: Read back the data written previously and verify that it is correct. */ afd = cfs_open("T3", CFS_READ); if(afd < 0) { @@ -376,7 +374,7 @@ PROCESS_THREAD(testcoffee_process, ev, data) result = coffee_test_gc(); print_result("Garbage collection", result); - printf("Coffee test finished. Duration: %d seconds\n", + printf("Coffee test finished. Duration: %d seconds\n", (int)(clock_seconds() - start)); PROCESS_END(); From 5d227b92a3619aa6330fb3a45dc2ec5e2b4ac9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 29 May 2016 21:43:11 +0200 Subject: [PATCH 62/80] test-cfs: Fix possible test failure after reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the file at the beginning of the test, before opening it for writing, in order to start the test with an empty file system, not only after flashing the test, but also following every reboot. Signed-off-by: Benoît Thébaudeau --- examples/cfs-coffee/test-cfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/cfs-coffee/test-cfs.c b/examples/cfs-coffee/test-cfs.c index b5068aaa2..2d44b6696 100644 --- a/examples/cfs-coffee/test-cfs.c +++ b/examples/cfs-coffee/test-cfs.c @@ -54,6 +54,7 @@ PROCESS_THREAD(cfs_process, ev, data) uint16_t filesize = 65000; #define CHUNKSIZE 128 + cfs_remove("hej"); fd = cfs_open("hej", CFS_WRITE); if(fd < 0) { printf("could not open file for writing, aborting\n"); From 76429e4f0e8858e094f5e6a2423833974ffc9a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 29 May 2016 22:01:40 +0200 Subject: [PATCH 63/80] test-coffee: Fix numbering of test failure cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benoît Thébaudeau --- examples/cfs-coffee/test-coffee.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/cfs-coffee/test-coffee.c b/examples/cfs-coffee/test-coffee.c index c274e5b81..c2a34d2c3 100644 --- a/examples/cfs-coffee/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -136,15 +136,15 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - TEST_FAIL(14); + TEST_FAIL(13); } else if(r < sizeof(buf)) { - TEST_FAIL(15); + TEST_FAIL(14); } /* Test 16: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != r) { - TEST_FAIL(16); + TEST_FAIL(15); } } @@ -153,16 +153,16 @@ coffee_test_basic(void) buf[r] = sizeof(buf) - r - 1; } if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { - TEST_FAIL(17); + TEST_FAIL(16); } r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - TEST_FAIL(18); + TEST_FAIL(17); } else if(r < sizeof(buf)) { - TEST_FAIL(19); + TEST_FAIL(18); } if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) { - TEST_FAIL(20); + TEST_FAIL(19); } /* Test 21 and 22: Read the reversed buffer. */ @@ -170,16 +170,16 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - TEST_FAIL(21); + TEST_FAIL(20); } else if(r < sizeof(buf)) { printf("r = %d\n", r); - TEST_FAIL(22); + TEST_FAIL(21); } /* Test 23: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != sizeof(buf) - r - 1) { - TEST_FAIL(23); + TEST_FAIL(22); } } From 150b9fbd8b5c0061f86604c86d4938f6d0ef2517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 29 May 2016 22:09:20 +0200 Subject: [PATCH 64/80] test-coffee: Fix test filenames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The filenames were mixed up between some of the tests, thus breaking the purpose of these tests. Signed-off-by: Benoît Thébaudeau --- examples/cfs-coffee/test-coffee.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/cfs-coffee/test-coffee.c b/examples/cfs-coffee/test-coffee.c index c2a34d2c3..9f134ae44 100644 --- a/examples/cfs-coffee/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -204,7 +204,7 @@ coffee_test_append(void) /* Test 1 and 2: Append data to the same file many times. */ for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) { - afd = cfs_open("T3", CFS_WRITE | CFS_APPEND); + afd = cfs_open("T2", CFS_WRITE | CFS_APPEND); if(afd < 0) { TEST_FAIL(1); } @@ -220,7 +220,7 @@ coffee_test_append(void) /* Test 3-6: Read back the data written previously and verify that it is correct. */ - afd = cfs_open("T3", CFS_READ); + afd = cfs_open("T2", CFS_READ); if(afd < 0) { TEST_FAIL(3); } @@ -269,7 +269,7 @@ coffee_test_modify(void) /* Test 16: Test multiple writes at random offset. */ for(r = 0; r < 100; r++) { - wfd = cfs_open("T2", CFS_WRITE | CFS_READ); + wfd = cfs_open("T3", CFS_WRITE | CFS_READ); if(wfd < 0) { TEST_FAIL(3); } From 003b4b0d6345f94fdc5b3f13e0f061252b67e01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Sun, 29 May 2016 22:23:15 +0200 Subject: [PATCH 65/80] test-coffee: Fix the file modification test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The r variable was used instead of i to fill the buffer, resulting in the end of the test loop after only a single iteration. The file was not even closed at the end of each iteration although it is opened at the beginning of each iteration, so the available file descriptors would very quickly be exhausted. Signed-off-by: Benoît Thébaudeau --- examples/cfs-coffee/test-coffee.c | 6 ++++-- regression-tests/03-base/02-sky-coffee.csc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/cfs-coffee/test-coffee.c b/examples/cfs-coffee/test-coffee.c index 9f134ae44..28cd3b5c6 100644 --- a/examples/cfs-coffee/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -276,8 +276,8 @@ coffee_test_modify(void) offset = random_rand() % FILE_SIZE; - for(r = 0; r < sizeof(buf); r++) { - buf[r] = r; + for(i = 0; i < sizeof(buf); i++) { + buf[i] = i; } if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { @@ -303,6 +303,8 @@ coffee_test_modify(void) TEST_FAIL(8); } } + + cfs_close(wfd); } error = 0; diff --git a/regression-tests/03-base/02-sky-coffee.csc b/regression-tests/03-base/02-sky-coffee.csc index 035f72843..050b4abc9 100644 --- a/regression-tests/03-base/02-sky-coffee.csc +++ b/regression-tests/03-base/02-sky-coffee.csc @@ -89,7 +89,7 @@ make test-coffee.sky TARGET=sky org.contikios.cooja.plugins.ScriptRunner -