Merge branch 'master' of https://github.com/contiki-os/contiki into fixes
This commit is contained in:
commit
cade3c7699
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -125,3 +125,7 @@ platform/galileo/bsp/grub/bin/
|
||||||
*.galileo.dll
|
*.galileo.dll
|
||||||
*.galileo.efi
|
*.galileo.efi
|
||||||
LOG_OPENOCD
|
LOG_OPENOCD
|
||||||
|
|
||||||
|
# nRF52 build artifacts
|
||||||
|
*.jlink
|
||||||
|
*.nrf52dk
|
||||||
|
|
14
.travis.yml
14
.travis.yml
|
@ -74,7 +74,6 @@ before_script:
|
||||||
git clone https://github.com/cc65/cc65 /tmp/cc65 &&
|
git clone https://github.com/cc65/cc65 /tmp/cc65 &&
|
||||||
make -C /tmp/cc65 bin apple2enh atarixl c64 c128 &&
|
make -C /tmp/cc65 bin apple2enh atarixl c64 c128 &&
|
||||||
sudo make -C /tmp/cc65 avail &&
|
sudo make -C /tmp/cc65 avail &&
|
||||||
export CC65_HOME=/tmp/cc65/ &&
|
|
||||||
cc65 --version ;
|
cc65 --version ;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -93,6 +92,18 @@ before_script:
|
||||||
rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* &&
|
rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* &&
|
||||||
ba-elf-gcc --version ;
|
ba-elf-gcc --version ;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
## Install mainline ARM toolchain and download nRF52 SDK
|
||||||
|
- if [ ${BUILD_ARCH:-0} = nrf52dk ] ; then
|
||||||
|
sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa &&
|
||||||
|
sudo apt-get -qq update &&
|
||||||
|
sudo apt-get -qq install gcc-arm-embedded 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
|
## Compile cooja.jar only when it's going to be needed
|
||||||
- if [ ${BUILD_CATEGORY:-sim} = sim ] ; then
|
- if [ ${BUILD_CATEGORY:-sim} = sim ] ; then
|
||||||
|
@ -142,6 +153,7 @@ env:
|
||||||
- BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502'
|
- 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-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs'
|
||||||
- BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x'
|
- 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='slip-radio' MAKE_TARGETS='cooja'
|
||||||
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
|
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
|
||||||
- BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2'
|
- BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2'
|
||||||
|
|
|
@ -182,7 +182,7 @@ CONTIKI_CPU_DIRS_CONCAT = ${addprefix $(CONTIKI_CPU)/, \
|
||||||
$(CONTIKI_CPU_DIRS)}
|
$(CONTIKI_CPU_DIRS)}
|
||||||
|
|
||||||
SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) \
|
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 %.c $(SOURCEDIRS)
|
||||||
vpath %.S $(SOURCEDIRS)
|
vpath %.S $(SOURCEDIRS)
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
oma-lwm2m_src = lwm2m-object.c lwm2m-engine.c \
|
oma-lwm2m_src = \
|
||||||
lwm2m-device.c lwm2m-server.c lwm2m-security.c \
|
lwm2m-object.c \
|
||||||
oma-tlv.c oma-tlv-reader.c oma-tlv-writer.c \
|
lwm2m-engine.c \
|
||||||
lwm2m-plain-text.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
|
CFLAGS += -DHAVE_OMA_LWM2M=1
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "lwm2m-object.h"
|
#include "lwm2m-object.h"
|
||||||
#include "lwm2m-device.h"
|
#include "lwm2m-device.h"
|
||||||
#include "lwm2m-plain-text.h"
|
#include "lwm2m-plain-text.h"
|
||||||
|
#include "lwm2m-json.h"
|
||||||
#include "rest-engine.h"
|
#include "rest-engine.h"
|
||||||
#include "er-coap-constants.h"
|
#include "er-coap-constants.h"
|
||||||
#include "er-coap-engine.h"
|
#include "er-coap-engine.h"
|
||||||
|
@ -727,6 +728,10 @@ lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept)
|
||||||
case TEXT_PLAIN:
|
case TEXT_PLAIN:
|
||||||
context->writer = &lwm2m_plain_text_writer;
|
context->writer = &lwm2m_plain_text_writer;
|
||||||
break;
|
break;
|
||||||
|
case LWM2M_JSON:
|
||||||
|
case APPLICATION_JSON:
|
||||||
|
context->writer = &lwm2m_json_writer;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept);
|
PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept);
|
||||||
context->writer = &lwm2m_plain_text_writer;
|
context->writer = &lwm2m_plain_text_writer;
|
||||||
|
|
162
apps/oma-lwm2m/lwm2m-json.c
Normal file
162
apps/oma-lwm2m/lwm2m-json.c
Normal file
|
@ -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 <joakim.nohlgard@eistec.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lwm2m-object.h"
|
||||||
|
#include "lwm2m-json.h"
|
||||||
|
#include "lwm2m-plain-text.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** @} */
|
51
apps/oma-lwm2m/lwm2m-json.h
Normal file
51
apps/oma-lwm2m/lwm2m-json.h
Normal file
|
@ -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 <joakim.nohlgard@eistec.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWM2M_JSON_H_
|
||||||
|
#define LWM2M_JSON_H_
|
||||||
|
|
||||||
|
#include "lwm2m-object.h"
|
||||||
|
|
||||||
|
extern const lwm2m_writer_t lwm2m_json_writer;
|
||||||
|
|
||||||
|
#endif /* LWM2M_JSON_H_ */
|
||||||
|
/** @} */
|
|
@ -196,7 +196,7 @@ struct file_header {
|
||||||
/* This is needed because of a buggy compiler. */
|
/* This is needed because of a buggy compiler. */
|
||||||
struct log_param {
|
struct log_param {
|
||||||
cfs_offset_t offset;
|
cfs_offset_t offset;
|
||||||
const char *buf;
|
char *buf;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1198,7 +1198,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
need_dummy_write = 0;
|
need_dummy_write = 0;
|
||||||
for(bytes_left = size; bytes_left > 0;) {
|
for(bytes_left = size; bytes_left > 0;) {
|
||||||
lp.offset = fdp->offset;
|
lp.offset = fdp->offset;
|
||||||
lp.buf = buf;
|
lp.buf = (void *)buf;
|
||||||
lp.size = bytes_left;
|
lp.size = bytes_left;
|
||||||
i = write_log_page(file, &lp);
|
i = write_log_page(file, &lp);
|
||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
* A set of debugging tools
|
* A set of debugging tools for the IP stack
|
||||||
* \author
|
* \author
|
||||||
* Nicolas Tsiftes <nvt@sics.se>
|
* Nicolas Tsiftes <nvt@sics.se>
|
||||||
* Niclas Finne <nfi@sics.se>
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
@ -92,19 +92,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr)
|
||||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
#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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
|
@ -31,57 +31,27 @@
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
* A set of debugging macros.
|
* A set of debugging macros for the IP stack
|
||||||
*
|
*
|
||||||
* \author Nicolas Tsiftes <nvt@sics.se>
|
* \author Nicolas Tsiftes <nvt@sics.se>
|
||||||
* Niclas Finne <nfi@sics.se>
|
* Niclas Finne <nfi@sics.se>
|
||||||
* Joakim Eriksson <joakime@sics.se>
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
* Simon Duquennoy <simon.duquennoy@inria.fr>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UIP_DEBUG_H
|
#ifndef UIP_DEBUG_H
|
||||||
#define UIP_DEBUG_H
|
#define UIP_DEBUG_H
|
||||||
|
|
||||||
|
#include "net/net-debug.h"
|
||||||
#include "net/ip/uip.h"
|
#include "net/ip/uip.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void uip_debug_ipaddr_print(const uip_ipaddr_t *addr);
|
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 <avr/pgmspace.h>
|
|
||||||
#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
|
#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 PRINT6ADDR(addr) uip_debug_ipaddr_print(addr)
|
||||||
#define PRINTLLADDR(lladdr) uip_debug_lladdr_print(lladdr)
|
|
||||||
#else
|
#else
|
||||||
#define PRINTF(...)
|
|
||||||
#define PRINT6ADDR(addr)
|
#define PRINT6ADDR(addr)
|
||||||
#define PRINTLLADDR(lladdr)
|
|
||||||
#endif /* (DEBUG) & DEBUG_PRINT */
|
#endif /* (DEBUG) & DEBUG_PRINT */
|
||||||
|
|
||||||
#endif
|
#endif /* UIP_DEBUG_H */
|
||||||
|
|
|
@ -163,6 +163,14 @@ void uip_log(char *msg);
|
||||||
#define COMPRESSION_THRESHOLD 0
|
#define COMPRESSION_THRESHOLD 0
|
||||||
#endif
|
#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
|
/** \name General variables
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
@ -1271,11 +1279,6 @@ output(const uip_lladdr_t *localdest)
|
||||||
/* The MAC address of the destination of the packet */
|
/* The MAC address of the destination of the packet */
|
||||||
linkaddr_t dest;
|
linkaddr_t dest;
|
||||||
|
|
||||||
#if SICSLOWPAN_CONF_FRAG
|
|
||||||
/* Number of bytes processed. */
|
|
||||||
uint16_t processed_ip_out_len;
|
|
||||||
#endif /* SICSLOWPAN_CONF_FRAG */
|
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
uncomp_hdr_len = 0;
|
uncomp_hdr_len = 0;
|
||||||
packetbuf_hdr_len = 0;
|
packetbuf_hdr_len = 0;
|
||||||
|
@ -1336,21 +1339,23 @@ output(const uip_lladdr_t *localdest)
|
||||||
/* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC.
|
/* 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
|
* We calculate it here only to make a better decision of whether the outgoing packet
|
||||||
* needs to be fragmented or not. */
|
* needs to be fragmented or not. */
|
||||||
#define USE_FRAMER_HDRLEN 1
|
#ifndef SICSLOWPAN_USE_FIXED_HDRLEN
|
||||||
#if USE_FRAMER_HDRLEN
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
|
||||||
framer_hdrlen = NETSTACK_FRAMER.length();
|
framer_hdrlen = NETSTACK_FRAMER.length();
|
||||||
if(framer_hdrlen < 0) {
|
if(framer_hdrlen < 0) {
|
||||||
/* Framing failed, we assume the maximum header length */
|
/* Framing failed, we assume the maximum header length */
|
||||||
framer_hdrlen = 21;
|
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
||||||
}
|
}
|
||||||
#else /* USE_FRAMER_HDRLEN */
|
#else /* USE_FRAMER_HDRLEN */
|
||||||
framer_hdrlen = 21;
|
framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
|
||||||
#endif /* USE_FRAMER_HDRLEN */
|
#endif /* USE_FRAMER_HDRLEN */
|
||||||
|
|
||||||
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
||||||
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
|
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
|
||||||
#if SICSLOWPAN_CONF_FRAG
|
#if SICSLOWPAN_CONF_FRAG
|
||||||
|
/* Number of bytes processed. */
|
||||||
|
uint16_t processed_ip_out_len;
|
||||||
|
|
||||||
struct queuebuf *q;
|
struct queuebuf *q;
|
||||||
uint16_t frag_tag;
|
uint16_t frag_tag;
|
||||||
|
|
||||||
|
|
|
@ -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
|
#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 */
|
/* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */
|
||||||
static void
|
static int
|
||||||
extract_lladdr_aligned(uip_lladdr_t *dest) {
|
extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) {
|
||||||
if(dest != NULL && nd6_opt_llao != NULL) {
|
if(dest != NULL && nd6_opt_llao != NULL) {
|
||||||
memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
|
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 */
|
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
|
@ -199,17 +201,23 @@ ns_input(void)
|
||||||
goto discard;
|
goto discard;
|
||||||
} else {
|
} else {
|
||||||
#endif /*UIP_CONF_IPV6_CHECKS */
|
#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);
|
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
|
||||||
if(nbr == NULL) {
|
if(nbr == NULL) {
|
||||||
uip_lladdr_t lladdr_aligned;
|
|
||||||
extract_lladdr_aligned(&lladdr_aligned);
|
|
||||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
||||||
0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
||||||
} else {
|
} 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],
|
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
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;
|
nbr->state = NBR_STALE;
|
||||||
} else {
|
} else {
|
||||||
if(nbr->state == NBR_INCOMPLETE) {
|
if(nbr->state == NBR_INCOMPLETE) {
|
||||||
|
@ -428,6 +436,7 @@ na_input(void)
|
||||||
uint8_t is_router;
|
uint8_t is_router;
|
||||||
uint8_t is_solicited;
|
uint8_t is_solicited;
|
||||||
uint8_t is_override;
|
uint8_t is_override;
|
||||||
|
uip_lladdr_t lladdr_aligned;
|
||||||
|
|
||||||
PRINTF("Received NA from ");
|
PRINTF("Received NA from ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
|
@ -490,23 +499,29 @@ na_input(void)
|
||||||
PRINTF("NA received is bad\n");
|
PRINTF("NA received is bad\n");
|
||||||
goto discard;
|
goto discard;
|
||||||
} else {
|
} else {
|
||||||
uip_lladdr_t *lladdr;
|
const uip_lladdr_t *lladdr;
|
||||||
nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
|
nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
|
||||||
lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
|
|
||||||
if(nbr == NULL) {
|
if(nbr == NULL) {
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
if(nd6_opt_llao != 0) {
|
lladdr = uip_ds6_nbr_get_ll(nbr);
|
||||||
|
if(lladdr == NULL) {
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
if(nd6_opt_llao != NULL) {
|
||||||
is_llchange =
|
is_llchange =
|
||||||
memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr,
|
memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr,
|
||||||
UIP_LLADDR_LEN);
|
UIP_LLADDR_LEN);
|
||||||
}
|
}
|
||||||
if(nbr->state == NBR_INCOMPLETE) {
|
if(nbr->state == NBR_INCOMPLETE) {
|
||||||
if(nd6_opt_llao == NULL) {
|
if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) {
|
||||||
UIP_LLADDR_LEN);
|
/* failed to update the lladdr */
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
|
||||||
if(is_solicited) {
|
if(is_solicited) {
|
||||||
nbr->state = NBR_REACHABLE;
|
nbr->state = NBR_REACHABLE;
|
||||||
nbr->nscount = 0;
|
nbr->nscount = 0;
|
||||||
|
@ -518,27 +533,29 @@ na_input(void)
|
||||||
nbr->state = NBR_STALE;
|
nbr->state = NBR_STALE;
|
||||||
}
|
}
|
||||||
nbr->isrouter = is_router;
|
nbr->isrouter = is_router;
|
||||||
} else {
|
} else { /* NBR is not INCOMPLETE */
|
||||||
if(!is_override && is_llchange) {
|
if(!is_override && is_llchange) {
|
||||||
if(nbr->state == NBR_REACHABLE) {
|
if(nbr->state == NBR_REACHABLE) {
|
||||||
nbr->state = NBR_STALE;
|
nbr->state = NBR_STALE;
|
||||||
}
|
}
|
||||||
goto discard;
|
goto discard;
|
||||||
} else {
|
} else {
|
||||||
if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange)
|
/**
|
||||||
|| nd6_opt_llao == 0) {
|
* If this is an cache override, or same lladdr, or no llao -
|
||||||
if(nd6_opt_llao != 0) {
|
* do updates of nbr states.
|
||||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
*/
|
||||||
UIP_LLADDR_LEN);
|
if(is_override || !is_llchange || nd6_opt_llao == NULL) {
|
||||||
|
if(nd6_opt_llao != NULL && is_llchange) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(is_solicited) {
|
if(is_solicited) {
|
||||||
nbr->state = NBR_REACHABLE;
|
nbr->state = NBR_REACHABLE;
|
||||||
/* reachable time is stored in ms */
|
/* reachable time is stored in ms */
|
||||||
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
|
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
|
||||||
} else {
|
|
||||||
if(nd6_opt_llao != 0 && is_llchange) {
|
|
||||||
nbr->state = NBR_STALE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,15 +649,19 @@ rs_input(void)
|
||||||
} else {
|
} else {
|
||||||
#endif /*UIP_CONF_IPV6_CHECKS */
|
#endif /*UIP_CONF_IPV6_CHECKS */
|
||||||
uip_lladdr_t lladdr_aligned;
|
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) {
|
if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
|
||||||
/* we need to add the neighbor */
|
/* we need to add the neighbor */
|
||||||
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
||||||
0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
||||||
} else {
|
} else {
|
||||||
/* If LL address changed, set neighbor state to stale */
|
/* 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],
|
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_t nbr_data = *nbr;
|
||||||
uip_ds6_nbr_rm(nbr);
|
uip_ds6_nbr_rm(nbr);
|
||||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
||||||
|
@ -826,6 +847,8 @@ uip_nd6_rs_output(void)
|
||||||
void
|
void
|
||||||
ra_input(void)
|
ra_input(void)
|
||||||
{
|
{
|
||||||
|
uip_lladdr_t lladdr_aligned;
|
||||||
|
|
||||||
PRINTF("Received RA from ");
|
PRINTF("Received RA from ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
PRINTF(" to ");
|
PRINTF(" to ");
|
||||||
|
@ -870,20 +893,28 @@ ra_input(void)
|
||||||
PRINTF("Processing SLLAO option in RA\n");
|
PRINTF("Processing SLLAO option in RA\n");
|
||||||
nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
|
nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
|
||||||
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
|
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) {
|
if(nbr == NULL) {
|
||||||
uip_lladdr_t lladdr_aligned;
|
|
||||||
extract_lladdr_aligned(&lladdr_aligned);
|
|
||||||
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
|
||||||
1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
|
||||||
} else {
|
} 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(nbr->state == NBR_INCOMPLETE) {
|
if(nbr->state == NBR_INCOMPLETE) {
|
||||||
nbr->state = NBR_STALE;
|
nbr->state = NBR_STALE;
|
||||||
}
|
}
|
||||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||||
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
/* change of link layer address */
|
||||||
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;
|
nbr->state = NBR_STALE;
|
||||||
}
|
}
|
||||||
nbr->isrouter = 1;
|
nbr->isrouter = 1;
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#include "net/mac/frame802154e-ie.h"
|
#include "net/mac/frame802154e-ie.h"
|
||||||
|
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#include "net/ip/uip-debug.h"
|
#include "net/net-debug.h"
|
||||||
|
|
||||||
/* c.f. IEEE 802.15.4e Table 4b */
|
/* c.f. IEEE 802.15.4e Table 4b */
|
||||||
enum ieee802154e_header_ie_id {
|
enum ieee802154e_header_ie_id {
|
||||||
|
|
|
@ -36,6 +36,7 @@ It has been tested on the following platforms:
|
||||||
* NXP JN516x (`jn516x`, tested on hardware)
|
* NXP JN516x (`jn516x`, tested on hardware)
|
||||||
* Tmote Sky (`sky`, tested on hardware and in cooja)
|
* Tmote Sky (`sky`, tested on hardware and in cooja)
|
||||||
* Zolertia Z1 (`z1`, tested in cooja only)
|
* Zolertia Z1 (`z1`, tested in cooja only)
|
||||||
|
* CC2538DK (`cc2538dk`, tested on hardware)
|
||||||
|
|
||||||
This implementation was present at the ETSI Plugtest
|
This implementation was present at the ETSI Plugtest
|
||||||
event in Prague in July 2015, and did successfully inter-operate with all
|
event in Prague in July 2015, and did successfully inter-operate with all
|
||||||
|
@ -76,7 +77,7 @@ Orchestra is implemented in:
|
||||||
|
|
||||||
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
|
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
|
||||||
To use TSCH, first make sure your platform supports it.
|
To use TSCH, first make sure your platform supports it.
|
||||||
Currently, `jn516x`, `sky` and `z1` are the supported platforms.
|
Currently, `jn516x`, `sky`, `z1` and `cc2538dk` are the supported platforms.
|
||||||
To add your own, we refer the reader to the next section.
|
To add your own, we refer the reader to the next section.
|
||||||
|
|
||||||
To add TSCH to your application, first include the TSCH module from your makefile with:
|
To add TSCH to your application, first include the TSCH module from your makefile with:
|
||||||
|
@ -162,7 +163,7 @@ Finally, one can also implement his own scheduler, centralized or distributed, b
|
||||||
## Porting TSCH to a new platform
|
## Porting TSCH to a new platform
|
||||||
|
|
||||||
Porting TSCH to a new platform requires a few new features in the radio driver, a number of timing-related configuration paramters.
|
Porting TSCH to a new platform requires a few new features in the radio driver, a number of timing-related configuration paramters.
|
||||||
The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`.
|
The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`, `cc2538dk`.
|
||||||
|
|
||||||
### Radio features required for TSCH
|
### Radio features required for TSCH
|
||||||
|
|
||||||
|
|
|
@ -175,4 +175,11 @@
|
||||||
#define TSCH_ADAPTIVE_TIMESYNC 0
|
#define TSCH_ADAPTIVE_TIMESYNC 0
|
||||||
#endif
|
#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 /* TSCH_CONF_HW_FRAME_FILTERING */
|
||||||
|
|
||||||
#endif /* __TSCH_CONF_H__ */
|
#endif /* __TSCH_CONF_H__ */
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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 */
|
#if TSCH_LOG_LEVEL >= 2 /* Skip this file for log levels 0 or 1 */
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#endif /* TSCH_LOG_LEVEL */
|
||||||
#include "net/ip/uip-debug.h"
|
#include "net/net-debug.h"
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Construct enhanced ACK packet and return ACK length */
|
/* Construct enhanced ACK packet and return ACK length */
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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 */
|
/* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */
|
||||||
#if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0
|
#if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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 */
|
/* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#endif /* TSCH_LOG_LEVEL */
|
||||||
#include "net/ip/uip-debug.h"
|
#include "net/net-debug.h"
|
||||||
|
|
||||||
/* Pre-allocated space for links */
|
/* Pre-allocated space for links */
|
||||||
MEMB(link_memb, struct tsch_link, TSCH_SCHEDULE_MAX_LINKS);
|
MEMB(link_memb, struct tsch_link, TSCH_SCHEDULE_MAX_LINKS);
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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
|
/* The two keys K1 and K2 from 6TiSCH minimal configuration
|
||||||
* K1: well-known, used for EBs
|
* K1: well-known, used for EBs
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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
|
/* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH
|
||||||
* timeslot events */
|
* timeslot events */
|
||||||
|
@ -493,9 +493,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
uint8_t ack_hdrlen;
|
uint8_t ack_hdrlen;
|
||||||
frame802154_t frame;
|
frame802154_t frame;
|
||||||
|
|
||||||
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_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));
|
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 */
|
/* Unicast: wait for ack after tx: sleep until ack time */
|
||||||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
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");
|
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
||||||
|
@ -514,9 +516,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
TSCH_DEBUG_TX_EVENT();
|
TSCH_DEBUG_TX_EVENT();
|
||||||
NETSTACK_RADIO.off();
|
NETSTACK_RADIO.off();
|
||||||
|
|
||||||
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
/* Leaving promiscuous mode */
|
/* Leaving promiscuous mode */
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_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);
|
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode | RADIO_RX_MODE_ADDRESS_FILTER);
|
||||||
|
#endif /* TSCH_HW_FRAME_FILTERING */
|
||||||
|
|
||||||
/* Read ack frame */
|
/* Read ack frame */
|
||||||
ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf));
|
ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf));
|
||||||
|
@ -737,7 +741,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
if(linkaddr_cmp(&destination_address, &linkaddr_node_addr)
|
if(linkaddr_cmp(&destination_address, &linkaddr_node_addr)
|
||||||
|| linkaddr_cmp(&destination_address, &linkaddr_null)) {
|
|| linkaddr_cmp(&destination_address, &linkaddr_null)) {
|
||||||
int do_nack = 0;
|
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
|
#if TSCH_TIMESYNC_REMOVE_JITTER
|
||||||
/* remove jitter due to measurement errors */
|
/* remove jitter due to measurement errors */
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
#else /* TSCH_LOG_LEVEL */
|
#else /* TSCH_LOG_LEVEL */
|
||||||
#define DEBUG DEBUG_NONE
|
#define DEBUG DEBUG_NONE
|
||||||
#endif /* TSCH_LOG_LEVEL */
|
#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
|
/* 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 */
|
* not sent from an upper layer and don't have a valid packet_sent callback */
|
||||||
|
|
|
@ -178,6 +178,25 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static nbr_table_key_t *
|
static nbr_table_key_t *
|
||||||
nbr_table_allocate(nbr_table_reason_t reason, void *data)
|
nbr_table_allocate(nbr_table_reason_t reason, void *data)
|
||||||
{
|
{
|
||||||
|
@ -253,21 +272,7 @@ nbr_table_allocate(nbr_table_reason_t reason, void *data)
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
/* Reuse least used item */
|
/* Reuse least used item */
|
||||||
int i;
|
remove_key(least_used_key);
|
||||||
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 */
|
|
||||||
return least_used_key;
|
return least_used_key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,6 +421,39 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item)
|
||||||
return key != NULL ? &key->lladdr : NULL;
|
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
|
#if DEBUG
|
||||||
static void
|
static void
|
||||||
print_table()
|
print_table()
|
||||||
|
|
|
@ -109,6 +109,7 @@ int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item);
|
||||||
/** \name Neighbor tables: address manipulation */
|
/** \name Neighbor tables: address manipulation */
|
||||||
/** @{ */
|
/** @{ */
|
||||||
linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item);
|
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_ */
|
#endif /* NBR_TABLE_H_ */
|
||||||
|
|
65
core/net/net-debug.c
Normal file
65
core/net/net-debug.c
Normal file
|
@ -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 <nvt@sics.se>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
* Simon Duquennoy <simon.duquennoy@inria.fr>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
86
core/net/net-debug.h
Normal file
86
core/net/net-debug.h
Normal file
|
@ -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 <nvt@sics.se>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
* Simon Duquennoy <simon.duquennoy@inria.fr>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_DEBUG_H
|
||||||
|
#define NET_DEBUG_H
|
||||||
|
|
||||||
|
#include "net/ip/uip.h"
|
||||||
|
#include "net/linkaddr.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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 <avr/pgmspace.h>
|
||||||
|
#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 */
|
5
core/net/rime/chameleon-raw.c
Normal file → Executable file
5
core/net/rime/chameleon-raw.c
Normal file → Executable file
|
@ -205,10 +205,7 @@ hdrsize(const struct packetbuf_attrlist *a)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
|
#endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
|
||||||
len = a->len;
|
len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);
|
||||||
if(len < 8) {
|
|
||||||
len = 8;
|
|
||||||
}
|
|
||||||
size += len;
|
size += len;
|
||||||
}
|
}
|
||||||
return size / 8;
|
return size / 8;
|
||||||
|
|
|
@ -245,10 +245,10 @@ do_poll(void)
|
||||||
static void
|
static void
|
||||||
do_event(void)
|
do_event(void)
|
||||||
{
|
{
|
||||||
static process_event_t ev;
|
process_event_t ev;
|
||||||
static process_data_t data;
|
process_data_t data;
|
||||||
static struct process *receiver;
|
struct process *receiver;
|
||||||
static struct process *p;
|
struct process *p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there are any events in the queue, take the first one and walk
|
* If there are any events in the queue, take the first one and walk
|
||||||
|
@ -321,7 +321,7 @@ process_nevents(void)
|
||||||
int
|
int
|
||||||
process_post(struct process *p, process_event_t ev, process_data_t data)
|
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) {
|
if(PROCESS_CURRENT() == NULL) {
|
||||||
PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n",
|
PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n",
|
||||||
|
|
|
@ -55,10 +55,12 @@
|
||||||
|
|
||||||
#include "contiki-conf.h"
|
#include "contiki-conf.h"
|
||||||
|
|
||||||
#ifndef RTIMER_CLOCK_LT
|
#ifndef RTIMER_CLOCK_DIFF
|
||||||
typedef unsigned short rtimer_clock_t;
|
typedef unsigned short rtimer_clock_t;
|
||||||
#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0)
|
#define RTIMER_CLOCK_DIFF(a,b) ((signed short)((a)-(b)))
|
||||||
#endif /* RTIMER_CLOCK_LT */
|
#endif /* RTIMER_CLOCK_DIFF */
|
||||||
|
|
||||||
|
#define RTIMER_CLOCK_LT(a, b) (RTIMER_CLOCK_DIFF((a),(b)) < 0)
|
||||||
|
|
||||||
#include "rtimer-arch.h"
|
#include "rtimer-arch.h"
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,6 @@
|
||||||
# Author: Oliver Schmidt <ol.sc@web.de>
|
# Author: Oliver Schmidt <ol.sc@web.de>
|
||||||
#
|
#
|
||||||
|
|
||||||
ifndef CC65_HOME
|
|
||||||
${error CC65_HOME not defined! You must specify where cc65 resides}
|
|
||||||
endif
|
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
|
||||||
CONTIKI_TARGET_DIRS = . lib sys
|
CONTIKI_TARGET_DIRS = . lib sys
|
||||||
|
@ -70,3 +66,5 @@ ASFLAGS = -t $(TARGET)
|
||||||
CFLAGS += -t $(TARGET) -Or -W -unused-param
|
CFLAGS += -t $(TARGET) -Or -W -unused-param
|
||||||
LDFLAGS = -t $(TARGET) -m contiki-$(TARGET).map -D __STACKSIZE__=0x200
|
LDFLAGS = -t $(TARGET) -m contiki-$(TARGET).map -D __STACKSIZE__=0x200
|
||||||
AROPTS = a
|
AROPTS = a
|
||||||
|
|
||||||
|
CC65_TARGET_DIR := $(shell $(CC) --print-target-path)/$(TARGET)
|
||||||
|
|
|
@ -46,7 +46,7 @@ typedef uint32_t clock_time_t;
|
||||||
typedef uint16_t uip_stats_t;
|
typedef uint16_t uip_stats_t;
|
||||||
|
|
||||||
typedef uint32_t rtimer_clock_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);
|
rtimer_clock_t rtimer_arch_now(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -115,8 +115,7 @@ CUSTOM_RULE_LINK=1
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
### This rule is used to generate the correct linker script
|
### This rule is used to generate the correct linker script
|
||||||
LDGENFLAGS += $(addprefix -D,$(subst $(COMMA), ,$(DEFINES)))
|
LDGENFLAGS += $(CFLAGS)
|
||||||
LDGENFLAGS += $(addprefix -I,$(SOURCEDIRS))
|
|
||||||
LDGENFLAGS += -imacros "contiki-conf.h" -imacros "dev/cc2538-dev.h"
|
LDGENFLAGS += -imacros "contiki-conf.h" -imacros "dev/cc2538-dev.h"
|
||||||
LDGENFLAGS += -imacros "dev/flash.h" -imacros "cfs-coffee-arch.h"
|
LDGENFLAGS += -imacros "dev/flash.h" -imacros "cfs-coffee-arch.h"
|
||||||
LDGENFLAGS += -x c -P -E
|
LDGENFLAGS += -x c -P -E
|
||||||
|
|
|
@ -102,6 +102,8 @@
|
||||||
/** Maximal amount of log table entries read in one batch */
|
/** Maximal amount of log table entries read in one batch */
|
||||||
#ifdef COFFEE_CONF_LOG_TABLE_LIMIT
|
#ifdef COFFEE_CONF_LOG_TABLE_LIMIT
|
||||||
#define COFFEE_LOG_TABLE_LIMIT COFFEE_CONF_LOG_TABLE_LIMIT
|
#define COFFEE_LOG_TABLE_LIMIT COFFEE_CONF_LOG_TABLE_LIMIT
|
||||||
|
#else
|
||||||
|
#define COFFEE_LOG_TABLE_LIMIT 16
|
||||||
#endif
|
#endif
|
||||||
/** Default reserved file size */
|
/** Default reserved file size */
|
||||||
#ifdef COFFEE_CONF_DYN_SIZE
|
#ifdef COFFEE_CONF_DYN_SIZE
|
||||||
|
@ -112,6 +114,8 @@
|
||||||
/** Default micro-log size */
|
/** Default micro-log size */
|
||||||
#ifdef COFFEE_CONF_LOG_SIZE
|
#ifdef COFFEE_CONF_LOG_SIZE
|
||||||
#define COFFEE_LOG_SIZE COFFEE_CONF_LOG_SIZE
|
#define COFFEE_LOG_SIZE COFFEE_CONF_LOG_SIZE
|
||||||
|
#else
|
||||||
|
#define COFFEE_LOG_SIZE (4 * COFFEE_PAGE_SIZE)
|
||||||
#endif
|
#endif
|
||||||
/** Whether Coffee will use micro logs */
|
/** Whether Coffee will use micro logs */
|
||||||
#ifdef COFFEE_CONF_MICRO_LOGS
|
#ifdef COFFEE_CONF_MICRO_LOGS
|
||||||
|
|
|
@ -119,6 +119,25 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
|
||||||
#else
|
#else
|
||||||
#define CC2538_RF_AUTOACK 1
|
#define CC2538_RF_AUTOACK 1
|
||||||
#endif
|
#endif
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
* MAC timer
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
/* Timer conversion */
|
||||||
|
#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))); \
|
||||||
|
} while(0)
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* 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_flags;
|
||||||
static uint8_t rf_channel = CC2538_RF_CHANNEL;
|
static uint8_t rf_channel = CC2538_RF_CHANNEL;
|
||||||
|
@ -329,6 +348,28 @@ set_frame_filtering(uint8_t enable)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
set_poll_mode(uint8_t enable)
|
||||||
|
{
|
||||||
|
poll_mode = enable;
|
||||||
|
|
||||||
|
if(enable) {
|
||||||
|
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
|
||||||
|
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)
|
set_auto_ack(uint8_t enable)
|
||||||
{
|
{
|
||||||
if(enable) {
|
if(enable) {
|
||||||
|
@ -395,7 +436,9 @@ off(void)
|
||||||
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
|
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
|
||||||
while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
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 */
|
/* Don't turn off if we are off as this will trigger a Strobe Error */
|
||||||
if(REG(RFCORE_XREG_RXENABLE) != 0) {
|
if(REG(RFCORE_XREG_RXENABLE) != 0) {
|
||||||
|
@ -459,10 +502,6 @@ init(void)
|
||||||
|
|
||||||
set_channel(rf_channel);
|
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 */
|
/* Acknowledge all RF Error interrupts */
|
||||||
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
|
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
|
||||||
nvic_interrupt_enable(NVIC_INT_RF_ERR);
|
nvic_interrupt_enable(NVIC_INT_RF_ERR);
|
||||||
|
@ -488,6 +527,8 @@ init(void)
|
||||||
*/
|
*/
|
||||||
udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA);
|
udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_poll_mode(poll_mode);
|
||||||
|
|
||||||
process_start(&cc2538_rf_process, NULL);
|
process_start(&cc2538_rf_process, NULL);
|
||||||
|
|
||||||
|
@ -571,9 +612,11 @@ transmit(unsigned short transmit_len)
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(channel_clear() == CC2538_RF_CCA_BUSY) {
|
if(send_on_cca) {
|
||||||
RIMESTATS_ADD(contentiondrop);
|
if(channel_clear() == CC2538_RF_CCA_BUSY) {
|
||||||
return RADIO_TX_COLLISION;
|
RIMESTATS_ADD(contentiondrop);
|
||||||
|
return RADIO_TX_COLLISION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -630,8 +673,6 @@ read(void *buf, unsigned short bufsize)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
uint8_t crc_corr;
|
|
||||||
int8_t rssi;
|
|
||||||
|
|
||||||
PRINTF("RF: Read\n");
|
PRINTF("RF: Read\n");
|
||||||
|
|
||||||
|
@ -731,14 +772,18 @@ read(void *buf, unsigned short bufsize)
|
||||||
flush();
|
flush();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
|
if(!poll_mode) {
|
||||||
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
|
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
|
||||||
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
|
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
|
||||||
process_poll(&cc2538_rf_process);
|
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
|
||||||
} else {
|
process_poll(&cc2538_rf_process);
|
||||||
CC2538_RF_CSP_ISFLUSHRX();
|
} else {
|
||||||
|
CC2538_RF_CSP_ISFLUSHRX();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CC2538_RF_CSP_ISFLUSHRX();
|
||||||
|
|
||||||
return (len);
|
return (len);
|
||||||
}
|
}
|
||||||
|
@ -796,6 +841,15 @@ get_value(radio_param_t param, radio_value_t *value)
|
||||||
if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) {
|
if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) {
|
||||||
*value |= RADIO_RX_MODE_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;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
*value = get_tx_power();
|
*value = get_tx_power();
|
||||||
|
@ -806,6 +860,12 @@ get_value(radio_param_t param, radio_value_t *value)
|
||||||
case RADIO_PARAM_RSSI:
|
case RADIO_PARAM_RSSI:
|
||||||
*value = get_rssi();
|
*value = get_rssi();
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
|
case RADIO_PARAM_LAST_RSSI:
|
||||||
|
*value = rssi;
|
||||||
|
return RADIO_RESULT_OK;
|
||||||
|
case RADIO_PARAM_LAST_LINK_QUALITY:
|
||||||
|
*value = crc_corr & LQI_BIT_MASK;
|
||||||
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_CONST_CHANNEL_MIN:
|
case RADIO_CONST_CHANNEL_MIN:
|
||||||
*value = CC2538_RF_CHANNEL_MIN;
|
*value = CC2538_RF_CHANNEL_MIN;
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
|
@ -854,13 +914,21 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_RX_MODE:
|
case RADIO_PARAM_RX_MODE:
|
||||||
if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
|
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;
|
return RADIO_RESULT_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
|
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
|
||||||
set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 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;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
|
if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
|
||||||
|
@ -895,6 +963,15 @@ get_object(radio_param_t param, void *dest, size_t size)
|
||||||
|
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
|
||||||
|
if(size != sizeof(rtimer_clock_t) || !dest) {
|
||||||
|
return RADIO_RESULT_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
*(rtimer_clock_t*)dest = get_sfd_timestamp();
|
||||||
|
return RADIO_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return RADIO_RESULT_NOT_SUPPORTED;
|
return RADIO_RESULT_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -950,15 +1027,18 @@ PROCESS_THREAD(cc2538_rf_process, ev, data)
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
while(1) {
|
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();
|
if(!poll_mode) {
|
||||||
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
packetbuf_clear();
|
||||||
|
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||||
|
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
packetbuf_set_datalen(len);
|
packetbuf_set_datalen(len);
|
||||||
|
|
||||||
NETSTACK_RDC.input();
|
NETSTACK_RDC.input();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we were polled due to an RF error, reset the transceiver */
|
/* If we were polled due to an RF error, reset the transceiver */
|
||||||
|
@ -995,8 +1075,10 @@ void
|
||||||
cc2538_rf_rx_tx_isr(void)
|
cc2538_rf_rx_tx_isr(void)
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||||
|
|
||||||
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 so we can safely wipe out the entire SFR */
|
||||||
REG(RFCORE_SFR_RFIRQF0) = 0;
|
REG(RFCORE_SFR_RFIRQF0) = 0;
|
||||||
|
@ -1045,4 +1127,44 @@ cc2538_rf_set_promiscous_mode(char p)
|
||||||
set_frame_filtering(p);
|
set_frame_filtering(p);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t get_sfd_timestamp(void)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2;
|
||||||
|
sfd |= (buffer << 32);
|
||||||
|
|
||||||
|
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_SYNC;
|
||||||
|
REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN);
|
||||||
|
while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE));
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -65,6 +65,20 @@
|
||||||
|
|
||||||
#define RTIMER_ARCH_SECOND 32768
|
#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() */
|
/** \sa RTIMER_NOW() */
|
||||||
rtimer_clock_t rtimer_arch_now(void);
|
rtimer_clock_t rtimer_arch_now(void);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,15 @@ CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES)
|
||||||
TARGET_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS)
|
TARGET_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS)
|
||||||
TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES)))
|
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
|
### Don't treat the .elf as intermediate
|
||||||
.PRECIOUS: %.elf %.hex %.bin
|
.PRECIOUS: %.elf %.hex %.bin
|
||||||
|
|
||||||
|
@ -125,3 +134,31 @@ 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 "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;}'
|
@$(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
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
|
@ -55,8 +55,8 @@ typedef unsigned short uip_stats_t;
|
||||||
|
|
||||||
typedef uint32_t clock_time_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;
|
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
|
#endif
|
||||||
|
|
262
cpu/nrf52832/Makefile.nrf52832
Normal file
262
cpu/nrf52832/Makefile.nrf52832
Normal file
|
@ -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
|
238
cpu/nrf52832/ble/ble-core.c
Normal file
238
cpu/nrf52832/ble/ble-core.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#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 <stdio.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
61
cpu/nrf52832/ble/ble-core.h
Normal file
61
cpu/nrf52832/ble/ble-core.h
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#ifndef DEV_BLE_H_
|
||||||
|
#define DEV_BLE_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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_ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
386
cpu/nrf52832/ble/ble-mac.c
Normal file
386
cpu/nrf52832/ble/ble-mac.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <ble-core.h>
|
||||||
|
#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 <stdio.h>
|
||||||
|
#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,
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
53
cpu/nrf52832/ble/ble-mac.h
Normal file
53
cpu/nrf52832/ble/ble-mac.h
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#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_ */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
171
cpu/nrf52832/dev/clock.c
Normal file
171
cpu/nrf52832/dev/clock.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
67
cpu/nrf52832/dev/lpm.h
Normal file
67
cpu/nrf52832/dev/lpm.h
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#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_ */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
90
cpu/nrf52832/dev/random.c
Normal file
90
cpu/nrf52832/dev/random.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <nrf_drv_rng.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
118
cpu/nrf52832/dev/uart0.c
Normal file
118
cpu/nrf52832/dev/uart0.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
57
cpu/nrf52832/dev/uart0.h
Normal file
57
cpu/nrf52832/dev/uart0.h
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#ifndef UART_0_H
|
||||||
|
#define UART_0_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#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 */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
93
cpu/nrf52832/dev/watchdog.c
Normal file
93
cpu/nrf52832/dev/watchdog.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
#include <nrf_drv_wdt.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
2
cpu/nrf52832/erase.jlink
Normal file
2
cpu/nrf52832/erase.jlink
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
erase
|
||||||
|
q
|
4
cpu/nrf52832/flash.jlink
Normal file
4
cpu/nrf52832/flash.jlink
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
loadfile #OUTPUT_FILENAME#
|
||||||
|
r
|
||||||
|
g
|
||||||
|
q
|
12
cpu/nrf52832/ld/nrf52-pca10036-sd.ld
Normal file
12
cpu/nrf52832/ld/nrf52-pca10036-sd.ld
Normal file
|
@ -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"
|
12
cpu/nrf52832/ld/nrf52-pca10040-sd.ld
Normal file
12
cpu/nrf52832/ld/nrf52-pca10040-sd.ld
Normal file
|
@ -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"
|
12
cpu/nrf52832/ld/nrf52.ld
Normal file
12
cpu/nrf52832/ld/nrf52.ld
Normal file
|
@ -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"
|
48
cpu/nrf52832/mtarch.h
Normal file
48
cpu/nrf52832/mtarch.h
Normal file
|
@ -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 - <oikonomou@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
#ifndef __MTARCH_H__
|
||||||
|
#define __MTARCH_H__
|
||||||
|
|
||||||
|
struct mtarch_thread {
|
||||||
|
unsigned char *sp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __MTARCH_H__ */
|
70
cpu/nrf52832/putchar.c
Normal file
70
cpu/nrf52832/putchar.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
110
cpu/nrf52832/rtimer-arch.c
Normal file
110
cpu/nrf52832/rtimer-arch.c
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
52
cpu/nrf52832/rtimer-arch.h
Normal file
52
cpu/nrf52832/rtimer-arch.h
Normal file
|
@ -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 <wojciech.bober@nordicsemi.no>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#ifndef RTIMER_ARCH_H_
|
||||||
|
#define RTIMER_ARCH_H_
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#include "contiki.h"
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
rtimer_clock_t rtimer_arch_now(void);
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#endif /* RTIMER_ARCH_H_ */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
12
examples/cfs-coffee/Makefile
Normal file
12
examples/cfs-coffee/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
|
||||||
|
CONTIKI = ../..
|
||||||
|
|
||||||
|
all: test-cfs test-coffee example-coffee
|
||||||
|
|
||||||
|
CONTIKI_WITH_RIME = 1
|
||||||
|
|
||||||
|
ifeq ($(TARGET),avr-raven)
|
||||||
|
COFFEE_FILES = 4
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(CONTIKI)/Makefile.include
|
29
examples/cfs-coffee/README.md
Normal file
29
examples/cfs-coffee/README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
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
|
||||||
|
* cc2538dk
|
||||||
|
* openmote-cc2538
|
||||||
|
* zoul
|
||||||
|
|
||||||
|
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.
|
|
@ -28,31 +28,31 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
* Example on how to use CFS/Coffee.
|
* Example on how to use CFS/Coffee.
|
||||||
* \author
|
* \author
|
||||||
* Nicolas Tsiftes <nvt@sics.se>
|
* Nicolas Tsiftes <nvt@sics.se>
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
#include "cfs/cfs.h"
|
#include "cfs/cfs.h"
|
||||||
#include "cfs/cfs-coffee.h"
|
#include "cfs/cfs-coffee.h"
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS(example_coffee_process, "Coffee example");
|
PROCESS(example_coffee_process, "Coffee example");
|
||||||
AUTOSTART_PROCESSES(&example_coffee_process);
|
AUTOSTART_PROCESSES(&example_coffee_process);
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
#define FILENAME "test"
|
#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. */
|
e.g., when using Coffee on the storage device for the first time. */
|
||||||
#ifndef NEED_FORMATTING
|
#ifndef NEED_FORMATTING
|
||||||
#define NEED_FORMATTING 0
|
#define NEED_FORMATTING 0
|
||||||
#endif
|
#endif
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
file_test(const char *filename, char *msg)
|
file_test(const char *filename, char *msg)
|
||||||
{
|
{
|
||||||
|
@ -65,12 +65,12 @@ file_test(const char *filename, char *msg)
|
||||||
} record;
|
} record;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Coffee determines the file length by finding the last non-zero byte
|
* 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
|
* 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
|
* with a non-zero, if we are writing multiple records and closing the
|
||||||
* file descriptor in between.
|
* 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.
|
* 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.message[sizeof(record.message) - 1] = '\0';
|
||||||
record.sequence = sequence;
|
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. */
|
reads and writes. */
|
||||||
fd = cfs_open(FILENAME, CFS_WRITE | CFS_APPEND | CFS_READ);
|
fd = cfs_open(FILENAME, CFS_WRITE | CFS_APPEND | CFS_READ);
|
||||||
if(fd < 0) {
|
if(fd < 0) {
|
||||||
|
@ -103,7 +103,7 @@ file_test(const char *filename, char *msg)
|
||||||
printf("Wrote message \"%s\", sequence %u\n",
|
printf("Wrote message \"%s\", sequence %u\n",
|
||||||
record.message, record.sequence);
|
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. */
|
beginning of the file. */
|
||||||
if(cfs_seek(fd, 0, CFS_SEEK_SET) != 0) {
|
if(cfs_seek(fd, 0, CFS_SEEK_SET) != 0) {
|
||||||
printf("seek failed\n");
|
printf("seek failed\n");
|
||||||
|
@ -133,7 +133,7 @@ file_test(const char *filename, char *msg)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
dir_test(void)
|
dir_test(void)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ dir_test(void)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS_THREAD(example_coffee_process, ev, data)
|
PROCESS_THREAD(example_coffee_process, ev, data)
|
||||||
{
|
{
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
40
examples/cfs-coffee/project-conf.h
Normal file
40
examples/cfs-coffee/project-conf.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#ifndef PROJECT_CONF_H_
|
||||||
|
#define PROJECT_CONF_H_
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#if CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_OPENMOTE_CC2538 || \
|
||||||
|
CONTIKI_TARGET_ZOUL
|
||||||
|
#define COFFEE_CONF_SIZE (CC2538_DEV_FLASH_SIZE / 2)
|
||||||
|
#define COFFEE_CONF_MICRO_LOGS 1
|
||||||
|
#define COFFEE_CONF_APPEND_ONLY 0
|
||||||
|
#endif /* CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL */
|
||||||
|
|
||||||
|
#endif /* PROJECT_CONF_H_ */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
|
@ -29,19 +29,18 @@
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
* A quick program for testing the CFS xmem driver
|
* A quick program for testing the CFS xmem driver
|
||||||
* \author
|
* \author
|
||||||
* Adam Dunkels <adam@sics.se>
|
* Adam Dunkels <adam@sics.se>
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
#include "cfs/cfs.h"
|
#include "cfs/cfs.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS(cfs_process, "Test CFS process");
|
PROCESS(cfs_process, "Test CFS process");
|
||||||
AUTOSTART_PROCESSES(&cfs_process);
|
AUTOSTART_PROCESSES(&cfs_process);
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -55,6 +54,7 @@ PROCESS_THREAD(cfs_process, ev, data)
|
||||||
uint16_t filesize = 65000;
|
uint16_t filesize = 65000;
|
||||||
#define CHUNKSIZE 128
|
#define CHUNKSIZE 128
|
||||||
|
|
||||||
|
cfs_remove("hej");
|
||||||
fd = cfs_open("hej", CFS_WRITE);
|
fd = cfs_open("hej", CFS_WRITE);
|
||||||
if(fd < 0) {
|
if(fd < 0) {
|
||||||
printf("could not open file for writing, aborting\n");
|
printf("could not open file for writing, aborting\n");
|
|
@ -29,14 +29,14 @@
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
* Basic test for CFS/Coffee.
|
* Basic test for CFS/Coffee.
|
||||||
* \author
|
* \author
|
||||||
* Nicolas Tsiftes <nvt@sics.se>
|
* Nicolas Tsiftes <nvt@sics.se>
|
||||||
*/
|
*/
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
#include "cfs/cfs.h"
|
#include "cfs/cfs.h"
|
||||||
#include "cfs/cfs-coffee.h"
|
#include "cfs/cfs-coffee.h"
|
||||||
|
@ -45,14 +45,12 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS(testcoffee_process, "Test CFS/Coffee process");
|
PROCESS(testcoffee_process, "Test CFS/Coffee process");
|
||||||
AUTOSTART_PROCESSES(&testcoffee_process);
|
AUTOSTART_PROCESSES(&testcoffee_process);
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
#define FAIL(x) error = (x); goto end;
|
#define TEST_FAIL(x) error = (x); goto end;
|
||||||
|
|
||||||
#define FILE_SIZE 4096
|
#define FILE_SIZE 4096
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
coffee_test_basic(void)
|
coffee_test_basic(void)
|
||||||
|
@ -62,8 +60,6 @@ coffee_test_basic(void)
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
cfs_remove("T1");
|
|
||||||
|
|
||||||
wfd = rfd = afd = -1;
|
wfd = rfd = afd = -1;
|
||||||
|
|
||||||
for(r = 0; r < sizeof(buf); r++) {
|
for(r = 0; r < sizeof(buf); r++) {
|
||||||
|
@ -73,64 +69,64 @@ coffee_test_basic(void)
|
||||||
/* Test 1: Open for writing. */
|
/* Test 1: Open for writing. */
|
||||||
wfd = cfs_open("T1", CFS_WRITE);
|
wfd = cfs_open("T1", CFS_WRITE);
|
||||||
if(wfd < 0) {
|
if(wfd < 0) {
|
||||||
FAIL(1);
|
TEST_FAIL(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 2 and 3: Write buffer. */
|
/* Test 2 and 3: Write buffer. */
|
||||||
r = cfs_write(wfd, buf, sizeof(buf));
|
r = cfs_write(wfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(2);
|
TEST_FAIL(2);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
FAIL(3);
|
TEST_FAIL(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 4: Deny reading. */
|
/* Test 4: Deny reading. */
|
||||||
r = cfs_read(wfd, buf, sizeof(buf));
|
r = cfs_read(wfd, buf, sizeof(buf));
|
||||||
if(r >= 0) {
|
if(r >= 0) {
|
||||||
FAIL(4);
|
TEST_FAIL(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 5: Open for reading. */
|
/* Test 5: Open for reading. */
|
||||||
rfd = cfs_open("T1", CFS_READ);
|
rfd = cfs_open("T1", CFS_READ);
|
||||||
if(rfd < 0) {
|
if(rfd < 0) {
|
||||||
FAIL(5);
|
TEST_FAIL(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 6: Write to read-only file. */
|
/* Test 6: Write to read-only file. */
|
||||||
r = cfs_write(rfd, buf, sizeof(buf));
|
r = cfs_write(rfd, buf, sizeof(buf));
|
||||||
if(r >= 0) {
|
if(r >= 0) {
|
||||||
FAIL(6);
|
TEST_FAIL(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 7 and 8: Read the buffer written in Test 2. */
|
/* Test 7 and 8: Read the buffer written in Test 2. */
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
r = cfs_read(rfd, buf, sizeof(buf));
|
r = cfs_read(rfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(7);
|
TEST_FAIL(7);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
printf("r=%d\n", r);
|
printf("r=%d\n", r);
|
||||||
FAIL(8);
|
TEST_FAIL(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 9: Verify that the buffer is correct. */
|
/* Test 9: Verify that the buffer is correct. */
|
||||||
for(r = 0; r < sizeof(buf); r++) {
|
for(r = 0; r < sizeof(buf); r++) {
|
||||||
if(buf[r] != r) {
|
if(buf[r] != r) {
|
||||||
printf("r=%d. buf[r]=%d\n", r, buf[r]);
|
printf("r=%d. buf[r]=%d\n", r, buf[r]);
|
||||||
FAIL(9);
|
TEST_FAIL(9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 10: Seek to beginning. */
|
/* Test 10: Seek to beginning. */
|
||||||
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
|
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
|
||||||
FAIL(10);
|
TEST_FAIL(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 11 and 12: Write to the log. */
|
/* Test 11 and 12: Write to the log. */
|
||||||
r = cfs_write(wfd, buf, sizeof(buf));
|
r = cfs_write(wfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(11);
|
TEST_FAIL(11);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
FAIL(12);
|
TEST_FAIL(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 13 and 14: Read the data from the log. */
|
/* Test 13 and 14: Read the data from the log. */
|
||||||
|
@ -138,15 +134,15 @@ coffee_test_basic(void)
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
r = cfs_read(rfd, buf, sizeof(buf));
|
r = cfs_read(rfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(14);
|
TEST_FAIL(13);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
FAIL(15);
|
TEST_FAIL(14);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 16: Verify that the data is correct. */
|
/* Test 16: Verify that the data is correct. */
|
||||||
for(r = 0; r < sizeof(buf); r++) {
|
for(r = 0; r < sizeof(buf); r++) {
|
||||||
if(buf[r] != r) {
|
if(buf[r] != r) {
|
||||||
FAIL(16);
|
TEST_FAIL(15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,16 +151,16 @@ coffee_test_basic(void)
|
||||||
buf[r] = sizeof(buf) - r - 1;
|
buf[r] = sizeof(buf) - r - 1;
|
||||||
}
|
}
|
||||||
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
|
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
|
||||||
FAIL(17);
|
TEST_FAIL(16);
|
||||||
}
|
}
|
||||||
r = cfs_write(wfd, buf, sizeof(buf));
|
r = cfs_write(wfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(18);
|
TEST_FAIL(17);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
FAIL(19);
|
TEST_FAIL(18);
|
||||||
}
|
}
|
||||||
if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) {
|
if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) {
|
||||||
FAIL(20);
|
TEST_FAIL(19);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 21 and 22: Read the reversed buffer. */
|
/* Test 21 and 22: Read the reversed buffer. */
|
||||||
|
@ -172,16 +168,16 @@ coffee_test_basic(void)
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
r = cfs_read(rfd, buf, sizeof(buf));
|
r = cfs_read(rfd, buf, sizeof(buf));
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(21);
|
TEST_FAIL(20);
|
||||||
} else if(r < sizeof(buf)) {
|
} else if(r < sizeof(buf)) {
|
||||||
printf("r = %d\n", r);
|
printf("r = %d\n", r);
|
||||||
FAIL(22);
|
TEST_FAIL(21);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 23: Verify that the data is correct. */
|
/* Test 23: Verify that the data is correct. */
|
||||||
for(r = 0; r < sizeof(buf); r++) {
|
for(r = 0; r < sizeof(buf); r++) {
|
||||||
if(buf[r] != sizeof(buf) - r - 1) {
|
if(buf[r] != sizeof(buf) - r - 1) {
|
||||||
FAIL(23);
|
TEST_FAIL(22);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +185,7 @@ coffee_test_basic(void)
|
||||||
end:
|
end:
|
||||||
cfs_close(wfd);
|
cfs_close(wfd);
|
||||||
cfs_close(rfd);
|
cfs_close(rfd);
|
||||||
|
cfs_remove("T1");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -202,50 +199,49 @@ coffee_test_append(void)
|
||||||
#define APPEND_BYTES 1000
|
#define APPEND_BYTES 1000
|
||||||
#define BULK_SIZE 10
|
#define BULK_SIZE 10
|
||||||
|
|
||||||
cfs_remove("T2");
|
|
||||||
|
|
||||||
/* Test 1 and 2: Append data to the same file many times. */
|
/* Test 1 and 2: Append data to the same file many times. */
|
||||||
for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) {
|
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) {
|
if(afd < 0) {
|
||||||
FAIL(1);
|
TEST_FAIL(1);
|
||||||
}
|
}
|
||||||
for(j = 0; j < BULK_SIZE; j++) {
|
for(j = 0; j < BULK_SIZE; j++) {
|
||||||
buf[j] = 1 + ((i + j) & 0x7f);
|
buf[j] = 1 + ((i + j) & 0x7f);
|
||||||
}
|
}
|
||||||
if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
|
if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
|
||||||
printf("r=%d\n", r);
|
printf("r=%d\n", r);
|
||||||
FAIL(2);
|
TEST_FAIL(2);
|
||||||
}
|
}
|
||||||
cfs_close(afd);
|
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. */
|
is correct. */
|
||||||
afd = cfs_open("T3", CFS_READ);
|
afd = cfs_open("T2", CFS_READ);
|
||||||
if(afd < 0) {
|
if(afd < 0) {
|
||||||
FAIL(3);
|
TEST_FAIL(3);
|
||||||
}
|
}
|
||||||
total_read = 0;
|
total_read = 0;
|
||||||
while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
|
while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
|
||||||
for(j = 0; j < r; j++) {
|
for(j = 0; j < r; j++) {
|
||||||
if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
|
if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
|
||||||
FAIL(4);
|
TEST_FAIL(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_read += r;
|
total_read += r;
|
||||||
}
|
}
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
FAIL(5);
|
TEST_FAIL(5);
|
||||||
}
|
}
|
||||||
if(total_read != APPEND_BYTES) {
|
if(total_read != APPEND_BYTES) {
|
||||||
FAIL(6);
|
TEST_FAIL(6);
|
||||||
}
|
}
|
||||||
cfs_close(afd);
|
cfs_close(afd);
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
end:
|
end:
|
||||||
cfs_close(afd);
|
cfs_close(afd);
|
||||||
|
cfs_remove("T2");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -258,58 +254,60 @@ coffee_test_modify(void)
|
||||||
int r, i;
|
int r, i;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
|
|
||||||
cfs_remove("T3");
|
|
||||||
wfd = -1;
|
wfd = -1;
|
||||||
|
|
||||||
if(cfs_coffee_reserve("T3", FILE_SIZE) < 0) {
|
if(cfs_coffee_reserve("T3", FILE_SIZE) < 0) {
|
||||||
FAIL(1);
|
TEST_FAIL(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfs_coffee_configure_log("T3", FILE_SIZE / 2, 11) < 0) {
|
if(cfs_coffee_configure_log("T3", FILE_SIZE / 2, 11) < 0) {
|
||||||
FAIL(2);
|
TEST_FAIL(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test 16: Test multiple writes at random offset. */
|
/* Test 16: Test multiple writes at random offset. */
|
||||||
for(r = 0; r < 100; r++) {
|
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) {
|
if(wfd < 0) {
|
||||||
FAIL(3);
|
TEST_FAIL(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = random_rand() % FILE_SIZE;
|
offset = random_rand() % FILE_SIZE;
|
||||||
|
|
||||||
for(r = 0; r < sizeof(buf); r++) {
|
for(i = 0; i < sizeof(buf); i++) {
|
||||||
buf[r] = r;
|
buf[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
|
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
|
||||||
FAIL(4);
|
TEST_FAIL(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) {
|
if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) {
|
||||||
FAIL(5);
|
TEST_FAIL(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
|
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
|
||||||
FAIL(6);
|
TEST_FAIL(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) {
|
if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) {
|
||||||
FAIL(7);
|
TEST_FAIL(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < sizeof(buf); i++) {
|
for(i = 0; i < sizeof(buf); i++) {
|
||||||
if(buf[i] != i) {
|
if(buf[i] != i) {
|
||||||
printf("buf[%d] != %d\n", i, buf[i]);
|
printf("buf[%d] != %d\n", i, buf[i]);
|
||||||
FAIL(8);
|
TEST_FAIL(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfs_close(wfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
end:
|
end:
|
||||||
cfs_close(wfd);
|
cfs_close(wfd);
|
||||||
|
cfs_remove("T3");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -318,21 +316,17 @@ coffee_test_gc(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cfs_remove("alpha");
|
|
||||||
cfs_remove("beta");
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
if (i & 1) {
|
if (i & 1) {
|
||||||
if(cfs_coffee_reserve("alpha", random_rand() & 0xffff) < 0) {
|
if(cfs_coffee_reserve("beta", random_rand() & 0xffff) < 0) {
|
||||||
return i;
|
|
||||||
}
|
|
||||||
cfs_remove("beta");
|
|
||||||
} else {
|
|
||||||
if(cfs_coffee_reserve("beta", 93171) < 0) {
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
cfs_remove("alpha");
|
cfs_remove("alpha");
|
||||||
|
} else {
|
||||||
|
if(cfs_coffee_reserve("alpha", 93171) < 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
cfs_remove("beta");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +370,7 @@ PROCESS_THREAD(testcoffee_process, ev, data)
|
||||||
result = coffee_test_gc();
|
result = coffee_test_gc();
|
||||||
print_result("Garbage collection", result);
|
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));
|
(int)(clock_seconds() - start));
|
||||||
|
|
||||||
PROCESS_END();
|
PROCESS_END();
|
|
@ -67,13 +67,19 @@
|
||||||
#define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network
|
#define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network
|
||||||
#define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_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
|
||||||
|
|
||||||
/* Needed for cc2420 platforms only */
|
/* Needed for cc2420 platforms only */
|
||||||
/* Disable DCO calibration (uses timerB) */
|
/* Disable DCO calibration (uses timerB) */
|
||||||
#undef DCOSYNCH_CONF_ENABLED
|
#undef DCOSYNCH_CONF_ENABLED
|
||||||
#define DCOSYNCH_CONF_ENABLED 0
|
#define DCOSYNCH_CONF_ENABLED 0
|
||||||
/* Enable SFD timestamps (uses timerB) */
|
/* Enable SFD timestamps (uses timerB) */
|
||||||
#undef CC2420_CONF_SFD_TIMESTAMPS
|
#undef CC2420_CONF_SFD_TIMESTAMPS
|
||||||
#define CC2420_CONF_SFD_TIMESTAMPS 1
|
#define CC2420_CONF_SFD_TIMESTAMPS 1
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
/******************* Configure TSCH ********************/
|
/******************* Configure TSCH ********************/
|
||||||
|
|
9
examples/nrf52dk/blink-hello/Makefile
Normal file
9
examples/nrf52dk/blink-hello/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
CONTIKI_PROJECT = blink-hello
|
||||||
|
|
||||||
|
CONTIKI_WITH_RPL=0
|
||||||
|
NRF52_WITHOUT_SOFTDEVICE=1
|
||||||
|
|
||||||
|
all: $(CONTIKI_PROJECT)
|
||||||
|
|
||||||
|
CONTIKI = ../../..
|
||||||
|
include $(CONTIKI)/Makefile.include
|
14
examples/nrf52dk/blink-hello/README.md
Normal file
14
examples/nrf52dk/blink-hello/README.md
Normal file
|
@ -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
|
182
examples/nrf52dk/blink-hello/blink-hello.c
Normal file
182
examples/nrf52dk/blink-hello/blink-hello.c
Normal file
|
@ -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 - <oikonomou@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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 <stdio.h> /* For printf() */
|
||||||
|
#include <inttypes.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
35
examples/nrf52dk/coap-demo/Makefile
Normal file
35
examples/nrf52dk/coap-demo/Makefile
Normal file
|
@ -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=<full 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
|
63
examples/nrf52dk/coap-demo/README.md
Normal file
63
examples/nrf52dk/coap-demo/README.md
Normal file
|
@ -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=<full-ip6-address> coap-client.flash
|
||||||
|
|
||||||
|
Note, that you can use `NRF52_JLINK_SN=<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
|
185
examples/nrf52dk/coap-demo/coap-client.c
Normal file
185
examples/nrf52dk/coap-demo/coap-client.c
Normal file
|
@ -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 <daniele.alessandrelli@gmail.com>
|
||||||
|
* \author
|
||||||
|
* Wojciech Bober <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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 <stdio.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
130
examples/nrf52dk/coap-demo/coap-server.c
Normal file
130
examples/nrf52dk/coap-demo/coap-server.c
Normal file
|
@ -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 <kovatsch@inf.ethz.ch>
|
||||||
|
* \author
|
||||||
|
* Wojciech Bober <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
85
examples/nrf52dk/coap-demo/project-conf.h
Normal file
85
examples/nrf52dk/coap-demo/project-conf.h
Normal file
|
@ -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 <kovatsch@inf.ethz.ch>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
106
examples/nrf52dk/coap-demo/resources/res-leds.c
Normal file
106
examples/nrf52dk/coap-demo/resources/res-leds.c
Normal file
|
@ -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 <kovatsch@inf.ethz.ch>
|
||||||
|
* \author
|
||||||
|
* Wojciech Bober <wojciech.bober@nordicsemi.no>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#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 <res_name>.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);
|
||||||
|
}
|
11
examples/nrf52dk/mqtt-demo/Makefile
Normal file
11
examples/nrf52dk/mqtt-demo/Makefile
Normal file
|
@ -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
|
74
examples/nrf52dk/mqtt-demo/README.md
Normal file
74
examples/nrf52dk/mqtt-demo/README.md
Normal file
|
@ -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:<device-id>`, where `<device-id>` 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 <broker IP> -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.
|
721
examples/nrf52dk/mqtt-demo/mqtt-demo.c
Normal file
721
examples/nrf52dk/mqtt-demo/mqtt-demo.c
Normal file
|
@ -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 <string.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
51
examples/nrf52dk/mqtt-demo/project-conf.h
Normal file
51
examples/nrf52dk/mqtt-demo/project-conf.h
Normal file
|
@ -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_ */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** @} */
|
9
examples/nrf52dk/timer-test/Makefile
Normal file
9
examples/nrf52dk/timer-test/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
CONTIKI_PROJECT = timer-test
|
||||||
|
|
||||||
|
CONTIKI_WITH_RPL=0
|
||||||
|
NRF52_WITHOUT_SOFTDEVICE=1
|
||||||
|
|
||||||
|
all: $(CONTIKI_PROJECT)
|
||||||
|
|
||||||
|
CONTIKI = ../../..
|
||||||
|
include $(CONTIKI)/Makefile.include
|
20
examples/nrf52dk/timer-test/README.md
Normal file
20
examples/nrf52dk/timer-test/README.md
Normal file
|
@ -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
|
131
examples/nrf52dk/timer-test/timer-test.c
Normal file
131
examples/nrf52dk/timer-test/timer-test.c
Normal file
|
@ -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 <zach@sensinode.com> (Original)
|
||||||
|
* George Oikonomou - <oikonomou@users.sourceforge.net> (rtimer code)
|
||||||
|
* Wojciech Bober <wojciech.bober@nordicsemi.no> (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 <stdio.h>
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
|
@ -83,31 +83,33 @@ static struct broadcast_conn bc;
|
||||||
PROCESS_THREAD(openmote_demo_process, ev, data)
|
PROCESS_THREAD(openmote_demo_process, ev, data)
|
||||||
{
|
{
|
||||||
static struct etimer et;
|
static struct etimer et;
|
||||||
static unsigned int raw, counter;
|
static int16_t counter;
|
||||||
static uint8_t adxl346_present, max44009_present, sht21_present;
|
static uint16_t adxl346_present, sht21_present, max44009_present;
|
||||||
static float light, temperature, humidity;
|
static int16_t accel, light, temperature, humidity;
|
||||||
|
|
||||||
PROCESS_EXITHANDLER(broadcast_close(&bc))
|
PROCESS_EXITHANDLER(broadcast_close(&bc))
|
||||||
|
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
adxl346_init();
|
/* Initialize and calibrate the ADXL346 sensor */
|
||||||
adxl346_present = adxl346_is_present();
|
adxl346_present = SENSORS_ACTIVATE(adxl346);
|
||||||
if(!adxl346_present) {
|
if(adxl346_present == ADXL346_ERROR) {
|
||||||
printf("ADXL346 sensor is NOT present!\n");
|
printf("ADXL346 sensor is NOT present!\n");
|
||||||
leds_on(LEDS_YELLOW);
|
leds_on(LEDS_YELLOW);
|
||||||
|
} else {
|
||||||
|
adxl346.configure(ADXL346_CALIB_OFFSET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
max44009_init();
|
/* Initialize the MAX44009 sensor */
|
||||||
max44009_present = max44009_is_present();
|
max44009_present = SENSORS_ACTIVATE(max44009);
|
||||||
if(!max44009_present) {
|
if(max44009_present == MAX44009_ERROR) {
|
||||||
printf("MAX44009 sensor is NOT present!\n");
|
printf("MAX44009 sensor is NOT present!\n");
|
||||||
leds_on(LEDS_ORANGE);
|
leds_on(LEDS_ORANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sht21_init();
|
/* Initialize the SHT21 sensor */
|
||||||
sht21_present = sht21_is_present();
|
sht21_present = SENSORS_ACTIVATE(sht21);
|
||||||
if(!sht21_present) {
|
if(sht21_present == SHT21_ERROR) {
|
||||||
printf("SHT21 sensor is NOT present!\n");
|
printf("SHT21 sensor is NOT present!\n");
|
||||||
leds_on(LEDS_RED);
|
leds_on(LEDS_RED);
|
||||||
}
|
}
|
||||||
|
@ -123,33 +125,30 @@ PROCESS_THREAD(openmote_demo_process, ev, data)
|
||||||
PROCESS_YIELD();
|
PROCESS_YIELD();
|
||||||
|
|
||||||
if(ev == PROCESS_EVENT_TIMER) {
|
if(ev == PROCESS_EVENT_TIMER) {
|
||||||
if(adxl346_present) {
|
if(adxl346_present != ADXL346_ERROR) {
|
||||||
leds_on(LEDS_YELLOW);
|
leds_on(LEDS_YELLOW);
|
||||||
raw = adxl346_read_x();
|
accel = adxl346.value(ADXL346_READ_X_mG);
|
||||||
printf("X Acceleration: %u\n", raw);
|
printf("X Acceleration: %d.%u G\n", accel / 1000, accel % 1000);
|
||||||
raw = adxl346_read_y();
|
accel = adxl346.value(ADXL346_READ_Y_mG);
|
||||||
printf("Y Acceleration: %u\n", raw);
|
printf("Y Acceleration: %d.%u G\n", accel / 1000, accel % 1000);
|
||||||
raw = adxl346_read_z();
|
accel = adxl346.value(ADXL346_READ_Z_mG);
|
||||||
printf("Z Acceleration: %u\n", raw);
|
printf("Z Acceleration: %d.%u G\n", accel / 1000, accel % 1000);
|
||||||
leds_off(LEDS_YELLOW);
|
leds_off(LEDS_YELLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(max44009_present) {
|
if(max44009_present != MAX44009_ERROR) {
|
||||||
leds_on(LEDS_ORANGE);
|
leds_on(LEDS_ORANGE);
|
||||||
raw = max44009_read_light();
|
light = max44009.value(MAX44009_READ_LIGHT);
|
||||||
light = max44009_convert_light(raw);
|
printf("Light: %u.%ulux\n", light / 100, light % 100);
|
||||||
printf("Light: %u.%ulux\n", (unsigned int)light, (unsigned int)(light * 100) % 100);
|
|
||||||
leds_off(LEDS_ORANGE);
|
leds_off(LEDS_ORANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sht21_present) {
|
if(sht21_present != SHT21_ERROR) {
|
||||||
leds_on(LEDS_RED);
|
leds_on(LEDS_RED);
|
||||||
raw = sht21_read_temperature();
|
temperature = sht21.value(SHT21_READ_TEMP);
|
||||||
temperature = sht21_convert_temperature(raw);
|
printf("Temperature: %u.%uC\n", temperature / 100, temperature % 100);
|
||||||
printf("Temperature: %u.%uC\n", (unsigned int)temperature, (unsigned int)(temperature * 100) % 100);
|
humidity = sht21.value(SHT21_READ_RHUM);
|
||||||
raw = sht21_read_humidity();
|
printf("Rel. humidity: %u.%u%%\n", humidity / 100, humidity % 100);
|
||||||
humidity = sht21_convert_humidity(raw);
|
|
||||||
printf("Rel. humidity: %u.%u%%\n", (unsigned int)humidity, (unsigned int)(humidity * 100) % 100);
|
|
||||||
leds_off(LEDS_RED);
|
leds_off(LEDS_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,6 @@
|
||||||
|
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
#include "net/rime/rime.h"
|
#include "net/rime/rime.h"
|
||||||
|
|
||||||
#include "dev/button-sensor.h"
|
|
||||||
|
|
||||||
#include "dev/leds.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -56,7 +51,19 @@ recv_uc(struct unicast_conn *c, const linkaddr_t *from)
|
||||||
printf("unicast message received from %d.%d\n",
|
printf("unicast message received from %d.%d\n",
|
||||||
from->u8[0], from->u8[1]);
|
from->u8[0], from->u8[1]);
|
||||||
}
|
}
|
||||||
static const struct unicast_callbacks unicast_callbacks = {recv_uc};
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
sent_uc(struct unicast_conn *c, int status, int num_tx)
|
||||||
|
{
|
||||||
|
const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
||||||
|
if(linkaddr_cmp(dest, &linkaddr_null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("unicast message sent to %d.%d: status %d num_tx %d\n",
|
||||||
|
dest->u8[0], dest->u8[1], status, num_tx);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static const struct unicast_callbacks unicast_callbacks = {recv_uc, sent_uc};
|
||||||
static struct unicast_conn uc;
|
static struct unicast_conn uc;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS_THREAD(example_unicast_process, ev, data)
|
PROCESS_THREAD(example_unicast_process, ev, data)
|
||||||
|
|
|
@ -77,7 +77,7 @@ do_rssi(void)
|
||||||
printf("RSSI:");
|
printf("RSSI:");
|
||||||
for(channel = 0; channel <= 85; ++channel) {
|
for(channel = 0; channel <= 85; ++channel) {
|
||||||
set_frq(channel);
|
set_frq(channel);
|
||||||
printf("%d ", cc2420_rssi() + 55);
|
printf("%d ", cc2420_rssi() + 100);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ ifndef TARGET
|
||||||
TARGET=sky
|
TARGET=sky
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0
|
all: blink sky-collect #rt-leds test-button tcprudolph0
|
||||||
|
|
||||||
%.tgz: %.ihex
|
%.tgz: %.ihex
|
||||||
mkdir $(basename $<) ; \
|
mkdir $(basename $<) ; \
|
||||||
|
|
|
@ -55,14 +55,14 @@ endif
|
||||||
|
|
||||||
disk: all
|
disk: all
|
||||||
cp $(CONTIKI)/tools/$(TARGET)/prodos.dsk contiki.dsk
|
cp $(CONTIKI)/tools/$(TARGET)/prodos.dsk contiki.dsk
|
||||||
java -jar $(AC) -p contiki.dsk contiki.system sys < $(CC65_HOME)/targetutil/loader.system
|
java -jar $(AC) -p contiki.dsk contiki.system sys < $(CC65_TARGET_DIR)/util/loader.system
|
||||||
java -jar $(AC) -cc65 contiki.dsk contiki bin < $(CONTIKI_PROJECT).$(TARGET)
|
java -jar $(AC) -cc65 contiki.dsk contiki bin < $(CONTIKI_PROJECT).$(TARGET)
|
||||||
java -jar $(AC) -p contiki.dsk contiki.cfg bin 0 < $(CONTIKI)/tools/$(TARGET)/sample.cfg
|
java -jar $(AC) -p contiki.dsk contiki.cfg bin 0 < $(CONTIKI)/tools/$(TARGET)/sample.cfg
|
||||||
java -jar $(AC) -p contiki.dsk cs8900a.eth rel 0 < cs8900a.eth
|
java -jar $(AC) -p contiki.dsk cs8900a.eth rel 0 < cs8900a.eth
|
||||||
java -jar $(AC) -p contiki.dsk lan91c96.eth rel 0 < lan91c96.eth
|
java -jar $(AC) -p contiki.dsk lan91c96.eth rel 0 < lan91c96.eth
|
||||||
java -jar $(AC) -p contiki.dsk w5100.eth rel 0 < w5100.eth
|
java -jar $(AC) -p contiki.dsk w5100.eth rel 0 < w5100.eth
|
||||||
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
||||||
java -jar $(AC) -p contiki.dsk contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou
|
java -jar $(AC) -p contiki.dsk contiki.mou rel 0 < $(CC65_TARGET_DIR)/drv/mou/a2e.stdmou.mou
|
||||||
endif
|
endif
|
||||||
ifeq ($(HTTPD-CFS),1)
|
ifeq ($(HTTPD-CFS),1)
|
||||||
java -jar $(AC) -p contiki.dsk index.htm bin 0 < httpd-cfs/index.htm
|
java -jar $(AC) -p contiki.dsk index.htm bin 0 < httpd-cfs/index.htm
|
||||||
|
|
|
@ -55,7 +55,7 @@ disk: all
|
||||||
cp $(CONTIKI)/tools/$(TARGET)/sample.cfg atr/contiki.cfg
|
cp $(CONTIKI)/tools/$(TARGET)/sample.cfg atr/contiki.cfg
|
||||||
cp cs8900a.eth atr/cs8900a.eth
|
cp cs8900a.eth atr/cs8900a.eth
|
||||||
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
||||||
cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou
|
cp $(CC65_TARGET_DIR)/drv/mou/atrxst.mou atr/contiki.mou
|
||||||
endif
|
endif
|
||||||
ifeq ($(HTTPD-CFS),1)
|
ifeq ($(HTTPD-CFS),1)
|
||||||
cp httpd-cfs/index.htm atr/index.htm
|
cp httpd-cfs/index.htm atr/index.htm
|
||||||
|
|
|
@ -46,16 +46,16 @@ endif
|
||||||
|
|
||||||
disk: all
|
disk: all
|
||||||
$(C1541) -format contiki,00 d71 contiki.d71
|
$(C1541) -format contiki,00 d71 contiki.d71
|
||||||
$(C1541) -attach contiki.d71 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p
|
$(C1541) -attach contiki.d71 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p
|
||||||
$(C1541) -attach contiki.d71 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s
|
$(C1541) -attach contiki.d71 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s
|
||||||
$(C1541) -attach contiki.d71 -write cs8900a.eth cs8900a.eth,s
|
$(C1541) -attach contiki.d71 -write cs8900a.eth cs8900a.eth,s
|
||||||
$(C1541) -attach contiki.d71 -write lan91c96.eth lan91c96.eth,s
|
$(C1541) -attach contiki.d71 -write lan91c96.eth lan91c96.eth,s
|
||||||
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
||||||
$(C1541) -attach contiki.d71 -write $(CC65_HOME)/mou/c128-1351.mou contiki.mou,s
|
$(C1541) -attach contiki.d71 -write $(CC65_TARGET_DIR)/drv/mou/c128-1351.mou contiki.mou,s
|
||||||
endif
|
endif
|
||||||
ifeq ($(HTTPD-CFS),1)
|
ifeq ($(HTTPD-CFS),1)
|
||||||
$(C1541) -attach contiki.d71 -write httpd-cfs/index.htm index.htm,s
|
$(C1541) -attach contiki.d71 -write httpd-cfs/index.htm index.htm,s
|
||||||
$(C1541) -attach contiki.d71 -write httpd-cfs/backgrnd.gif backgrnd.gif,s
|
$(C1541) -attach contiki.d71 -write httpd-cfs/backgrnd.gif backgrnd.gif,s
|
||||||
$(C1541) -attach contiki.d71 -write httpd-cfs/contiki.gif contiki.gif,s
|
$(C1541) -attach contiki.d71 -write httpd-cfs/contiki.gif contiki.gif,s
|
||||||
$(C1541) -attach contiki.d71 -write httpd-cfs/notfound.htm notfound.htm,s
|
$(C1541) -attach contiki.d71 -write httpd-cfs/notfound.htm notfound.htm,s
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -50,16 +50,16 @@ endif
|
||||||
|
|
||||||
disk: all
|
disk: all
|
||||||
$(C1541) -format contiki,00 d64 contiki.d64
|
$(C1541) -format contiki,00 d64 contiki.d64
|
||||||
$(C1541) -attach contiki.d64 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p
|
$(C1541) -attach contiki.d64 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p
|
||||||
$(C1541) -attach contiki.d64 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s
|
$(C1541) -attach contiki.d64 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s
|
||||||
$(C1541) -attach contiki.d64 -write cs8900a.eth cs8900a.eth,s
|
$(C1541) -attach contiki.d64 -write cs8900a.eth cs8900a.eth,s
|
||||||
$(C1541) -attach contiki.d64 -write lan91c96.eth lan91c96.eth,s
|
$(C1541) -attach contiki.d64 -write lan91c96.eth lan91c96.eth,s
|
||||||
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE)
|
||||||
$(C1541) -attach contiki.d64 -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s
|
$(C1541) -attach contiki.d64 -write $(CC65_TARGET_DIR)/drv/mou/c64-1351.mou contiki.mou,s
|
||||||
endif
|
endif
|
||||||
ifeq ($(HTTPD-CFS),1)
|
ifeq ($(HTTPD-CFS),1)
|
||||||
$(C1541) -attach contiki.d64 -write httpd-cfs/index.htm index.htm,s
|
$(C1541) -attach contiki.d64 -write httpd-cfs/index.htm index.htm,s
|
||||||
$(C1541) -attach contiki.d64 -write httpd-cfs/backgrnd.gif backgrnd.gif,s
|
$(C1541) -attach contiki.d64 -write httpd-cfs/backgrnd.gif backgrnd.gif,s
|
||||||
$(C1541) -attach contiki.d64 -write httpd-cfs/contiki.gif contiki.gif,s
|
$(C1541) -attach contiki.d64 -write httpd-cfs/contiki.gif contiki.gif,s
|
||||||
$(C1541) -attach contiki.d64 -write httpd-cfs/notfound.htm notfound.htm,s
|
$(C1541) -attach contiki.d64 -write httpd-cfs/notfound.htm notfound.htm,s
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -68,15 +68,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr)
|
||||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
#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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
|
@ -34,12 +34,20 @@ typedef uint32_t uip_stats_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define
|
* 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;
|
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 TSCH_CONF_HW_FRAME_FILTERING 0
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* \name Serial Boot Loader Backdoor configuration
|
* \name Serial Boot Loader Backdoor configuration
|
||||||
*
|
*
|
||||||
|
|
|
@ -198,7 +198,7 @@ typedef unsigned short uip_stats_t;
|
||||||
#define CLOCK_CONF_SECOND 1000L
|
#define CLOCK_CONF_SECOND 1000L
|
||||||
typedef unsigned long clock_time_t;
|
typedef unsigned long clock_time_t;
|
||||||
typedef unsigned long rtimer_clock_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_COMPLIANCE
|
||||||
#define AODV_NUM_RT_ENTRIES 32
|
#define AODV_NUM_RT_ENTRIES 32
|
||||||
|
|
|
@ -46,7 +46,7 @@ typedef unsigned long clock_time_t;
|
||||||
|
|
||||||
typedef uint64_t rtimer_clock_t;
|
typedef uint64_t rtimer_clock_t;
|
||||||
#define RTIMER_ARCH_SECOND 1024
|
#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
|
/* We define the following macros and types otherwise Contiki does not
|
||||||
* compile.
|
* compile.
|
||||||
|
|
|
@ -80,9 +80,9 @@
|
||||||
#define JN516X_EXTERNAL_CRYSTAL_OSCILLATOR (RTIMER_USE_32KHZ || JN516X_SLEEP_ENABLED)
|
#define JN516X_EXTERNAL_CRYSTAL_OSCILLATOR (RTIMER_USE_32KHZ || JN516X_SLEEP_ENABLED)
|
||||||
#endif /* JN516X_EXTERNAL_CRYSTAL_OSCILLATOR */
|
#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;
|
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 */
|
/* 8ms timer tick */
|
||||||
#define CLOCK_CONF_SECOND 125
|
#define CLOCK_CONF_SECOND 125
|
||||||
|
|
|
@ -179,7 +179,7 @@ main(void)
|
||||||
NETSTACK_RDC.channel_check_interval()));
|
NETSTACK_RDC.channel_check_interval()));
|
||||||
printf("802.15.4 PAN ID 0x%x, EUI-%d:",
|
printf("802.15.4 PAN ID 0x%x, EUI-%d:",
|
||||||
IEEE802154_CONF_PANID, UIP_CONF_LL_802154?64:16);
|
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);
|
printf(", radio channel %u\n", RF_CHANNEL);
|
||||||
|
|
||||||
procinit_init();
|
procinit_init();
|
||||||
|
|
|
@ -87,7 +87,7 @@ typedef unsigned long clock_time_t;
|
||||||
|
|
||||||
typedef unsigned long rtimer_clock_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_RED_PIN boardDescription->io->leds[1].gpioPin
|
||||||
#define LEDS_CONF_GREEN_PIN boardDescription->io->leds[0].gpioPin
|
#define LEDS_CONF_GREEN_PIN boardDescription->io->leds[0].gpioPin
|
||||||
|
|
34
platform/nrf52dk/Makefile.nrf52dk
Normal file
34
platform/nrf52dk/Makefile.nrf52dk
Normal file
|
@ -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
|
100
platform/nrf52dk/README-BLE-6LoWPAN.md
Normal file
100
platform/nrf52dk/README-BLE-6LoWPAN.md
Normal file
|
@ -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
|
254
platform/nrf52dk/README.md
Normal file
254
platform/nrf52dk/README.md
Normal file
|
@ -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=<SDK PATH>`
|
||||||
|
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=<serial number>`
|
||||||
|
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 `<application>.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<n>` or `/ttyUSB<n>` 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 <CONTIKI_ROOT>\doc
|
||||||
|
make
|
||||||
|
|
||||||
|
Support
|
||||||
|
=======
|
||||||
|
This port is officially supported by Nordic Semiconductor. Please send bug
|
||||||
|
reports or/and suggestions to <wojciech.bober@nordicsemi.no>.
|
||||||
|
|
||||||
|
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/)
|
329
platform/nrf52dk/config/nrf_drv_config.h
Normal file
329
platform/nrf52dk/config/nrf_drv_config.h
Normal file
|
@ -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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue