Merge branch 'develop' into contrib/spi-sel-desel

This commit is contained in:
George Oikonomou 2018-10-12 16:24:52 +01:00 committed by GitHub
commit d4fd286b34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 2518 additions and 759 deletions

View File

@ -29,10 +29,17 @@ else
CFLAGS += -O2
endif
### Use CMSIS and the existing dbg-io from arch/cpu/arm/common
CONTIKI_ARM_DIRS += . common/dbg-io
### Use CMSIS from arch/cpu/arm/common
CONTIKI_ARM_DIRS += .
CONTIKI_CPU_DIRS += $(addprefix ../arm/, $(CONTIKI_ARM_DIRS))
### Default to use os/lib/dbg-io unless configured to do otherwise
MAKE_WITH_LIB_DBG_IO ?= 1
ifeq ($(MAKE_WITH_LIB_DBG_IO),1)
MODULES += os/lib/dbg-io
endif
### CPU-dependent cleanup files
CLEAN += *.elf *.bin *.lst *.hex *.i16hex

View File

@ -28,8 +28,6 @@ CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c
CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c
CONTIKI_CPU_SOURCEFILES += cfs-coffee.c cfs-coffee-arch.c pwm.c
MODULES += os/lib/dbg-io
USB_SOURCEFILES += usb-core.c cdc-acm.c usb-arch.c usb-serial.c cdc-acm-descriptors.c
CPU_START_SOURCEFILES = startup-gcc.c

View File

@ -37,10 +37,13 @@
#define RTIMER_ARCH_SECOND 32768
/*---------------------------------------------------------------------------*/
/* 352us from calling transmit() until the SFD byte has been sent */
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352))
#define CC2538_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
#define CC2538_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250))
#define CC2538_DELAY_BEFORE_DETECT 0
/* Frame filtering done in software */
#define TSCH_CONF_HW_FRAME_FILTERING 0
#ifndef TSCH_CONF_BASE_DRIFT_PPM
/* The drift compared to "true" 10ms slots.
* Enable adaptive sync to enable compensation for this.
@ -54,9 +57,6 @@
#define TSCH_CONF_BASE_DRIFT_PPM -977
#endif
#if MAC_CONF_WITH_TSCH
#define TSCH_CONF_HW_FRAME_FILTERING 0
#endif /* MAC_CONF_WITH_TSCH */
/*---------------------------------------------------------------------------*/
#define SPI_CONF_CONTROLLER_COUNT 2
/*---------------------------------------------------------------------------*/

View File

@ -42,6 +42,7 @@
#include "net/packetbuf.h"
#include "net/linkaddr.h"
#include "net/netstack.h"
#include "net/mac/tsch/tsch.h"
#include "sys/energest.h"
#include "dev/cc2538-rf.h"
#include "dev/rfcore.h"
@ -68,13 +69,10 @@
*/
#define UDMA_RX_SIZE_THRESHOLD 3
/*---------------------------------------------------------------------------*/
#include <stdio.h>
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "cc2538-rf"
#define LOG_LEVEL LOG_LEVEL_NONE
/*---------------------------------------------------------------------------*/
/* Local RF Flags */
#define RX_ACTIVE 0x80
@ -86,6 +84,7 @@
#define LQI_BIT_MASK 0x7F
/* RSSI Offset */
#define RSSI_OFFSET 73
#define RSSI_INVALID -128
/* 192 usec off -> on interval (RX Callib -> SFD Wait). We wait a bit more */
#define ONOFF_TIME RTIMER_ARCH_SECOND / 3125
@ -156,28 +155,19 @@ PROCESS(cc2538_rf_process, "cc2538 RF driver");
static uint8_t
get_channel()
{
uint8_t chan = REG(RFCORE_XREG_FREQCTRL) & RFCORE_XREG_FREQCTRL_FREQ;
return (chan - CC2538_RF_CHANNEL_MIN) / CC2538_RF_CHANNEL_SPACING
+ CC2538_RF_CHANNEL_MIN;
return rf_channel;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Set the current operating channel
* \param channel The desired channel as a value in [11,26]
* \return Returns a value in [11,26] representing the current channel
* or a negative value if \e channel was out of bounds
*/
static int8_t
static void
set_channel(uint8_t channel)
{
uint8_t was_on = 0;
PRINTF("RF: Set Channel\n");
if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) {
return CC2538_RF_CHANNEL_SET_ERROR;
}
LOG_INFO("Set Channel\n");
/* Changes to FREQCTRL take effect after the next recalibration */
@ -195,8 +185,6 @@ set_channel(uint8_t channel)
}
rf_channel = channel;
return (int8_t)channel;
}
/*---------------------------------------------------------------------------*/
static radio_value_t
@ -244,10 +232,11 @@ get_rssi(void)
on();
}
/* Wait on RSSI_VALID */
while((REG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0);
rssi = (int8_t)(REG(RFCORE_XREG_RSSI) & RFCORE_XREG_RSSI_RSSI_VAL) - RSSI_OFFSET;
/* Wait for a valid RSSI reading */
do {
rssi = REG(RFCORE_XREG_RSSI);
} while(rssi == RSSI_INVALID);
rssi -= RSSI_OFFSET;
/* If we were off, turn back off */
if(was_off) {
@ -322,6 +311,16 @@ set_frame_filtering(uint8_t enable)
}
/*---------------------------------------------------------------------------*/
static void
set_shr_search(int enable)
{
if(enable) {
REG(RFCORE_XREG_FRMCTRL0) &= ~RFCORE_XREG_FRMCTRL0_RX_MODE;
} else {
REG(RFCORE_XREG_FRMCTRL0) |= RFCORE_XREG_FRMCTRL0_RX_MODE;
}
}
/*---------------------------------------------------------------------------*/
static void
mac_timer_init(void)
{
CLOCK_STABLE();
@ -403,7 +402,7 @@ channel_clear(void)
int cca;
uint8_t was_off = 0;
PRINTF("RF: CCA\n");
LOG_INFO("CCA\n");
/* If we are off, turn on first */
if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) {
@ -431,7 +430,7 @@ channel_clear(void)
static int
on(void)
{
PRINTF("RF: On\n");
LOG_INFO("On\n");
if(!(rf_flags & RX_ACTIVE)) {
CC2538_RF_CSP_ISFLUSHRX();
@ -447,7 +446,7 @@ on(void)
static int
off(void)
{
PRINTF("RF: Off\n");
LOG_INFO("Off\n");
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
@ -470,7 +469,7 @@ off(void)
static int
init(void)
{
PRINTF("RF: Init\n");
LOG_INFO("Init\n");
if(rf_flags & RF_ON) {
return 0;
@ -490,6 +489,7 @@ init(void)
REG(RFCORE_XREG_TXFILTCFG) = 0x09; /** TX anti-aliasing filter bandwidth */
REG(RFCORE_XREG_AGCCTRL1) = 0x15; /** AGC target value */
REG(ANA_REGS_IVCTRL) = 0x0B; /** Bias currents */
REG(RFCORE_XREG_FSCAL1) = 0x01; /** Tune frequency calibration */
/*
* Defaults:
@ -513,6 +513,9 @@ init(void)
set_channel(rf_channel);
/* Enable SHR search */
set_shr_search(1);
/* Acknowledge all RF Error interrupts */
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
NVIC_EnableIRQ(RF_ERR_IRQn);
@ -545,8 +548,6 @@ init(void)
rf_flags |= RF_ON;
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
return 1;
}
/*---------------------------------------------------------------------------*/
@ -555,7 +556,7 @@ prepare(const void *payload, unsigned short payload_len)
{
uint8_t i;
PRINTF("RF: Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);
LOG_INFO("Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);
/*
* When we transmit in very quick bursts, make sure previous transmission
@ -569,12 +570,12 @@ prepare(const void *payload, unsigned short payload_len)
CC2538_RF_CSP_ISFLUSHTX();
PRINTF("RF: data = ");
LOG_INFO("data = ");
/* Send the phy length byte first */
REG(RFCORE_SFR_RFDATA) = payload_len + CHECKSUM_LEN;
if(CC2538_RF_CONF_TX_USE_DMA) {
PRINTF("<uDMA payload>");
LOG_INFO_("<uDMA payload>");
/* Set the transfer source's end address */
udma_set_channel_src(CC2538_RF_CONF_TX_DMA_CHAN,
@ -598,10 +599,10 @@ prepare(const void *payload, unsigned short payload_len)
} else {
for(i = 0; i < payload_len; i++) {
REG(RFCORE_SFR_RFDATA) = ((unsigned char *)(payload))[i];
PRINTF("%02x", ((unsigned char *)(payload))[i]);
LOG_INFO_("%02x", ((unsigned char *)(payload))[i]);
}
}
PRINTF("\n");
LOG_INFO_("\n");
return 0;
}
@ -614,7 +615,7 @@ transmit(unsigned short transmit_len)
rtimer_clock_t t0;
uint8_t was_off = 0;
PRINTF("RF: Transmit\n");
LOG_INFO("Transmit\n");
if(!(rf_flags & RX_ACTIVE)) {
t0 = RTIMER_NOW();
@ -649,7 +650,7 @@ transmit(unsigned short transmit_len)
}
if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) {
PRINTF("RF: TX never active.\n");
LOG_ERR("TX never active.\n");
CC2538_RF_CSP_ISFLUSHTX();
ret = RADIO_TX_ERR;
} else {
@ -679,7 +680,7 @@ read(void *buf, unsigned short bufsize)
uint8_t i;
uint8_t len;
PRINTF("RF: Read\n");
LOG_INFO("Read\n");
if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) {
return 0;
@ -691,33 +692,33 @@ read(void *buf, unsigned short bufsize)
/* Check for validity */
if(len > CC2538_RF_MAX_PACKET_LEN) {
/* Oops, we must be out of sync. */
PRINTF("RF: bad sync\n");
LOG_ERR("RF: bad sync\n");
CC2538_RF_CSP_ISFLUSHRX();
return 0;
}
if(len <= CC2538_RF_MIN_PACKET_LEN) {
PRINTF("RF: too short\n");
LOG_ERR("RF: too short\n");
CC2538_RF_CSP_ISFLUSHRX();
return 0;
}
if(len - CHECKSUM_LEN > bufsize) {
PRINTF("RF: too long\n");
LOG_ERR("RF: too long\n");
CC2538_RF_CSP_ISFLUSHRX();
return 0;
}
/* If we reach here, chances are the FIFO is holding a valid frame */
PRINTF("RF: read (0x%02x bytes) = ", len);
LOG_INFO("read (0x%02x bytes) = ", len);
len -= CHECKSUM_LEN;
/* Don't bother with uDMA for short frames (e.g. ACKs) */
if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) {
PRINTF("<uDMA payload>");
LOG_INFO_("<uDMA payload>");
/* Set the transfer destination's end address */
udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN,
@ -738,7 +739,7 @@ read(void *buf, unsigned short bufsize)
} else {
for(i = 0; i < len; ++i) {
((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA);
PRINTF("%02x", ((unsigned char *)(buf))[i]);
LOG_INFO_("%02x", ((unsigned char *)(buf))[i]);
}
}
@ -746,14 +747,14 @@ read(void *buf, unsigned short bufsize)
rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET;
crc_corr = REG(RFCORE_SFR_RFDATA);
PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr);
LOG_INFO_("%02x%02x\n", (uint8_t)rssi, crc_corr);
/* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
if(crc_corr & CRC_BIT_MASK) {
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
} else {
PRINTF("RF: Bad CRC\n");
LOG_ERR("Bad CRC\n");
CC2538_RF_CSP_ISFLUSHRX();
return 0;
}
@ -775,7 +776,7 @@ read(void *buf, unsigned short bufsize)
static int
receiving_packet(void)
{
PRINTF("RF: Receiving\n");
LOG_INFO("Receiving\n");
/*
* SFD high while transmitting and receiving.
@ -791,7 +792,7 @@ receiving_packet(void)
static int
pending_packet(void)
{
PRINTF("RF: Pending\n");
LOG_INFO("Pending\n");
return REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP;
}
@ -862,6 +863,21 @@ get_value(radio_param_t param, radio_value_t *value)
case RADIO_CONST_TXPOWER_MAX:
*value = OUTPUT_POWER_MAX;
return RADIO_RESULT_OK;
case RADIO_CONST_PHY_OVERHEAD:
*value = (radio_value_t)3; /* 1 len byte, 2 bytes CRC */
return RADIO_RESULT_OK;
case RADIO_CONST_BYTE_AIR_TIME:
*value = (radio_value_t)32; /* 250kbps data rate. One byte = 32us.*/
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_TX:
*value = (radio_value_t)CC2538_DELAY_BEFORE_TX;
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_RX:
*value = (radio_value_t)CC2538_DELAY_BEFORE_RX;
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_DETECT:
*value = (radio_value_t)CC2538_DELAY_BEFORE_DETECT;
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
}
@ -886,9 +902,7 @@ set_value(radio_param_t param, radio_value_t value)
value > CC2538_RF_CHANNEL_MAX) {
return RADIO_RESULT_INVALID_VALUE;
}
if(set_channel(value) == CC2538_RF_CHANNEL_SET_ERROR) {
return RADIO_RESULT_ERROR;
}
set_channel(value);
return RADIO_RESULT_OK;
case RADIO_PARAM_PAN_ID:
set_pan_id(value & 0xffff);
@ -924,6 +938,9 @@ set_value(radio_param_t param, radio_value_t value)
case RADIO_PARAM_CCA_THRESHOLD:
set_cca_threshold(value);
return RADIO_RESULT_OK;
case RADIO_PARAM_SHR_SEARCH:
set_shr_search(value);
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
}
@ -956,6 +973,16 @@ get_object(radio_param_t param, void *dest, size_t size)
return RADIO_RESULT_OK;
}
#if MAC_CONF_WITH_TSCH
if(param == RADIO_CONST_TSCH_TIMING) {
if(size != sizeof(uint16_t *) || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
*(const uint16_t **)dest = tsch_timeslot_timing_us_10000;
return RADIO_RESULT_OK;
}
#endif /* MAC_CONF_WITH_TSCH */
return RADIO_RESULT_NOT_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
@ -1085,7 +1112,7 @@ cc2538_rf_rx_tx_isr(void)
void
cc2538_rf_err_isr(void)
{
PRINTF("RF Error: 0x%08lx\n", REG(RFCORE_SFR_RFERRF));
LOG_ERR("Error 0x%08lx occurred\n", REG(RFCORE_SFR_RFERRF));
/* If the error is not an RX FIFO overflow, set a flag */
if(REG(RFCORE_SFR_RFERRF) != RFCORE_SFR_RFERRF_RXOVERF) {
@ -1097,10 +1124,5 @@ cc2538_rf_err_isr(void)
process_poll(&cc2538_rf_process);
}
/*---------------------------------------------------------------------------*/
void
cc2538_rf_set_promiscous_mode(char p)
{
set_frame_filtering(p);
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -56,7 +56,6 @@
#define CC2538_RF_CHANNEL_MIN 11
#define CC2538_RF_CHANNEL_MAX 26
#define CC2538_RF_CHANNEL_SPACING 5
#define CC2538_RF_CHANNEL_SET_ERROR -1
#define CC2538_RF_MAX_PACKET_LEN 127
#define CC2538_RF_MIN_PACKET_LEN 4
#define CC2538_RF_CCA_CLEAR 1
@ -113,7 +112,6 @@
*/
#define CC2538_RF_CSP_ISFLUSHRX() do { \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; \
} while(0)
/**
@ -121,7 +119,6 @@
*/
#define CC2538_RF_CSP_ISFLUSHTX() do { \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \
} while(0)
/*---------------------------------------------------------------------------*/
/** The NETSTACK data structure for the cc2538 RF driver */
@ -138,16 +135,6 @@ extern const struct radio_driver cc2538_rf_driver;
*/
void cc2538_rf_set_addr(uint16_t pan);
/**
* \brief Turn promiscous mode on or off
* \param p If promiscous mode should be on (1) or off (0)
*
* This function turns promiscous mode on or off. In promiscous mode,
* every received frame is returned from the RF core. In
* non-promiscous mode, only broadcast frames or frames with our
* address as the receive address are returned from the RF core.
*/
void cc2538_rf_set_promiscous_mode(char p);
/*---------------------------------------------------------------------------*/
#endif /* CC2538_RF_H__ */

View File

@ -2,6 +2,6 @@ TI_XXWARE_PATH = lib/cc13xxware
CONTIKI_CPU_SOURCEFILES += smartrf-settings.c prop-mode.c prop-mode-tx-power.c
CFLAGS += -DCPU_FAMILY_CC13XX=1
CFLAGS += -DCPU_FAMILY_CC13X0=1 -DCPU_FAMILY_CC13XX=1
include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx

View File

@ -1,3 +1,5 @@
TI_XXWARE_PATH = lib/cc2640r2-sdk
CFLAGS += -DCPU_FAMILY_CC26X0R2=1 -DCPU_FAMILY_CC26XXR2=1
include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx

View File

@ -1,3 +1,5 @@
TI_XXWARE_PATH = lib/cc26xxware
CFLAGS += -DCPU_FAMILY_CC26X0=1 -DCPU_FAMILY_CC26XX=1
include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx

View File

@ -45,8 +45,6 @@ CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c
CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c
CONTIKI_CPU_SOURCEFILES += spi-arch.c
MODULES += os/lib/dbg-io
CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES)
CPU_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS)

View File

@ -64,11 +64,11 @@
* project has specified otherwise. Depending on the final mode, determine a
* default channel (again, if unspecified) and configure RDC params
*/
#if CPU_FAMILY_CC13XX
#if CPU_FAMILY_CC13X0
#ifndef CC13XX_CONF_PROP_MODE
#define CC13XX_CONF_PROP_MODE 1
#endif /* CC13XX_CONF_PROP_MODE */
#endif /* CPU_FAMILY_CC13XX */
#endif /* CPU_FAMILY_CC13X0 */
#if CC13XX_CONF_PROP_MODE
#ifndef NETSTACK_CONF_RADIO

View File

@ -36,6 +36,10 @@
/*---------------------------------------------------------------------------*/
/* TSCH related defines */
/* 1 len byte, 2 bytes CRC */
#define RADIO_PHY_OVERHEAD 3
/* 250kbps data rate. One byte = 32us */
#define RADIO_BYTE_AIR_TIME 32
/* Delay between GO signal and SFD */
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(81))
/* Delay between GO signal and start listening.

View File

@ -39,7 +39,6 @@
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "ti-lib.h"
#include "ti-lib-rom.h"
#include "dev/gpio-hal.h"
#include <stdint.h>
@ -53,11 +52,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
gpio_hal_pin_cfg_t tmp;
/* Clear settings that we are about to change, keep everything else */
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
config = ti_lib_ioc_port_configure_get(pin);
#else
config = ti_lib_rom_ioc_port_configure_get(pin);
#endif
config &= ~CONFIG_MASK;
tmp = cfg & GPIO_HAL_PIN_CFG_EDGE_BOTH;
@ -87,7 +82,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
config |= IOC_INT_ENABLE;
}
ti_lib_rom_ioc_port_configure_set(pin, IOC_PORT_GPIO, config);
ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, config);
}
/*---------------------------------------------------------------------------*/
gpio_hal_pin_cfg_t
@ -98,11 +93,7 @@ gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
uint32_t config;
cfg = 0;
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
config = ti_lib_ioc_port_configure_get(pin);
#else
config = ti_lib_rom_ioc_port_configure_get(pin);
#endif
/* Pull */
tmp = config & IOC_IOPULL_M;

View File

@ -49,7 +49,6 @@
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "ti-lib.h"
#include "ti-lib-rom.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
@ -57,15 +56,10 @@
#define gpio_hal_arch_interrupt_enable(p) interrupt_enable(p)
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
#define gpio_hal_arch_interrupt_disable(p) ti_lib_ioc_int_disable(p)
#define gpio_hal_arch_pin_set_input(p) ti_lib_ioc_pin_type_gpio_input(p)
#define gpio_hal_arch_pin_set_output(p) ti_lib_ioc_pin_type_gpio_output(p)
#else
#define gpio_hal_arch_interrupt_disable(p) ti_lib_rom_ioc_int_disable(p)
#define gpio_hal_arch_pin_set_input(p) ti_lib_rom_ioc_pin_type_gpio_input(p)
#define gpio_hal_arch_pin_set_output(p) ti_lib_rom_ioc_pin_type_gpio_output(p)
#endif
#define gpio_hal_arch_set_pin(p) ti_lib_gpio_set_dio(p)
#define gpio_hal_arch_clear_pin(p) ti_lib_gpio_clear_dio(p)
#define gpio_hal_arch_toggle_pin(p) ti_lib_gpio_toggle_dio(p)
@ -80,11 +74,7 @@ static inline void
interrupt_enable(gpio_hal_pin_t pin)
{
ti_lib_gpio_clear_event_dio(pin);
#ifndef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
ti_lib_rom_ioc_int_enable(pin);
#else
ti_lib_ioc_int_enable(pin);
#endif
}
/*---------------------------------------------------------------------------*/
#endif /* GPIO_HAL_ARCH_H_ */

View File

@ -99,7 +99,7 @@ soc_rtc_init(void)
ti_lib_aon_rtc_channel_enable(AON_RTC_CH1);
ti_lib_aon_rtc_enable();
ti_lib_rom_int_enable(INT_AON_RTC_COMB);
ti_lib_int_enable(INT_AON_RTC_COMB);
/* Re-enable interrupts */
if(!interrupts_disabled) {

View File

@ -71,7 +71,7 @@ static void
disable_number_ready_interrupt(void)
{
ti_lib_trng_int_disable(TRNG_NUMBER_READY);
ti_lib_rom_int_disable(INT_TRNG_IRQ);
ti_lib_int_disable(INT_TRNG_IRQ);
}
/*---------------------------------------------------------------------------*/
static void
@ -79,14 +79,14 @@ enable_number_ready_interrupt(void)
{
ti_lib_trng_int_clear(TRNG_NUMBER_READY);
ti_lib_trng_int_enable(TRNG_NUMBER_READY);
ti_lib_rom_int_enable(INT_TRNG_IRQ);
ti_lib_int_enable(INT_TRNG_IRQ);
}
/*---------------------------------------------------------------------------*/
static bool
accessible(void)
{
/* First, check the PD */
if(ti_lib_rom_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
!= PRCM_DOMAIN_POWER_ON) {
return false;
}
@ -104,12 +104,12 @@ static void
power_up(void)
{
/* First, make sure the PERIPH PD is on */
ti_lib_rom_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
while((ti_lib_rom_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
!= PRCM_DOMAIN_POWER_ON));
/* Enable clock in active mode */
ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_TRNG);
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TRNG);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
@ -136,7 +136,7 @@ static uint64_t
read_number(void)
{
uint64_t ran = (uint64_t)HWREG(TRNG_BASE + TRNG_O_OUT1) << 32;
ran += ti_lib_rom_trng_number_get(TRNG_LOW_WORD);
ran += ti_lib_trng_number_get(TRNG_LOW_WORD);
return ran;
}
@ -237,7 +237,7 @@ soc_trng_rand_asynchronous(uint32_t samples, soc_trng_callback_t cb)
ti_lib_trng_int_clear(TRNG_NUMBER_READY);
/* Enable clock in sleep mode and register with LPM */
ti_lib_rom_prcm_peripheral_sleep_enable(PRCM_PERIPH_TRNG);
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TRNG);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
@ -271,7 +271,7 @@ PROCESS_THREAD(soc_trng_process, ev, data)
}
/* Disable clock in sleep mode */
ti_lib_rom_prcm_peripheral_sleep_disable(PRCM_PERIPH_TRNG);
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_TRNG);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());

View File

@ -123,7 +123,7 @@ spi_arch_lock_and_open(const spi_device_t *dev)
!= PRCM_DOMAIN_POWER_ON)) ;
/* Enable clock in active mode */
ti_lib_rom_prcm_peripheral_run_enable(spi_controller[dev->spi_controller].prcm_periph);
ti_lib_prcm_peripheral_run_enable(spi_controller[dev->spi_controller].prcm_periph);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()) ;
@ -131,17 +131,14 @@ spi_arch_lock_and_open(const spi_device_t *dev)
ti_lib_ssi_int_disable(spi_controller[dev->spi_controller].ssi_base, SSI_RXOR | SSI_RXFF | SSI_RXTO | SSI_TXFF);
ti_lib_ssi_int_clear(spi_controller[dev->spi_controller].ssi_base, SSI_RXOR | SSI_RXTO);
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
ti_lib_ssi_config_set_exp_clk(spi_controller[dev->spi_controller].ssi_base, ti_lib_sys_ctrl_clock_get(),
get_mode(dev), SSI_MODE_MASTER, dev->spi_bit_rate, 8);
ti_lib_ioc_pin_type_ssi_master(spi_controller[dev->spi_controller].ssi_base, dev->pin_spi_miso,
dev->pin_spi_mosi, IOID_UNUSED, dev->pin_spi_sck);
#else
ti_lib_rom_ssi_config_set_exp_clk(spi_controller[dev->spi_controller].ssi_base, ti_lib_sys_ctrl_clock_get(),
get_mode(dev), SSI_MODE_MASTER, dev->spi_bit_rate, 8);
ti_lib_rom_ioc_pin_type_ssi_master(spi_controller[dev->spi_controller].ssi_base, dev->pin_spi_miso,
dev->pin_spi_mosi, IOID_UNUSED, dev->pin_spi_sck);
#endif
ti_lib_ssi_config_set_exp_clk(spi_controller[dev->spi_controller].ssi_base,
ti_lib_sys_ctrl_clock_get(),
get_mode(dev), SSI_MODE_MASTER,
dev->spi_bit_rate, 8);
ti_lib_ioc_pin_type_ssi_master(spi_controller[dev->spi_controller].ssi_base,
dev->pin_spi_miso,
dev->pin_spi_mosi, IOID_UNUSED,
dev->pin_spi_sck);
ti_lib_ssi_enable(spi_controller[dev->spi_controller].ssi_base);
@ -159,7 +156,7 @@ spi_arch_close_and_unlock(const spi_device_t *dev)
}
/* Power down SSI */
ti_lib_rom_prcm_peripheral_run_disable(spi_controller[dev->spi_controller].prcm_periph);
ti_lib_prcm_peripheral_run_disable(spi_controller[dev->spi_controller].prcm_periph);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()) ;
@ -213,20 +210,12 @@ spi_arch_transfer(const spi_device_t *dev,
for(i = 0; i < totlen; i++) {
c = i < wlen ? write_buf[i] : 0;
ti_lib_ssi_data_put(spi_controller[dev->spi_controller].ssi_base, (uint8_t)c);
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
ti_lib_ssi_data_get(spi_controller[dev->spi_controller].ssi_base, &c);
#else
ti_lib_rom_ssi_data_get(spi_controller[dev->spi_controller].ssi_base, &c);
#endif
if(i < rlen) {
inbuf[i] = (uint8_t)c;
}
}
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
while(ti_lib_ssi_data_get_non_blocking(spi_controller[dev->spi_controller].ssi_base, &c)) ;
#else
while(ti_lib_rom_ssi_data_get_non_blocking(spi_controller[dev->spi_controller].ssi_base, &c)) ;
#endif
return SPI_DEV_STATUS_OK;
}
/*---------------------------------------------------------------------------*/

View File

@ -162,10 +162,10 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);
/* Latch the IOs in the padring and enable I/O pad sleep mode */
#if !defined(ThisLibraryIsFor_CC26x0R2_HaltIfViolated)
ti_lib_pwr_ctrl_io_freeze_enable();
ti_lib_aon_ioc_freeze_enable();
HWREG(AON_SYSCTL_BASE + AON_SYSCTL_O_SLEEPCTL) = 0;
ti_lib_sys_ctrl_aon_sync();
#endif
/* Turn off VIMS cache, CRAM and TRAM - possibly not required */
ti_lib_prcm_cache_retention_disable();
ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
@ -193,12 +193,7 @@ wake_up(void)
ti_lib_sys_ctrl_aon_sync();
/* Adjust recharge settings */
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
// May need to change to XOSC_IN_LOW_POWER_MODE
ti_lib_sys_ctrl_adjust_recharge_after_power_down(XOSC_IN_HIGH_POWER_MODE);
#else
ti_lib_sys_ctrl_adjust_recharge_after_power_down();
#endif
/*
* Release the request to the uLDO

View File

@ -399,8 +399,8 @@ rf_core_set_modesel()
} else if(chip_type == CHIP_TYPE_CC1350) {
HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
rv = RF_CORE_CMD_OK;
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
} else if (chip_type == CHIP_TYPE_CC2640R2) {
#if CPU_FAMILY_CC26X0R2
} else if(chip_type == CHIP_TYPE_CC2640R2) {
HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE1;
rv = RF_CORE_CMD_OK;
#endif

View File

@ -1,195 +0,0 @@
/*
* Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup cc26xx-ti-lib
* @{
*
* \file
* Header file with CC13xxware/CC26xxware ROM API.
*/
/*---------------------------------------------------------------------------*/
#ifndef TI_LIB_ROM_H_
#define TI_LIB_ROM_H_
/*---------------------------------------------------------------------------*/
/* rom.h */
#include "driverlib/rom.h"
/* AON API */
#define ti_lib_rom_aon_event_mcu_wake_up_set ROM_AONEventMcuWakeUpSet
#define ti_lib_rom_aon_event_mcu_wake_up_get ROM_AONEventMcuWakeUpGet
#define ti_lib_rom_aon_event_aux_wake_up_set ROM_AONEventAuxWakeUpSet
#define ti_lib_rom_aon_event_aux_wake_up_get ROM_AONEventAuxWakeUpGet
#define ti_lib_rom_aon_event_mcu_set ROM_AONEventMcuSet
#define ti_lib_rom_aon_event_mcu_get ROM_AONEventMcuGet
/* AON_WUC API */
#define ti_lib_rom_aon_wuc_aux_reset ROM_AONWUCAuxReset
#define ti_lib_rom_aon_wuc_recharge_ctrl_config_set ROM_AONWUCRechargeCtrlConfigSet
#define ti_lib_rom_aon_wuc_osc_config ROM_AONWUCOscConfig
/* AUX_TDC API */
#define ti_lib_rom_aux_tdc_config_set ROM_AUXTDCConfigSet
#define ti_lib_rom_aux_tdc_measurement_done ROM_AUXTDCMeasurementDone
/* AUX_WUC API */
#define ti_lib_rom_aux_wuc_clock_enable ROM_AUXWUCClockEnable
#define ti_lib_rom_aux_wuc_clock_disable ROM_AUXWUCClockDisable
#define ti_lib_rom_aux_wuc_clock_status ROM_AUXWUCClockStatus
#define ti_lib_rom_aux_wuc_power_ctrl ROM_AUXWUCPowerCtrl
/* FLASH API */
#define ti_lib_rom_flash_power_mode_get ROM_FlashPowerModeGet
#define ti_lib_rom_flash_protection_set ROM_FlashProtectionSet
#define ti_lib_rom_flash_protection_get ROM_FlashProtectionGet
#define ti_lib_rom_flash_protection_save ROM_FlashProtectionSave
#define ti_lib_rom_flash_efuse_read_row ROM_FlashEfuseReadRow
#define ti_lib_rom_flash_disable_sectors_for_write ROM_FlashDisableSectorsForWrite
/* I2C API */
#define ti_lib_rom_i2c_master_init_exp_clk ROM_I2CMasterInitExpClk
#define ti_lib_rom_i2c_master_err ROM_I2CMasterErr
/* INTERRUPT API */
#define ti_lib_rom_int_priority_grouping_set ROM_IntPriorityGroupingSet
#define ti_lib_rom_int_priority_grouping_get ROM_IntPriorityGroupingGet
#define ti_lib_rom_int_priority_set ROM_IntPrioritySet
#define ti_lib_rom_int_priority_get ROM_IntPriorityGet
#define ti_lib_rom_int_enable ROM_IntEnable
#define ti_lib_rom_int_disable ROM_IntDisable
#define ti_lib_rom_int_pend_set ROM_IntPendSet
#define ti_lib_rom_int_pend_get ROM_IntPendGet
#define ti_lib_rom_int_pend_clear ROM_IntPendClear
/* IOC API */
#define ti_lib_rom_ioc_port_configure_set ROM_IOCPortConfigureSet
#if !defined(ThisLibraryIsFor_CC26x0R2_HaltIfViolated)
#define ti_lib_rom_ioc_port_configure_get ROM_IOCPortConfigureGet
#define ti_lib_rom_ioc_io_shutdown_set ROM_IOCIOShutdownSet
#define ti_lib_rom_ioc_io_mode_set ROM_IOCIOModeSet
#define ti_lib_rom_ioc_io_int_set ROM_IOCIOIntSet
#define ti_lib_rom_ioc_io_port_pull_set ROM_IOCIOPortPullSet
#define ti_lib_rom_ioc_io_hyst_set ROM_IOCIOHystSet
#define ti_lib_rom_ioc_io_input_set ROM_IOCIOInputSet
#define ti_lib_rom_ioc_io_slew_ctrl_set ROM_IOCIOSlewCtrlSet
#define ti_lib_rom_ioc_io_drv_strength_set ROM_IOCIODrvStrengthSet
#define ti_lib_rom_ioc_io_port_id_set ROM_IOCIOPortIdSet
#define ti_lib_rom_ioc_int_enable ROM_IOCIntEnable
#define ti_lib_rom_ioc_int_disable ROM_IOCIntDisable
#define ti_lib_rom_ioc_pin_type_gpio_input ROM_IOCPinTypeGpioInput
#define ti_lib_rom_ioc_pin_type_gpio_output ROM_IOCPinTypeGpioOutput
#define ti_lib_rom_ioc_pin_type_uart ROM_IOCPinTypeUart
#define ti_lib_rom_ioc_pin_type_ssi_master ROM_IOCPinTypeSsiMaster
#define ti_lib_rom_ioc_pin_type_ssi_slave ROM_IOCPinTypeSsiSlave
#define ti_lib_rom_ioc_pin_type_i2c ROM_IOCPinTypeI2c
#define ti_lib_rom_ioc_pin_type_aux ROM_IOCPinTypeAux
#endif
/* PRCM API */
#define ti_lib_rom_prcm_inf_clock_configure_set ROM_PRCMInfClockConfigureSet
#define ti_lib_rom_prcm_inf_clock_configure_get ROM_PRCMInfClockConfigureGet
#define ti_lib_rom_prcm_audio_clock_config_set ROM_PRCMAudioClockConfigSet
#define ti_lib_rom_prcm_power_domain_on ROM_PRCMPowerDomainOn
#define ti_lib_rom_prcm_power_domain_off ROM_PRCMPowerDomainOff
#define ti_lib_rom_prcm_peripheral_run_enable ROM_PRCMPeripheralRunEnable
#define ti_lib_rom_prcm_peripheral_run_disable ROM_PRCMPeripheralRunDisable
#define ti_lib_rom_prcm_peripheral_sleep_enable ROM_PRCMPeripheralSleepEnable
#define ti_lib_rom_prcm_peripheral_sleep_disable ROM_PRCMPeripheralSleepDisable
#define ti_lib_rom_prcm_peripheral_deep_sleep_enable ROM_PRCMPeripheralDeepSleepEnable
#define ti_lib_rom_prcm_peripheral_deep_sleep_disable ROM_PRCMPeripheralDeepSleepDisable
#define ti_lib_rom_prcm_power_domain_status ROM_PRCMPowerDomainStatus
#define ti_lib_rom_prcm_deep_sleep ROM_PRCMDeepSleep
/* SMPH API */
#define ti_lib_rom_smph_acquire ROM_SMPHAcquire
/* SSI API */
#define ti_lib_rom_ssi_config_set_exp_clk ROM_SSIConfigSetExpClk
#define ti_lib_rom_ssi_data_put ROM_SSIDataPut
#define ti_lib_rom_ssi_data_put_non_blocking ROM_SSIDataPutNonBlocking
#define ti_lib_rom_ssi_data_get ROM_SSIDataGet
#define ti_lib_rom_ssi_data_get_non_blocking ROM_SSIDataGetNonBlocking
/* TIMER API */
#define ti_lib_rom_timer_configure ROM_TimerConfigure
#define ti_lib_rom_timer_level_control ROM_TimerLevelControl
#define ti_lib_rom_timer_stall_control ROM_TimerStallControl
#define ti_lib_rom_timer_wait_on_trigger_control ROM_TimerWaitOnTriggerControl
/* TRNG API */
#define ti_lib_rom_trng_number_get ROM_TRNGNumberGet
/* UART API */
#define ti_lib_rom_uart_fifo_level_get ROM_UARTFIFOLevelGet
#define ti_lib_rom_uart_config_set_exp_clk ROM_UARTConfigSetExpClk
#define ti_lib_rom_uart_config_get_exp_clk ROM_UARTConfigGetExpClk
#define ti_lib_rom_uart_disable ROM_UARTDisable
#define ti_lib_rom_uart_char_get_non_blocking ROM_UARTCharGetNonBlocking
#define ti_lib_rom_uart_char_get ROM_UARTCharGet
#define ti_lib_rom_uart_char_put_non_blocking ROM_UARTCharPutNonBlocking
#define ti_lib_rom_uart_char_put ROM_UARTCharPut
/* UDMA API */
#define ti_lib_rom_udma_channel_attribute_enable ROM_uDMAChannelAttributeEnable
#define ti_lib_rom_udma_channel_attribute_disable ROM_uDMAChannelAttributeDisable
#define ti_lib_rom_udma_channel_attribute_get ROM_uDMAChannelAttributeGet
#define ti_lib_rom_udma_channel_control_set ROM_uDMAChannelControlSet
#define ti_lib_rom_udma_channel_transfer_set ROM_uDMAChannelTransferSet
#define ti_lib_rom_udma_channel_scatter_gather_set ROM_uDMAChannelScatterGatherSet
#define ti_lib_rom_udma_channel_size_get ROM_uDMAChannelSizeGet
#define ti_lib_rom_udma_channel_mode_get ROM_uDMAChannelModeGet
/* VIMS API */
#define ti_lib_rom_vims_configure ROM_VIMSConfigure
#define ti_lib_rom_vims_mode_set ROM_VIMSModeSet
/* HAPI */
#define ti_lib_hapi_crc32(a, b, c) HapiCrc32(a, b, c)
#define ti_lib_hapi_get_flash_size() HapiGetFlashSize()
#define ti_lib_hapi_get_chip_id() HapiGetChipId()
#define ti_lib_hapi_sector_erase(a) HapiSectorErase(a)
#define ti_lib_hapi_program_flash(a, b, c) HapiProgramFlash(a, b, c)
#define ti_lib_hapi_reset_device() HapiResetDevice()
#define ti_lib_hapi_fletcher32(a, b, c) HapiFletcher32(a, b, c)
#define ti_lib_hapi_min_value(a, b) HapiMinValue(a,b)
#define ti_lib_hapi_max_value(a, b) HapiMaxValue(a,b)
#define ti_lib_hapi_mean_value(a, b) HapiMeanValue(a,b)
#define ti_lib_hapi_stand_deviation_value(a, b) HapiStandDeviationValue(a,b)
#define ti_lib_hapi_hf_source_safe_switch() HapiHFSourceSafeSwitch()
#define ti_lib_hapi_select_comp_a_input(a) HapiSelectCompAInput(a)
#define ti_lib_hapi_select_comp_a_ref(a) HapiSelectCompARef(a)
#define ti_lib_hapi_select_adc_comp_b_input(a) HapiSelectADCCompBInput(a)
#define ti_lib_hapi_select_comp_b_ref(a) HapiSelectCompBRef(a)
/*---------------------------------------------------------------------------*/
#endif /* TI_LIB_ROM_H_ */
/*---------------------------------------------------------------------------*/
/**
* @}
*/

View File

@ -52,9 +52,6 @@
#ifndef TI_LIB_H_
#define TI_LIB_H_
/*---------------------------------------------------------------------------*/
/* Include ROM API */
#include "ti-lib-rom.h"
/*---------------------------------------------------------------------------*/
/* aon_batmon.h */
#include "driverlib/aon_batmon.h"
@ -200,14 +197,16 @@
#define ti_lib_chipinfo_get_device_id_hw_rev_code(...) ChipInfo_GetDeviceIdHwRevCode(__VA_ARGS__)
#define ti_lib_chipinfo_get_chip_type(...) ChipInfo_GetChipType(__VA_ARGS__)
#define ti_lib_chipinfo_get_chip_family(...) ChipInfo_GetChipFamily(__VA_ARGS__)
#ifdef ThisLibraryIsFor_CC26x0R2_HaltIfViolated
#if CPU_FAMILY_CC26X0R2
#define ti_lib_chipinfo_chip_family_is_cc26xx(...) ChipInfo_ChipFamilyIs_CC26x0(__VA_ARGS__)
#define ti_lib_chipinfo_chip_family_is_cc13xx(...) ChipInfo_ChipFamilyIs_CC13x0(__VA_ARGS__)
#define ti_lib_chipinfo_chip_family_is_cc26x0r2(...) ChipInfo_ChipFamilyIs_CC26x0R2(__VA_ARGS__)
#define ti_lib_chipinfo_chip_family_is_cc26x0r2(...) ChipInfo_ChipFamilyIs_CC26x0R2(__VA_ARGS__)
#else
#define ti_lib_chipinfo_chip_family_is_cc26xx(...) ChipInfo_ChipFamilyIsCC26xx(__VA_ARGS__)
#define ti_lib_chipinfo_chip_family_is_cc13xx(...) ChipInfo_ChipFamilyIsCC13xx(__VA_ARGS__)
#endif
#endif /* CPU_FAMILY_CC26X0R2 */
#define ti_lib_chipinfo_get_hw_revision(...) ChipInfo_GetHwRevision(__VA_ARGS__)
#define ti_lib_chipinfo_hw_revision_is_1_0(...) ChipInfo_HwRevisionIs_1_0(__VA_ARGS__)
#define ti_lib_chipinfo_hw_revision_is_gteq_2_0(...) ChipInfo_HwRevisionIs_GTEQ_2_0(__VA_ARGS__)
@ -394,10 +393,6 @@
#define ti_lib_pwr_ctrl_source_get(...) PowerCtrlSourceGet(__VA_ARGS__)
#define ti_lib_pwr_ctrl_reset_source_get(...) PowerCtrlResetSourceGet(__VA_ARGS__)
#define ti_lib_pwr_ctrl_reset_source_clear(...) PowerCtrlResetSourceClear(__VA_ARGS__)
#if !defined(ThisLibraryIsFor_CC26x0R2_HaltIfViolated)
#define ti_lib_pwr_ctrl_io_freeze_enable(...) PowerCtrlIOFreezeEnable(__VA_ARGS__)
#define ti_lib_pwr_ctrl_io_freeze_disable(...) PowerCtrlIOFreezeDisable(__VA_ARGS__)
#endif
/*---------------------------------------------------------------------------*/
/* rfc.h */
#include "driverlib/rfc.h"
@ -416,7 +411,14 @@
#define ti_lib_sys_ctrl_aon_sync(...) SysCtrlAonSync(__VA_ARGS__)
#define ti_lib_sys_ctrl_aon_update(...) SysCtrlAonUpdate(__VA_ARGS__)
#define ti_lib_sys_ctrl_set_recharge_before_power_down(...) SysCtrlSetRechargeBeforePowerDown(__VA_ARGS__)
#define ti_lib_sys_ctrl_adjust_recharge_after_power_down(...) SysCtrlAdjustRechargeAfterPowerDown(__VA_ARGS__)
#if CPU_FAMILY_CC26X0R2
/* May need to change to XOSC_IN_LOW_POWER_MODE */
#define ti_lib_sys_ctrl_adjust_recharge_after_power_down() SysCtrlAdjustRechargeAfterPowerDown(XOSC_IN_HIGH_POWER_MODE)
#else
#define ti_lib_sys_ctrl_adjust_recharge_after_power_down() SysCtrlAdjustRechargeAfterPowerDown()
#endif /* CPU_FAMILY_CC26X0R2 */
#define ti_lib_sys_ctrl_dcdc_voltage_conditional_control(...) SysCtrl_DCDC_VoltageConditionalControl(__VA_ARGS__)
#define ti_lib_sys_ctrl_reset_source_get(...) SysCtrlResetSourceGet(__VA_ARGS__)
#define ti_lib_sys_ctrl_system_reset(...) SysCtrlSystemReset(__VA_ARGS__)

View File

@ -91,9 +91,6 @@ SDK_DEVICES := $(CORE_SDK)/source/ti/devices/$(SDK_DEVICES_NAME)
EXTERNALDIRS += $(SDK_SOURCE) $(SDK_NORTOS)
# CPU-dependent debug source files
MODULES += os/lib/dbg-io
# CPU-dependent directories
CONTIKI_CPU_DIRS += . dev $(SUBFAMILY)
CONTIKI_CPU_DIRS += rf rf-settings rf-settings/$(DEVICE_FAMILY_LC)

View File

@ -57,6 +57,10 @@
/*---------------------------------------------------------------------------*/
/* TSCH related defines */
/* 1 len byte, 2 bytes CRC */
#define RADIO_PHY_OVERHEAD 3
/* 250kbps data rate. One byte = 32us */
#define RADIO_BYTE_AIR_TIME 32
/* Delay between GO signal and SFD */
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(81))
/* Delay between GO signal and start listening.

View File

@ -34,6 +34,7 @@
#include "cc1200-rf-cfg.h"
#include "cc1200-const.h"
#include "net/mac/tsch/tsch.h"
/*
* This is a setup for the following configuration:
@ -62,7 +63,53 @@
/*---------------------------------------------------------------------------*/
static const char rf_cfg_descriptor[] = "802.15.4g 863-870MHz MR-FSK mode #1";
/*---------------------------------------------------------------------------*/
/*
/* 1 byte time: 160 usec */
#define CC1200_TSCH_PREAMBLE_LENGTH 800 /* 5 bytes */
#define CC1200_TSCH_CONF_RX_WAIT 2200
#define CC1200_TSCH_CONF_RX_ACK_WAIT 400
#define CC1200_TSCH_DEFAULT_TS_CCA_OFFSET 1800
#define CC1200_TSCH_DEFAULT_TS_CCA 128
#define CC1200_TSCH_DEFAULT_TS_TX_OFFSET 3800
#define CC1200_TSCH_DEFAULT_TS_RX_OFFSET (CC1200_TSCH_DEFAULT_TS_TX_OFFSET - CC1200_TSCH_PREAMBLE_LENGTH - (CC1200_TSCH_CONF_RX_WAIT / 2))
#define CC1200_TSCH_DEFAULT_TS_RX_ACK_DELAY (CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY - CC1200_TSCH_PREAMBLE_LENGTH - (CC1200_TSCH_CONF_RX_ACK_WAIT / 2))
#define CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY 3000
#define CC1200_TSCH_DEFAULT_TS_RX_WAIT (CC1200_TSCH_PREAMBLE_LENGTH + CC1200_TSCH_CONF_RX_WAIT)
#define CC1200_TSCH_DEFAULT_TS_ACK_WAIT (CC1200_TSCH_PREAMBLE_LENGTH + CC1200_TSCH_CONF_RX_ACK_WAIT)
#define CC1200_TSCH_DEFAULT_TS_RX_TX 192
#define CC1200_TSCH_DEFAULT_TS_MAX_ACK 3360 /* 17+1+3 bytes at 50 kbps */
#define CC1200_TSCH_DEFAULT_TS_MAX_TX 20800 /* 126+1+3 bytes at 50 kbps */
#define CC1200_TSCH_DEFAULT_SLACK_TIME 500
/* Timeslot length: 31460 usec */
#define CC1200_TSCH_DEFAULT_TS_TIMESLOT_LENGTH \
( CC1200_TSCH_DEFAULT_TS_TX_OFFSET \
+ CC1200_TSCH_DEFAULT_TS_MAX_TX \
+ CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY \
+ CC1200_TSCH_DEFAULT_TS_MAX_ACK \
+ CC1200_TSCH_DEFAULT_SLACK_TIME \
)
/* TSCH timeslot timing (mircoseconds) */
static const uint16_t cc1200_50kbps_tsch_timing[tsch_ts_elements_count] = {
CC1200_TSCH_DEFAULT_TS_CCA_OFFSET,
CC1200_TSCH_DEFAULT_TS_CCA,
CC1200_TSCH_DEFAULT_TS_TX_OFFSET,
CC1200_TSCH_DEFAULT_TS_RX_OFFSET,
CC1200_TSCH_DEFAULT_TS_RX_ACK_DELAY,
CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY,
CC1200_TSCH_DEFAULT_TS_RX_WAIT,
CC1200_TSCH_DEFAULT_TS_ACK_WAIT,
CC1200_TSCH_DEFAULT_TS_RX_TX,
CC1200_TSCH_DEFAULT_TS_MAX_ACK,
CC1200_TSCH_DEFAULT_TS_MAX_TX,
CC1200_TSCH_DEFAULT_TS_TIMESLOT_LENGTH,
};
/*
* Register settings exported from SmartRF Studio using the standard template
* "trxEB RF Settings Performance Line".
*/
@ -159,6 +206,11 @@ const cc1200_rf_cfg_t cc1200_802154g_863_870_fsk_50kbps = {
.size_of_register_settings = sizeof(preferredSettings),
.tx_pkt_lifetime = (RTIMER_SECOND / 20),
.tx_rx_turnaround = (RTIMER_SECOND / 100),
/* Includes 3 Bytes preamble + 2 Bytes SFD, at 160usec per byte = 800 usec */
/* Includes time to completion of "Wait for TX to start" if cc1200.c: 397 usec */
.delay_before_tx = ((unsigned)US_TO_RTIMERTICKS(800 + 397 + 423)),
.delay_before_rx = (unsigned)US_TO_RTIMERTICKS(400),
.delay_before_detect = 0,
.chan_center_freq0 = RF_CFG_CHAN_CENTER_F0,
.chan_spacing = RF_CFG_CHAN_SPACING,
.min_channel = RF_CFG_MIN_CHANNEL,
@ -166,5 +218,7 @@ const cc1200_rf_cfg_t cc1200_802154g_863_870_fsk_50kbps = {
.max_txpower = RF_CFG_MAX_TXPOWER,
.cca_threshold = RF_CFG_CCA_THRESHOLD,
.rssi_offset = RF_CFG_RSSI_OFFSET,
.bitrate = 50000,
.tsch_timing = cc1200_50kbps_tsch_timing,
};
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2015, Weptech elektronik GmbH Germany
* http://www.weptech.de
*
* 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.
*
* This file is part of the Contiki operating system.
*/
#include "cc1200-rf-cfg.h"
#include "cc1200-const.h"
#include "net/mac/tsch/tsch.h"
/*
* Register settings exported from SmartRF Studio using the standard 1000kpbs 868MHz template
*/
/* Base frequency in kHz */
#define RF_CFG_CHAN_CENTER_F0 863125
/* Channel spacing in Hz */
#define RF_CFG_CHAN_SPACING 1666667
/* The minimum channel */
#define RF_CFG_MIN_CHANNEL 0
/* The maximum channel */
#define RF_CFG_MAX_CHANNEL 3
/* The maximum output power in dBm */
#define RF_CFG_MAX_TXPOWER CC1200_CONST_TX_POWER_MAX
/* The carrier sense level used for CCA in dBm */
#define RF_CFG_CCA_THRESHOLD (-91)
/* The RSSI offset in dBm */
#define RF_CFG_RSSI_OFFSET (-81)
/*---------------------------------------------------------------------------*/
static const char rf_cfg_descriptor[] = "868MHz 2-GFSK 1000 kbps";
/*---------------------------------------------------------------------------*/
/* 1 byte time: 8 usec */
#define CC1200_TSCH_PREAMBLE_LENGTH 800 /* 5 bytes */
#define CC1200_TSCH_CONF_RX_WAIT 2200
#define CC1200_TSCH_CONF_RX_ACK_WAIT 400
#define CC1200_TSCH_DEFAULT_TS_CCA_OFFSET 1800
#define CC1200_TSCH_DEFAULT_TS_CCA 128
#define CC1200_TSCH_DEFAULT_TS_TX_OFFSET 2200
#define CC1200_TSCH_DEFAULT_TS_RX_OFFSET (CC1200_TSCH_DEFAULT_TS_TX_OFFSET - CC1200_TSCH_PREAMBLE_LENGTH - (CC1200_TSCH_CONF_RX_WAIT / 2))
#define CC1200_TSCH_DEFAULT_TS_RX_ACK_DELAY (CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY - CC1200_TSCH_PREAMBLE_LENGTH - (CC1200_TSCH_CONF_RX_ACK_WAIT / 2))
#define CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY 1900
#define CC1200_TSCH_DEFAULT_TS_RX_WAIT (CC1200_TSCH_PREAMBLE_LENGTH + CC1200_TSCH_CONF_RX_WAIT)
#define CC1200_TSCH_DEFAULT_TS_ACK_WAIT (CC1200_TSCH_PREAMBLE_LENGTH + CC1200_TSCH_CONF_RX_ACK_WAIT)
#define CC1200_TSCH_DEFAULT_TS_RX_TX 192
#define CC1200_TSCH_DEFAULT_TS_MAX_ACK 168 /* 17+1+3 bytes at 1000 kbps */
#define CC1200_TSCH_DEFAULT_TS_MAX_TX 1040 /* 126+1+3 bytes at 1000 kbps */
#define CC1200_TSCH_DEFAULT_SLACK_TIME 500
/* Timeslot length: 5808 usec */
#define CC1200_TSCH_DEFAULT_TS_TIMESLOT_LENGTH \
( CC1200_TSCH_DEFAULT_TS_TX_OFFSET \
+ CC1200_TSCH_DEFAULT_TS_MAX_TX \
+ CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY \
+ CC1200_TSCH_DEFAULT_TS_MAX_ACK \
+ CC1200_TSCH_DEFAULT_SLACK_TIME \
)
/* TSCH timeslot timing (in rtimer ticks) */
static const uint16_t cc1200_1000kbps_tsch_timing[tsch_ts_elements_count] = {
CC1200_TSCH_DEFAULT_TS_CCA_OFFSET,
CC1200_TSCH_DEFAULT_TS_CCA,
CC1200_TSCH_DEFAULT_TS_TX_OFFSET,
CC1200_TSCH_DEFAULT_TS_RX_OFFSET,
CC1200_TSCH_DEFAULT_TS_RX_ACK_DELAY,
CC1200_TSCH_DEFAULT_TS_TX_ACK_DELAY,
CC1200_TSCH_DEFAULT_TS_RX_WAIT,
CC1200_TSCH_DEFAULT_TS_ACK_WAIT,
CC1200_TSCH_DEFAULT_TS_RX_TX,
CC1200_TSCH_DEFAULT_TS_MAX_ACK,
CC1200_TSCH_DEFAULT_TS_MAX_TX,
CC1200_TSCH_DEFAULT_TS_TIMESLOT_LENGTH,
};
static const registerSetting_t preferredSettings[]=
{
{CC1200_IOCFG2, 0x06},
{CC1200_SYNC_CFG1, 0xA8},
{CC1200_DEVIATION_M, 0x47},
{CC1200_MODCFG_DEV_E, 0x2F},
{CC1200_DCFILT_CFG, 0x1E},
{CC1200_PREAMBLE_CFG0, 0x8A},
{CC1200_IQIC, 0x00},
{CC1200_CHAN_BW, 0x01},
{CC1200_MDMCFG1, 0x42},
{CC1200_MDMCFG0, 0x05},
{CC1200_SYMBOL_RATE2, 0xC9},
{CC1200_SYMBOL_RATE1, 0x99},
{CC1200_SYMBOL_RATE0, 0x99},
{CC1200_AGC_REF, 0x2F},
{CC1200_AGC_CS_THR, 0xF8},
{CC1200_AGC_CFG2, 0x60},
{CC1200_AGC_CFG1, 0x12},
{CC1200_AGC_CFG0, 0x84},
{CC1200_FIFO_CFG, 0x00},
{CC1200_FS_CFG, 0x12},
{CC1200_PKT_CFG2, 0x00},
{CC1200_PKT_CFG0, 0x20},
{CC1200_PKT_LEN, 0xFF},
{CC1200_FREQOFF_CFG, 0x23},
{CC1200_MDMCFG2, 0x00},
{CC1200_FREQ2, 0x56},
{CC1200_FREQ1, 0xCC},
{CC1200_FREQ0, 0xCC},
{CC1200_IF_ADC1, 0xEE},
{CC1200_IF_ADC0, 0x10},
{CC1200_FS_DIG1, 0x04},
{CC1200_FS_DIG0, 0xA3},
{CC1200_FS_CAL1, 0x40},
{CC1200_FS_CAL0, 0x0E},
{CC1200_FS_DIVTWO, 0x03},
{CC1200_FS_DSM0, 0x33},
{CC1200_FS_DVC1, 0xF7},
{CC1200_FS_DVC0, 0x0F},
{CC1200_FS_PFD, 0x00},
{CC1200_FS_PRE, 0x6E},
{CC1200_FS_REG_DIV_CML, 0x1C},
{CC1200_FS_SPARE, 0xAC},
{CC1200_FS_VCO0, 0xB5},
{CC1200_IFAMP, 0x0D},
{CC1200_XOSC5, 0x0E},
{CC1200_XOSC1, 0x03},
};
/*---------------------------------------------------------------------------*/
/* Global linkage: symbol name must be different in each exported file! */
const cc1200_rf_cfg_t cc1200_868_4gfsk_1000kbps = {
.cfg_descriptor = rf_cfg_descriptor,
.register_settings = preferredSettings,
.size_of_register_settings = sizeof(preferredSettings),
.tx_pkt_lifetime = (RTIMER_SECOND),
.tx_rx_turnaround = (RTIMER_SECOND / 100),
/* Includes 3 Bytes preamble + 2 Bytes SFD, at 8usec per byte = 40 usec */
/* Includes time to completion of "Wait for TX to start" if cc1200.c: 397 usec */
.delay_before_tx = ((unsigned)US_TO_RTIMERTICKS(40 + 397 + 207)),
.delay_before_rx = (unsigned)US_TO_RTIMERTICKS(400),
.delay_before_detect = 0,
.chan_center_freq0 = RF_CFG_CHAN_CENTER_F0,
.chan_spacing = RF_CFG_CHAN_SPACING,
.min_channel = RF_CFG_MIN_CHANNEL,
.max_channel = RF_CFG_MAX_CHANNEL,
.max_txpower = RF_CFG_MAX_TXPOWER,
.cca_threshold = RF_CFG_CCA_THRESHOLD,
.rssi_offset = RF_CFG_RSSI_OFFSET,
.bitrate = 1000000,
.tsch_timing = cc1200_1000kbps_tsch_timing,
};
/*---------------------------------------------------------------------------*/

View File

@ -126,6 +126,9 @@ const cc1200_rf_cfg_t cc1200_868_fsk_1_2kbps = {
.size_of_register_settings = sizeof(preferredSettings),
.tx_pkt_lifetime = (2 * RTIMER_SECOND),
.tx_rx_turnaround = (RTIMER_SECOND / 2),
.delay_before_tx = 0,
.delay_before_rx = 0,
.delay_before_detect = 0,
.chan_center_freq0 = RF_CFG_CHAN_CENTER_F0,
.chan_spacing = RF_CFG_CHAN_SPACING,
.min_channel = RF_CFG_MIN_CHANNEL,
@ -133,5 +136,7 @@ const cc1200_rf_cfg_t cc1200_868_fsk_1_2kbps = {
.max_txpower = RF_CFG_MAX_TXPOWER,
.cca_threshold = RF_CFG_CCA_THRESHOLD,
.rssi_offset = RF_CFG_RSSI_OFFSET,
.bitrate = 1200,
.tsch_timing = NULL,
};
/*---------------------------------------------------------------------------*/

View File

@ -69,6 +69,13 @@ typedef struct cc1200_rf_cfg {
rtimer_clock_t tx_pkt_lifetime;
/* The maximum time it takes to switch from Tx to Rx */
rtimer_clock_t tx_rx_turnaround;
/* The delay between a call to transmit() and end of SFD */
rtimer_clock_t delay_before_tx;
/* Delay between GO signal and start listening
* Measured 104us: between GO signal and start listening */
rtimer_clock_t delay_before_rx;
/* Delay between the SFD finishes arriving and it is detected in software */
rtimer_clock_t delay_before_detect;
/* Base frequency in kHz */
uint32_t chan_center_freq0;
/* Channel spacing in Hz */
@ -87,6 +94,10 @@ typedef struct cc1200_rf_cfg {
/* The RSSI offset in dBm.
* -99 when MDMCFG1.DVGA_GAIN=00, -81 when MDMCFG1.DVGA_GAIN=01 */
int8_t rssi_offset;
/* The bitrate in bps */
uint32_t bitrate;
/* TSCH timeslot timing */
const uint16_t *tsch_timing;
} cc1200_rf_cfg_t;
/*---------------------------------------------------------------------------*/
#endif /* CC1200_RF_CFG_H */

View File

@ -47,6 +47,9 @@
#include <string.h>
#include <stdio.h>
static int16_t rssi;
static rtimer_clock_t sfd_timestamp = 0;
/*---------------------------------------------------------------------------*/
/* Various implementation specific defines */
/*---------------------------------------------------------------------------*/
@ -57,7 +60,7 @@
* - 2: Print errors + warnings (recoverable errors)
* - 3: Print errors + warnings + information (what's going on...)
*/
#define DEBUG_LEVEL 2
#define DEBUG_LEVEL 0
/*
* RF test mode. Blocks inside "configure()".
* - Set this parameter to 1 in order to produce an modulated carrier (PN9)
@ -79,6 +82,14 @@
#define CC1200_RF_CFG cc1200_802154g_863_870_fsk_50kbps
#endif
#endif
/*
* When set, a software buffer is used to store outgoing packets before copying
* to Tx FIFO. This enabled sending packets larger than the FIFO. When unset,
* no buffer is used; instead, the payload is copied directly to the Tx FIFO.
* This is requried by TSCH, for shorter and more predictable delay in the Tx
* chain. This, however, restircts the payload length to the Tx FIFO size.
*/
#define CC1200_WITH_TX_BUF (!MAC_CONF_WITH_TSCH)
/*
* Set this parameter to 1 in order to use the MARC_STATE register when
* polling the chips's status. Else use the status byte returned when sending
@ -93,7 +104,11 @@
*
* TODO: Option to be removed upon approval of the driver
*/
#if MAC_CONF_WITH_TSCH
#define USE_SFSTXON 0
#else /* MAC_CONF_WITH_TSCH */
#define USE_SFSTXON 1
#endif /* MAC_CONF_WITH_TSCH */
/*---------------------------------------------------------------------------*/
/* Phy header length */
#if CC1200_802154G
@ -133,7 +148,15 @@
/* Use GPIO2 as RX / TX FIFO threshold indicator pin */
#define GPIO2_IOCFG CC1200_IOCFG_RXFIFO_THR
/* This is the FIFO threshold we use */
#if MAC_CONF_WITH_TSCH
#if CC1200_802154G
#define FIFO_THRESHOLD 1
#else
#define FIFO_THRESHOLD 0
#endif
#else /* MAC_CONF_WITH_TSCH */
#define FIFO_THRESHOLD 32
#endif /* MAC_CONF_WITH_TSCH */
/* Turn on RX after packet reception */
#define RXOFF_MODE_RX 1
/* Let the CC1200 append RSSI + LQI */
@ -249,6 +272,8 @@ extern const cc1200_rf_cfg_t CC1200_RF_CFG;
#define RF_UPDATE_CHANNEL 0x10
/* SPI was locked when calling RX interrupt, let the pollhandler do the job */
#define RF_POLL_RX_INTERRUPT 0x20
/* Ongoing reception */
#define RF_RX_ONGOING 0x40
/* Force calibration in case we don't use CC1200 AUTOCAL + timeout */
#if !CC1200_AUTOCAL
#if CC1200_CAL_TIMEOUT_SECONDS
@ -285,15 +310,7 @@ extern const cc1200_rf_cfg_t CC1200_RF_CFG;
#define LOCK_SPI() do { spi_locked++; } while(0)
#define SPI_IS_LOCKED() (spi_locked != 0)
#define RELEASE_SPI() do { spi_locked--; } while(0)
/*---------------------------------------------------------------------------*/
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) { \
watchdog_periodic(); \
} \
} while(0)
/*---------------------------------------------------------------------------*/
#if CC1200_USE_GPIO2
/* Configure GPIO interrupts. GPIO0: falling, GPIO2: rising edge */
@ -353,38 +370,22 @@ extern const cc1200_rf_cfg_t CC1200_RF_CFG;
#define INFO(...)
#endif
#if DEBUG_LEVEL > 0
/*
* As BUSYWAIT_UNTIL was mainly used to test for a state transition,
* we define a separate macro for this adding the possibility to
* throw an error message when the timeout exceeds
*/
#define BUSYWAIT_UNTIL_STATE(s, t) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while((state() != s) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (t))) {} \
if(!(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (t)))) { \
printf("RF: Timeout exceeded in line %d!\n", __LINE__); \
} \
} while(0)
#else
#define BUSYWAIT_UNTIL_STATE(s, t) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while((state() != s) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (t))) {} \
} while(0)
#endif
/* Busy-wait (time-bounded) until the radio reaches a given state */
#define RTIMER_BUSYWAIT_UNTIL_STATE(s, t) RTIMER_BUSYWAIT_UNTIL(state() == (s), t)
/*---------------------------------------------------------------------------*/
/* Variables */
/*---------------------------------------------------------------------------*/
/* Flag indicating whether non-interrupt routines are using SPI */
static volatile uint8_t spi_locked = 0;
#if CC1200_WITH_TX_BUF
/* Packet buffer for transmission, filled within prepare() */
static uint8_t tx_pkt[CC1200_MAX_PAYLOAD_LEN];
#endif /* CC1200_WITH_TX_BUF */
/* The number of bytes waiting in tx_pkt */
static uint16_t tx_pkt_len;
/* Number of bytes from tx_pkt left to write to FIFO */
uint16_t bytes_left_to_write;
/* Packet buffer for reception */
static uint8_t rx_pkt[CC1200_MAX_PAYLOAD_LEN + APPENDIX_LEN];
/* The number of bytes placed in rx_pkt */
@ -422,6 +423,9 @@ static struct etimer et;
/* Init the radio. */
static int
init(void);
/* Prepare and copy PHY header to Tx FIFO */
static int
copy_header_to_tx_fifo(unsigned short payload_len);
/* Prepare the radio with a packet to be sent. */
static int
prepare(const void *payload, unsigned short payload_len);
@ -530,7 +534,7 @@ idle_calibrate_rx(void);
/* Restart RX from within RX interrupt. */
static void
rx_rx(void);
/* Fill TX FIFO, start TX and wait for TX to complete (blocking!). */
/* Fill TX FIFO (if not already done), start TX and wait for TX to complete (blocking!). */
static int
idle_tx_rx(const uint8_t *payload, uint16_t payload_len);
/* Update TX power */
@ -572,7 +576,7 @@ PROCESS_THREAD(cc1200_process, ev, data)
/*
* We are on and not in TX. As every function of this driver
* assures that we are in RX mode
* (using BUSYWAIT_UNTIL_STATE(STATE_RX, ...) construct) in
* (using RTIMER_BUSYWAIT_UNTIL_STATE(STATE_RX, ...) construct) in
* either rx_rx(), idle_calibrate_rx() or transmit(),
* something probably went wrong in the rx interrupt handler
* if we are not in RX at this point.
@ -624,7 +628,7 @@ pollhandler(void)
set_channel(new_rf_channel);
}
if(rx_pkt_len > 0) {
if((rx_mode_value & RADIO_RX_MODE_POLL_MODE) == 0 && rx_pkt_len > 0) {
int len;
@ -722,10 +726,67 @@ prepare(const void *payload, unsigned short payload_len)
}
tx_pkt_len = payload_len;
#if CC1200_WITH_TX_BUF
/* Copy payload to buffer, will be sent later */
memcpy(tx_pkt, payload, tx_pkt_len);
#else /* CC1200_WITH_TX_BUF */
#if (CC1200_MAX_PAYLOAD_LEN > (CC1200_FIFO_SIZE - PHR_LEN))
#error CC1200 max payload too large
#else
/* Copy header and payload directly to Radio Tx FIFO (127 bytes max) */
copy_header_to_tx_fifo(payload_len);
burst_write(CC1200_TXFIFO, payload, payload_len);
#endif
#endif /* CC1200_WITH_TX_BUF */
return RADIO_TX_OK;
}
/*---------------------------------------------------------------------------*/
/* Prepare the radio with a packet to be sent. */
static int
copy_header_to_tx_fifo(unsigned short payload_len)
{
#if CC1200_802154G
/* Prepare PHR for 802.15.4g frames */
struct {
uint8_t phra;
uint8_t phrb;
} phr;
#if CC1200_802154G_CRC16
payload_len += 2;
#else
payload_len += 4;
#endif
/* Frame length */
phr.phrb = (uint8_t)(payload_len & 0x00FF);
phr.phra = (uint8_t)((payload_len >> 8) & 0x0007);
#if CC1200_802154G_WHITENING
/* Enable Whitening */
phr.phra |= (1 << 3);
#endif /* #if CC1200_802154G_WHITENING */
#if CC1200_802154G_CRC16
/* FCS type 1, 2 Byte CRC */
phr.phra |= (1 << 4);
#endif /* #if CC1200_802154G_CRC16 */
#endif /* #if CC1200_802154G */
idle();
rf_flags &= ~RF_RX_PROCESSING_PKT;
strobe(CC1200_SFRX);
/* Flush TX FIFO */
strobe(CC1200_SFTX);
#if CC1200_802154G
/* Write PHR */
burst_write(CC1200_TXFIFO, (uint8_t *)&phr, PHR_LEN);
#else
/* Write length byte */
burst_write(CC1200_TXFIFO, (uint8_t *)&payload_len, PHR_LEN);
#endif /* #if CC1200_802154G */
return 0;
}
/*---------------------------------------------------------------------------*/
/* Send the packet that has previously been prepared. */
@ -735,6 +796,7 @@ transmit(unsigned short transmit_len)
uint8_t was_off = 0;
int ret = RADIO_TX_OK;
int txret;
INFO("RF: Transmit (%d)\n", transmit_len);
@ -790,7 +852,12 @@ transmit(unsigned short transmit_len)
#endif
/* Send data using TX FIFO */
if(idle_tx_rx((const uint8_t *)tx_pkt, tx_pkt_len) == RADIO_TX_OK) {
#if CC1200_WITH_TX_BUF
txret = idle_tx_rx(tx_pkt, tx_pkt_len);
#else /* CC1200_WITH_TX_BUF */
txret = idle_tx_rx(NULL, tx_pkt_len);
#endif /* CC1200_WITH_TX_BUF */
if(txret == RADIO_TX_OK) {
/*
* TXOFF_MODE is set to RX,
@ -798,7 +865,7 @@ transmit(unsigned short transmit_len)
* again as they were turned off in idle()
*/
BUSYWAIT_UNTIL_STATE(STATE_RX,
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_RX,
CC1200_RF_CFG.tx_rx_turnaround);
ENABLE_GPIO_INTERRUPTS();
@ -861,7 +928,7 @@ read(void *buf, unsigned short buf_len)
if(rx_pkt_len > 0) {
int8_t rssi = rx_pkt[rx_pkt_len - 2];
rssi = (int8_t)rx_pkt[rx_pkt_len - 2] + (int)CC1200_RF_CFG.rssi_offset;
/* CRC is already checked */
uint8_t crc_lqi = rx_pkt[rx_pkt_len - 1];
@ -938,7 +1005,7 @@ channel_clear(void)
}
/* Wait for CARRIER_SENSE_VALID signal */
BUSYWAIT_UNTIL(((rssi0 = single_read(CC1200_RSSI0))
RTIMER_BUSYWAIT_UNTIL(((rssi0 = single_read(CC1200_RSSI0))
& CC1200_CARRIER_SENSE_VALID),
RTIMER_SECOND / 100);
RF_ASSERT(rssi0 & CC1200_CARRIER_SENSE_VALID);
@ -1009,9 +1076,16 @@ receiving_packet(void)
static int
pending_packet(void)
{
int ret;
ret = ((rx_pkt_len != 0) ? 1 : 0);
if(ret == 0 && !SPI_IS_LOCKED()) {
LOCK_SPI();
ret = (single_read(CC1200_NUM_RXBYTES) > 0);
RELEASE_SPI();
}
INFO("RF: Pending (%d)\n", ((rx_pkt_len != 0) ? 1 : 0));
return (rx_pkt_len != 0) ? 1 : 0;
INFO("RF: Pending (%d)\n", ret);
return ret;
}
/*---------------------------------------------------------------------------*/
@ -1033,11 +1107,12 @@ on(void)
/* Wake-up procedure. Wait for GPIO0 to de-assert (CHIP_RDYn) */
cc1200_arch_spi_select();
BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
RTIMER_BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
RTIMER_SECOND / 100);
RF_ASSERT((cc1200_arch_gpio0_read_pin() == 0));
cc1200_arch_spi_deselect();
rf_flags = RF_INITIALIZED;
rf_flags |= RF_ON;
/* Radio is IDLE now, re-configure GPIO0 (modified inside off()) */
@ -1080,6 +1155,16 @@ off(void)
idle();
if(single_read(CC1200_NUM_RXBYTES) > 0) {
RELEASE_SPI();
/* In case there is something in the Rx FIFO, read it */
cc1200_rx_interrupt();
if(SPI_IS_LOCKED()) {
return 0;
}
LOCK_SPI();
}
/*
* As we use GPIO as CHIP_RDYn signal on wake-up / on(),
* we re-configure it for CHIP_RDYn.
@ -1106,6 +1191,40 @@ off(void)
}
/*---------------------------------------------------------------------------*/
/**
* \brief Reads the current signal strength (RSSI)
* \return The current RSSI in dBm
*
* This function reads the current RSSI on the currently configured
* channel.
*/
static int16_t
get_rssi(void)
{
int16_t rssi0, rssi1;
uint8_t was_off = 0;
/* If we are off, turn on first */
if(!(rf_flags & RF_ON)) {
was_off = 1;
on();
}
/* Wait for CARRIER_SENSE_VALID signal */
RTIMER_BUSYWAIT_UNTIL(((rssi0 = single_read(CC1200_RSSI0))
& CC1200_CARRIER_SENSE_VALID),
RTIMER_SECOND / 100);
RF_ASSERT(rssi0 & CC1200_CARRIER_SENSE_VALID);
rssi1 = (int8_t)single_read(CC1200_RSSI1) + (int)CC1200_RF_CFG.rssi_offset;
/* If we were off, turn back off */
if(was_off) {
off();
}
return rssi1;
}
/*---------------------------------------------------------------------------*/
/* Get a radio parameter value. */
static radio_result_t
get_value(radio_param_t param, radio_value_t *value)
@ -1156,6 +1275,13 @@ get_value(radio_param_t param, radio_value_t *value)
return RADIO_RESULT_OK;
case RADIO_PARAM_RSSI:
*value = get_rssi();
return RADIO_RESULT_OK;
case RADIO_PARAM_LAST_RSSI:
*value = (radio_value_t)rssi;
return RADIO_RESULT_OK;
case RADIO_PARAM_64BIT_ADDR:
return RADIO_RESULT_NOT_SUPPORTED;
@ -1180,6 +1306,34 @@ get_value(radio_param_t param, radio_value_t *value)
*value = (radio_value_t)CC1200_RF_CFG.max_txpower;
return RADIO_RESULT_OK;
case RADIO_CONST_PHY_OVERHEAD:
#if CC1200_802154G
#if CC1200_802154G_CRC16
*value = (radio_value_t)4; /* 2 bytes PHR, 2 bytes CRC */
#else
*value = (radio_value_t)6; /* 2 bytes PHR, 4 bytes CRC */
#endif
#else
*value = (radio_value_t)3; /* 1 len byte, 2 bytes CRC */
#endif
return RADIO_RESULT_OK;
case RADIO_CONST_BYTE_AIR_TIME:
*value = (radio_value_t)8*1000*1000 / CC1200_RF_CFG.bitrate;
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_TX:
*value = (radio_value_t)CC1200_RF_CFG.delay_before_tx;
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_RX:
*value = (radio_value_t)CC1200_RF_CFG.delay_before_rx;
return RADIO_RESULT_OK;
case RADIO_CONST_DELAY_BEFORE_DETECT:
*value = (radio_value_t)CC1200_RF_CFG.delay_before_detect;
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
@ -1282,6 +1436,23 @@ set_value(radio_param_t param, radio_value_t value)
static radio_result_t
get_object(radio_param_t param, void *dest, size_t size)
{
if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
if(size != sizeof(rtimer_clock_t) || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
*(rtimer_clock_t *)dest = sfd_timestamp;
return RADIO_RESULT_OK;
}
#if MAC_CONF_WITH_TSCH
if(param == RADIO_CONST_TSCH_TIMING) {
if(size != sizeof(uint16_t *) || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
*(const uint16_t **)dest = CC1200_RF_CFG.tsch_timing;
return RADIO_RESULT_OK;
}
#endif /* MAC_CONF_WITH_TSCH */
return RADIO_RESULT_NOT_SUPPORTED;
@ -1507,20 +1678,20 @@ configure(void)
while(1) {
#if (CC1200_RF_TESTMODE == 1)
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_YELLOW);
leds_on(LEDS_RED);
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_RED);
leds_on(LEDS_YELLOW);
#else
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_GREEN);
leds_on(LEDS_RED);
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_RED);
leds_on(LEDS_GREEN);
#endif
@ -1542,11 +1713,11 @@ configure(void)
while(1) {
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_GREEN);
leds_on(LEDS_YELLOW);
watchdog_periodic();
BUSYWAIT_UNTIL(0, RTIMER_SECOND / 10);
RTIMER_BUSYWAIT(RTIMER_SECOND / 10);
leds_off(LEDS_YELLOW);
leds_on(LEDS_GREEN);
clock_delay_usec(1000);
@ -1667,8 +1838,8 @@ calibrate(void)
INFO("RF: Calibrate\n");
strobe(CC1200_SCAL);
BUSYWAIT_UNTIL_STATE(STATE_CALIBRATE, RTIMER_SECOND / 100);
BUSYWAIT_UNTIL_STATE(STATE_IDLE, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_CALIBRATE, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_IDLE, RTIMER_SECOND / 100);
#if CC1200_CAL_TIMEOUT_SECONDS
cal_timer = clock_seconds();
@ -1705,7 +1876,7 @@ idle(void)
}
strobe(CC1200_SIDLE);
BUSYWAIT_UNTIL_STATE(STATE_IDLE, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_IDLE, RTIMER_SECOND / 100);
} /* idle(), 21.05.2015 */
/*---------------------------------------------------------------------------*/
@ -1723,7 +1894,7 @@ idle_calibrate_rx(void)
rf_flags &= ~RF_RX_PROCESSING_PKT;
strobe(CC1200_SFRX);
strobe(CC1200_SRX);
BUSYWAIT_UNTIL_STATE(STATE_RX, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_RX, RTIMER_SECOND / 100);
ENABLE_GPIO_INTERRUPTS();
@ -1748,7 +1919,7 @@ rx_rx(void)
strobe(CC1200_SFTX);
} else {
strobe(CC1200_SIDLE);
BUSYWAIT_UNTIL_STATE(STATE_IDLE,
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_IDLE,
RTIMER_SECOND / 100);
}
@ -1760,79 +1931,29 @@ rx_rx(void)
strobe(CC1200_SFRX);
strobe(CC1200_SRX);
BUSYWAIT_UNTIL_STATE(STATE_RX, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_RX, RTIMER_SECOND / 100);
}
/*---------------------------------------------------------------------------*/
/* Fill TX FIFO, start TX and wait for TX to complete (blocking!). */
/* Fill TX FIFO (if not already done), start TX and wait for TX to complete (blocking!). */
static int
idle_tx_rx(const uint8_t *payload, uint16_t payload_len)
{
#if (CC1200_MAX_PAYLOAD_LEN > (CC1200_FIFO_SIZE - PHR_LEN))
uint16_t bytes_left_to_write;
uint8_t to_write;
const uint8_t *p;
#endif
#if CC1200_802154G
/* Prepare PHR for 802.15.4g frames */
struct {
uint8_t phra;
uint8_t phrb;
} phr;
#if CC1200_802154G_CRC16
payload_len += 2;
#else
payload_len += 4;
#endif
/* Frame length */
phr.phrb = (uint8_t)(payload_len & 0x00FF);
phr.phra = (uint8_t)((payload_len >> 8) & 0x0007);
#if CC1200_802154G_WHITENING
/* Enable Whitening */
phr.phra |= (1 << 3);
#endif /* #if CC1200_802154G_WHITENING */
#if CC1200_802154G_CRC16
/* FCS type 1, 2 Byte CRC */
phr.phra |= (1 << 4);
#endif /* #if CC1200_802154G_CRC16 */
#endif /* #if CC1200_802154G */
/* Prepare for RX */
rf_flags &= ~RF_RX_PROCESSING_PKT;
strobe(CC1200_SFRX);
/* Flush TX FIFO */
strobe(CC1200_SFTX);
#if USE_SFSTXON
/*
* Enable synthesizer. Saves us a few µs especially if it takes
* long enough to fill the FIFO. This strobe must not be
* send before SFTX!
*/
strobe(CC1200_SFSTXON);
#endif
/* Configure GPIO0 to detect TX state */
single_write(CC1200_IOCFG0, CC1200_IOCFG_MARC_2PIN_STATUS_0);
#if (CC1200_MAX_PAYLOAD_LEN > (CC1200_FIFO_SIZE - PHR_LEN))
/*
* We already checked that GPIO2 is used if
* CC1200_MAX_PAYLOAD_LEN > 127 / 126 in the header of this file
*/
single_write(CC1200_IOCFG2, CC1200_IOCFG_TXFIFO_THR);
#endif
#if CC1200_802154G
/* Write PHR */
burst_write(CC1200_TXFIFO, (uint8_t *)&phr, PHR_LEN);
#else
/* Write length byte */
burst_write(CC1200_TXFIFO, (uint8_t *)&payload_len, PHR_LEN);
#endif /* #if CC1200_802154G */
#if CC1200_WITH_TX_BUF
/* Prepare and write header */
copy_header_to_tx_fifo(payload_len);
/*
* Fill FIFO with data. If SPI is slow it might make sense
@ -1849,17 +1970,18 @@ idle_tx_rx(const uint8_t *payload, uint16_t payload_len)
#else
burst_write(CC1200_TXFIFO, payload, payload_len);
#endif
#endif /* CC1200_WITH_TX_BUF */
#if USE_SFSTXON
/* Wait for synthesizer to be ready */
BUSYWAIT_UNTIL_STATE(STATE_FSTXON, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_STATE(STATE_FSTXON, RTIMER_SECOND / 100);
#endif
/* Start TX */
strobe(CC1200_STX);
/* Wait for TX to start. */
BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 1), RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 1), RTIMER_SECOND / 100);
/* Turned off at the latest in idle() */
TX_LEDS_ON();
@ -1888,7 +2010,7 @@ idle_tx_rx(const uint8_t *payload, uint16_t payload_len)
}
#if (CC1200_MAX_PAYLOAD_LEN > (CC1200_FIFO_SIZE - PHR_LEN))
#if (CC1200_MAX_PAYLOAD_LEN > (CC1200_FIFO_SIZE - PHR_LEN)) && CC1200_WITH_TX_BUF
if(bytes_left_to_write != 0) {
rtimer_clock_t t0;
uint8_t s;
@ -1922,7 +2044,7 @@ idle_tx_rx(const uint8_t *payload, uint16_t payload_len)
*/
INFO("RF: TX failure!\n");
BUSYWAIT_UNTIL((state() != STATE_TX), RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL((state() != STATE_TX), RTIMER_SECOND / 100);
/* Re-configure GPIO2 */
single_write(CC1200_IOCFG2, GPIO2_IOCFG);
idle();
@ -1936,12 +2058,12 @@ idle_tx_rx(const uint8_t *payload, uint16_t payload_len)
} else {
/* Wait for TX to complete */
BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
RTIMER_BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
CC1200_RF_CFG.tx_pkt_lifetime);
}
#else
/* Wait for TX to complete */
BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
RTIMER_BUSYWAIT_UNTIL((cc1200_arch_gpio0_read_pin() == 0),
CC1200_RF_CFG.tx_pkt_lifetime);
#endif
@ -2026,6 +2148,9 @@ set_channel(uint8_t channel)
uint8_t was_off = 0;
uint32_t freq;
channel %= (CC1200_RF_CFG.max_channel - CC1200_RF_CFG.min_channel + 1);
channel += CC1200_RF_CFG.min_channel;
#if 0
/*
* We explicitly allow a channel update even if the channel does not change.
@ -2156,6 +2281,7 @@ addr_check_auto_ack(uint8_t *frame, uint16_t frame_len)
idle();
#endif
prepare((const uint8_t *)ack, ACK_LEN);
idle_tx_rx((const uint8_t *)ack, ACK_LEN);
/* rx_rx() will follow */
@ -2204,6 +2330,23 @@ cc1200_rx_interrupt(void)
*/
static uint8_t buf[CC1200_MAX_PAYLOAD_LEN + APPENDIX_LEN];
/*
* If CC1200_USE_GPIO2 is enabled, we come here either once RX FIFO
* threshold is reached (GPIO2 rising edge)
* or at the end of the packet (GPIO0 falling edge).
*/
#if CC1200_USE_GPIO2
int gpio2 = cc1200_arch_gpio2_read_pin();
int gpio0 = cc1200_arch_gpio0_read_pin();
if((rf_flags & RF_RX_ONGOING) == 0 && gpio2 > 0) {
rf_flags |= RF_RX_ONGOING;
sfd_timestamp = RTIMER_NOW();
}
if(gpio0 == 0) {
rf_flags &= ~RF_RX_ONGOING;
}
#endif
if(SPI_IS_LOCKED()) {
/*

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018, RISE SICS.
* 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
* IEEE 802.15.4 TSCH timeslot timings for 15ms slots
* \author
* Simon Duquennoy <simon.duquennoy@ri.se>
*
*/
#include "contiki.h"
#include "net/mac/tsch/tsch.h"
/**
* \brief 15ms TSCH timeslot timings, required for cc2420 platforms as
* they are unable to keep up with the defulat 10ms timeslots.
*/
const uint16_t tsch_timeslot_timing_us_15000[tsch_ts_elements_count] = {
1800, /* CCAOffset */
128, /* CCA */
4000, /* TxOffset */
(4000 - (TSCH_CONF_RX_WAIT / 2)), /* RxOffset */
3600, /* RxAckDelay */
4000, /* TxAckDelay */
TSCH_CONF_RX_WAIT, /* RxWait */
800, /* AckWait */
2072, /* RxTx */
2400, /* MaxAck */
4256, /* MaxTx */
15000, /* TimeslotLength */
};

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018, RISE SICS.
* 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.
*
*/
#include "contiki.h"
extern const uint16_t tsch_timeslot_timing_us_15000[];

View File

@ -96,9 +96,6 @@ static const struct output_config output_power[] = {
void cc2420_arch_init(void);
/* XXX hack: these will be made as Chameleon packet attributes */
rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure;
int cc2420_authority_level_of_sender;
volatile uint8_t cc2420_sfd_counter;

View File

@ -102,9 +102,6 @@ int cc2420_get_txpower(void);
*/
int cc2420_interrupt(void);
/* XXX hack: these will be made as Chameleon packet attributes */
extern rtimer_clock_t cc2420_time_of_arrival,
cc2420_time_of_departure;
extern int cc2420_authority_level_of_sender;
int cc2420_on(void);

View File

@ -122,6 +122,10 @@ typedef unsigned long clock_time_t;
/* Use 64-bit rtimer (default in Contiki-NG is 32) */
#define RTIMER_CONF_CLOCK_SIZE 8
/* 1 len byte, 2 bytes CRC */
#define RADIO_PHY_OVERHEAD 3
/* 250kbps data rate. One byte = 32us */
#define RADIO_BYTE_AIR_TIME 32
#define RADIO_DELAY_BEFORE_TX 0
#define RADIO_DELAY_BEFORE_RX 0
#define RADIO_DELAY_BEFORE_DETECT 0

View File

@ -330,6 +330,10 @@ get_value(radio_param_t param, radio_value_t *value)
case RADIO_PARAM_LAST_LINK_QUALITY:
*value = simLQI;
return RADIO_RESULT_OK;
case RADIO_PARAM_RSSI:
/* return a fixed value depending on the channel */
*value = -90 + simRadioChannel - 11;
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
}

View File

@ -30,8 +30,10 @@
*
*/
/* Dummy watchdog routines for the Raven 1284p */
/* Dummy watchdog routines for Cooja motes */
#include "dev/watchdog.h"
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
/*---------------------------------------------------------------------------*/
void
@ -47,6 +49,9 @@ watchdog_start(void)
void
watchdog_periodic(void)
{
/* Yield and give control back to the simulator scheduler */
simProcessRunValue = 1;
cooja_mt_yield();
}
/*---------------------------------------------------------------------------*/
void

View File

@ -103,8 +103,6 @@ endif
CONTIKI_TARGET_DIRS = . dev
CONTIKI_TARGET_MAIN = platform.c
MODULES += os/lib/dbg-io
ifeq ($(JN516x_WITH_DR1175),1)
JN516x_WITH_DR1174 = 1
CFLAGS += -DSENSOR_BOARD_DR1175

View File

@ -130,13 +130,6 @@
#define MICROMAC_CONF_ALWAYS_ON 1
#endif /* MICROMAC_CONF_ALWAYS_ON */
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) ; \
} while(0)
/* Local variables */
static volatile signed char radio_last_rssi;
static volatile uint8_t radio_last_correlation; /* LQI */
@ -377,14 +370,14 @@ transmit(unsigned short payload_len)
(send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));
#endif
if(poll_mode) {
BUSYWAIT_UNTIL(u32MMAC_PollInterruptSource(E_MMAC_INT_TX_COMPLETE), MAX_PACKET_DURATION);
RTIMER_BUSYWAIT_UNTIL(u32MMAC_PollInterruptSource(E_MMAC_INT_TX_COMPLETE), MAX_PACKET_DURATION);
} else {
if(in_ack_transmission) {
/* as nested interupts are not possible, the tx flag will never be cleared */
BUSYWAIT_UNTIL(FALSE, MAX_ACK_DURATION);
RTIMER_BUSYWAIT_UNTIL(FALSE, MAX_ACK_DURATION);
} else {
/* wait until the tx flag is cleared */
BUSYWAIT_UNTIL(!tx_in_progress, MAX_PACKET_DURATION);
RTIMER_BUSYWAIT_UNTIL(!tx_in_progress, MAX_PACKET_DURATION);
}
}

View File

@ -66,14 +66,6 @@ extern volatile unsigned char xonxoff_state;
#endif /* UART_XONXOFF_FLOW_CTRL */
/*** Macro Definitions ***/
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) ; \
} while(0)
#define DEBUG_UART_BUFFERED FALSE
#define CHAR_DEADLINE (uart_char_delay * 100)
@ -276,7 +268,7 @@ uart_driver_write_with_deadline(uint8_t uart_dev, uint8_t ch)
volatile int16_t write = 0;
watchdog_periodic();
/* wait until there is space in tx fifo */
BUSYWAIT_UNTIL(write = (uart_driver_get_tx_fifo_available_space(uart_dev) > 0),
RTIMER_BUSYWAIT_UNTIL(write = (uart_driver_get_tx_fifo_available_space(uart_dev) > 0),
CHAR_DEADLINE);
/* write only if there is space so we do not get stuck */
if(write) {

View File

@ -38,6 +38,10 @@
#undef putchar
/* 1 len byte, 2 bytes CRC */
#define RADIO_PHY_OVERHEAD 3
/* 250kbps data rate. One byte = 32us */
#define RADIO_BYTE_AIR_TIME 32
/* Delay between GO signal and SFD
* Measured 153us between GO and preamble. Add 5 bytes (preamble + SFD) air time: 153+5*32 = 313 */
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(313))

View File

@ -9,12 +9,12 @@ CONTIKI_TARGET_DIRS += . dev config
CONTIKI_SOURCEFILES += platform.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 arch/cpu/arm/common
### Suppress the existing debug I/O in os/lib
MAKE_WITH_LIB_DBG_IO = 0
CONTIKI_TARGET_DIRS += rtt
CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c
else
CONTIKI_SOURCEFILES += dbg.c
MODULES += os/lib/dbg-io
endif
### Unless the example dictates otherwise, build with code size optimisations switched off

View File

@ -8,9 +8,7 @@ ifndef CONTIKI
$(error 'CONTIKI' not defined! You must specify where CONTIKI resides!)
endif
ifndef BOARD
$(error 'BOARD' not defined! You must specify which board you are using!)
endif
BOARD ?= srf06/cc26x0
################################################################################
### Resolve the SimpleLink Family

View File

@ -17,11 +17,14 @@
#define NETSTACK_CONF_RADIO cc2420_driver
#endif /* NETSTACK_CONF_RADIO */
/* Symbol for the TSCH 15ms timeslot timing template */
#define TSCH_CONF_ARCH_HDR_PATH "dev/cc2420/cc2420-tsch-15ms.h"
/* The TSCH default slot length of 10ms is a bit too short for this platform,
* use 15ms instead. */
#ifndef TSCH_CONF_DEFAULT_TIMESLOT_LENGTH
#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 15000
#endif /* TSCH_CONF_DEFAULT_TIMESLOT_LENGTH */
#ifndef TSCH_CONF_DEFAULT_TIMESLOT_TIMING
#define TSCH_CONF_DEFAULT_TIMESLOT_TIMING tsch_timeslot_timing_us_15000
#endif /* TSCH_CONF_DEFAULT_TIMESLOT_TIMING */
/* Save RAM through a smaller uIP buffer */
#ifndef UIP_CONF_BUFFER_SIZE

View File

@ -43,6 +43,7 @@
#include "lib/random.h"
#include "net/netstack.h"
#include "net/mac/framer/frame802154.h"
#include "net/mac/tsch/tsch.h"
#if NETSTACK_CONF_WITH_IPV6
#include "net/ipv6/uip-ds6.h"

View File

@ -43,6 +43,11 @@
* Definitions below are dictated by the hardware and not really
* changeable!
*/
/* 1 len byte, 2 bytes CRC */
#define RADIO_PHY_OVERHEAD 3
/* 250kbps data rate. One byte = 32us */
#define RADIO_BYTE_AIR_TIME 32
/* Delay between GO signal and SFD: radio fixed delay + 4Bytes preample + 1B SFD -- 1Byte time is 32us
* ~327us + 129preample = 456 us */
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(456))

View File

@ -63,9 +63,9 @@ LPM_MODULE(rf_switch_module, NULL, shutdown_handler, NULL, LPM_DOMAIN_NONE);
void
rf_switch_init()
{
ti_lib_rom_ioc_pin_type_gpio_output(POWER_PIN);
ti_lib_ioc_pin_type_gpio_output(POWER_PIN);
ti_lib_gpio_clear_dio(POWER_PIN);
ti_lib_rom_ioc_pin_type_gpio_output(SELECT_PIN);
ti_lib_ioc_pin_type_gpio_output(SELECT_PIN);
ti_lib_gpio_clear_dio(SELECT_PIN);
lpm_register_module(&rf_switch_module);

View File

@ -158,11 +158,11 @@ platform_init_stage_one()
* latches in the first place. Before doing these things though, we should
* allow software to first regain control of pins
*/
#if !defined(ThisLibraryIsFor_CC26x0R2_HaltIfViolated)
ti_lib_pwr_ctrl_io_freeze_disable();
ti_lib_aon_ioc_freeze_disable();
HWREG(AON_SYSCTL_BASE + AON_SYSCTL_O_SLEEPCTL) = 1;
ti_lib_sys_ctrl_aon_sync();
#endif
ti_lib_rom_int_enable(INT_AON_GPIO_EDGE);
ti_lib_int_enable(INT_AON_GPIO_EDGE);
ti_lib_int_master_enable();
soc_rtc_init();

View File

@ -601,11 +601,11 @@ configure(int type, int enable)
{
switch(type) {
case SENSORS_HW_INIT:
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN);
ti_lib_ioc_io_hyst_set(BOARD_IOID_MPU_INT, IOC_HYST_ENABLE);
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);
ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MPU_POWER, IOC_CURRENT_4MA,
IOC_STRENGTH_MAX);
ti_lib_gpio_clear_dio(BOARD_IOID_MPU_POWER);

View File

@ -59,10 +59,10 @@ config(int type, int enable)
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR);
break;
case SENSORS_ACTIVE:
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR);
ti_lib_rom_ioc_port_configure_set(BOARD_IOID_ALS_OUT, IOC_PORT_GPIO,
IOC_STD_OUTPUT);
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT);
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR);
ti_lib_ioc_port_configure_set(BOARD_IOID_ALS_OUT, IOC_PORT_GPIO,
IOC_STD_OUTPUT);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT);
if(enable) {
ti_lib_gpio_set_dio(BOARD_IOID_ALS_PWR);

View File

@ -55,6 +55,25 @@
#endif /* PROJECT_CONF_PATH */
/*---------------------------------------------------------------------------*/
#include "cc2538-def.h"
unsigned radio_phy_overhead(void);
unsigned radio_byte_air_time(void);
unsigned radio_delay_before_tx(void);
unsigned radio_delay_before_rx(void);
unsigned radio_delay_before_detect(void);
uint16_t *radio_tsch_timeslot_timing(void);
/** @} */
/*---------------------------------------------------------------------------*/
#define RADIO_PHY_OVERHEAD radio_phy_overhead()
#define RADIO_BYTE_AIR_TIME radio_byte_air_time()
#define RADIO_DELAY_BEFORE_TX radio_delay_before_tx()
#define RADIO_DELAY_BEFORE_RX radio_delay_before_rx()
#define RADIO_DELAY_BEFORE_DETECT radio_delay_before_detect()
#define TSCH_CONF_DEFAULT_TIMESLOT_TIMING radio_tsch_timeslot_timing()
/*---------------------------------------------------------------------------*/
/**
* \name Serial Boot Loader Backdoor configuration

View File

@ -76,18 +76,8 @@
/*---------------------------------------------------------------------------*/
#if DEBUG_CC1200_ARCH > 0
#define PRINTF(...) printf(__VA_ARGS__)
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) {} \
if(!(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time)))) { \
printf("ARCH: Timeout exceeded in line %d!\n", __LINE__); \
} \
} while(0)
#else
#define PRINTF(...)
#define BUSYWAIT_UNTIL(cond, max_time) while(!cond)
#endif
/*---------------------------------------------------------------------------*/
extern int cc1200_rx_interrupt(void);
@ -105,7 +95,7 @@ cc1200_arch_spi_select(void)
/* Set CSn to low (0) */
GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
/* The MISO pin should go low before chip is fully enabled. */
BUSYWAIT_UNTIL(
RTIMER_BUSYWAIT_UNTIL(
GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK) == 0,
RTIMER_SECOND / 100);
}
@ -288,7 +278,7 @@ cc1200_arch_init(void)
cc1200_arch_spi_deselect();
/* Ensure MISO is high */
BUSYWAIT_UNTIL(
RTIMER_BUSYWAIT_UNTIL(
GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK),
RTIMER_SECOND / 10);
}
@ -297,4 +287,3 @@ cc1200_arch_init(void)
* @}
* @}
*/

View File

@ -51,15 +51,6 @@
#define PRINTF(...)
#endif
/*---------------------------------------------------------------------------*/
#define BUSYWAIT_UNTIL(max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) { \
watchdog_periodic(); \
} \
} while(0)
/*---------------------------------------------------------------------------*/
#define DHT22_PORT_BASE GPIO_PORT_TO_BASE(DHT22_PORT)
#define DHT22_PIN_MASK GPIO_PIN_MASK(DHT22_PIN)
/*---------------------------------------------------------------------------*/
@ -80,12 +71,12 @@ dht22_read(void)
/* Exit low power mode and initialize variables */
GPIO_SET_OUTPUT(DHT22_PORT_BASE, DHT22_PIN_MASK);
GPIO_SET_PIN(DHT22_PORT_BASE, DHT22_PIN_MASK);
BUSYWAIT_UNTIL(DHT22_AWAKE_TIME);
RTIMER_BUSYWAIT(DHT22_AWAKE_TIME);
memset(dht22_data, 0, DHT22_BUFFER);
/* Initialization sequence */
GPIO_CLR_PIN(DHT22_PORT_BASE, DHT22_PIN_MASK);
BUSYWAIT_UNTIL(DHT22_START_TIME);
RTIMER_BUSYWAIT(DHT22_START_TIME);
GPIO_SET_PIN(DHT22_PORT_BASE, DHT22_PIN_MASK);
clock_delay_usec(DHT22_READY_TIME);

View File

@ -257,6 +257,48 @@ platform_idle()
lpm_enter();
}
/*---------------------------------------------------------------------------*/
unsigned
radio_phy_overhead(void) {
radio_value_t ret;
NETSTACK_RADIO.get_value(RADIO_CONST_PHY_OVERHEAD, &ret);
return (unsigned)ret;
}
/*---------------------------------------------------------------------------*/
unsigned
radio_byte_air_time(void) {
radio_value_t ret;
NETSTACK_RADIO.get_value(RADIO_CONST_BYTE_AIR_TIME, &ret);
return (unsigned)ret;
}
/*---------------------------------------------------------------------------*/
unsigned
radio_delay_before_tx(void) {
radio_value_t ret;
NETSTACK_RADIO.get_value(RADIO_CONST_DELAY_BEFORE_TX, &ret);
return (unsigned)ret;
}
/*---------------------------------------------------------------------------*/
unsigned
radio_delay_before_rx(void) {
radio_value_t ret;
NETSTACK_RADIO.get_value(RADIO_CONST_DELAY_BEFORE_RX, &ret);
return (unsigned)ret;
}
/*---------------------------------------------------------------------------*/
unsigned
radio_delay_before_detect(void) {
radio_value_t ret;
NETSTACK_RADIO.get_value(RADIO_CONST_DELAY_BEFORE_DETECT, &ret);
return (unsigned)ret;
}
/*---------------------------------------------------------------------------*/
uint16_t *
radio_tsch_timeslot_timing(void) {
uint16_t *ret;
NETSTACK_RADIO.get_object(RADIO_CONST_TSCH_TIMING, &ret, sizeof(ret));
return ret;
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}

View File

@ -0,0 +1,34 @@
CONTIKI_PROJECT = node
all: $(CONTIKI_PROJECT)
CONTIKI=../../..
PLATFORMS_EXCLUDE = sky nrf52dk native
BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
# The channel selection library
MODULES += os/services/tsch-cs
# force Orchestra from command line
MAKE_WITH_ORCHESTRA ?= 0
# force Security from command line
MAKE_WITH_SECURITY ?= 0
# print #routes periodically, used for regression tests
MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0
MAKE_MAC = MAKE_MAC_TSCH
MODULES += os/services/shell
ifeq ($(MAKE_WITH_ORCHESTRA),1)
MODULES += os/services/orchestra
endif
ifeq ($(MAKE_WITH_SECURITY),1)
CFLAGS += -DWITH_SECURITY=1
endif
ifeq ($(MAKE_WITH_PERIODIC_ROUTES_PRINT),1)
CFLAGS += -DWITH_PERIODIC_ROUTES_PRINT=1
endif
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,8 @@
Demonstration of TSCH adaptive channel selection based on background noise RSSI metric.
TSCH stats must be enabled for the adaptive selection functionality to compile and work.
This code relies on the `os/services/channel-selection` library that implements
the "RSSI upstream" adaptative channel selection strategy, described in the following paper:
A. Elsts, X. Fafoutis, G. Oikonomou and R. Piechocki. Adaptive Channel Selection in IEEE 802.15.4 TSCH Networks, 1st Global Internet of Things Summit, 2017.
http://ieeexplore.ieee.org/document/8016246/

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk
* 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 RPL+TSCH node.
*
* \author Simon Duquennoy <simonduq@sics.se>
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#include "contiki.h"
#include "sys/node-id.h"
#include "sys/log.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/ipv6/uip-sr.h"
#include "net/mac/tsch/tsch.h"
#include "net/routing/routing.h"
#include "tsch-cs.h"
#define DEBUG DEBUG_PRINT
#include "net/ipv6/uip-debug.h"
/*---------------------------------------------------------------------------*/
PROCESS(node_process, "RPL Node");
AUTOSTART_PROCESSES(&node_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(node_process, ev, data)
{
int is_coordinator;
PROCESS_BEGIN();
is_coordinator = 0;
#if CONTIKI_TARGET_COOJA
is_coordinator = (node_id == 1);
#endif
if(is_coordinator) {
NETSTACK_ROUTING.root_start();
}
NETSTACK_MAC.on();
#if WITH_PERIODIC_ROUTES_PRINT
{
static struct etimer et;
/* Print out routing tables every minute */
etimer_set(&et, CLOCK_SECOND * 60);
while(1) {
/* Used for non-regression testing */
#if (UIP_MAX_ROUTES != 0)
PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes());
#endif
#if (UIP_SR_LINK_NUM != 0)
PRINTF("Routing links: %u\n", uip_sr_num_nodes());
#endif
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
}
}
#endif /* WITH_PERIODIC_ROUTES_PRINT */
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk
* 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.
*
*/
/**
* \author Simon Duquennoy <simonduq@sics.se>
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#ifndef __PROJECT_CONF_H__
#define __PROJECT_CONF_H__
#include <stdint.h>
#include <stdbool.h>
/* Set to enable TSCH security */
#ifndef WITH_SECURITY
#define WITH_SECURITY 0
#endif /* WITH_SECURITY */
/* USB serial takes space, free more space elsewhere */
#define SICSLOWPAN_CONF_FRAG 0
#define UIP_CONF_BUFFER_SIZE 160
/*******************************************************/
/******************* Configure TSCH ********************/
/*******************************************************/
/* IEEE802.15.4 PANID */
#define IEEE802154_CONF_PANID 0x81a5
/* Do not start TSCH at init, wait for NETSTACK_MAC.on() */
#define TSCH_CONF_AUTOSTART 0
/* 6TiSCH minimal schedule length.
* Larger values result in less frequent active slots: reduces capacity and saves energy. */
#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 3
#if WITH_SECURITY
/* Enable security */
#define LLSEC802154_CONF_ENABLED 1
#endif /* WITH_SECURITY */
/* Enable TSCH statistics: must be on for channel selection to work */
#define TSCH_STATS_CONF_ON 1
/* Enable periodic RSSI sampling for TSCH statistics */
#define TSCH_STATS_CONF_SAMPLE_NOISE_RSSI 1
/* Reduce the TSCH stat "decay to normal" period to get printouts more often */
#define TSCH_STATS_CONF_DECAY_INTERVAL (60 * CLOCK_SECOND)
/* For adaptive channel selection */
extern void tsch_cs_channel_stats_updated(uint8_t updated_channel, uint16_t old_busyness_metric);
extern bool tsch_cs_process(void);
/* These will be called from the core TSCH code */
#define TSCH_CALLBACK_CHANNEL_STATS_UPDATED tsch_cs_channel_stats_updated
#define TSCH_CALLBACK_SELECT_CHANNELS tsch_cs_process
/* The coordinator will update the network nodes with new hopping sequences */
#define TSCH_PACKET_CONF_EB_WITH_HOPPING_SEQUENCE 1
/* Reduce the EB period in order to update the network nodes with more agility */
#define TSCH_CONF_EB_PERIOD (4 * CLOCK_SECOND)
#define TSCH_CONF_MAX_EB_PERIOD (4 * CLOCK_SECOND)
/*******************************************************/
/************* Other system configuration **************/
/*******************************************************/
/* Logging */
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_INFO
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_INFO
#define TSCH_LOG_CONF_PER_SLOT 1
#endif /* __PROJECT_CONF_H__ */

View File

@ -74,33 +74,4 @@
#endif /* WITH_SECURITY */
/*******************************************************/
/************* Other system configuration **************/
/*******************************************************/
#if CONTIKI_TARGET_Z1
/* Save some space to fit the limited RAM of the z1 */
#define UIP_CONF_TCP 0
#define QUEUEBUF_CONF_NUM 2
#define NETSTACK_MAX_ROUTE_ENTRIES 2
#define NBR_TABLE_CONF_MAX_NEIGHBORS 2
#define UIP_CONF_ND6_SEND_NA 0
#define SICSLOWPAN_CONF_FRAG 0
#if WITH_SECURITY
/* Note: on sky or z1 in cooja, crypto operations are done in S/W and
* cannot be accommodated in normal slots. Use 65ms slots instead, and
* a very short 6TiSCH minimal schedule length */
#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 65000
#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 2
#endif /* WITH_SECURITY */
#endif /* CONTIKI_TARGET_Z1 */
#if CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL || \
CONTIKI_TARGET_OPENMOTE_CC2538
#define TSCH_CONF_HW_FRAME_FILTERING 0
#endif /* CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL \
|| CONTIKI_TARGET_OPENMOTE_CC2538 */
#endif /* PROJECT_CONF_H_ */

View File

@ -0,0 +1,31 @@
CONTIKI_PROJECT = node
all: $(CONTIKI_PROJECT)
CONTIKI=../../..
PLATFORMS_EXCLUDE = sky nrf52dk native
BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
# force Orchestra from command line
MAKE_WITH_ORCHESTRA ?= 0
# force Security from command line
MAKE_WITH_SECURITY ?= 0
# print #routes periodically, used for regression tests
MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0
MAKE_MAC = MAKE_MAC_TSCH
MODULES += os/services/shell
ifeq ($(MAKE_WITH_ORCHESTRA),1)
MODULES += os/services/orchestra
endif
ifeq ($(MAKE_WITH_SECURITY),1)
CFLAGS += -DWITH_SECURITY=1
endif
ifeq ($(MAKE_WITH_PERIODIC_ROUTES_PRINT),1)
CFLAGS += -DWITH_PERIODIC_ROUTES_PRINT=1
endif
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1 @@
Demonstration of TSCH stats.

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk
* 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 RPL+TSCH node.
*
* \author Simon Duquennoy <simonduq@sics.se>
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#include "contiki.h"
#include "sys/node-id.h"
#include "sys/log.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/ipv6/uip-sr.h"
#include "net/mac/tsch/tsch.h"
#include "net/routing/routing.h"
#define DEBUG DEBUG_PRINT
#include "net/ipv6/uip-debug.h"
/*---------------------------------------------------------------------------*/
PROCESS(node_process, "RPL Node");
AUTOSTART_PROCESSES(&node_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(node_process, ev, data)
{
int is_coordinator;
PROCESS_BEGIN();
is_coordinator = 0;
#if CONTIKI_TARGET_COOJA
is_coordinator = (node_id == 1);
#endif
if(is_coordinator) {
NETSTACK_ROUTING.root_start();
}
NETSTACK_MAC.on();
#if WITH_PERIODIC_ROUTES_PRINT
{
static struct etimer et;
/* Print out routing tables every minute */
etimer_set(&et, CLOCK_SECOND * 60);
while(1) {
/* Used for non-regression testing */
#if (UIP_MAX_ROUTES != 0)
PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes());
#endif
#if (UIP_SR_LINK_NUM != 0)
PRINTF("Routing links: %u\n", uip_sr_num_nodes());
#endif
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
}
}
#endif /* WITH_PERIODIC_ROUTES_PRINT */
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk
* 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.
*
*/
/**
* \author Simon Duquennoy <simonduq@sics.se>
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#ifndef __PROJECT_CONF_H__
#define __PROJECT_CONF_H__
/* Set to enable TSCH security */
#ifndef WITH_SECURITY
#define WITH_SECURITY 0
#endif /* WITH_SECURITY */
/* USB serial takes space, free more space elsewhere */
#define SICSLOWPAN_CONF_FRAG 0
#define UIP_CONF_BUFFER_SIZE 160
/*******************************************************/
/******************* Configure TSCH ********************/
/*******************************************************/
/* IEEE802.15.4 PANID */
#define IEEE802154_CONF_PANID 0x81a5
/* Do not start TSCH at init, wait for NETSTACK_MAC.on() */
#define TSCH_CONF_AUTOSTART 0
/* 6TiSCH minimal schedule length.
* Larger values result in less frequent active slots: reduces capacity and saves energy. */
#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 3
#if WITH_SECURITY
/* Enable security */
#define LLSEC802154_CONF_ENABLED 1
#endif /* WITH_SECURITY */
/* Enable TSCH statistics */
#define TSCH_STATS_CONF_ON 1
/* Enable periodic RSSI sampling for TSCH statistics */
#define TSCH_STATS_CONF_SAMPLE_NOISE_RSSI 1
/* Reduce the TSCH stat "decay to normal" period to get printouts more often */
#define TSCH_STATS_CONF_DECAY_INTERVAL (60 * CLOCK_SECOND)
/*******************************************************/
/************* Other system configuration **************/
/*******************************************************/
/* Logging */
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_INFO
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_INFO
#define TSCH_LOG_CONF_PER_SLOT 1
#endif /* __PROJECT_CONF_H__ */

View File

@ -119,7 +119,7 @@
/*---------------------------------------------------------------------------*/
/* Default configuration values */
#define CC26XX_WEB_DEMO_DEFAULT_ORG_ID "quickstart"
#if CPU_FAMILY_CC13XX
#if CPU_FAMILY_CC13X0
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc13xx"
#else
#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc26xx"

View File

@ -194,7 +194,7 @@ PROCESS_THREAD(node_process, ev, data)
if (host_found) {
/* Make sample count dependent on asn. After a disconnect, waveforms remain
synchronous. Use node_mac to create phase offset between waveforms in different nodes */
sample_count = ((tsch_current_asn.ls4b/((1000/(TSCH_CONF_DEFAULT_TIMESLOT_LENGTH/1000)))/INTERVAL)+node_mac[7]) % (SIZE_OF_WAVEFORM-1);
sample_count = ((tsch_current_asn.ls4b/((1000/(tsch_timing_us[tsch_ts_timeslot_length]/1000)))/INTERVAL)+node_mac[7]) % (SIZE_OF_WAVEFORM-1);
printf("%d sec. waveform=%s. cnt=%d. value=%d\n", total_time, waveform_table[selected_waveform].str, sample_count, waveform_table[selected_waveform].table[sample_count]);
my_sprintf(udp_buf, waveform_table[selected_waveform].table[sample_count]);
uip_udp_packet_send(udp_conn_tx, udp_buf, strlen(udp_buf));

View File

@ -53,6 +53,7 @@
#include "services/orchestra/orchestra.h"
#include "services/shell/serial-shell.h"
#include "services/simple-energest/simple-energest.h"
#include "services/tsch-cs/tsch-cs.h"
#include <stdio.h>
#include <stdint.h>
@ -146,6 +147,11 @@ main(void)
simple_energest_init();
#endif /* BUILD_WITH_SIMPLE_ENERGEST */
#if BUILD_WITH_TSCH_CS
/* Initialize the channel selection module */
tsch_cs_adaptations_init();
#endif /* BUILD_WITH_TSCH_CS */
autostart_start(autostart_processes);
watchdog_start();

View File

@ -170,6 +170,9 @@ enum {
* it needs to be used with radio.get_object()/set_object(). */
RADIO_PARAM_LAST_PACKET_TIMESTAMP,
/* For enabling and disabling the SHR search */
RADIO_PARAM_SHR_SEARCH,
/* Constants (read only) */
/* The lowest radio channel. */
@ -180,7 +183,14 @@ enum {
/* The minimum transmission power in dBm. */
RADIO_CONST_TXPOWER_MIN,
/* The maximum transmission power in dBm. */
RADIO_CONST_TXPOWER_MAX
RADIO_CONST_TXPOWER_MAX,
RADIO_CONST_TSCH_TIMING,
RADIO_CONST_PHY_OVERHEAD,
RADIO_CONST_BYTE_AIR_TIME,
RADIO_CONST_DELAY_BEFORE_TX,
RADIO_CONST_DELAY_BEFORE_RX,
RADIO_CONST_DELAY_BEFORE_DETECT,
};
/* Radio power modes */

View File

@ -37,12 +37,10 @@
#include "net/link-stats.h"
#include <stdio.h>
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "Link Stats"
#define LOG_LEVEL LOG_LEVEL_MAC
/* Maximum value for the Tx count counter */
#define TX_COUNT_MAX 32
@ -82,6 +80,13 @@ link_stats_from_lladdr(const linkaddr_t *lladdr)
return nbr_table_get_from_lladdr(link_stats, lladdr);
}
/*---------------------------------------------------------------------------*/
/* Returns the neighbor's address given a link stats item */
const linkaddr_t *
link_stats_get_lladdr(const struct link_stats *stat)
{
return nbr_table_get_lladdr(link_stats, stat);
}
/*---------------------------------------------------------------------------*/
/* Are the statistics fresh? */
int
link_stats_is_fresh(const struct link_stats *stats)
@ -156,6 +161,14 @@ link_stats_packet_sent(const linkaddr_t *lladdr, int status, int numtx)
stats->last_tx_time = clock_time();
stats->freshness = MIN(stats->freshness + numtx, FRESHNESS_MAX);
#if LINK_STATS_PACKET_COUNTERS
/* Update paket counters */
stats->cnt_current.num_packets_tx += numtx;
if(status == MAC_TX_OK) {
stats->cnt_current.num_packets_acked++;
}
#endif
/* Add penalty in case of no-ACK */
if(status == MAC_TX_NOACK) {
numtx += ETX_NOACK_PENALTY;
@ -219,8 +232,38 @@ link_stats_input_callback(const linkaddr_t *lladdr)
/* Update RSSI EWMA */
stats->rssi = ((int32_t)stats->rssi * (EWMA_SCALE - EWMA_ALPHA) +
(int32_t)packet_rssi * EWMA_ALPHA) / EWMA_SCALE;
#if LINK_STATS_PACKET_COUNTERS
stats->cnt_current.num_packets_rx++;
#endif
}
/*---------------------------------------------------------------------------*/
#if LINK_STATS_PACKET_COUNTERS
/*---------------------------------------------------------------------------*/
static void
print_and_update_counters(void)
{
struct link_stats *stats;
for(stats = nbr_table_head(link_stats); stats != NULL;
stats = nbr_table_next(link_stats, stats)) {
struct link_packet_counter *c = &stats->cnt_current;
LOG_INFO("num packets: tx=%u ack=%u rx=%u to=",
c->num_packets_tx, c->num_packets_acked, c->num_packets_rx);
LOG_INFO_LLADDR(link_stats_get_lladdr(stats));
LOG_INFO_("\n");
stats->cnt_total.num_packets_tx += stats->cnt_current.num_packets_tx;
stats->cnt_total.num_packets_acked += stats->cnt_current.num_packets_acked;
stats->cnt_total.num_packets_rx += stats->cnt_current.num_packets_rx;
memset(&stats->cnt_current, 0, sizeof(stats->cnt_current));
}
}
/*---------------------------------------------------------------------------*/
#endif /* LINK_STATS_PACKET_COUNTERS */
/*---------------------------------------------------------------------------*/
/* Periodic timer called at a period of FRESHNESS_HALF_LIFE */
static void
periodic(void *ptr)
@ -231,6 +274,10 @@ periodic(void *ptr)
for(stats = nbr_table_head(link_stats); stats != NULL; stats = nbr_table_next(link_stats, stats)) {
stats->freshness >>= 1;
}
#if LINK_STATS_PACKET_COUNTERS
print_and_update_counters();
#endif
}
/*---------------------------------------------------------------------------*/
/* Resets link-stats module */

View File

@ -56,6 +56,25 @@
#define LINK_STATS_ETX_FROM_PACKET_COUNT 0
#endif /* LINK_STATS_ETX_FROM_PACKET_COUNT */
/* Store and periodically print packet counters? */
#ifdef LINK_STATS_CONF_PACKET_COUNTERS
#define LINK_STATS_PACKET_COUNTERS LINK_STATS_CONF_PACKET_COUNTERS
#else /* LINK_STATS_CONF_PACKET_COUNTERS */
#define LINK_STATS_PACKET_COUNTERS 0
#endif /* LINK_STATS_PACKET_COUNTERS */
typedef uint16_t link_packet_stat_t;
struct link_packet_counter {
/* total attempts to transmit unicast packets */
link_packet_stat_t num_packets_tx;
/* total ACKs for unicast packets */
link_packet_stat_t num_packets_acked;
/* total number of unicast and broadcast packets received */
link_packet_stat_t num_packets_rx;
};
/* All statistics of a given link */
struct link_stats {
clock_time_t last_tx_time; /* Last Tx timestamp */
@ -66,10 +85,17 @@ struct link_stats {
uint8_t tx_count; /* Tx count, used for ETX calculation */
uint8_t ack_count; /* ACK count, used for ETX calculation */
#endif /* LINK_STATS_ETX_FROM_PACKET_COUNT */
#if LINK_STATS_PACKET_COUNTERS
struct link_packet_counter cnt_current; /* packets in the current period */
struct link_packet_counter cnt_total; /* packets in total */
#endif
};
/* Returns the neighbor's link statistics */
const struct link_stats *link_stats_from_lladdr(const linkaddr_t *lladdr);
/* Returns the address of the neighbor */
const linkaddr_t *link_stats_get_lladdr(const struct link_stats *);
/* Are the statistics fresh? */
int link_stats_is_fresh(const struct link_stats *stats);
/* Resets link-stats module */

View File

@ -50,11 +50,6 @@
#include "lib/list.h"
#include "lib/memb.h"
#if CONTIKI_TARGET_COOJA
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "CSMA"
@ -201,17 +196,10 @@ send_one_packet(void *ptr)
if(is_broadcast) {
ret = MAC_TX_OK;
} else {
rtimer_clock_t wt;
/* Check for ack */
wt = RTIMER_NOW();
watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + CSMA_ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
}
/* Wait for max CSMA_ACK_WAIT_TIME */
RTIMER_BUSYWAIT_UNTIL(NETSTACK_RADIO.pending_packet(), CSMA_ACK_WAIT_TIME);
ret = MAC_TX_NOACK;
if(NETSTACK_RADIO.receiving_packet() ||
@ -220,17 +208,8 @@ send_one_packet(void *ptr)
int len;
uint8_t ackbuf[CSMA_ACK_LEN];
if(CSMA_AFTER_ACK_DETECTED_WAIT_TIME > 0) {
wt = RTIMER_NOW();
watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(),
wt + CSMA_AFTER_ACK_DETECTED_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
}
}
/* Wait an additional CSMA_AFTER_ACK_DETECTED_WAIT_TIME to complete reception */
RTIMER_BUSYWAIT_UNTIL(NETSTACK_RADIO.pending_packet(), CSMA_AFTER_ACK_DETECTED_WAIT_TIME);
if(NETSTACK_RADIO.pending_packet()) {
len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN);

View File

@ -151,7 +151,7 @@
#ifdef TSCH_CONF_HOPPING_SEQUENCE_MAX_LEN
#define TSCH_HOPPING_SEQUENCE_MAX_LEN TSCH_CONF_HOPPING_SEQUENCE_MAX_LEN
#else
#define TSCH_HOPPING_SEQUENCE_MAX_LEN 16
#define TSCH_HOPPING_SEQUENCE_MAX_LEN sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)
#endif
/******** Configuration: association *******/
@ -365,18 +365,21 @@
/******** Configuration: CSMA *******/
/* TSCH CSMA-CA parameters, see IEEE 802.15.4e-2012 */
/* Min backoff exponent */
#ifdef TSCH_CONF_MAC_MIN_BE
#define TSCH_MAC_MIN_BE TSCH_CONF_MAC_MIN_BE
#else
#define TSCH_MAC_MIN_BE 1
#endif
/* Max backoff exponent */
#ifdef TSCH_CONF_MAC_MAX_BE
#define TSCH_MAC_MAX_BE TSCH_CONF_MAC_MAX_BE
#else
#define TSCH_MAC_MAX_BE 5
#endif
/* Max number of re-transmissions */
#ifdef TSCH_CONF_MAC_MAX_FRAME_RETRIES
#define TSCH_MAC_MAX_FRAME_RETRIES TSCH_CONF_MAC_MAX_FRAME_RETRIES
@ -391,6 +394,13 @@
#define TSCH_PACKET_EACK_WITH_SRC_ADDR 0
#endif
/* Perform CCA before sending? */
#ifdef TSCH_CONF_CCA_ENABLED
#define TSCH_CCA_ENABLED TSCH_CONF_CCA_ENABLED
#else
#define TSCH_CCA_ENABLED 0
#endif
/* Include destination address in ACK? */
#ifdef TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR
#define TSCH_PACKET_EACK_WITH_DEST_ADDR TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR
@ -415,12 +425,12 @@ by default, useful in case of duplicate seqno */
#define TSCH_RADIO_ON_DURING_TIMESLOT 0
#endif
/* Timeslot timing */
#ifndef TSCH_CONF_DEFAULT_TIMESLOT_LENGTH
#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 10000
#endif /* TSCH_CONF_DEFAULT_TIMESLOT_LENGTH */
/* TSCH timeslot timing template */
#ifdef TSCH_CONF_DEFAULT_TIMESLOT_TIMING
#define TSCH_DEFAULT_TIMESLOT_TIMING TSCH_CONF_DEFAULT_TIMESLOT_TIMING
#else
#define TSCH_DEFAULT_TIMESLOT_TIMING tsch_timeslot_timing_us_10000
#endif
/* Configurable Rx guard time is micro-seconds */
#ifndef TSCH_CONF_RX_WAIT

View File

@ -75,87 +75,16 @@
#define TSCH_TIMESYNC_MEASUREMENT_ERROR US_TO_RTIMERTICKS(32)
/* The approximate number of slots per second */
#define TSCH_SLOTS_PER_SECOND (1000000 / TSCH_DEFAULT_TS_TIMESLOT_LENGTH)
#define TSCH_SLOTS_PER_SECOND (1000000 / tsch_timing_us[tsch_ts_timeslot_length])
/* Calculate packet tx/rx duration in rtimer ticks based on sent
* packet len in bytes with 802.15.4 250kbps data rate.
* One byte = 32us. Add two bytes for CRC and one for len field */
#define TSCH_PACKET_DURATION(len) US_TO_RTIMERTICKS(32 * ((len) + 3))
#define TSCH_PACKET_DURATION(len) US_TO_RTIMERTICKS(RADIO_BYTE_AIR_TIME * ((len) + RADIO_PHY_OVERHEAD))
/* Convert rtimer ticks to clock and vice versa */
#define TSCH_CLOCK_TO_TICKS(c) (((c) * RTIMER_SECOND) / CLOCK_SECOND)
#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length)
/* The default timeslot timing in the standard is a guard time of
* 2200 us, a Tx offset of 2120 us and a Rx offset of 1120 us.
* As a result, the listening device has a guard time not centered
* on the expected Tx time. This is to be fixed in the next iteration
* of the standard. This can be enabled with:
* #define TSCH_DEFAULT_TS_TX_OFFSET 2120
* #define TSCH_DEFAULT_TS_RX_OFFSET 1120
* #define TSCH_DEFAULT_TS_RX_WAIT 2200
*
* Instead, we align the Rx guard time on expected Tx time. The Rx
* guard time is user-configurable with TSCH_CONF_RX_WAIT.
* (TS_TX_OFFSET - (TS_RX_WAIT / 2)) instead */
#if TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 10000
/* Default timeslot timing as per IEEE 802.15.4e */
#define TSCH_DEFAULT_TS_CCA_OFFSET 1800
#define TSCH_DEFAULT_TS_CCA 128
#define TSCH_DEFAULT_TS_TX_OFFSET 2120
#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2))
#define TSCH_DEFAULT_TS_RX_ACK_DELAY 800
#define TSCH_DEFAULT_TS_TX_ACK_DELAY 1000
#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT
#define TSCH_DEFAULT_TS_ACK_WAIT 400
#define TSCH_DEFAULT_TS_RX_TX 192
#define TSCH_DEFAULT_TS_MAX_ACK 2400
#define TSCH_DEFAULT_TS_MAX_TX 4256
#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000
#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000
/* Default timeslot timing for platforms requiring 15ms slots */
#define TSCH_DEFAULT_TS_CCA_OFFSET 1800
#define TSCH_DEFAULT_TS_CCA 128
#define TSCH_DEFAULT_TS_TX_OFFSET 4000
#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2))
#define TSCH_DEFAULT_TS_RX_ACK_DELAY 3600
#define TSCH_DEFAULT_TS_TX_ACK_DELAY 4000
#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT
#define TSCH_DEFAULT_TS_ACK_WAIT 800
#define TSCH_DEFAULT_TS_RX_TX 2072
#define TSCH_DEFAULT_TS_MAX_ACK 2400
#define TSCH_DEFAULT_TS_MAX_TX 4256
#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 15000
#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000U
/* 65ms timeslot, i.e. nearly the max length allowed by standard (16-bit unsigned in micro-seconds).
* Useful for running link-layer security on sky in Cooja, where only S/W security is supported.
* Note: this slot timing would require a total of 120ms. If a slot overlaps with the next active slot,
* the latter will be skipped.
* This configuration is mostly a work-around to test link-layer security in Cooja, it is recommended
* to use it with a 6TiSCH minimal schedule of length >= 2. */
#define TSCH_DEFAULT_TS_CCA_OFFSET 1800
#define TSCH_DEFAULT_TS_CCA 128
#define TSCH_DEFAULT_TS_TX_OFFSET 52000
#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2))
#define TSCH_DEFAULT_TS_RX_ACK_DELAY 58600
#define TSCH_DEFAULT_TS_TX_ACK_DELAY 59000
#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT
#define TSCH_DEFAULT_TS_ACK_WAIT 800
#define TSCH_DEFAULT_TS_RX_TX 2072
#define TSCH_DEFAULT_TS_MAX_ACK 2400
#define TSCH_DEFAULT_TS_MAX_TX 4256
#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 65000
#else
#error "TSCH: Unsupported default timeslot length"
#endif
#endif /* __TSCH_CONST_H__ */
/** @} */

View File

@ -173,6 +173,8 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
old_time_src->is_time_source = 0;
}
tsch_stats_reset_neighbor_stats();
#ifdef TSCH_CALLBACK_NEW_TIME_SOURCE
TSCH_CALLBACK_NEW_TIME_SOURCE(old_time_src, new_time_src);
#endif

View File

@ -52,10 +52,6 @@
#include "net/queuebuf.h"
#include "net/mac/framer/framer-802154.h"
#include "net/mac/tsch/tsch.h"
#if CONTIKI_TARGET_COOJA
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */
#include "sys/log.h"
/* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH
@ -94,7 +90,7 @@
/* Truncate received drift correction information to maximum half
* of the guard time (one fourth of TSCH_DEFAULT_TS_RX_WAIT) */
#define SYNC_IE_BOUND ((int32_t)US_TO_RTIMERTICKS(TSCH_DEFAULT_TS_RX_WAIT / 4))
#define SYNC_IE_BOUND ((int32_t)US_TO_RTIMERTICKS(tsch_timing_us[tsch_ts_rx_wait] / 4))
/* By default: check that rtimer runs at >=32kHz and use a guard time of 10us */
#if RTIMER_SECOND < (32 * 1024)
@ -206,10 +202,7 @@ tsch_get_lock(void)
busy_wait = 1;
busy_wait_time = RTIMER_NOW();
while(tsch_in_slot_operation) {
#if CONTIKI_TARGET_COOJA
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
watchdog_periodic();
}
busy_wait_time = RTIMER_NOW() - busy_wait_time;
}
@ -303,7 +296,7 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_
}
/* block until the time to schedule comes */
BUSYWAIT_UNTIL_ABS(0, ref_time, offset);
RTIMER_BUSYWAIT_UNTIL_ABS(0, ref_time, offset);
return 0;
}
/*---------------------------------------------------------------------------*/
@ -314,7 +307,7 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_
do { \
if(tsch_schedule_slot_operation(tm, ref_time, offset - RTIMER_GUARD, str)) { \
PT_YIELD(pt); \
BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \
RTIMER_BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \
} \
} while(0);
/*---------------------------------------------------------------------------*/
@ -464,9 +457,9 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
/* Did we set the frame pending bit to request an extra burst link? */
static int burst_link_requested;
#if CCA_ENABLED
#if TSCH_CCA_ENABLED
static uint8_t cca_status;
#endif
#endif /* TSCH_CCA_ENABLED */
/* get payload */
packet = queuebuf_dataptr(current_packet->qb);
@ -507,22 +500,22 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
if(packet_ready && NETSTACK_RADIO.prepare(packet, packet_len) == 0) { /* 0 means success */
static rtimer_clock_t tx_duration;
#if CCA_ENABLED
#if TSCH_CCA_ENABLED
cca_status = 1;
/* delay before CCA */
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET, "cca");
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_cca_offset], "cca");
TSCH_DEBUG_TX_EVENT();
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
/* CCA */
BUSYWAIT_UNTIL_ABS(!(cca_status |= NETSTACK_RADIO.channel_clear()),
current_slot_start, TS_CCA_OFFSET + TS_CCA);
RTIMER_BUSYWAIT_UNTIL_ABS(!(cca_status &= NETSTACK_RADIO.channel_clear()),
current_slot_start, tsch_timing[tsch_ts_cca_offset] + tsch_timing[tsch_ts_cca]);
TSCH_DEBUG_TX_EVENT();
/* there is not enough time to turn radio off */
/* NETSTACK_RADIO.off(); */
if(cca_status == 0) {
mac_tx_status = MAC_TX_COLLISION;
} else
#endif /* CCA_ENABLED */
#endif /* TSCH_CCA_ENABLED */
{
/* delay before TX */
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_tx_offset] - RADIO_DELAY_BEFORE_TX, "TxBeforeTx");
@ -561,14 +554,14 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
TSCH_DEBUG_TX_EVENT();
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
/* Wait for ACK to come */
BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
RTIMER_BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
tx_start_time, tx_duration + tsch_timing[tsch_ts_rx_ack_delay] + tsch_timing[tsch_ts_ack_wait] + RADIO_DELAY_BEFORE_DETECT);
TSCH_DEBUG_TX_EVENT();
ack_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
/* Wait for ACK to finish */
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
RTIMER_BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
ack_start_time, tsch_timing[tsch_ts_max_ack]);
TSCH_DEBUG_TX_EVENT();
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
@ -625,6 +618,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
"!truncated dr %d %d", (int)eack_time_correction, (int)drift_correction);
);
}
tsch_stats_on_time_synchronization(eack_time_correction);
is_drift_correction_used = 1;
tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
/* Keep track of sync time */
@ -666,6 +660,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
ringbufindex_put(&dequeued_ringbuf);
}
/* If this is an unicast packet to timesource, update stats */
if(current_neighbor != NULL && current_neighbor->is_time_source) {
tsch_stats_tx_packet(current_neighbor, mac_tx_status, tsch_current_channel);
}
/* Log every tx attempt */
TSCH_LOG_ADD(tsch_log_tx,
log->tx.mac_tx_status = mac_tx_status;
@ -742,7 +741,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
packet_seen = NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet();
if(!packet_seen) {
/* Check if receiving within guard time */
BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
RTIMER_BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + RADIO_DELAY_BEFORE_DETECT);
}
if(!packet_seen) {
@ -754,7 +753,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
rx_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
/* Wait until packet is received, turn radio off */
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
RTIMER_BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + tsch_timing[tsch_ts_max_tx]);
TSCH_DEBUG_RX_EVENT();
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
@ -764,6 +763,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
static int header_len;
static frame802154_t frame;
radio_value_t radio_last_rssi;
radio_value_t radio_last_lqi;
/* Read packet */
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
@ -782,6 +782,8 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
#endif
packet_duration = TSCH_PACKET_DURATION(current_input->len);
/* limit packet_duration to its max value */
packet_duration = MIN(packet_duration, tsch_timing[tsch_ts_max_tx]);
if(!frame_valid) {
TSCH_LOG_ADD(tsch_log_message,
@ -821,6 +823,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
int do_nack = 0;
rx_count++;
estimated_drift = RTIMER_CLOCK_DIFF(expected_rx_time, rx_start_time);
tsch_stats_on_time_synchronization(estimated_drift);
#if TSCH_TIMESYNC_REMOVE_JITTER
/* remove jitter due to measurement errors */
@ -889,6 +892,12 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
/* Add current input to ringbuf */
ringbufindex_put(&input_ringbuf);
/* If the neighbor is known, update its stats */
if(n != NULL) {
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_LINK_QUALITY, &radio_last_lqi);
tsch_stats_rx_packet(n, current_input->rssi, radio_last_lqi, tsch_current_channel);
}
/* Log every reception */
TSCH_LOG_ADD(tsch_log_rx,
linkaddr_copy(&log->rx.src, (linkaddr_t *)&frame.src_addr);
@ -951,6 +960,8 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
int is_active_slot;
TSCH_DEBUG_SLOT_START();
tsch_in_slot_operation = 1;
/* Measure on-air noise level while TSCH is idle */
tsch_stats_sample_rssi();
/* Reset drift correction */
drift_correction = 0;
is_drift_correction_used = 0;

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2016-2017, University of Bristol - http://www.bristol.ac.uk
*
* 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 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
* Source file for TSCH statistics
* \author
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#include "contiki.h"
#include "net/mac/tsch/tsch.h"
#include "net/netstack.h"
#include "dev/radio.h"
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH Stats"
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
#if TSCH_STATS_ON
/*---------------------------------------------------------------------------*/
struct tsch_global_stats tsch_stats;
struct tsch_neighbor_stats tsch_neighbor_stats;
/* Called every TSCH_STATS_DECAY_INTERVAL ticks */
static struct ctimer periodic_timer;
static void periodic(void *);
/*---------------------------------------------------------------------------*/
void
tsch_stats_init(void)
{
#if TSCH_STATS_SAMPLE_NOISE_RSSI
int i;
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
tsch_stats.noise_rssi[i] = TSCH_STATS_DEFAULT_RSSI;
tsch_stats.channel_free_ewma[i] = TSCH_STATS_DEFAULT_CHANNEL_FREE;
}
#endif
tsch_stats_reset_neighbor_stats();
/* Start the periodic processing soonish */
ctimer_set(&periodic_timer, TSCH_STATS_DECAY_INTERVAL / 10, periodic, NULL);
}
/*---------------------------------------------------------------------------*/
void
tsch_stats_reset_neighbor_stats(void)
{
int i;
struct tsch_channel_stats *ch_stats;
ch_stats = tsch_neighbor_stats.channel_stats;
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
ch_stats[i].rssi = TSCH_STATS_DEFAULT_RSSI;
ch_stats[i].lqi = TSCH_STATS_DEFAULT_LQI;
ch_stats[i].p_tx_success = TSCH_STATS_DEFAULT_P_TX;
}
}
/*---------------------------------------------------------------------------*/
struct tsch_neighbor_stats *
tsch_stats_get_from_neighbor(struct tsch_neighbor *n)
{
/* Due to RAM limitations, this module only collects neighbor stats about the time source */
if(n != NULL && n->is_time_source) {
return &tsch_neighbor_stats;
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
tsch_stats_tx_packet(struct tsch_neighbor *n, uint8_t mac_status, uint8_t channel)
{
struct tsch_neighbor_stats *stats;
stats = tsch_stats_get_from_neighbor(n);
if(stats != NULL) {
uint8_t index = tsch_stats_channel_to_index(channel);
uint16_t new_tx_value = (mac_status == MAC_TX_OK ? 1 : 0);
new_tx_value *= TSCH_STATS_BINARY_SCALING_FACTOR;
TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].p_tx_success, new_tx_value);
}
}
/*---------------------------------------------------------------------------*/
void
tsch_stats_rx_packet(struct tsch_neighbor *n, int8_t rssi, uint8_t lqi, uint8_t channel)
{
struct tsch_neighbor_stats *stats;
stats = tsch_stats_get_from_neighbor(n);
if(stats != NULL) {
uint8_t index = tsch_stats_channel_to_index(channel);
TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].rssi,
TSCH_STATS_TRANSFORM(rssi, TSCH_STATS_RSSI_SCALING_FACTOR));
TSCH_STATS_EWMA_UPDATE(stats->channel_stats[index].lqi,
TSCH_STATS_TRANSFORM(lqi, TSCH_STATS_LQI_SCALING_FACTOR));
}
}
/*---------------------------------------------------------------------------*/
void
tsch_stats_on_time_synchronization(int32_t sync_error)
{
/* Update the maximal error so far if the absolute value of the new one is larger */
tsch_stats.max_sync_error = MAX(tsch_stats.max_sync_error, ABS(sync_error));
}
/*---------------------------------------------------------------------------*/
void
tsch_stats_sample_rssi(void)
{
#if TSCH_STATS_SAMPLE_NOISE_RSSI
uint8_t index;
radio_value_t value;
radio_result_t rv;
static uint8_t measurement_channel = TSCH_STATS_FIRST_CHANNEL;
index = tsch_stats_channel_to_index(measurement_channel);
/* Select the measurement channel */
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, measurement_channel);
/* Need to explicitly turn on for Coojamotes */
NETSTACK_RADIO.on();
/* Measure the background noise RSSI and act on it */
rv = NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value);
if(rv == RADIO_RESULT_OK) {
tsch_stat_t prev_busyness_metric;
uint16_t is_free;
is_free = (((int)value <= TSCH_STATS_BUSY_CHANNEL_RSSI) ? 1 : 0) * TSCH_STATS_BINARY_SCALING_FACTOR;
/* LOG_DBG("noise RSSI on %u: %d\n", measurement_channel, (int)value); */
TSCH_STATS_EWMA_UPDATE(tsch_stats.noise_rssi[index],
TSCH_STATS_TRANSFORM((int)value, TSCH_STATS_RSSI_SCALING_FACTOR));
prev_busyness_metric = tsch_stats.channel_free_ewma[index];
(void)prev_busyness_metric;
TSCH_STATS_EWMA_UPDATE(tsch_stats.channel_free_ewma[index], is_free);
/* potentially select a new TSCH hopping sequence */
#ifdef TSCH_CALLBACK_CHANNEL_STATS_UPDATED
TSCH_CALLBACK_CHANNEL_STATS_UPDATED(measurement_channel, prev_busyness_metric);
#endif
} else {
LOG_ERR("! sampling RSSI failed: %d\n", (int)rv);
}
/* Increment the channel index for the next time */
measurement_channel++;
if(measurement_channel >= TSCH_STATS_FIRST_CHANNEL + TSCH_STATS_NUM_CHANNELS) {
measurement_channel = TSCH_STATS_FIRST_CHANNEL;
}
#endif /* TSCH_STATS_SAMPLE_NOISE_RSSI */
}
/*---------------------------------------------------------------------------*/
/* Periodic timer called every TSCH_STATS_DECAY_INTERVAL ticks */
static void
periodic(void *ptr)
{
int i;
struct tsch_neighbor *timesource;
struct tsch_channel_stats *stats = tsch_neighbor_stats.channel_stats;
#if TSCH_STATS_SAMPLE_NOISE_RSSI
LOG_DBG("Noise RSSI:\n");
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
LOG_DBG(" channel %u: %d rssi, %u/%u free\n",
TSCH_STATS_FIRST_CHANNEL + i,
tsch_stats.noise_rssi[i] / TSCH_STATS_RSSI_SCALING_FACTOR,
tsch_stats.channel_free_ewma[i],
TSCH_STATS_BINARY_SCALING_FACTOR);
}
#endif
timesource = tsch_queue_get_time_source();
if(timesource != NULL) {
LOG_DBG("Time source neighbor:\n");
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
LOG_DBG(" channel %u: %d rssi, %u lqi, %u/%u P(tx)\n",
TSCH_STATS_FIRST_CHANNEL + i,
stats[i].rssi / TSCH_STATS_RSSI_SCALING_FACTOR,
stats[i].lqi / TSCH_STATS_LQI_SCALING_FACTOR,
stats[i].p_tx_success,
TSCH_STATS_BINARY_SCALING_FACTOR);
}
}
/* Do not decay the periodic global stats, as they are updated independely of packet rate */
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
/* decay Rx stats */
TSCH_STATS_EWMA_UPDATE(stats[i].rssi, TSCH_STATS_DEFAULT_RSSI);
TSCH_STATS_EWMA_UPDATE(stats[i].lqi, TSCH_STATS_DEFAULT_LQI);
/* decay Tx stats */
TSCH_STATS_EWMA_UPDATE(stats[i].p_tx_success, TSCH_STATS_DEFAULT_P_TX);
}
ctimer_set(&periodic_timer, TSCH_STATS_DECAY_INTERVAL, periodic, NULL);
}
/*---------------------------------------------------------------------------*/
#endif /* TSCH_STATS_ON */
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2016-2017, University of Bristol - http://www.bristol.ac.uk
*
* 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 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
* Header file for TSCH statistics
* \author
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
/**
* \addtogroup tsch
* @{
*/
#ifndef __TSCH_STATS_H__
#define __TSCH_STATS_H__
/********** Includes **********/
#include "contiki.h"
#include "net/linkaddr.h"
#include "net/mac/tsch/tsch-conf.h"
#include "net/mac/tsch/tsch-queue.h"
/************ Constants ***********/
/* Enable the collection of TSCH statistics? */
#ifdef TSCH_STATS_CONF_ON
#define TSCH_STATS_ON TSCH_STATS_CONF_ON
#else
#define TSCH_STATS_ON 0
#endif
/* Enable the collection background noise RSSI? */
#ifdef TSCH_STATS_CONF_SAMPLE_NOISE_RSSI
#define TSCH_STATS_SAMPLE_NOISE_RSSI TSCH_STATS_CONF_SAMPLE_NOISE_RSSI
#else
#define TSCH_STATS_SAMPLE_NOISE_RSSI 0
#endif
/*
* How to update a TSCH statistic.
* Uses a hardcoded EWMA alpha value equal to 0.125 by default.
*/
#ifdef TSCH_STATS_CONF_EWMA_UPDATE
#define TSCH_STATS_EWMA_UPDATE TSCH_STATS_CONF_EWMA_UPDATE
#else
#define TSCH_STATS_EWMA_UPDATE(x, v) (x) = (((x) * 7 / 8) + (v) / 8)
#endif
/*
* A channel is considered busy if at the sampling instant
* it has RSSI higher or equal to this limit.
*/
#ifdef TSCH_STATS_CONF_BUSY_CHANNEL_RSSI
#define TSCH_STATS_BUSY_CHANNEL_RSSI TSCH_STATS_CONF_BUSY_CHANNEL_RSSI
#else
#define TSCH_STATS_BUSY_CHANNEL_RSSI -85
#endif
/* The period after which stat values are decayed towards the default values */
#ifdef TSCH_STATS_CONF_DECAY_INTERVAL
#define TSCH_STATS_DECAY_INTERVAL TSCH_STATS_CONF_DECAY_INTERVAL
#else
#define TSCH_STATS_DECAY_INTERVAL (20ul * 60 * CLOCK_SECOND)
#endif
/*
* The total number of MAC-layer channels.
* Sixteen for the IEEE802.15.4 2.4 GHz band.
*/
#ifdef TSCH_STATS_CONF_NUM_CHANNELS
#define TSCH_STATS_NUM_CHANNELS TSCH_STATS_CONF_NUM_CHANNELS
#else
#define TSCH_STATS_NUM_CHANNELS 16
#endif
/* The number of the first MAC-layer channel. */
#ifdef TSCH_STATS_CONF_FIRST_CHANNEL
#define TSCH_STATS_FIRST_CHANNEL TSCH_STATS_CONF_FIRST_CHANNEL
#else
#define TSCH_STATS_FIRST_CHANNEL 11
#endif
/* Internal: the scaling of the various stats */
#define TSCH_STATS_RSSI_SCALING_FACTOR -16
#define TSCH_STATS_LQI_SCALING_FACTOR 16
#define TSCH_STATS_BINARY_SCALING_FACTOR 4096
/*
* Transform a statistic from external form to the internal representation.
* To transform back, simply divide by the factor.
*/
#define TSCH_STATS_TRANSFORM(x, factor) ((int16_t)(x) * factor)
/* The default value for RSSI statistics: -90 dBm */
#define TSCH_STATS_DEFAULT_RSSI TSCH_STATS_TRANSFORM(-90, TSCH_STATS_RSSI_SCALING_FACTOR)
/* The default value for LQI statistics: 100 */
#define TSCH_STATS_DEFAULT_LQI TSCH_STATS_TRANSFORM(100, TSCH_STATS_LQI_SCALING_FACTOR)
/* The default value for P_tx (packet transmission probability) statistics: 50% */
#define TSCH_STATS_DEFAULT_P_TX (TSCH_STATS_BINARY_SCALING_FACTOR / 2)
/* The default value for channel free status: 100% */
#define TSCH_STATS_DEFAULT_CHANNEL_FREE TSCH_STATS_BINARY_SCALING_FACTOR
/* #define these callbacks to do the adaptive channel selection based on RSSI */
/* TSCH_CALLBACK_CHANNEL_STATS_UPDATED(channel, previous_metric); */
/* TSCH_CALLBACK_SELECT_CHANNELS(); */
/************ Types ***********/
typedef uint16_t tsch_stat_t;
struct tsch_global_stats {
/* the maximum synchronization error */
uint32_t max_sync_error;
/* number of disassociations */
uint16_t num_disassociations;
#if TSCH_STATS_SAMPLE_NOISE_RSSI
/* per-channel noise estimates */
tsch_stat_t noise_rssi[TSCH_STATS_NUM_CHANNELS];
/* derived from `noise_rssi` and BUSY_CHANNEL_RSSI */
tsch_stat_t channel_free_ewma[TSCH_STATS_NUM_CHANNELS];
#endif /* TSCH_STATS_SAMPLE_NOISE_RSSI */
};
struct tsch_channel_stats {
/* EWMA, from receptions */
tsch_stat_t rssi;
/* EWMA, from receptions */
tsch_stat_t lqi;
/* EWMA of probability, for unicast transmissions only */
tsch_stat_t p_tx_success;
};
struct tsch_neighbor_stats {
struct tsch_channel_stats channel_stats[TSCH_STATS_NUM_CHANNELS];
};
struct tsch_neighbor; /* Forward declaration */
/************ External variables ***********/
#if TSCH_STATS_ON
/* Statistics for the local node */
extern struct tsch_global_stats tsch_stats;
/* For the timesource neighbor */
extern struct tsch_neighbor_stats tsch_neighbor_stats;
/************ Functions ***********/
void tsch_stats_init(void);
void tsch_stats_tx_packet(struct tsch_neighbor *, uint8_t mac_status, uint8_t channel);
void tsch_stats_rx_packet(struct tsch_neighbor *, int8_t rssi, uint8_t lqi, uint8_t channel);
void tsch_stats_on_time_synchronization(int32_t sync_error);
void tsch_stats_sample_rssi(void);
struct tsch_neighbor_stats *tsch_stats_get_from_neighbor(struct tsch_neighbor *);
void tsch_stats_reset_neighbor_stats(void);
#else /* TSCH_STATS_ON */
#define tsch_stats_init()
#define tsch_stats_tx_packet(n, mac_status, channel)
#define tsch_stats_rx_packet(n, rssi, lqi, channel)
#define tsch_stats_on_time_synchronization(sync_error)
#define tsch_stats_sample_rssi()
#define tsch_stats_get_from_neighbor(neighbor) NULL
#define tsch_stats_reset_neighbor_stats()
#endif /* TSCH_STATS_ON */
static inline uint8_t
tsch_stats_channel_to_index(uint8_t channel)
{
return channel - TSCH_STATS_FIRST_CHANNEL;
}
static inline uint8_t
tsch_stats_index_to_channel(uint8_t channel_index)
{
return channel_index + TSCH_STATS_FIRST_CHANNEL;
}
#endif /* __TSCH_STATS_H__ */
/** @} */

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2018, RISE SICS.
* 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
* IEEE 802.15.4 TSCH timeslot timings
* \author
* Simon Duquennoy <simon.duquennoy@ri.se>
*
*/
/**
* \addtogroup tsch
* @{
*/
#include "contiki.h"
#include "net/mac/tsch/tsch.h"
/**
* \brief The default timeslot timing in the standard is a guard time of
* 2200 us, a Tx offset of 2120 us and a Rx offset of 1120 us.
* As a result, the listening device has a guard time not centered
* on the expected Tx time. This is to be fixed in the next iteration
* of the standard. This can be enabled with:
* TxOffset: 2120
* RxOffset: 1120
* RxWait: 2200
*
* Instead, we align the Rx guard time on expected Tx time. The Rx
* guard time is user-configurable with TSCH_CONF_RX_WAIT.
* (TxOffset - (RxWait / 2)) instead
*/
const uint16_t tsch_timeslot_timing_us_10000[tsch_ts_elements_count] = {
1800, /* CCAOffset */
128, /* CCA */
2120, /* TxOffset */
(2120 - (TSCH_CONF_RX_WAIT / 2)), /* RxOffset */
800, /* RxAckDelay */
1000, /* TxAckDelay */
TSCH_CONF_RX_WAIT, /* RxWait */
400, /* AckWait */
192, /* RxTx */
2400, /* MaxAck */
4256, /* MaxTx */
10000, /* TimeslotLength */
};
/** @} */

View File

@ -102,20 +102,9 @@ uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* Default TSCH timeslot timing (in micro-second) */
static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = {
TSCH_DEFAULT_TS_CCA_OFFSET,
TSCH_DEFAULT_TS_CCA,
TSCH_DEFAULT_TS_TX_OFFSET,
TSCH_DEFAULT_TS_RX_OFFSET,
TSCH_DEFAULT_TS_RX_ACK_DELAY,
TSCH_DEFAULT_TS_TX_ACK_DELAY,
TSCH_DEFAULT_TS_RX_WAIT,
TSCH_DEFAULT_TS_ACK_WAIT,
TSCH_DEFAULT_TS_RX_TX,
TSCH_DEFAULT_TS_MAX_ACK,
TSCH_DEFAULT_TS_MAX_TX,
TSCH_DEFAULT_TS_TIMESLOT_LENGTH,
};
static const uint16_t *tsch_default_timing_us;
/* TSCH timeslot timing (in micro-second) */
uint16_t tsch_timing_us[tsch_ts_elements_count];
/* TSCH timeslot timing (in rtimer ticks) */
rtimer_clock_t tsch_timing[tsch_ts_elements_count];
@ -231,8 +220,10 @@ tsch_reset(void)
TSCH_ASN_INIT(tsch_current_asn, 0, 0);
current_link = NULL;
/* Reset timeslot timing to defaults */
tsch_default_timing_us = TSCH_DEFAULT_TIMESLOT_TIMING;
for(i = 0; i < tsch_ts_elements_count; i++) {
tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]);
tsch_timing_us[i] = tsch_default_timing_us[i];
tsch_timing[i] = US_TO_RTIMERTICKS(tsch_timing_us[i]);
}
#ifdef TSCH_CALLBACK_LEAVING_NETWORK
TSCH_CALLBACK_LEAVING_NETWORK();
@ -412,6 +403,22 @@ eb_input(struct input_packet *current_input)
}
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
}
/* TSCH hopping sequence */
if(eb_ies.ie_channel_hopping_sequence_id != 0) {
if(eb_ies.ie_hopping_sequence_len != tsch_hopping_sequence_length.val
|| memcmp((uint8_t *)tsch_hopping_sequence, eb_ies.ie_hopping_sequence_list, tsch_hopping_sequence_length.val)) {
if(eb_ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) {
memcpy((uint8_t *)tsch_hopping_sequence, eb_ies.ie_hopping_sequence_list,
eb_ies.ie_hopping_sequence_len);
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, eb_ies.ie_hopping_sequence_len);
LOG_WARN("Updating TSCH hopping sequence from EB\n");
} else {
LOG_WARN("TSCH:! parse_eb: hopping sequence too long (%u)\n", eb_ies.ie_hopping_sequence_len);
}
}
}
}
}
}
@ -565,10 +572,11 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
/* TSCH timeslot timing */
for(i = 0; i < tsch_ts_elements_count; i++) {
if(ies.ie_tsch_timeslot_id == 0) {
tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]);
tsch_timing_us[i] = tsch_default_timing_us[i];
} else {
tsch_timing[i] = US_TO_RTIMERTICKS(ies.ie_tsch_timeslot[i]);
tsch_timing_us[i] = ies.ie_tsch_timeslot[i];
}
tsch_timing[i] = US_TO_RTIMERTICKS(tsch_timing_us[i]);
}
/* TSCH hopping sequence */
@ -714,11 +722,11 @@ PT_THREAD(tsch_scan(struct pt *pt))
/* Pick a channel at random in TSCH_JOIN_HOPPING_SEQUENCE */
uint8_t scan_channel = TSCH_JOIN_HOPPING_SEQUENCE[
random_rand() % sizeof(TSCH_JOIN_HOPPING_SEQUENCE)];
if(current_channel != scan_channel) {
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, scan_channel);
current_channel = scan_channel;
LOG_INFO("scanning on channel %u\n", scan_channel);
}
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, scan_channel);
current_channel = scan_channel;
LOG_INFO("scanning on channel %u\n", scan_channel);
current_channel_since = now_time;
}
@ -729,20 +737,30 @@ PT_THREAD(tsch_scan(struct pt *pt))
if(!is_packet_pending && NETSTACK_RADIO.receiving_packet()) {
/* If we are currently receiving a packet, wait until end of reception */
t0 = RTIMER_NOW();
BUSYWAIT_UNTIL_ABS((is_packet_pending = NETSTACK_RADIO.pending_packet()), t0, RTIMER_SECOND / 100);
RTIMER_BUSYWAIT_UNTIL_ABS((is_packet_pending = NETSTACK_RADIO.pending_packet()), t0, RTIMER_SECOND / 100);
}
if(is_packet_pending) {
rtimer_clock_t t1;
/* Read packet */
input_eb.len = NETSTACK_RADIO.read(input_eb.payload, TSCH_PACKET_MAX_LEN);
/* Save packet timestamp */
NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t0, sizeof(rtimer_clock_t));
t1 = RTIMER_NOW();
/* Parse EB and attempt to associate */
LOG_INFO("scan: received packet (%u bytes) on channel %u\n", input_eb.len, current_channel);
tsch_associate(&input_eb, t0);
/* Sanity-check the timestamp */
if(ABS(RTIMER_CLOCK_DIFF(t0, t1)) < tsch_timing[tsch_ts_timeslot_length]) {
tsch_associate(&input_eb, t0);
} else {
LOG_WARN("scan: dropping packet, timestamp too far from current time %u %u\n",
(unsigned)t0,
(unsigned)t1
);
}
}
if(tsch_is_associated) {
@ -864,6 +882,9 @@ PROCESS_THREAD(tsch_pending_events_process, ev, data)
tsch_rx_process_pending();
tsch_tx_process_pending();
tsch_log_process_pending();
#ifdef TSCH_CALLBACK_SELECT_CHANNELS
TSCH_CALLBACK_SELECT_CHANNELS();
#endif
}
PROCESS_END();
}
@ -878,6 +899,12 @@ tsch_init(void)
radio_value_t radio_tx_mode;
rtimer_clock_t t;
/* Check that the platform provides a TSCH timeslot timing template */
if(TSCH_DEFAULT_TIMESLOT_TIMING == NULL) {
LOG_ERR("! platform does not provide a timeslot timing template.\n");
return;
}
/* Radio Rx mode */
if(NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode) != RADIO_RESULT_OK) {
LOG_ERR("! radio does not support getting RADIO_PARAM_RX_MODE. Abort init.\n");
@ -918,6 +945,7 @@ tsch_init(void)
/* Check max hopping sequence length vs default sequence length */
if(TSCH_HOPPING_SEQUENCE_MAX_LEN < sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)) {
LOG_ERR("! TSCH_HOPPING_SEQUENCE_MAX_LEN < sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE). Abort init.\n");
return;
}
/* Init the queuebuf and TSCH sub-modules */
@ -944,6 +972,8 @@ tsch_init(void)
#if TSCH_WITH_SIXTOP
sixtop_init();
#endif
tsch_stats_init();
}
/*---------------------------------------------------------------------------*/
/* Function send for TSCH-MAC, puts the packet in packetbuf in the MAC queue */

View File

@ -60,28 +60,16 @@ frequency hopping for enhanced reliability.
#include "net/mac/tsch/tsch-packet.h"
#include "net/mac/tsch/tsch-security.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "net/mac/tsch/tsch-stats.h"
#if UIP_CONF_IPV6_RPL
#include "net/mac/tsch/tsch-rpl.h"
#endif /* UIP_CONF_IPV6_RPL */
#if CONTIKI_TARGET_COOJA
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */
/*********** Macros *********/
/* Wait for a condition with timeout t0+offset. */
#if CONTIKI_TARGET_COOJA
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \
simProcessRunValue = 1; \
cooja_mt_yield(); \
};
#else
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ;
#endif /* CONTIKI_TARGET_COOJA */
/* Include Arch-Specific conf */
#ifdef TSCH_CONF_ARCH_HDR_PATH
#include TSCH_CONF_ARCH_HDR_PATH
#endif /* TSCH_CONF_ARCH_HDR_PATH */
/*********** Callbacks *********/
@ -169,6 +157,8 @@ extern uint8_t tsch_current_channel;
/* TSCH channel hopping sequence */
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* TSCH timeslot timing (in micro-second) */
uint16_t tsch_timing_us[tsch_ts_elements_count];
/* TSCH timeslot timing (in rtimer ticks) */
extern rtimer_clock_t tsch_timing[tsch_ts_elements_count];
/* Statistics on the current session */
@ -177,6 +167,8 @@ extern unsigned long rx_count;
extern unsigned long sync_count;
extern int32_t min_drift_seen;
extern int32_t max_drift_seen;
/* The TSCH standard 10ms timeslot timing */
extern const uint16_t tsch_timeslot_timing_us_10000[tsch_ts_elements_count];
/* TSCH processes */
PROCESS_NAME(tsch_process);

View File

@ -272,7 +272,7 @@
#ifdef RPL_CONF_DAG_LIFETIME
#define RPL_DAG_LIFETIME RPL_CONF_DAG_LIFETIME
#else
#define RPL_DAG_LIFETIME (60 * 60) /* one hour */
#define RPL_DAG_LIFETIME (8 * 60) /* 8 hours */
#endif /* RPL_CONF_DAG_LIFETIME */
/*

View File

@ -0,0 +1 @@
CFLAGS += -DBUILD_WITH_TSCH_CS=1

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 2016-2018, University of Bristol - http://www.bristol.ac.uk
*
* 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 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
* Source file for TSCH adaptive channel selection
* \author
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#include "tsch.h"
#include "tsch-stats.h"
#include "tsch-cs.h"
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH CS"
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
/* Allow to change only 1 channel at once */
#define TSCH_CS_MAX_CHANNELS_CHANGED 1
/* Do not up change channels more frequently than this */
#define TSCH_CS_MIN_UPDATE_INTERVAL_SEC 60
/* Do not change channels if the difference in qualities is below this */
#define TSCH_CS_HYSTERESIS (TSCH_STATS_BINARY_SCALING_FACTOR / 10)
/* After removing a channel from the sequence, do not add it back at least this time */
#define TSCH_CS_BLACKLIST_DURATION_SEC (5 * 60)
/* A potential for change detected? */
static bool recaculation_requested;
/* Time (in seconds) when channels were marked as busy; 0 if they are not busy */
static uint32_t tsch_cs_busy_since[TSCH_STATS_NUM_CHANNELS];
/*
* The following variables are kept in order to avoid completely migrating away
* from the initial hopping sequence (as then new nodes would not be able to join).
* The invariant is: tsch_cs_initial_bitmap & tsch_cs_current_bitmap != 0
*/
/* The bitmap with the initial channels */
static tsch_cs_bitmap_t tsch_cs_initial_bitmap;
/* The bitmap with the current channels */
static tsch_cs_bitmap_t tsch_cs_current_bitmap;
/* structure for sorting */
struct tsch_cs_quality {
/* channel number */
uint8_t channel;
/* the higher, the better */
tsch_stat_t metric;
};
/*---------------------------------------------------------------------------*/
static inline bool
tsch_cs_bitmap_contains(tsch_cs_bitmap_t bitmap, uint8_t channel)
{
return (1 << (channel - TSCH_STATS_FIRST_CHANNEL)) & bitmap;
}
/*---------------------------------------------------------------------------*/
static inline tsch_cs_bitmap_t
tsch_cs_bitmap_set(tsch_cs_bitmap_t bitmap, uint8_t channel)
{
return (1 << (channel - TSCH_STATS_FIRST_CHANNEL)) | bitmap;
}
/*---------------------------------------------------------------------------*/
static tsch_cs_bitmap_t
tsch_cs_bitmap_calc(void)
{
tsch_cs_bitmap_t result = 0;
int i;
for(i = 0; i < tsch_hopping_sequence_length.val; ++i) {
result = tsch_cs_bitmap_set(result, tsch_hopping_sequence[i]);
}
return result;
}
/*---------------------------------------------------------------------------*/
void
tsch_cs_adaptations_init(void)
{
tsch_cs_initial_bitmap = tsch_cs_bitmap_calc();
tsch_cs_current_bitmap = tsch_cs_initial_bitmap;
}
/*---------------------------------------------------------------------------*/
/* Sort the elements to that the channels with the best metrics are in the front */
static void
tsch_cs_bubble_sort(struct tsch_cs_quality *qualities)
{
int i, j;
struct tsch_cs_quality tmp;
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
for(j = 0; j + 1 < TSCH_STATS_NUM_CHANNELS; ++j) {
if(qualities[j].metric < qualities[j+1].metric){
tmp = qualities[j];
qualities[j] = qualities[j+1];
qualities[j+1] = tmp;
}
}
}
}
/*---------------------------------------------------------------------------*/
/* Select a single, currently unused, good enough channel. Returns 0xff on failure. */
static uint8_t
tsch_cs_select_replacement(uint8_t old_channel, tsch_stat_t old_ewma,
struct tsch_cs_quality *qualities, uint8_t is_in_sequence[])
{
int i;
uint32_t now = clock_seconds();
tsch_cs_bitmap_t bitmap = tsch_cs_bitmap_set(0, old_channel);
/* Don't want to replace a channel if the improvement is miniscule (< 10%) */
old_ewma += TSCH_CS_HYSTERESIS;
/* iterate up to -1 because we know that at least one of the channels is bad */
for(i = 0; i < TSCH_STATS_NUM_CHANNELS - 1; ++i) {
/* select a replacement candidate */
uint8_t candidate = qualities[i].channel;
if(qualities[i].metric < TSCH_CS_FREE_THRESHOLD) {
/* This channel is not good enough.
* since we know that the other channels in the sorted list are even worse,
* it makes sense to return immediately rather than to continue t
*/
LOG_DBG("ch %u: busy\n", candidate);
return 0xff;
}
if(qualities[i].metric < old_ewma) {
/* not good enough to replace */
LOG_DBG("ch %u: hysteresis check failed\n", candidate);
return 0xff;
}
/* already in the current TSCH hopping sequence? */
if(is_in_sequence[candidate - TSCH_STATS_FIRST_CHANNEL] != 0xff) {
LOG_DBG("ch %u: in seq\n", candidate);
continue;
}
/* ignore this candidate if too recently blacklisted */
if(tsch_cs_busy_since[candidate - TSCH_STATS_FIRST_CHANNEL] != 0
&& tsch_cs_busy_since[candidate - TSCH_STATS_FIRST_CHANNEL] + TSCH_CS_BLACKLIST_DURATION_SEC > now) {
LOG_DBG("ch %u: recent bl\n", candidate);
continue;
}
/* check if removing the old channel would break our hopping sequence invariant */
if(bitmap == (tsch_cs_initial_bitmap & tsch_cs_current_bitmap)) {
/* the channel is the only one that belongs to both */
if(!tsch_cs_bitmap_contains(tsch_cs_initial_bitmap, candidate)) {
/* the candidate is not in the initial sequence; not acceptable */
continue;
}
}
return candidate;
}
return 0xff;
}
/*---------------------------------------------------------------------------*/
bool
tsch_cs_process(void)
{
int i;
bool try_replace;
bool has_replaced;
struct tsch_cs_quality qualities[TSCH_STATS_NUM_CHANNELS];
uint8_t is_channel_busy[TSCH_STATS_NUM_CHANNELS];
uint8_t is_in_sequence[TSCH_STATS_NUM_CHANNELS];
static uint32_t last_time_changed;
if(!recaculation_requested) {
/* nothing to do */
return false;
}
if(last_time_changed != 0 && last_time_changed + TSCH_CS_MIN_UPDATE_INTERVAL_SEC > clock_seconds()) {
/* too soon */
return false;
}
/* reset the flag */
recaculation_requested = false;
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
qualities[i].channel = i + TSCH_STATS_FIRST_CHANNEL;
qualities[i].metric = tsch_stats.channel_free_ewma[i];
}
/* bubble sort the channels */
tsch_cs_bubble_sort(qualities);
/* start with the threshold values */
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
is_channel_busy[i] = (tsch_stats.channel_free_ewma[i] < TSCH_CS_FREE_THRESHOLD);
}
memset(is_in_sequence, 0xff, sizeof(is_in_sequence));
for(i = 0; i < tsch_hopping_sequence_length.val; ++i) {
uint8_t channel = tsch_hopping_sequence[i];
is_in_sequence[channel - TSCH_STATS_FIRST_CHANNEL] = i;
}
/* mark the first N channels as "good" - there is nothing better to select */
for(i = 0; i < tsch_hopping_sequence_length.val; ++i) {
is_channel_busy[qualities[i].channel - TSCH_STATS_FIRST_CHANNEL] = 0;
}
for(i = 0; i < TSCH_STATS_NUM_CHANNELS; ++i) {
uint8_t ci = qualities[i].channel - TSCH_STATS_FIRST_CHANNEL;
(void)ci;
LOG_DBG("ch %u q %u busy %u in seq %u\n",
qualities[i].channel,
qualities[i].metric,
is_channel_busy[ci],
is_in_sequence[ci] == 0xff ? 0 : 1);
}
try_replace = false;
for(i = 0; i < tsch_hopping_sequence_length.val; ++i) {
uint8_t channel = tsch_hopping_sequence[i];
if(is_channel_busy[channel - TSCH_STATS_FIRST_CHANNEL]) {
try_replace = true;
}
}
if(!try_replace) {
LOG_DBG("cs: not replacing\n");
return false;
}
has_replaced = false;
for(i = TSCH_STATS_NUM_CHANNELS - 1; i >= tsch_hopping_sequence_length.val; --i) {
if(is_in_sequence[qualities[i].channel - TSCH_STATS_FIRST_CHANNEL] != 0xff) {
/* found the worst channel; it must be busy */
uint8_t channel = qualities[i].channel;
tsch_stat_t ewma_metric = qualities[i].metric;
uint8_t replacement = tsch_cs_select_replacement(channel, ewma_metric,
qualities, is_in_sequence);
uint8_t position = is_in_sequence[channel - TSCH_STATS_FIRST_CHANNEL];
if(replacement != 0xff) {
printf("\ncs: replacing channel %u %u (%u) with %u\n",
channel, tsch_hopping_sequence[position], position, replacement);
/* mark the old channel as busy */
tsch_cs_busy_since[channel - TSCH_STATS_FIRST_CHANNEL] = clock_seconds();
/* do the actual replacement in the global TSCH HS variable */
tsch_hopping_sequence[position] = replacement;
has_replaced = true;
/* recalculate the hopping sequence bitmap */
tsch_cs_current_bitmap = tsch_cs_bitmap_calc();
}
break; /* replace just one at once */
}
}
if(has_replaced) {
last_time_changed = clock_seconds();
return true;
}
LOG_DBG("cs: no changes\n");
return false;
}
/*---------------------------------------------------------------------------*/
void
tsch_cs_channel_stats_updated(uint8_t updated_channel, uint16_t old_busyness_metric)
{
uint8_t index;
bool old_is_busy;
bool new_is_busy;
/* Enable this only on the coordinator node */
if(!tsch_is_coordinator) {
return;
}
/* Do not try to adapt before enough information has been learned */
if(clock_seconds() < TSCH_CS_LEARNING_PERIOD_SEC) {
return;
}
index = tsch_stats_channel_to_index(updated_channel);
old_is_busy = (old_busyness_metric < TSCH_CS_FREE_THRESHOLD);
new_is_busy = (tsch_stats.channel_free_ewma[index] < TSCH_CS_FREE_THRESHOLD);
if(old_is_busy != new_is_busy) {
/* the status of the channel has changed*/
recaculation_requested = true;
} else if(new_is_busy) {
/* run the reselection algorithm iff the channel is both (1) bad and (2) in use */
if(tsch_cs_bitmap_contains(tsch_cs_current_bitmap, updated_channel)) {
/* the channel is in use and is busy */
recaculation_requested = true;
}
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2016-2018, University of Bristol - http://www.bristol.ac.uk
*
* 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 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
* Header file for TSCH adaptive channel selection
* \author
* Atis Elsts <atis.elsts@bristol.ac.uk>
*/
#ifndef __TSCH_CS_H__
#define __TSCH_CS_H__
#include "contiki.h"
#include <stdbool.h>
/* If `channel_free_ewma` value is less than this, the channel is considered busy */
#ifdef TSCH_CS_CONF_FREE_THRESHOLD
#define TSCH_CS_FREE_THRESHOLD TSCH_CS_CONF_FREE_THRESHOLD
#else
/* < 85% free */
#define TSCH_CS_FREE_THRESHOLD ((tsch_stat_t)(85ul * TSCH_STATS_BINARY_SCALING_FACTOR / 100))
#endif
#define TSCH_CS_LEARNING_PERIOD_SEC 30
/**
* \brief Initializes the TSCH hopping sequence selection module.
*/
void tsch_cs_adaptations_init(void);
/**
* \brief Signal the need to potentially update the TSCH hopping sequence.
* \param updated_channel The channel with the updated RSSI measurement
* \param old_busyness_metric The EWMA value of the "channel busy" status before the last RSSI measurement
*/
void tsch_cs_channel_stats_updated(uint8_t updated_channel, uint16_t old_busyness_metric);
/**
* \brief Potentially update the TSCH hopping sequence
* \return true if the hopping sequence was updated, false otherwise
*/
bool tsch_cs_process(void);
/* A bit corresponds to a channel; `uint16_t` value is OK for up to 16 channels. */
typedef uint16_t tsch_cs_bitmap_t;
#endif /* __TSCH_CS_H__ */

View File

@ -54,6 +54,8 @@
#define RTIMER_H_
#include "contiki.h"
#include "dev/watchdog.h"
#include <stdbool.h>
/** \brief The rtimer size (in bytes) */
#ifdef RTIMER_CONF_CLOCK_SIZE
@ -186,6 +188,26 @@ void rtimer_arch_schedule(rtimer_clock_t t);
#define RTIMER_GUARD_TIME (RTIMER_ARCH_SECOND >> 14)
#endif /* RTIMER_CONF_GUARD_TIME */
/** \brief Busy-wait until a condition. Start time is t0, max wait time is max_time */
#define RTIMER_BUSYWAIT_UNTIL_ABS(cond, t0, max_time) \
({ \
bool c; \
while(!(c = cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (max_time))) { \
watchdog_periodic(); \
} \
c; \
})
/** \brief Busy-wait until a condition for at most max_time */
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time) \
({ \
rtimer_clock_t t0 = RTIMER_NOW(); \
RTIMER_BUSYWAIT_UNTIL_ABS(cond, t0, max_time); \
})
/** \brief Busy-wait for a fixed duration */
#define RTIMER_BUSYWAIT(duration) RTIMER_BUSYWAIT_UNTIL(0, duration)
#endif /* RTIMER_H_ */
/** @} */

View File

@ -16,7 +16,7 @@ libs/stack-check/sky \
lwm2m-ipso-objects/native \
lwm2m-ipso-objects/native:MAKE_WITH_DTLS=1 \
lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1 \
lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1\
lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1 \
rpl-udp/sky \
rpl-border-router/native \
rpl-border-router/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \

View File

@ -80,7 +80,6 @@ coap/coap-example-server/cc2538dk \
slip-radio/cc2538dk \
lwm2m-ipso-objects/cc2538dk \
lwm2m-ipso-objects/cc2538dk:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1 \
lwm2m-ipso-objects/native:DEFINES=LWM2M_Q_MODE_CONF_ENABLED=1,LWM2M_Q_MODE_CONF_INCLUDE_DYNAMIC_ADAPTATION=1\
multicast/cc2538dk \
dev/gpio-hal/cc2538dk \
dev/leds/cc2538dk \

View File

@ -54,10 +54,10 @@
##### "TSCH_CONF_MAX_EB_PERIOD": _______________ -> TSCH_MAX_EB_PERIOD
#endif
#if TSCH_CONF_DEFAULT_TIMESLOT_LENGTH
##### "TSCH_CONF_DEFAULT_TIMESLOT_LENGTH": _____ == TSCH_CONF_DEFAULT_TIMESLOT_LENGTH
#ifdef TSCH_CONF_DEFAULT_TIMESLOT_TIMING
##### "TSCH_CONF_DEFAULT_TIMESLOT_TIMING": _____ == TSCH_CONF_DEFAULT_TIMESLOT_TIMING
#else
##### "TSCH_CONF_DEFAULT_TIMESLOT_LENGTH": _____ -> TSCH_DEFAULT_TIMESLOT_LENGTH
##### "TSCH_CONF_DEFAULT_TIMESLOT_TIMING": _____ -> TSCH_DEFAULT_TIMESLOT_TIMING
#endif
#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH